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

Commit b7ce190a authored by Kweku Adams's avatar Kweku Adams
Browse files

Ensure AlarmManager is brought out of device idle.

In certain cases, DeviceIdleController would come out of STATE_IDLE but
not properly tell AlarmManager (by removing the IDLE_UNTIL alarm). This
meant that alarms wouldn't go off even though the user may be using the
device.

Manual testing steps:
1. Turn on WAIT_FOR_UNLOCK ('adb shell settings put global device_idle_constants "wait_for_unlock=true"')
2. Enable screen lock
3. Unplug device ('adb shell dumpsys battery unplug')
3. Turn screen off
4. Enter IDLE state (repeat 'adb shell dumpsys deviceidle step' until IDLE)
5. Turn screen on
6. Shake device (or run 'adb shell dumpsys deviceidle motion')
7. Check dumpsys output:
  - 'adb shell dumpsys deviceidle get deep' should say "INACTIVE"
  - 'adb shell dumpsys alarm' should not have "Idle state mode" in the output

Bug: 118321869
Test: atest com.android.server.DeviceIdleControllerTest
Change-Id: Ie41b5a4bd9f2b386fe709108c39a443bd40fd573
parent b9218244
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ public interface AlarmManagerInternal {
        void broadcastAlarmComplete(int recipientUid);
    }

    /** Returns true if AlarmManager is delaying alarms due to device idle. */
    boolean isIdling();
    public void removeAlarmsForUid(int uid);
    public void registerInFlightListener(InFlightListener callback);
}
+11 −0
Original line number Diff line number Diff line
@@ -1990,6 +1990,11 @@ class AlarmManagerService extends SystemService {
     * System-process internal API
     */
    private final class LocalService implements AlarmManagerInternal {
        @Override
        public boolean isIdling() {
            return isIdlingImpl();
        }

        @Override
        public void removeAlarmsForUid(int uid) {
            synchronized (mLock) {
@@ -2823,6 +2828,12 @@ class AlarmManagerService extends SystemService {
        }
    }

    private boolean isIdlingImpl() {
        synchronized (mLock) {
            return mPendingIdleUntil != null;
        }
    }

    AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
        synchronized (mLock) {
            return mNextAlarmClockForUser.get(userId);
+110 −75
Original line number Diff line number Diff line
@@ -271,6 +271,7 @@ public class DeviceIdleController extends SystemService
    private static final int EVENT_BUFFER_SIZE = 100;

    private AlarmManager mAlarmManager;
    private AlarmManagerInternal mLocalAlarmManager;
    private IBatteryStats mBatteryStats;
    private ActivityManagerInternal mLocalActivityManager;
    private ActivityTaskManagerInternal mLocalActivityTaskManager;
@@ -616,7 +617,8 @@ public class DeviceIdleController extends SystemService
        }
    };

    private final AlarmManager.OnAlarmListener mDeepAlarmListener
    @VisibleForTesting
    final AlarmManager.OnAlarmListener mDeepAlarmListener
            = new AlarmManager.OnAlarmListener() {
        @Override
        public void onAlarm() {
@@ -1874,6 +1876,7 @@ public class DeviceIdleController extends SystemService
        if (phase == PHASE_SYSTEM_SERVICES_READY) {
            synchronized (this) {
                mAlarmManager = mInjector.getAlarmManager();
                mLocalAlarmManager = getLocalService(AlarmManagerInternal.class);
                mBatteryStats = BatteryStatsService.getService();
                mLocalActivityManager = getLocalService(ActivityManagerInternal.class);
                mLocalActivityTaskManager = getLocalService(ActivityTaskManagerInternal.class);
@@ -2605,6 +2608,16 @@ public class DeviceIdleController extends SystemService
        // next natural time to come out of it.
    }


    /** Returns true if the screen is locked. */
    @VisibleForTesting
    boolean isKeyguardShowing() {
        synchronized (this) {
            return mScreenLocked;
        }
    }

    @VisibleForTesting
    void keyguardShowingLocked(boolean showing) {
        if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
        if (mScreenLocked != showing) {
@@ -2616,27 +2629,40 @@ public class DeviceIdleController extends SystemService
        }
    }

    @VisibleForTesting
    void scheduleReportActiveLocked(String activeReason, int activeUid) {
        Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
        mHandler.sendMessage(msg);
    }

    void becomeActiveLocked(String activeReason, int activeUid) {
        if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
        becomeActiveLocked(activeReason, activeUid, mConstants.INACTIVE_TIMEOUT, true);
    }

    private void becomeActiveLocked(String activeReason, int activeUid,
            long newInactiveTimeout, boolean changeLightIdle) {
        if (DEBUG) {
            Slog.i(TAG, "becomeActiveLocked, reason=" + activeReason
                    + ", changeLightIdle=" + changeLightIdle);
        }
        if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
            EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
            EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
            scheduleReportActiveLocked(activeReason, activeUid);
            mState = STATE_ACTIVE;
            mLightState = LIGHT_STATE_ACTIVE;
            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
            mInactiveTimeout = newInactiveTimeout;
            mCurIdleBudget = 0;
            mMaintenanceStartTime = 0;
            resetIdleManagementLocked();

            if (changeLightIdle) {
                EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
                mLightState = LIGHT_STATE_ACTIVE;
                resetLightIdleManagementLocked();
                // Only report active if light is also ACTIVE.
                scheduleReportActiveLocked(activeReason, activeUid);
                addEvent(EVENT_NORMAL, activeReason);
            }
        }
    }

    /** Must only be used in tests. */
    @VisibleForTesting
@@ -2654,9 +2680,42 @@ public class DeviceIdleController extends SystemService
        }
    }

    /** Sanity check to make sure DeviceIdleController and AlarmManager are on the same page. */
    private void verifyAlarmStateLocked() {
        if (mState == STATE_ACTIVE && mNextAlarmTime != 0) {
            Slog.wtf(TAG, "mState=ACTIVE but mNextAlarmTime=" + mNextAlarmTime);
        }
        if (mState != STATE_IDLE && mLocalAlarmManager.isIdling()) {
            Slog.wtf(TAG, "mState=" + stateToString(mState) + " but AlarmManager is idling");
        }
        if (mState == STATE_IDLE && !mLocalAlarmManager.isIdling()) {
            Slog.wtf(TAG, "mState=IDLE but AlarmManager is not idling");
        }
        if (mLightState == LIGHT_STATE_ACTIVE && mNextLightAlarmTime != 0) {
            Slog.wtf(TAG, "mLightState=ACTIVE but mNextLightAlarmTime is "
                    + TimeUtils.formatDuration(mNextLightAlarmTime - SystemClock.elapsedRealtime())
                    + " from now");
        }
    }

    void becomeInactiveIfAppropriateLocked() {
        if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
        if ((!mScreenOn && !mCharging) || mForceIdle) {
        verifyAlarmStateLocked();

        final boolean isScreenBlockingInactive =
                mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
        if (DEBUG) {
            Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
                    + " isScreenBlockingInactive=" + isScreenBlockingInactive
                    + " (mScreenOn=" + mScreenOn
                    + ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
                    + ", mScreenLocked=" + mScreenLocked + ")"
                    + " mCharging=" + mCharging
                    + " mForceIdle=" + mForceIdle
            );
        }
        if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
            return;
        }
        // Become inactive and determine if we will ultimately go idle.
        if (mDeepEnabled) {
            if (mQuickDozeActivated) {
@@ -2698,7 +2757,6 @@ public class DeviceIdleController extends SystemService
            EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
        }
    }
    }

    private void resetIdleManagementLocked() {
        mNextIdlePendingDelay = 0;
@@ -3216,33 +3274,10 @@ public class DeviceIdleController extends SystemService
        // The device is not yet active, so we want to go back to the pending idle
        // state to wait again for no motion.  Note that we only monitor for motion
        // after moving out of the inactive state, so no need to worry about that.
        boolean becomeInactive = false;
        if (mState != STATE_ACTIVE) {
            // Motion shouldn't affect light state, if it's already in doze-light or maintenance
            boolean lightIdle = mLightState == LIGHT_STATE_IDLE
                    || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK
                    || mLightState == LIGHT_STATE_IDLE_MAINTENANCE;
            if (!lightIdle) {
                // Only switch to active state if we're not in either idle state
                scheduleReportActiveLocked(type, Process.myUid());
                addEvent(EVENT_NORMAL, type);
            }
            mActiveReason = ACTIVE_REASON_MOTION;
            mState = STATE_ACTIVE;
            mInactiveTimeout = timeout;
            mCurIdleBudget = 0;
            mMaintenanceStartTime = 0;
            EventLogTags.writeDeviceIdle(mState, type);
            becomeInactive = true;
            updateActiveConstraintsLocked();
        }
        if (mLightState == LIGHT_STATE_OVERRIDE) {
            // We went out of light idle mode because we had started deep idle mode...  let's
            // now go back and reset things so we resume light idling if appropriate.
            mLightState = LIGHT_STATE_ACTIVE;
            EventLogTags.writeDeviceIdleLight(mLightState, type);
            becomeInactive = true;
        }
        final boolean becomeInactive = mState != STATE_ACTIVE
                || mLightState == LIGHT_STATE_OVERRIDE;
        // We only want to change the IDLE state if it's OVERRIDE.
        becomeActiveLocked(type, Process.myUid(), timeout, mLightState == LIGHT_STATE_OVERRIDE);
        if (becomeInactive) {
            becomeInactiveIfAppropriateLocked();
        }
+217 −13
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import static androidx.test.InstrumentationRegistry.getContext;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -51,6 +52,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;

import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
@@ -82,6 +86,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
@@ -105,6 +110,8 @@ public class DeviceIdleControllerTest {
    @Mock
    private ContentResolver mContentResolver;
    @Mock
    private DeviceIdleController.MyHandler mHandler;
    @Mock
    private IActivityManager mIActivityManager;
    @Mock
    private LocationManager mLocationManager;
@@ -154,7 +161,7 @@ public class DeviceIdleControllerTest {

        @Override
        DeviceIdleController.MyHandler getHandler(DeviceIdleController controller) {
            return mock(DeviceIdleController.MyHandler.class, Answers.RETURNS_DEEP_STUBS);
            return mHandler;
        }

        @Override
@@ -232,10 +239,12 @@ public class DeviceIdleControllerTest {
                .when(() -> LocalServices.getService(ActivityManagerInternal.class));
        doReturn(mock(ActivityTaskManagerInternal.class))
                .when(() -> LocalServices.getService(ActivityTaskManagerInternal.class));
        doReturn(mock(AlarmManagerInternal.class))
                .when(() -> LocalServices.getService(AlarmManagerInternal.class));
        doReturn(mPowerManagerInternal)
                .when(() -> LocalServices.getService(PowerManagerInternal.class));
        when(mPowerManagerInternal.getLowPowerState(anyInt())).thenReturn(
                mock(PowerSaveState.class));
        when(mPowerManagerInternal.getLowPowerState(anyInt()))
                .thenReturn(mock(PowerSaveState.class));
        doReturn(mock(NetworkPolicyManagerInternal.class))
                .when(() -> LocalServices.getService(NetworkPolicyManagerInternal.class));
        when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
@@ -246,8 +255,11 @@ public class DeviceIdleControllerTest {
        doReturn(true).when(mSensorManager).registerListener(any(), any(), anyInt());
        mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
        mAnyMotionDetector = new AnyMotionDetectorForTest();
        mHandler = mock(DeviceIdleController.MyHandler.class, Answers.RETURNS_DEEP_STUBS);
        doNothing().when(mHandler).handleMessage(any());
        mInjector = new InjectorForTest(getContext());
        doNothing().when(mContentResolver).registerContentObserver(any(), anyBoolean(), any());

        mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
        spyOn(mDeviceIdleController);
        doNothing().when(mDeviceIdleController).publishBinderService(any(), any());
@@ -423,6 +435,29 @@ public class DeviceIdleControllerTest {

        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
        verifyStateConditions(STATE_ACTIVE);

        mConstants.WAIT_FOR_UNLOCK = false;
        setScreenLocked(true);
        setScreenOn(true);
        setChargingOn(false);

        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
        verifyStateConditions(STATE_ACTIVE);

        setScreenLocked(false);
        setScreenOn(true);
        setChargingOn(false);

        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
        verifyStateConditions(STATE_ACTIVE);

        mConstants.WAIT_FOR_UNLOCK = true;
        setScreenLocked(false);
        setScreenOn(true);
        setChargingOn(false);

        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
        verifyStateConditions(STATE_ACTIVE);
    }

    @Test
@@ -1307,7 +1342,7 @@ public class DeviceIdleControllerTest {
    }

    @Test
    public void testbecomeActiveLocked_deep() {
    public void testBecomeActiveLocked_deep() {
        // becomeActiveLocked should put everything into ACTIVE.

        enterDeepState(STATE_ACTIVE);
@@ -1344,7 +1379,7 @@ public class DeviceIdleControllerTest {
    }

    @Test
    public void testbecomeActiveLocked_light() {
    public void testBecomeActiveLocked_light() {
        // becomeActiveLocked should put everything into ACTIVE.

        enterLightState(LIGHT_STATE_ACTIVE);
@@ -1376,6 +1411,163 @@ public class DeviceIdleControllerTest {
        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
    }

    /** Test based on b/119058625. */
    @Test
    public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_ScreenThenMotion() {
        mConstants.WAIT_FOR_UNLOCK = true;
        enterDeepState(STATE_IDLE);
        reset(mAlarmManager);
        spyOn(mDeviceIdleController);

        mDeviceIdleController.keyguardShowingLocked(true);
        setScreenOn(true);
        // With WAIT_FOR_UNLOCK = true and the screen locked, turning the screen on by itself
        // shouldn't bring the device out of deep IDLE.
        verifyStateConditions(STATE_IDLE);
        mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
        // Motion should bring the device out of Doze. Since the screen is still locked (albeit
        // on), the states should go back into INACTIVE.
        verifyStateConditions(STATE_INACTIVE);
        verifyLightStateConditions(LIGHT_STATE_INACTIVE);
        verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
    }

    /** Test based on b/119058625. */
    @Test
    public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_ScreenThenMotion() {
        mConstants.WAIT_FOR_UNLOCK = true;
        enterDeepState(STATE_IDLE);
        reset(mAlarmManager);
        spyOn(mDeviceIdleController);

        mDeviceIdleController.keyguardShowingLocked(false);
        setScreenOn(true);
        // With WAIT_FOR_UNLOCK = true and the screen unlocked, turning the screen on by itself
        // should bring the device out of deep IDLE.
        verifyStateConditions(STATE_ACTIVE);
        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
        verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
    }

    /** Test based on b/119058625. */
    @Test
    public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOn_MotionThenScreen() {
        mConstants.WAIT_FOR_UNLOCK = true;
        enterDeepState(STATE_IDLE);
        reset(mAlarmManager);
        spyOn(mDeviceIdleController);

        InOrder alarmManagerInOrder = inOrder(mAlarmManager);
        InOrder controllerInOrder = inOrder(mDeviceIdleController);

        mDeviceIdleController.keyguardShowingLocked(true);
        mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
        // The screen is still off, so motion should result in the INACTIVE state.
        verifyStateConditions(STATE_INACTIVE);
        verifyLightStateConditions(LIGHT_STATE_INACTIVE);
        alarmManagerInOrder.verify(mAlarmManager)
                .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        controllerInOrder.verify(mDeviceIdleController)
                .scheduleReportActiveLocked(anyString(), anyInt());

        setScreenOn(true);
        // With WAIT_FOR_UNLOCK = true and the screen locked, turning the screen on by itself
        // shouldn't bring the device all the way to ACTIVE.
        verifyStateConditions(STATE_INACTIVE);
        verifyLightStateConditions(LIGHT_STATE_INACTIVE);
        alarmManagerInOrder.verify(mAlarmManager, never()).cancel(
                eq(mDeviceIdleController.mDeepAlarmListener));

        // User finally unlocks the device. Device should be fully active.
        mDeviceIdleController.keyguardShowingLocked(false);
        verifyStateConditions(STATE_ACTIVE);
        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
        alarmManagerInOrder.verify(mAlarmManager)
                .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        controllerInOrder.verify(mDeviceIdleController)
                .scheduleReportActiveLocked(anyString(), anyInt());
    }

    /** Test based on b/119058625. */
    @Test
    public void testExitNotifiesDependencies_WaitForUnlockOn_KeyguardOff_MotionThenScreen() {
        mConstants.WAIT_FOR_UNLOCK = true;
        enterDeepState(STATE_IDLE);
        reset(mAlarmManager);
        spyOn(mDeviceIdleController);

        InOrder alarmManagerInOrder = inOrder(mAlarmManager);
        InOrder controllerInOrder = inOrder(mDeviceIdleController);

        mDeviceIdleController.keyguardShowingLocked(false);
        mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
        // The screen is still off, so motion should result in the INACTIVE state.
        verifyStateConditions(STATE_INACTIVE);
        verifyLightStateConditions(LIGHT_STATE_INACTIVE);
        alarmManagerInOrder.verify(mAlarmManager)
                .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        controllerInOrder.verify(mDeviceIdleController)
                .scheduleReportActiveLocked(anyString(), anyInt());

        setScreenOn(true);
        // With WAIT_FOR_UNLOCK = true and the screen unlocked, turning the screen on by itself
        // should bring the device out of deep IDLE.
        verifyStateConditions(STATE_ACTIVE);
        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
        alarmManagerInOrder.verify(mAlarmManager)
                .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        controllerInOrder.verify(mDeviceIdleController)
                .scheduleReportActiveLocked(anyString(), anyInt());
    }

    @Test
    public void testExitNotifiesDependencies_WaitForUnlockOff_Screen() {
        mConstants.WAIT_FOR_UNLOCK = false;
        enterDeepState(STATE_IDLE);
        reset(mAlarmManager);
        spyOn(mDeviceIdleController);

        setScreenOn(true);
        // With WAIT_FOR_UNLOCK = false and the screen locked, turning the screen on by itself
        // should bring the device out of deep IDLE.
        verifyStateConditions(STATE_ACTIVE);
        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
        verify(mAlarmManager).cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        verify(mDeviceIdleController).scheduleReportActiveLocked(anyString(), anyInt());
    }

    @Test
    public void testExitNotifiesDependencies_WaitForUnlockOff_MotionThenScreen() {
        mConstants.WAIT_FOR_UNLOCK = false;
        enterDeepState(STATE_IDLE);
        reset(mAlarmManager);
        spyOn(mDeviceIdleController);

        InOrder alarmManagerInOrder = inOrder(mAlarmManager);
        InOrder controllerInOrder = inOrder(mDeviceIdleController);

        mDeviceIdleController.handleMotionDetectedLocked(1000, "test");
        // The screen is still off, so motion should result in the INACTIVE state.
        verifyStateConditions(STATE_INACTIVE);
        verifyLightStateConditions(LIGHT_STATE_INACTIVE);
        alarmManagerInOrder.verify(mAlarmManager)
                .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        controllerInOrder.verify(mDeviceIdleController)
                .scheduleReportActiveLocked(anyString(), anyInt());

        setScreenOn(true);
        // With WAIT_FOR_UNLOCK = false and the screen locked, turning the screen on by itself
        // should bring the device out of deep IDLE.
        verifyStateConditions(STATE_ACTIVE);
        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
        alarmManagerInOrder.verify(mAlarmManager)
                .cancel(eq(mDeviceIdleController.mDeepAlarmListener));
        controllerInOrder.verify(mDeviceIdleController)
                .scheduleReportActiveLocked(anyString(), anyInt());
    }

    @Test
    public void testStepToIdleMode() {
        float delta = mDeviceIdleController.MIN_PRE_IDLE_FACTOR_CHANGE;
@@ -1508,6 +1700,10 @@ public class DeviceIdleControllerTest {
        mDeviceIdleController.updateChargingLocked(on);
    }

    private void setScreenLocked(boolean locked) {
        mDeviceIdleController.keyguardShowingLocked(locked);
    }

    private void setScreenOn(boolean on) {
        doReturn(on).when(mPowerManager).isInteractive();
        mDeviceIdleController.updateInteractivityLocked();
@@ -1549,7 +1745,8 @@ public class DeviceIdleControllerTest {
                assertFalse(mDeviceIdleController.mMotionListener.isActive());
                assertFalse(mAnyMotionDetector.isMonitoring);
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                break;
            case STATE_IDLE_PENDING:
                assertEquals(
@@ -1557,7 +1754,8 @@ public class DeviceIdleControllerTest {
                        mDeviceIdleController.mMotionListener.isActive());
                assertFalse(mAnyMotionDetector.isMonitoring);
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                break;
            case STATE_SENSING:
                assertEquals(
@@ -1567,14 +1765,16 @@ public class DeviceIdleControllerTest {
                        mDeviceIdleController.hasMotionSensor(),
                        mAnyMotionDetector.isMonitoring);
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                break;
            case STATE_LOCATING:
                assertEquals(
                        mDeviceIdleController.hasMotionSensor(),
                        mDeviceIdleController.mMotionListener.isActive());
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                break;
            case STATE_IDLE:
                if (mDeviceIdleController.hasMotionSensor()) {
@@ -1584,7 +1784,8 @@ public class DeviceIdleControllerTest {
                }
                assertFalse(mAnyMotionDetector.isMonitoring);
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                // Light state should be OVERRIDE at this point.
                verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
                break;
@@ -1596,14 +1797,16 @@ public class DeviceIdleControllerTest {
                }
                assertFalse(mAnyMotionDetector.isMonitoring);
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                break;
            case STATE_QUICK_DOZE_DELAY:
                // If quick doze is enabled, the motion listener should NOT be active.
                assertFalse(mDeviceIdleController.mMotionListener.isActive());
                assertFalse(mAnyMotionDetector.isMonitoring);
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                break;
            default:
                fail("Conditions for " + stateToString(expectedState) + " unknown.");
@@ -1632,7 +1835,8 @@ public class DeviceIdleControllerTest {
            case LIGHT_STATE_IDLE_MAINTENANCE:
            case LIGHT_STATE_OVERRIDE:
                assertFalse(mDeviceIdleController.isCharging());
                assertFalse(mDeviceIdleController.isScreenOn());
                assertFalse(mDeviceIdleController.isScreenOn()
                        && !mDeviceIdleController.isKeyguardShowing());
                break;
            default:
                fail("Conditions for " + lightStateToString(expectedLightState) + " unknown.");