diff options
| author | 2019-10-15 15:41:28 -0700 | |
|---|---|---|
| committer | 2019-10-30 15:05:34 -0700 | |
| commit | 9e5ef1d8d18f6b6e80abb2b2e6c277f1fd48e9c0 (patch) | |
| tree | acd209d441d42f19586e3f54f887e2ae5aa4b280 | |
| parent | 181c51f18b7c1d856740da2cd54ff45673884a93 (diff) | |
Remove standby delay from AlarmManager in favor of quotas.
We're moving forward with the quota system, and so no longer need to
keep the delay code or tests.
Bug: 142569967
Test: atest com.android.server.AlarmManagerServiceTest
Test: atest com.android.server.AppStateTrackerTest
Test: atest AppStandbyControllerTests
Test: atest CtsAlarmManagerTestCases
Change-Id: I9ce96a6e050f8dcd14d02fd707c8f4693e397ac5
| -rw-r--r-- | services/core/java/com/android/server/AlarmManagerService.java | 130 | ||||
| -rw-r--r-- | services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java | 87 |
2 files changed, 30 insertions, 187 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index ff0044f6f1ad..1ce11378efda 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -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; @@ -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 = { @@ -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; @@ -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} @@ -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; @@ -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; @@ -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); @@ -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(); @@ -1826,27 +1785,6 @@ class AlarmManagerService extends SystemService { } /** - * 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 * @return true if the alarm delivery time was updated. @@ -1872,50 +1810,34 @@ 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); - final int quotaForBucket = getQuotaForBucketLocked(standbyBucket); - boolean deferred = false; - if (wakeupsInWindow >= quotaForBucket) { - final long minElapsed; - if (quotaForBucket <= 0) { - // Just keep deferring for a day till the quota changes - minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY; - } else { - // Suppose the quota for window was q, and the qth last delivery time for this - // package was t(q) then the next delivery must be after t(q) + <window_size> - final long t = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage, - sourceUserId, quotaForBucket); - minElapsed = t + 1 + mConstants.APP_STANDBY_WINDOW; - } - if (alarm.expectedWhenElapsed < minElapsed) { - alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; - deferred = true; - } - } - if (!deferred) { - // Restore original requirements in case they were changed earlier. - alarm.whenElapsed = alarm.expectedWhenElapsed; - alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; + // Quota deferring implementation: + final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage, + sourceUserId); + final int quotaForBucket = getQuotaForBucketLocked(standbyBucket); + boolean deferred = false; + if (wakeupsInWindow >= quotaForBucket) { + final long minElapsed; + if (quotaForBucket <= 0) { + // Just keep deferring for a day till the quota changes + minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY; + } else { + // Suppose the quota for window was q, and the qth last delivery time for this + // package was t(q) then the next delivery must be after t(q) + <window_size> + final long t = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage, + sourceUserId, quotaForBucket); + minElapsed = t + 1 + mConstants.APP_STANDBY_WINDOW; } - } 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; - } + if (alarm.expectedWhenElapsed < minElapsed) { + alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed; + deferred = true; } } + if (!deferred) { + // Restore original requirements in case they were changed earlier. + alarm.whenElapsed = alarm.expectedWhenElapsed; + alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed; + } + return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed); } diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java index 9e7b80567263..485f436f7f65 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java @@ -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; @@ -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) { @@ -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,"); @@ -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 @@ -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(), @@ -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); } @@ -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); @@ -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); @@ -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); |