Loading apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java +29 −13 Original line number Diff line number Diff line Loading @@ -82,6 +82,10 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id * be a negative value if the device is not in state to be considered idle. */ private long mIdlenessCheckScheduledElapsed = -1; /** * Time (in the elapsed realtime timebase) when the device can be considered idle. */ private long mIdleStartElapsed = Long.MAX_VALUE; private IdlenessListener mIdleListener; private final UiModeManager.OnProjectionStateChangedListener mOnProjectionStateChangedListener = Loading Loading @@ -191,11 +195,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id } mProjectionActive = projectionActive; if (mProjectionActive) { cancelIdlenessCheck(); if (mIdle) { mIdle = false; mIdleListener.reportNewIdleState(mIdle); } exitIdle(); } else { maybeScheduleIdlenessCheck("Projection ended"); } Loading @@ -209,6 +209,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id pw.print(" mDockIdle: "); pw.println(mDockIdle); pw.print(" mProjectionActive: "); pw.println(mProjectionActive); pw.print(" mIdlenessCheckScheduledElapsed: "); pw.println(mIdlenessCheckScheduledElapsed); pw.print(" mIdleStartElapsed: "); pw.println(mIdleStartElapsed); } @Override Loading Loading @@ -270,11 +271,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id if (DEBUG) { Slog.v(TAG, "exiting idle"); } cancelIdlenessCheck(); if (mIdle) { mIdle = false; mIdleListener.reportNewIdleState(mIdle); } exitIdle(); break; case Intent.ACTION_SCREEN_OFF: case Intent.ACTION_DREAMING_STARTED: Loading Loading @@ -302,6 +299,12 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id } private void maybeScheduleIdlenessCheck(String reason) { if (mIdle) { if (DEBUG) { Slog.w(TAG, "Already idle. Redundant reason=" + reason); } return; } if ((!mScreenOn || mDockIdle) && !mProjectionActive) { final long nowElapsed = sElapsedRealtimeClock.millis(); final long inactivityThresholdMs = mIsStablePower Loading @@ -319,19 +322,32 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id mIdlenessCheckScheduledElapsed = nowElapsed; } final long when = mIdlenessCheckScheduledElapsed + inactivityThresholdMs; if (when == mIdleStartElapsed) { if (DEBUG) { Slog.i(TAG, "No change to idle start time"); } return; } mIdleStartElapsed = when; if (DEBUG) { Slog.v(TAG, "Scheduling idle : " + reason + " now:" + nowElapsed + " checkElapsed=" + mIdlenessCheckScheduledElapsed + " when=" + when); + " checkElapsed=" + mIdlenessCheckScheduledElapsed + " when=" + mIdleStartElapsed); } mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, mIdleWindowSlop, "JS idleness", mIdleStartElapsed, mIdleWindowSlop, "JS idleness", AppSchedulingModuleThread.getExecutor(), mIdleAlarmListener); } } private void cancelIdlenessCheck() { private void exitIdle() { mAlarm.cancel(mIdleAlarmListener); mIdlenessCheckScheduledElapsed = -1; mIdleStartElapsed = Long.MAX_VALUE; if (mIdle) { mIdle = false; mIdleListener.reportNewIdleState(false); } } private void handleIdleTrigger() { Loading services/tests/mockingservicestests/src/com/android/server/job/controllers/idle/DeviceIdlenessTrackerTest.java +71 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,77 @@ public class DeviceIdlenessTrackerTest { mDeviceIdlenessTracker.processConstant(mDeviceConfigPropertiesBuilder.build(), key); } @Test public void testAlarmSkippedIfAlreadyIdle() { setDeviceConfigLong(KEY_INACTIVITY_IDLE_THRESHOLD_MS, MINUTE_IN_MILLIS); setDeviceConfigLong(KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS, 5 * MINUTE_IN_MILLIS); setBatteryState(false, false); Intent dockIdleIntent = new Intent(Intent.ACTION_DOCK_IDLE); mBroadcastReceiver.onReceive(mContext, dockIdleIntent); final long nowElapsed = sElapsedRealtimeClock.millis(); long expectedAlarmElapsed = nowElapsed + MINUTE_IN_MILLIS; ArgumentCaptor<AlarmManager.OnAlarmListener> onAlarmListenerCaptor = ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); InOrder inOrder = inOrder(mAlarmManager); inOrder.verify(mAlarmManager) .setWindow(anyInt(), eq(expectedAlarmElapsed), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), onAlarmListenerCaptor.capture()); AlarmManager.OnAlarmListener onAlarmListener = onAlarmListenerCaptor.getValue(); advanceElapsedClock(MINUTE_IN_MILLIS); onAlarmListener.onAlarm(); // Now in idle. // Trigger SCREEN_OFF. Make sure alarm isn't set again. Intent screenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); mBroadcastReceiver.onReceive(mContext, screenOffIntent); inOrder.verify(mAlarmManager, never()) .setWindow(anyInt(), anyLong(), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); } @Test public void testAlarmSkippedIfNoThresholdChange() { setDeviceConfigLong(KEY_INACTIVITY_IDLE_THRESHOLD_MS, 10 * MINUTE_IN_MILLIS); setDeviceConfigLong(KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS, 10 * MINUTE_IN_MILLIS); setBatteryState(false, false); Intent screenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); mBroadcastReceiver.onReceive(mContext, screenOffIntent); final long nowElapsed = sElapsedRealtimeClock.millis(); long expectedAlarmElapsed = nowElapsed + 10 * MINUTE_IN_MILLIS; InOrder inOrder = inOrder(mAlarmManager); inOrder.verify(mAlarmManager) .setWindow(anyInt(), eq(expectedAlarmElapsed), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); // Advanced the clock a little to make sure the tracker continues to use the original time. advanceElapsedClock(MINUTE_IN_MILLIS); // Now on stable power. Thresholds are the same, so alarm doesn't need to be rescheduled. setBatteryState(true, true); inOrder.verify(mAlarmManager, never()) .setWindow(anyInt(), eq(expectedAlarmElapsed), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); // Not on stable power. Thresholds are the same, so alarm doesn't need to be rescheduled. setBatteryState(false, false); inOrder.verify(mAlarmManager, never()) .setWindow(anyInt(), anyLong(), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); } @Test public void testThresholdChangeWithStablePowerChange() { setDeviceConfigLong(KEY_INACTIVITY_IDLE_THRESHOLD_MS, 10 * MINUTE_IN_MILLIS); Loading Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java +29 −13 Original line number Diff line number Diff line Loading @@ -82,6 +82,10 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id * be a negative value if the device is not in state to be considered idle. */ private long mIdlenessCheckScheduledElapsed = -1; /** * Time (in the elapsed realtime timebase) when the device can be considered idle. */ private long mIdleStartElapsed = Long.MAX_VALUE; private IdlenessListener mIdleListener; private final UiModeManager.OnProjectionStateChangedListener mOnProjectionStateChangedListener = Loading Loading @@ -191,11 +195,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id } mProjectionActive = projectionActive; if (mProjectionActive) { cancelIdlenessCheck(); if (mIdle) { mIdle = false; mIdleListener.reportNewIdleState(mIdle); } exitIdle(); } else { maybeScheduleIdlenessCheck("Projection ended"); } Loading @@ -209,6 +209,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id pw.print(" mDockIdle: "); pw.println(mDockIdle); pw.print(" mProjectionActive: "); pw.println(mProjectionActive); pw.print(" mIdlenessCheckScheduledElapsed: "); pw.println(mIdlenessCheckScheduledElapsed); pw.print(" mIdleStartElapsed: "); pw.println(mIdleStartElapsed); } @Override Loading Loading @@ -270,11 +271,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id if (DEBUG) { Slog.v(TAG, "exiting idle"); } cancelIdlenessCheck(); if (mIdle) { mIdle = false; mIdleListener.reportNewIdleState(mIdle); } exitIdle(); break; case Intent.ACTION_SCREEN_OFF: case Intent.ACTION_DREAMING_STARTED: Loading Loading @@ -302,6 +299,12 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id } private void maybeScheduleIdlenessCheck(String reason) { if (mIdle) { if (DEBUG) { Slog.w(TAG, "Already idle. Redundant reason=" + reason); } return; } if ((!mScreenOn || mDockIdle) && !mProjectionActive) { final long nowElapsed = sElapsedRealtimeClock.millis(); final long inactivityThresholdMs = mIsStablePower Loading @@ -319,19 +322,32 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id mIdlenessCheckScheduledElapsed = nowElapsed; } final long when = mIdlenessCheckScheduledElapsed + inactivityThresholdMs; if (when == mIdleStartElapsed) { if (DEBUG) { Slog.i(TAG, "No change to idle start time"); } return; } mIdleStartElapsed = when; if (DEBUG) { Slog.v(TAG, "Scheduling idle : " + reason + " now:" + nowElapsed + " checkElapsed=" + mIdlenessCheckScheduledElapsed + " when=" + when); + " checkElapsed=" + mIdlenessCheckScheduledElapsed + " when=" + mIdleStartElapsed); } mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, mIdleWindowSlop, "JS idleness", mIdleStartElapsed, mIdleWindowSlop, "JS idleness", AppSchedulingModuleThread.getExecutor(), mIdleAlarmListener); } } private void cancelIdlenessCheck() { private void exitIdle() { mAlarm.cancel(mIdleAlarmListener); mIdlenessCheckScheduledElapsed = -1; mIdleStartElapsed = Long.MAX_VALUE; if (mIdle) { mIdle = false; mIdleListener.reportNewIdleState(false); } } private void handleIdleTrigger() { Loading
services/tests/mockingservicestests/src/com/android/server/job/controllers/idle/DeviceIdlenessTrackerTest.java +71 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,77 @@ public class DeviceIdlenessTrackerTest { mDeviceIdlenessTracker.processConstant(mDeviceConfigPropertiesBuilder.build(), key); } @Test public void testAlarmSkippedIfAlreadyIdle() { setDeviceConfigLong(KEY_INACTIVITY_IDLE_THRESHOLD_MS, MINUTE_IN_MILLIS); setDeviceConfigLong(KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS, 5 * MINUTE_IN_MILLIS); setBatteryState(false, false); Intent dockIdleIntent = new Intent(Intent.ACTION_DOCK_IDLE); mBroadcastReceiver.onReceive(mContext, dockIdleIntent); final long nowElapsed = sElapsedRealtimeClock.millis(); long expectedAlarmElapsed = nowElapsed + MINUTE_IN_MILLIS; ArgumentCaptor<AlarmManager.OnAlarmListener> onAlarmListenerCaptor = ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); InOrder inOrder = inOrder(mAlarmManager); inOrder.verify(mAlarmManager) .setWindow(anyInt(), eq(expectedAlarmElapsed), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), onAlarmListenerCaptor.capture()); AlarmManager.OnAlarmListener onAlarmListener = onAlarmListenerCaptor.getValue(); advanceElapsedClock(MINUTE_IN_MILLIS); onAlarmListener.onAlarm(); // Now in idle. // Trigger SCREEN_OFF. Make sure alarm isn't set again. Intent screenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); mBroadcastReceiver.onReceive(mContext, screenOffIntent); inOrder.verify(mAlarmManager, never()) .setWindow(anyInt(), anyLong(), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); } @Test public void testAlarmSkippedIfNoThresholdChange() { setDeviceConfigLong(KEY_INACTIVITY_IDLE_THRESHOLD_MS, 10 * MINUTE_IN_MILLIS); setDeviceConfigLong(KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS, 10 * MINUTE_IN_MILLIS); setBatteryState(false, false); Intent screenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); mBroadcastReceiver.onReceive(mContext, screenOffIntent); final long nowElapsed = sElapsedRealtimeClock.millis(); long expectedAlarmElapsed = nowElapsed + 10 * MINUTE_IN_MILLIS; InOrder inOrder = inOrder(mAlarmManager); inOrder.verify(mAlarmManager) .setWindow(anyInt(), eq(expectedAlarmElapsed), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); // Advanced the clock a little to make sure the tracker continues to use the original time. advanceElapsedClock(MINUTE_IN_MILLIS); // Now on stable power. Thresholds are the same, so alarm doesn't need to be rescheduled. setBatteryState(true, true); inOrder.verify(mAlarmManager, never()) .setWindow(anyInt(), eq(expectedAlarmElapsed), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); // Not on stable power. Thresholds are the same, so alarm doesn't need to be rescheduled. setBatteryState(false, false); inOrder.verify(mAlarmManager, never()) .setWindow(anyInt(), anyLong(), anyLong(), anyString(), eq(AppSchedulingModuleThread.getExecutor()), any()); } @Test public void testThresholdChangeWithStablePowerChange() { setDeviceConfigLong(KEY_INACTIVITY_IDLE_THRESHOLD_MS, 10 * MINUTE_IN_MILLIS); Loading