Loading services/core/java/com/android/server/AlarmManagerService.java +26 −104 Original line number Diff line number Diff line Loading @@ -154,7 +154,7 @@ class AlarmManagerService extends SystemService { static final int TICK_HISTORY_DEPTH = 10; static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000; // Indices into the APP_STANDBY_MIN_DELAYS and KEYS_APP_STANDBY_DELAY arrays // Indices into the KEYS_APP_STANDBY_QUOTAS array. static final int ACTIVE_INDEX = 0; static final int WORKING_INDEX = 1; static final int FREQUENT_INDEX = 2; Loading Loading @@ -401,8 +401,6 @@ class AlarmManagerService extends SystemService { static final String KEY_LISTENER_TIMEOUT = "listener_timeout"; @VisibleForTesting static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid"; @VisibleForTesting static final String KEY_APP_STANDBY_QUOTAS_ENABLED = "app_standby_quotas_enabled"; private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window"; @VisibleForTesting final String[] KEYS_APP_STANDBY_QUOTAS = { Loading @@ -413,15 +411,6 @@ class AlarmManagerService extends SystemService { "standby_never_quota", }; // Keys for specifying throttling delay based on app standby bucketing private final String[] KEYS_APP_STANDBY_DELAY = { "standby_active_delay", "standby_working_delay", "standby_frequent_delay", "standby_rare_delay", "standby_never_delay", }; private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS; Loading @@ -430,7 +419,6 @@ class AlarmManagerService extends SystemService { private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000; private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000; private static final int DEFAULT_MAX_ALARMS_PER_UID = 500; private static final boolean DEFAULT_APP_STANDBY_QUOTAS_ENABLED = true; private static final long DEFAULT_APP_STANDBY_WINDOW = 60 * 60 * 1000; // 1 hr /** * Max number of times an app can receive alarms in {@link #APP_STANDBY_WINDOW} Loading @@ -442,13 +430,6 @@ class AlarmManagerService extends SystemService { 1, // Rare 0 // Never }; private final long[] DEFAULT_APP_STANDBY_DELAYS = { 0, // Active 6 * 60_000, // Working 30 * 60_000, // Frequent 2 * 60 * 60_000, // Rare 10 * 24 * 60 * 60_000 // Never }; // Minimum futurity of a new alarm public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; Loading @@ -473,10 +454,7 @@ class AlarmManagerService extends SystemService { public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT; public int MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID; public boolean APP_STANDBY_QUOTAS_ENABLED = DEFAULT_APP_STANDBY_QUOTAS_ENABLED; public long APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW; public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length]; public int[] APP_STANDBY_QUOTAS = new int[DEFAULT_APP_STANDBY_QUOTAS.length]; private ContentResolver mResolver; Loading Loading @@ -532,16 +510,6 @@ class AlarmManagerService extends SystemService { DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION); LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT); APP_STANDBY_MIN_DELAYS[ACTIVE_INDEX] = mParser.getDurationMillis( KEYS_APP_STANDBY_DELAY[ACTIVE_INDEX], DEFAULT_APP_STANDBY_DELAYS[ACTIVE_INDEX]); for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_DELAY.length; i++) { APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i], Math.max(APP_STANDBY_MIN_DELAYS[i - 1], DEFAULT_APP_STANDBY_DELAYS[i])); } APP_STANDBY_QUOTAS_ENABLED = mParser.getBoolean(KEY_APP_STANDBY_QUOTAS_ENABLED, DEFAULT_APP_STANDBY_QUOTAS_ENABLED); APP_STANDBY_WINDOW = mParser.getLong(KEY_APP_STANDBY_WINDOW, DEFAULT_APP_STANDBY_WINDOW); Loading Loading @@ -614,15 +582,6 @@ class AlarmManagerService extends SystemService { pw.print(KEY_MAX_ALARMS_PER_UID); pw.print("="); pw.println(MAX_ALARMS_PER_UID); for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) { pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("="); TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw); pw.println(); } pw.print(KEY_APP_STANDBY_QUOTAS_ENABLED); pw.print("="); pw.println(APP_STANDBY_QUOTAS_ENABLED); pw.print(KEY_APP_STANDBY_WINDOW); pw.print("="); TimeUtils.formatDuration(APP_STANDBY_WINDOW, pw); pw.println(); Loading Loading @@ -1825,27 +1784,6 @@ class AlarmManagerService extends SystemService { return mConstants.APP_STANDBY_QUOTAS[index]; } /** * Return the minimum time that should elapse before an app in the specified bucket * can receive alarms again */ @VisibleForTesting long getMinDelayForBucketLocked(int bucket) { // UsageStats bucket values are treated as floors of their behavioral range. // In other words, a bucket value between WORKING and ACTIVE is treated as // WORKING, not as ACTIVE. The ACTIVE and NEVER bucket apply only at specific // values. final int index; if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) index = NEVER_INDEX; else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) index = RARE_INDEX; else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) index = FREQUENT_INDEX; else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) index = WORKING_INDEX; else index = ACTIVE_INDEX; return mConstants.APP_STANDBY_MIN_DELAYS[index]; } /** * Adjusts the alarm delivery time based on the current app standby bucket. * @param alarm The alarm to adjust Loading @@ -1872,7 +1810,6 @@ class AlarmManagerService extends SystemService { final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket( sourcePackage, sourceUserId, mInjector.getElapsedRealtime()); if (mConstants.APP_STANDBY_QUOTAS_ENABLED) { // Quota deferring implementation: final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage, sourceUserId); Loading Loading @@ -1900,22 +1837,7 @@ class AlarmManagerService extends SystemService { alarm.whenElapsed = alarm.expectedWhenElapsed; alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; } } else { // Minimum delay deferring implementation: final long lastElapsed = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage, sourceUserId, 1); if (lastElapsed > 0) { final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket); if (alarm.expectedWhenElapsed < minElapsed) { alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; } else { // app is now eligible to run alarms at the originally requested window. // Restore original requirements in case they were changed earlier. alarm.whenElapsed = alarm.expectedWhenElapsed; alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; } } } return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed); } Loading services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +4 −83 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATU import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION; import static com.android.server.AlarmManagerService.Constants.KEY_APP_STANDBY_QUOTAS_ENABLED; import static com.android.server.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT; import static com.android.server.AlarmManagerService.Constants.KEY_MAX_INTERVAL; import static com.android.server.AlarmManagerService.Constants.KEY_MIN_FUTURITY; Loading Loading @@ -305,6 +304,8 @@ public class AlarmManagerServiceTest { argThat((filter) -> filter.hasAction(BatteryManager.ACTION_CHARGING) && filter.hasAction(BatteryManager.ACTION_DISCHARGING))); mChargingReceiver = chargingReceiverCaptor.getValue(); setTestableQuotas(); } private void setTestAlarm(int type, long triggerTime, PendingIntent operation) { Loading Loading @@ -342,9 +343,10 @@ public class AlarmManagerServiceTest { } /** * Lowers quotas to make testing feasible. * Careful while calling as this will replace any existing settings for the calling test. */ private void setQuotasEnabled(boolean enabled) { private void setTestableQuotas() { final StringBuilder constantsBuilder = new StringBuilder(); constantsBuilder.append(KEY_MIN_FUTURITY); constantsBuilder.append("=0,"); Loading @@ -353,14 +355,9 @@ public class AlarmManagerServiceTest { constantsBuilder.append("=8,"); constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]); constantsBuilder.append("=5,"); if (!enabled) { constantsBuilder.append(KEY_APP_STANDBY_QUOTAS_ENABLED); constantsBuilder.append("=false,"); } doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS)); mService.mConstants.onChange(false, null); assertEquals(mService.mConstants.APP_STANDBY_QUOTAS_ENABLED, enabled); } @Test Loading Loading @@ -481,67 +478,6 @@ public class AlarmManagerServiceTest { assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed()); } @Test public void testStandbyBucketDelay_workingSet() throws Exception { setQuotasEnabled(false); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); verify(mUsageStatsManagerInternal, atLeastOnce()) .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); final long expectedNextTrigger = mNowElapsedTest + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_WORKING_SET); assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); } @Test public void testStandbyBucketDelay_frequent() throws Exception { setQuotasEnabled(false); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); verify(mUsageStatsManagerInternal, atLeastOnce()) .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); final long expectedNextTrigger = mNowElapsedTest + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_FREQUENT); assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed()); } @Test public void testStandbyBucketDelay_rare() throws Exception { setQuotasEnabled(false); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_RARE); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); verify(mUsageStatsManagerInternal, atLeastOnce()) .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); final long expectedNextTrigger = mNowElapsedTest + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_RARE); assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed()); } private void testQuotasDeferralOnSet(int standbyBucket) throws Exception { final int quota = mService.getQuotaForBucketLocked(standbyBucket); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), Loading Loading @@ -601,73 +537,61 @@ public class AlarmManagerServiceTest { @Test public void testActiveQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE); } @Test public void testActiveQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE); } @Test public void testActiveQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_ACTIVE); } @Test public void testWorkingQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET); } @Test public void testWorkingQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET); } @Test public void testWorkingQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET); } @Test public void testFrequentQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT); } @Test public void testFrequentQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT); } @Test public void testFrequentQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_FREQUENT); } @Test public void testRareQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_RARE); } @Test public void testRareQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE); } @Test public void testRareQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_RARE); } Loading @@ -686,7 +610,6 @@ public class AlarmManagerServiceTest { @Test public void testQuotaDowngrade() throws Exception { setQuotasEnabled(true); final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); Loading Loading @@ -714,7 +637,6 @@ public class AlarmManagerServiceTest { @Test public void testQuotaUpgrade() throws Exception { setQuotasEnabled(true); final int frequentQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_FREQUENT); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT); Loading Loading @@ -752,7 +674,6 @@ public class AlarmManagerServiceTest { @Test public void testCharging() throws Exception { setQuotasEnabled(true); final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); Loading Loading
services/core/java/com/android/server/AlarmManagerService.java +26 −104 Original line number Diff line number Diff line Loading @@ -154,7 +154,7 @@ class AlarmManagerService extends SystemService { static final int TICK_HISTORY_DEPTH = 10; static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000; // Indices into the APP_STANDBY_MIN_DELAYS and KEYS_APP_STANDBY_DELAY arrays // Indices into the KEYS_APP_STANDBY_QUOTAS array. static final int ACTIVE_INDEX = 0; static final int WORKING_INDEX = 1; static final int FREQUENT_INDEX = 2; Loading Loading @@ -401,8 +401,6 @@ class AlarmManagerService extends SystemService { static final String KEY_LISTENER_TIMEOUT = "listener_timeout"; @VisibleForTesting static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid"; @VisibleForTesting static final String KEY_APP_STANDBY_QUOTAS_ENABLED = "app_standby_quotas_enabled"; private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window"; @VisibleForTesting final String[] KEYS_APP_STANDBY_QUOTAS = { Loading @@ -413,15 +411,6 @@ class AlarmManagerService extends SystemService { "standby_never_quota", }; // Keys for specifying throttling delay based on app standby bucketing private final String[] KEYS_APP_STANDBY_DELAY = { "standby_active_delay", "standby_working_delay", "standby_frequent_delay", "standby_rare_delay", "standby_never_delay", }; private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS; Loading @@ -430,7 +419,6 @@ class AlarmManagerService extends SystemService { private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000; private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000; private static final int DEFAULT_MAX_ALARMS_PER_UID = 500; private static final boolean DEFAULT_APP_STANDBY_QUOTAS_ENABLED = true; private static final long DEFAULT_APP_STANDBY_WINDOW = 60 * 60 * 1000; // 1 hr /** * Max number of times an app can receive alarms in {@link #APP_STANDBY_WINDOW} Loading @@ -442,13 +430,6 @@ class AlarmManagerService extends SystemService { 1, // Rare 0 // Never }; private final long[] DEFAULT_APP_STANDBY_DELAYS = { 0, // Active 6 * 60_000, // Working 30 * 60_000, // Frequent 2 * 60 * 60_000, // Rare 10 * 24 * 60 * 60_000 // Never }; // Minimum futurity of a new alarm public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; Loading @@ -473,10 +454,7 @@ class AlarmManagerService extends SystemService { public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT; public int MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID; public boolean APP_STANDBY_QUOTAS_ENABLED = DEFAULT_APP_STANDBY_QUOTAS_ENABLED; public long APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW; public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length]; public int[] APP_STANDBY_QUOTAS = new int[DEFAULT_APP_STANDBY_QUOTAS.length]; private ContentResolver mResolver; Loading Loading @@ -532,16 +510,6 @@ class AlarmManagerService extends SystemService { DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION); LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT); APP_STANDBY_MIN_DELAYS[ACTIVE_INDEX] = mParser.getDurationMillis( KEYS_APP_STANDBY_DELAY[ACTIVE_INDEX], DEFAULT_APP_STANDBY_DELAYS[ACTIVE_INDEX]); for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_DELAY.length; i++) { APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i], Math.max(APP_STANDBY_MIN_DELAYS[i - 1], DEFAULT_APP_STANDBY_DELAYS[i])); } APP_STANDBY_QUOTAS_ENABLED = mParser.getBoolean(KEY_APP_STANDBY_QUOTAS_ENABLED, DEFAULT_APP_STANDBY_QUOTAS_ENABLED); APP_STANDBY_WINDOW = mParser.getLong(KEY_APP_STANDBY_WINDOW, DEFAULT_APP_STANDBY_WINDOW); Loading Loading @@ -614,15 +582,6 @@ class AlarmManagerService extends SystemService { pw.print(KEY_MAX_ALARMS_PER_UID); pw.print("="); pw.println(MAX_ALARMS_PER_UID); for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) { pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("="); TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw); pw.println(); } pw.print(KEY_APP_STANDBY_QUOTAS_ENABLED); pw.print("="); pw.println(APP_STANDBY_QUOTAS_ENABLED); pw.print(KEY_APP_STANDBY_WINDOW); pw.print("="); TimeUtils.formatDuration(APP_STANDBY_WINDOW, pw); pw.println(); Loading Loading @@ -1825,27 +1784,6 @@ class AlarmManagerService extends SystemService { return mConstants.APP_STANDBY_QUOTAS[index]; } /** * Return the minimum time that should elapse before an app in the specified bucket * can receive alarms again */ @VisibleForTesting long getMinDelayForBucketLocked(int bucket) { // UsageStats bucket values are treated as floors of their behavioral range. // In other words, a bucket value between WORKING and ACTIVE is treated as // WORKING, not as ACTIVE. The ACTIVE and NEVER bucket apply only at specific // values. final int index; if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) index = NEVER_INDEX; else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) index = RARE_INDEX; else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) index = FREQUENT_INDEX; else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) index = WORKING_INDEX; else index = ACTIVE_INDEX; return mConstants.APP_STANDBY_MIN_DELAYS[index]; } /** * Adjusts the alarm delivery time based on the current app standby bucket. * @param alarm The alarm to adjust Loading @@ -1872,7 +1810,6 @@ class AlarmManagerService extends SystemService { final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket( sourcePackage, sourceUserId, mInjector.getElapsedRealtime()); if (mConstants.APP_STANDBY_QUOTAS_ENABLED) { // Quota deferring implementation: final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage, sourceUserId); Loading Loading @@ -1900,22 +1837,7 @@ class AlarmManagerService extends SystemService { alarm.whenElapsed = alarm.expectedWhenElapsed; alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; } } else { // Minimum delay deferring implementation: final long lastElapsed = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage, sourceUserId, 1); if (lastElapsed > 0) { final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket); if (alarm.expectedWhenElapsed < minElapsed) { alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; } else { // app is now eligible to run alarms at the originally requested window. // Restore original requirements in case they were changed earlier. alarm.whenElapsed = alarm.expectedWhenElapsed; alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; } } } return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed); } Loading
services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +4 −83 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATU import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION; import static com.android.server.AlarmManagerService.Constants.KEY_APP_STANDBY_QUOTAS_ENABLED; import static com.android.server.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT; import static com.android.server.AlarmManagerService.Constants.KEY_MAX_INTERVAL; import static com.android.server.AlarmManagerService.Constants.KEY_MIN_FUTURITY; Loading Loading @@ -305,6 +304,8 @@ public class AlarmManagerServiceTest { argThat((filter) -> filter.hasAction(BatteryManager.ACTION_CHARGING) && filter.hasAction(BatteryManager.ACTION_DISCHARGING))); mChargingReceiver = chargingReceiverCaptor.getValue(); setTestableQuotas(); } private void setTestAlarm(int type, long triggerTime, PendingIntent operation) { Loading Loading @@ -342,9 +343,10 @@ public class AlarmManagerServiceTest { } /** * Lowers quotas to make testing feasible. * Careful while calling as this will replace any existing settings for the calling test. */ private void setQuotasEnabled(boolean enabled) { private void setTestableQuotas() { final StringBuilder constantsBuilder = new StringBuilder(); constantsBuilder.append(KEY_MIN_FUTURITY); constantsBuilder.append("=0,"); Loading @@ -353,14 +355,9 @@ public class AlarmManagerServiceTest { constantsBuilder.append("=8,"); constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]); constantsBuilder.append("=5,"); if (!enabled) { constantsBuilder.append(KEY_APP_STANDBY_QUOTAS_ENABLED); constantsBuilder.append("=false,"); } doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS)); mService.mConstants.onChange(false, null); assertEquals(mService.mConstants.APP_STANDBY_QUOTAS_ENABLED, enabled); } @Test Loading Loading @@ -481,67 +478,6 @@ public class AlarmManagerServiceTest { assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed()); } @Test public void testStandbyBucketDelay_workingSet() throws Exception { setQuotasEnabled(false); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); verify(mUsageStatsManagerInternal, atLeastOnce()) .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); final long expectedNextTrigger = mNowElapsedTest + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_WORKING_SET); assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); } @Test public void testStandbyBucketDelay_frequent() throws Exception { setQuotasEnabled(false); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); verify(mUsageStatsManagerInternal, atLeastOnce()) .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); final long expectedNextTrigger = mNowElapsedTest + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_FREQUENT); assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed()); } @Test public void testStandbyBucketDelay_rare() throws Exception { setQuotasEnabled(false); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent()); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent()); assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed()); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_RARE); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); verify(mUsageStatsManagerInternal, atLeastOnce()) .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()); final long expectedNextTrigger = mNowElapsedTest + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_RARE); assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed()); } private void testQuotasDeferralOnSet(int standbyBucket) throws Exception { final int quota = mService.getQuotaForBucketLocked(standbyBucket); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), Loading Loading @@ -601,73 +537,61 @@ public class AlarmManagerServiceTest { @Test public void testActiveQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE); } @Test public void testActiveQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE); } @Test public void testActiveQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_ACTIVE); } @Test public void testWorkingQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET); } @Test public void testWorkingQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET); } @Test public void testWorkingQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET); } @Test public void testFrequentQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT); } @Test public void testFrequentQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT); } @Test public void testFrequentQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_FREQUENT); } @Test public void testRareQuota_deferredOnSet() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnSet(STANDBY_BUCKET_RARE); } @Test public void testRareQuota_deferredOnExpiration() throws Exception { setQuotasEnabled(true); testQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE); } @Test public void testRareQuota_notDeferred() throws Exception { setQuotasEnabled(true); testQuotasNoDeferral(STANDBY_BUCKET_RARE); } Loading @@ -686,7 +610,6 @@ public class AlarmManagerServiceTest { @Test public void testQuotaDowngrade() throws Exception { setQuotasEnabled(true); final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); Loading Loading @@ -714,7 +637,6 @@ public class AlarmManagerServiceTest { @Test public void testQuotaUpgrade() throws Exception { setQuotasEnabled(true); final int frequentQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_FREQUENT); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT); Loading Loading @@ -752,7 +674,6 @@ public class AlarmManagerServiceTest { @Test public void testCharging() throws Exception { setQuotasEnabled(true); final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); Loading