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

Commit e39a19a1 authored by Kweku Adams's avatar Kweku Adams Committed by Automerger Merge Worker
Browse files

Merge "Ensure AlarmManager knows of IDLE state." into udc-dev am: c95d515c

parents 98f78a94 c95d515c
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -2402,7 +2402,6 @@ public class DeviceIdleController extends SystemService
            return mConstants;
        }


        /** Returns the current elapsed realtime in milliseconds. */
        long getElapsedRealtime() {
            return SystemClock.elapsedRealtime();
@@ -3819,6 +3818,7 @@ public class DeviceIdleController extends SystemService

                // Everything is in place to go into IDLE state.
            case STATE_IDLE_MAINTENANCE:
                moveToStateLocked(STATE_IDLE, reason);
                scheduleAlarmLocked(mNextIdleDelay, true);
                if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
                        " ms.");
@@ -3829,7 +3829,6 @@ public class DeviceIdleController extends SystemService
                if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
                    mNextIdleDelay = mConstants.IDLE_TIMEOUT;
                }
                moveToStateLocked(STATE_IDLE, reason);
                if (mLightState != LIGHT_STATE_OVERRIDE) {
                    moveToLightStateLocked(LIGHT_STATE_OVERRIDE, "deep");
                    cancelLightAlarmLocked();
@@ -3842,6 +3841,7 @@ public class DeviceIdleController extends SystemService
                // We have been idling long enough, now it is time to do some work.
                mActiveIdleOpCount = 1;
                mActiveIdleWakeLock.acquire();
                moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
                scheduleAlarmLocked(mNextIdlePendingDelay, false);
                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
                        "Next alarm in " + mNextIdlePendingDelay + " ms.");
@@ -3851,7 +3851,6 @@ public class DeviceIdleController extends SystemService
                if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
                    mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
                }
                moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
                addEvent(EVENT_DEEP_MAINTENANCE, null);
                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
                break;
+154 −1
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ public class DeviceIdleControllerTest {
        ConstraintController constraintController;
        // Freeze time for testing.
        long nowElapsed;
        boolean useMotionSensor = true;

        InjectorForTest(Context ctx) {
            super(ctx);
@@ -245,7 +246,7 @@ public class DeviceIdleControllerTest {

        @Override
        boolean useMotionSensor() {
            return true;
            return useMotionSensor;
        }
    }

@@ -345,6 +346,12 @@ public class DeviceIdleControllerTest {
        mAnyMotionDetector = new AnyMotionDetectorForTest();
        mInjector = new InjectorForTest(getContext());

        setupDeviceIdleController();
    }

    private void setupDeviceIdleController() {
        reset(mTelephonyManager);

        mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
        spyOn(mDeviceIdleController);
        doNothing().when(mDeviceIdleController).publishBinderService(any(), any());
@@ -371,6 +378,10 @@ public class DeviceIdleControllerTest {
        if (mMockingSession != null) {
            mMockingSession.finishMocking();
        }
    }

    @After
    public void cleanupDeviceIdleController() {
        // DeviceIdleController adds these to LocalServices in the constructor, so we have to remove
        // them after each test, otherwise, subsequent tests will fail.
        LocalServices.removeServiceForTest(AppStateTracker.class);
@@ -617,6 +628,60 @@ public class DeviceIdleControllerTest {
                .scheduleAlarmLocked(eq(mConstants.INACTIVE_TIMEOUT), eq(false));
    }

    @Test
    public void testStateActiveToStateInactive_DoNotUseMotionSensor() {
        mInjector.useMotionSensor = false;
        cleanupDeviceIdleController();
        setupDeviceIdleController();
        mDeviceIdleController.becomeActiveLocked("testing", 0);
        verifyStateConditions(STATE_ACTIVE);

        setAlarmSoon(false);
        setChargingOn(false);
        setScreenOn(false);
        setEmergencyCallActive(false);

        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
        verifyStateConditions(STATE_INACTIVE);
        verify(mDeviceIdleController)
                .scheduleAlarmLocked(eq(mConstants.INACTIVE_TIMEOUT), eq(false));
        // The device configuration doesn't require a motion sensor to proceed with idling.
        // This should be the case on TVs or other such devices. We should set an alarm to move
        // forward if the motion sensor is missing in this case.
        verify(mAlarmManager).setWindow(
                anyInt(), anyLong(), anyLong(),
                eq("DeviceIdleController.deep"), any(), any(Handler.class));
    }

    @Test
    public void testStateActiveToStateInactive_MissingMotionSensor() {
        mInjector.useMotionSensor = true;
        mMotionSensor = null;
        cleanupDeviceIdleController();
        setupDeviceIdleController();
        mDeviceIdleController.becomeActiveLocked("testing", 0);
        verifyStateConditions(STATE_ACTIVE);

        setAlarmSoon(false);
        setChargingOn(false);
        setScreenOn(false);
        setEmergencyCallActive(false);

        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
        verifyStateConditions(STATE_INACTIVE);
        verify(mDeviceIdleController)
                .scheduleAlarmLocked(eq(mConstants.INACTIVE_TIMEOUT), eq(false));
        // The device configuration requires a motion sensor to proceed with idling,
        // so we should never set an alarm to move forward if the motion sensor is
        // missing in this case.
        verify(mAlarmManager, never()).setWindow(
                anyInt(), anyLong(), anyLong(),
                eq("DeviceIdleController.deep"), any(), any(Handler.class));
        verify(mAlarmManager, never()).set(
                anyInt(), anyLong(),
                eq("DeviceIdleController.deep"), any(), any(Handler.class));
    }

    @Test
    public void testStateActiveToStateInactive_UpcomingAlarm() {
        final long timeUntilAlarm = mConstants.MIN_TIME_TO_ALARM / 2;
@@ -756,6 +821,94 @@ public class DeviceIdleControllerTest {
        verifyStateConditions(STATE_IDLE_MAINTENANCE);
    }

    @Test
    public void testStepIdleStateLocked_ValidStates_MissingMotionSensor() {
        mInjector.useMotionSensor = true;
        mMotionSensor = null;
        cleanupDeviceIdleController();
        setupDeviceIdleController();
        mInjector.locationManager = mLocationManager;
        doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(anyString());
        // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
        setAlarmSoon(false);

        InOrder alarmManagerInOrder = inOrder(mAlarmManager);

        // Set state to INACTIVE.
        mDeviceIdleController.becomeActiveLocked("testing", 0);
        setChargingOn(false);
        setScreenOn(false);
        verifyStateConditions(STATE_INACTIVE);

        // The device configuration requires a motion sensor to proceed with idling,
        // so we should never set an alarm to move forward if the motion sensor is
        // missing in this case.
        alarmManagerInOrder.verify(mAlarmManager, never())
                .setWindow(anyInt(), anyLong(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));

        // Pretend that someone is forcing state stepping via adb

        mDeviceIdleController.stepIdleStateLocked("testing");
        // verifyStateConditions knows this state typically shouldn't happen during normal
        // operation, so we can't use it directly here. For this test, all we care about
        // is that the state stepped forward.
        assertEquals(STATE_IDLE_PENDING, mDeviceIdleController.getState());
        // Still no alarm
        alarmManagerInOrder.verify(mAlarmManager, never())
                .setWindow(anyInt(), anyLong(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));

        mDeviceIdleController.stepIdleStateLocked("testing");
        // verifyStateConditions knows this state typically shouldn't happen during normal
        // operation, so we can't use it directly here. For this test, all we care about
        // is that the state stepped forward.
        assertEquals(STATE_SENSING, mDeviceIdleController.getState());
        // Still no alarm
        alarmManagerInOrder.verify(mAlarmManager, never())
                .setWindow(anyInt(), anyLong(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));

        mDeviceIdleController.stepIdleStateLocked("testing");
        // Location manager exists with a provider, so SENSING should go to LOCATING.
        // verifyStateConditions knows this state typically shouldn't happen during normal
        // operation, so we can't use it directly here. For this test, all we care about
        // is that the state stepped forward.
        assertEquals(STATE_LOCATING, mDeviceIdleController.getState());
        // Still no alarm
        alarmManagerInOrder.verify(mAlarmManager, never())
                .setWindow(anyInt(), anyLong(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));

        mDeviceIdleController.stepIdleStateLocked("testing");
        verifyStateConditions(STATE_IDLE);
        // The device was forced into IDLE. AlarmManager should be notified.
        alarmManagerInOrder.verify(mAlarmManager)
                .setIdleUntil(anyInt(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));

        // Should just alternate between IDLE and IDLE_MAINTENANCE now. Since we've gotten to this
        // point, alarms should be set on each transition.

        mDeviceIdleController.stepIdleStateLocked("testing");
        verifyStateConditions(STATE_IDLE_MAINTENANCE);
        alarmManagerInOrder.verify(mAlarmManager)
                .setWindow(anyInt(), anyLong(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));

        mDeviceIdleController.stepIdleStateLocked("testing");
        verifyStateConditions(STATE_IDLE);
        alarmManagerInOrder.verify(mAlarmManager)
                .setIdleUntil(anyInt(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));

        mDeviceIdleController.stepIdleStateLocked("testing");
        verifyStateConditions(STATE_IDLE_MAINTENANCE);
        alarmManagerInOrder.verify(mAlarmManager)
                .setWindow(anyInt(), anyLong(), anyLong(),
                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
    }

    @Test
    public void testStepIdleStateLocked_ValidStates_WithWakeFromIdleAlarmSoon() {
        enterDeepState(STATE_ACTIVE);