Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58772783 authored by Beth Thibodeau's avatar Beth Thibodeau
Browse files

Adding unit tests

Tests that the screen record tile on/off/cancel works as expected and that the
recording controller updates state and calls listeners correctly

Also updated a couple methods so they make more sense (aren't called
multiple times per event, differentiating between onRecordingEnd and
onCountdownEnd)

Test: atest ScreenRecordTileTest RecordingControllerTest
Bug: 144944929
Change-Id: Ic2d44bbc250bcb1e90eff78839c9ab37c0d93564
parent cb7f6ffe
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
        Log.d(TAG, "Starting countdown");
        // Close QS, otherwise the permission dialog appears beneath it
        getHost().collapsePanels();
        mController.launchRecordPrompt(this);
        mController.launchRecordPrompt();
    }

    private void cancelCountdown() {
@@ -128,6 +128,11 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
            refreshState();
        }

        @Override
        public void onCountdownEnd() {
            refreshState();
        }

        @Override
        public void onRecordingStart() {
            refreshState();
+15 −12
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.os.CountDownTimer;
import android.util.Log;

import com.android.systemui.qs.tiles.ScreenRecordTile;
import com.android.systemui.statusbar.policy.CallbackController;

import java.util.ArrayList;
@@ -62,7 +61,7 @@ public class RecordingController
    /**
     * Show dialog of screen recording options to user.
     */
    public void launchRecordPrompt(ScreenRecordTile tileToUpdate) {
    public void launchRecordPrompt() {
        final ComponentName launcherComponent = new ComponentName(SYSUI_PACKAGE,
                SYSUI_SCREENRECORD_LAUNCHER);
        final Intent intent = new Intent();
@@ -73,15 +72,17 @@ public class RecordingController

    /**
     * Start counting down in preparation to start a recording
     * @param ms Time in ms to count down
     * @param ms Total time in ms to wait before starting
     * @param interval Time in ms per countdown step
     * @param startIntent Intent to start a recording
     * @param stopIntent Intent to stop a recording
     */
    public void startCountdown(long ms, PendingIntent startIntent, PendingIntent stopIntent) {
    public void startCountdown(long ms, long interval, PendingIntent startIntent,
            PendingIntent stopIntent) {
        mIsStarting = true;
        mStopIntent = stopIntent;

        mCountDownTimer = new CountDownTimer(ms, 1000) {
        mCountDownTimer = new CountDownTimer(ms, interval) {
            @Override
            public void onTick(long millisUntilFinished) {
                for (RecordingStateChangeCallback cb : mListeners) {
@@ -94,7 +95,7 @@ public class RecordingController
                mIsStarting = false;
                mIsRecording = true;
                for (RecordingStateChangeCallback cb : mListeners) {
                    cb.onRecordingEnd();
                    cb.onCountdownEnd();
                }
                try {
                    startIntent.send();
@@ -120,7 +121,7 @@ public class RecordingController
        mIsStarting = false;

        for (RecordingStateChangeCallback cb : mListeners) {
            cb.onRecordingEnd();
            cb.onCountdownEnd();
        }
    }

@@ -144,16 +145,12 @@ public class RecordingController
     * Stop the recording
     */
    public void stopRecording() {
        updateState(false);
        try {
            mStopIntent.send();
            updateState(false);
        } catch (PendingIntent.CanceledException e) {
            Log.e(TAG, "Error stopping: " + e.getMessage());
        }

        for (RecordingStateChangeCallback cb : mListeners) {
            cb.onRecordingEnd();
        }
    }

    /**
@@ -192,6 +189,12 @@ public class RecordingController
         */
        default void onCountdown(long millisUntilFinished) {}

        /**
         * Called when a countdown to recording has ended. This is a separate method so that if
         * needed, listeners can handle cases where recording fails to start
         */
        default void onCountdownEnd() {}

        /**
         * Called when a screen recording has started
         */
+2 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import javax.inject.Inject;
 */
public class ScreenRecordDialog extends Activity {
    private static final long DELAY_MS = 3000;
    private static final long INTERVAL_MS = 1000;

    private final RecordingController mController;
    private Switch mAudioSwitch;
@@ -83,6 +84,6 @@ public class ScreenRecordDialog extends Activity {
                RecordingService.REQUEST_CODE,
                RecordingService.getStopIntent(this),
                PendingIntent.FLAG_UPDATE_CURRENT);
        mController.startCountdown(DELAY_MS, startIntent, stopIntent);
        mController.startCountdown(DELAY_MS, INTERVAL_MS, startIntent, stopIntent);
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -677,6 +677,12 @@ public class PhoneStatusBarPolicy
        mIconController.setIconVisibility(mSlotScreenRecord, true);
    }

    @Override
    public void onCountdownEnd() {
        if (DEBUG) Log.d(TAG, "screenrecord: hiding icon during countdown");
        mHandler.post(() -> mIconController.setIconVisibility(mSlotScreenRecord, false));
    }

    @Override
    public void onRecordingStart() {
        if (DEBUG) Log.d(TAG, "screenrecord: showing icon");
@@ -687,7 +693,7 @@ public class PhoneStatusBarPolicy

    @Override
    public void onRecordingEnd() {
        // Ensure this is on the main thread, since it could be called during countdown
        // Ensure this is on the main thread
        if (DEBUG) Log.d(TAG, "screenrecord: hiding icon");
        mHandler.post(() -> mIconController.setIconVisibility(mSlotScreenRecord, false));
    }
+136 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.tiles;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;

import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.service.quicksettings.Tile;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import androidx.test.filters.SmallTest;

import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.screenrecord.RecordingController;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class ScreenRecordTileTest extends SysuiTestCase {

    @Mock
    private RecordingController mController;
    @Mock
    private QSTileHost mHost;

    private TestableLooper mTestableLooper;
    private ScreenRecordTile mTile;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mTestableLooper = TestableLooper.get(this);
        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
        mController = mDependency.injectMockDependency(RecordingController.class);

        when(mHost.getContext()).thenReturn(mContext);

        mTile = new ScreenRecordTile(mHost, mController);
    }

    // Test that the tile is inactive and labeled correctly when the controller is neither starting
    // or recording, and that clicking on the tile in this state brings up the record prompt
    @Test
    public void testNotActive() {
        when(mController.isStarting()).thenReturn(false);
        when(mController.isRecording()).thenReturn(false);

        mTile.refreshState();
        mTestableLooper.processAllMessages();

        assertEquals(Tile.STATE_INACTIVE, mTile.getState().state);
        assertTrue(mTile.getState().secondaryLabel.toString().equals(
                mContext.getString(R.string.quick_settings_screen_record_start)));

        mTile.handleClick();
        verify(mController, times(1)).launchRecordPrompt();
    }

    // Test that the tile is active and labeled correctly when the controller is starting
    @Test
    public void testIsStarting() {
        when(mController.isStarting()).thenReturn(true);
        when(mController.isRecording()).thenReturn(false);

        mTile.refreshState();
        mTestableLooper.processAllMessages();

        assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
        assertTrue(mTile.getState().secondaryLabel.toString().endsWith("..."));
    }

    // Test that the tile cancels countdown if it is clicked when the controller is starting
    @Test
    public void testCancelRecording() {
        when(mController.isStarting()).thenReturn(true);
        when(mController.isRecording()).thenReturn(false);

        mTile.handleClick();

        verify(mController, times(1)).cancelCountdown();
    }

    // Test that the tile is active and labeled correctly when the controller is recording
    @Test
    public void testIsRecording() {
        when(mController.isStarting()).thenReturn(false);
        when(mController.isRecording()).thenReturn(true);

        mTile.refreshState();
        mTestableLooper.processAllMessages();

        assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
        assertTrue(mTile.getState().secondaryLabel.toString().equals(
                mContext.getString(R.string.quick_settings_screen_record_stop)));
    }

    // Test that the tile stops the recording if it is clicked when the controller is recording
    @Test
    public void testStopRecording() {
        when(mController.isStarting()).thenReturn(false);
        when(mController.isRecording()).thenReturn(true);

        mTile.handleClick();

        verify(mController, times(1)).stopRecording();
    }
}
Loading