Loading services/core/java/com/android/server/DeviceIdleController.java +29 −15 Original line number Diff line number Diff line Loading @@ -429,7 +429,15 @@ public class DeviceIdleController extends SystemService private long mNextLightIdleDelay; private long mNextLightAlarmTime; private long mNextSensingTimeoutAlarmTime; private long mCurIdleBudget; /** How long a light idle maintenance window should last. */ private long mCurLightIdleBudget; /** * Start time of the current (light or full) maintenance window, in the elapsed timebase. Valid * only if {@link #mState} == {@link #STATE_IDLE_MAINTENANCE} or * {@link #mLightState} == {@link #LIGHT_STATE_IDLE_MAINTENANCE}. */ private long mMaintenanceStartTime; private long mIdleStartTime; Loading Loading @@ -2651,9 +2659,12 @@ public class DeviceIdleController extends SystemService EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason); mState = STATE_ACTIVE; mInactiveTimeout = newInactiveTimeout; mCurIdleBudget = 0; mMaintenanceStartTime = 0; resetIdleManagementLocked(); // Don't reset maintenance window start time if we're in a light idle maintenance window // because its used in the light idle budget calculation. if (mLightState != LIGHT_STATE_IDLE_MAINTENANCE) { mMaintenanceStartTime = 0; } if (changeLightIdle) { EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason); Loading Loading @@ -2763,7 +2774,6 @@ public class DeviceIdleController extends SystemService private void resetIdleManagementLocked() { mNextIdlePendingDelay = 0; mNextIdleDelay = 0; mNextLightIdleDelay = 0; mIdleStartTime = 0; cancelAlarmLocked(); cancelSensingTimeoutAlarmLocked(); Loading @@ -2774,6 +2784,8 @@ public class DeviceIdleController extends SystemService } private void resetLightIdleManagementLocked() { mNextLightIdleDelay = 0; mCurLightIdleBudget = 0; cancelLightAlarmLocked(); } Loading Loading @@ -2816,7 +2828,7 @@ public class DeviceIdleController extends SystemService switch (mLightState) { case LIGHT_STATE_INACTIVE: mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; // Reset the upcoming idle delays. mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT; mMaintenanceStartTime = 0; Loading @@ -2835,10 +2847,12 @@ public class DeviceIdleController extends SystemService long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime; if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { // We didn't use up all of our minimum budget; add this to the reserve. mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration); mCurLightIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET - duration); } else { // We used more than our minimum budget; this comes out of the reserve. mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); mCurLightIdleBudget -= (duration - mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); } } mMaintenanceStartTime = 0; Loading @@ -2862,12 +2876,12 @@ public class DeviceIdleController extends SystemService mActiveIdleOpCount = 1; mActiveIdleWakeLock.acquire(); mMaintenanceStartTime = SystemClock.elapsedRealtime(); if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) { mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; if (mCurLightIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; } else if (mCurLightIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) { mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; } scheduleLightAlarmLocked(mCurIdleBudget); scheduleLightAlarmLocked(mCurLightIdleBudget); if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE."); mLightState = LIGHT_STATE_IDLE_MAINTENANCE; Loading Loading @@ -4360,9 +4374,9 @@ public class DeviceIdleController extends SystemService TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw); pw.println(); } if (mCurIdleBudget != 0) { pw.print(" mCurIdleBudget="); TimeUtils.formatDuration(mCurIdleBudget, pw); if (mCurLightIdleBudget != 0) { pw.print(" mCurLightIdleBudget="); TimeUtils.formatDuration(mCurLightIdleBudget, pw); pw.println(); } if (mMaintenanceStartTime != 0) { Loading services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +49 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ 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.ArgumentMatchers.longThat; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; Loading Loading @@ -894,6 +895,54 @@ public class DeviceIdleControllerTest { verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); } @Test public void testLightIdleAlarmUnaffectedByMotion() { setNetworkConnected(true); mDeviceIdleController.setJobsActive(false); mDeviceIdleController.setAlarmsActive(false); mDeviceIdleController.setActiveIdleOpsForTest(0); spyOn(mDeviceIdleController); InOrder inOrder = inOrder(mDeviceIdleController); // Set state to INACTIVE. mDeviceIdleController.becomeActiveLocked("testing", 0); setChargingOn(false); setScreenOn(false); verifyLightStateConditions(LIGHT_STATE_INACTIVE); // No active ops means INACTIVE should go straight to IDLE. mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT)); // Should just alternate between IDLE and IDLE_MAINTENANCE now. mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET)); mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT)); mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET)); // Test that motion doesn't reset the idle timeout. mDeviceIdleController.handleMotionDetectedLocked(50, "test"); mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT)); } ///////////////// EXIT conditions /////////////////// @Test Loading Loading
services/core/java/com/android/server/DeviceIdleController.java +29 −15 Original line number Diff line number Diff line Loading @@ -429,7 +429,15 @@ public class DeviceIdleController extends SystemService private long mNextLightIdleDelay; private long mNextLightAlarmTime; private long mNextSensingTimeoutAlarmTime; private long mCurIdleBudget; /** How long a light idle maintenance window should last. */ private long mCurLightIdleBudget; /** * Start time of the current (light or full) maintenance window, in the elapsed timebase. Valid * only if {@link #mState} == {@link #STATE_IDLE_MAINTENANCE} or * {@link #mLightState} == {@link #LIGHT_STATE_IDLE_MAINTENANCE}. */ private long mMaintenanceStartTime; private long mIdleStartTime; Loading Loading @@ -2651,9 +2659,12 @@ public class DeviceIdleController extends SystemService EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason); mState = STATE_ACTIVE; mInactiveTimeout = newInactiveTimeout; mCurIdleBudget = 0; mMaintenanceStartTime = 0; resetIdleManagementLocked(); // Don't reset maintenance window start time if we're in a light idle maintenance window // because its used in the light idle budget calculation. if (mLightState != LIGHT_STATE_IDLE_MAINTENANCE) { mMaintenanceStartTime = 0; } if (changeLightIdle) { EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason); Loading Loading @@ -2763,7 +2774,6 @@ public class DeviceIdleController extends SystemService private void resetIdleManagementLocked() { mNextIdlePendingDelay = 0; mNextIdleDelay = 0; mNextLightIdleDelay = 0; mIdleStartTime = 0; cancelAlarmLocked(); cancelSensingTimeoutAlarmLocked(); Loading @@ -2774,6 +2784,8 @@ public class DeviceIdleController extends SystemService } private void resetLightIdleManagementLocked() { mNextLightIdleDelay = 0; mCurLightIdleBudget = 0; cancelLightAlarmLocked(); } Loading Loading @@ -2816,7 +2828,7 @@ public class DeviceIdleController extends SystemService switch (mLightState) { case LIGHT_STATE_INACTIVE: mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; // Reset the upcoming idle delays. mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT; mMaintenanceStartTime = 0; Loading @@ -2835,10 +2847,12 @@ public class DeviceIdleController extends SystemService long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime; if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { // We didn't use up all of our minimum budget; add this to the reserve. mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration); mCurLightIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET - duration); } else { // We used more than our minimum budget; this comes out of the reserve. mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); mCurLightIdleBudget -= (duration - mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); } } mMaintenanceStartTime = 0; Loading @@ -2862,12 +2876,12 @@ public class DeviceIdleController extends SystemService mActiveIdleOpCount = 1; mActiveIdleWakeLock.acquire(); mMaintenanceStartTime = SystemClock.elapsedRealtime(); if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) { mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; if (mCurLightIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) { mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; } else if (mCurLightIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) { mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; } scheduleLightAlarmLocked(mCurIdleBudget); scheduleLightAlarmLocked(mCurLightIdleBudget); if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE."); mLightState = LIGHT_STATE_IDLE_MAINTENANCE; Loading Loading @@ -4360,9 +4374,9 @@ public class DeviceIdleController extends SystemService TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw); pw.println(); } if (mCurIdleBudget != 0) { pw.print(" mCurIdleBudget="); TimeUtils.formatDuration(mCurIdleBudget, pw); if (mCurLightIdleBudget != 0) { pw.print(" mCurLightIdleBudget="); TimeUtils.formatDuration(mCurLightIdleBudget, pw); pw.println(); } if (mMaintenanceStartTime != 0) { Loading
services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +49 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ 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.ArgumentMatchers.longThat; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; Loading Loading @@ -894,6 +895,54 @@ public class DeviceIdleControllerTest { verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); } @Test public void testLightIdleAlarmUnaffectedByMotion() { setNetworkConnected(true); mDeviceIdleController.setJobsActive(false); mDeviceIdleController.setAlarmsActive(false); mDeviceIdleController.setActiveIdleOpsForTest(0); spyOn(mDeviceIdleController); InOrder inOrder = inOrder(mDeviceIdleController); // Set state to INACTIVE. mDeviceIdleController.becomeActiveLocked("testing", 0); setChargingOn(false); setScreenOn(false); verifyLightStateConditions(LIGHT_STATE_INACTIVE); // No active ops means INACTIVE should go straight to IDLE. mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT)); // Should just alternate between IDLE and IDLE_MAINTENANCE now. mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET)); mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT)); mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET)); // Test that motion doesn't reset the idle timeout. mDeviceIdleController.handleMotionDetectedLocked(50, "test"); mDeviceIdleController.stepLightIdleStateLocked("testing"); verifyLightStateConditions(LIGHT_STATE_IDLE); inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked( longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT)); } ///////////////// EXIT conditions /////////////////// @Test Loading