Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +26 −7 Original line number Diff line number Diff line Loading @@ -256,6 +256,7 @@ public class AlarmManagerService extends SystemService { AlarmHandler mHandler; AppWakeupHistory mAppWakeupHistory; AppWakeupHistory mAllowWhileIdleHistory; AppWakeupHistory mAllowWhileIdleCompatHistory; private final SparseLongArray mLastPriorityAlarmDispatch = new SparseLongArray(); private final SparseArray<RingBuffer<RemovedAlarm>> mRemovalHistory = new SparseArray<>(); ClockReceiver mClockReceiver; Loading Loading @@ -1633,6 +1634,7 @@ public class AlarmManagerService extends SystemService { mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW); mAllowWhileIdleHistory = new AppWakeupHistory(INTERVAL_HOUR); mAllowWhileIdleCompatHistory = new AppWakeupHistory(INTERVAL_HOUR); mNextWakeup = mNextNonWakeup = 0; Loading Loading @@ -2142,20 +2144,23 @@ public class AlarmManagerService extends SystemService { final int userId = UserHandle.getUserId(alarm.creatorUid); final int quota; final long window; final AppWakeupHistory history; if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) { quota = mConstants.ALLOW_WHILE_IDLE_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_WINDOW; history = mAllowWhileIdleHistory; } else { quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; history = mAllowWhileIdleCompatHistory; } final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow( final int dispatchesInHistory = history.getTotalWakeupsInWindow( alarm.sourcePackage, userId); if (dispatchesInWindow < quota) { if (dispatchesInHistory < quota) { // fine to go out immediately. batterySaverPolicyElapsed = nowElapsed; } else { batterySaverPolicyElapsed = mAllowWhileIdleHistory.getNthLastWakeupForPackage( batterySaverPolicyElapsed = history.getNthLastWakeupForPackage( alarm.sourcePackage, userId, quota) + window; } } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) { Loading Loading @@ -2201,20 +2206,23 @@ public class AlarmManagerService extends SystemService { final int userId = UserHandle.getUserId(alarm.creatorUid); final int quota; final long window; final AppWakeupHistory history; if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) { quota = mConstants.ALLOW_WHILE_IDLE_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_WINDOW; history = mAllowWhileIdleHistory; } else { quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; history = mAllowWhileIdleCompatHistory; } final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow( final int dispatchesInHistory = history.getTotalWakeupsInWindow( alarm.sourcePackage, userId); if (dispatchesInWindow < quota) { if (dispatchesInHistory < quota) { // fine to go out immediately. deviceIdlePolicyTime = nowElapsed; } else { final long whenInQuota = mAllowWhileIdleHistory.getNthLastWakeupForPackage( final long whenInQuota = history.getNthLastWakeupForPackage( alarm.sourcePackage, userId, quota) + window; deviceIdlePolicyTime = Math.min(whenInQuota, mPendingIdleUntil.getWhenElapsed()); } Loading Loading @@ -2502,6 +2510,7 @@ public class AlarmManagerService extends SystemService { Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized"); // The API doesn't allow using both together. flags &= ~FLAG_ALLOW_WHILE_IDLE; // Prioritized alarms don't need any extra permission to be exact. } else if (exact || allowWhileIdle) { final boolean needsPermission; boolean lowerQuota; Loading Loading @@ -2992,6 +3001,10 @@ public class AlarmManagerService extends SystemService { mAllowWhileIdleHistory.dump(pw, nowELAPSED); pw.println(); pw.println("Allow while idle compat history:"); mAllowWhileIdleCompatHistory.dump(pw, nowELAPSED); pw.println(); if (mLastPriorityAlarmDispatch.size() > 0) { pw.println("Last priority alarm dispatches:"); pw.increaseIndent(); Loading Loading @@ -4553,6 +4566,7 @@ public class AlarmManagerService extends SystemService { removeUserLocked(userHandle); mAppWakeupHistory.removeForUser(userHandle); mAllowWhileIdleHistory.removeForUser(userHandle); mAllowWhileIdleCompatHistory.removeForUser(userHandle); } return; case Intent.ACTION_UID_REMOVED: Loading Loading @@ -4588,6 +4602,8 @@ public class AlarmManagerService extends SystemService { // package-removed and package-restarted case mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); mAllowWhileIdleHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); mAllowWhileIdleCompatHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); removeLocked(uid, REMOVE_REASON_UNDEFINED); } else { // external-applications-unavailable case Loading Loading @@ -4965,7 +4981,10 @@ public class AlarmManagerService extends SystemService { if (isAllowedWhileIdleRestricted(alarm)) { // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm while the // device was in doze or battery saver. mAllowWhileIdleHistory.recordAlarmForPackage(alarm.sourcePackage, final AppWakeupHistory history = ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) ? mAllowWhileIdleHistory : mAllowWhileIdleCompatHistory; history.recordAlarmForPackage(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid), nowELAPSED); mAlarmStore.updateAlarmDeliveries(a -> { if (a.creatorUid != alarm.creatorUid || !isAllowedWhileIdleRestricted(a)) { Loading services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +148 −9 Original line number Diff line number Diff line Loading @@ -514,8 +514,16 @@ public class AlarmManagerServiceTest { } private void setAllowWhileIdleAlarm(int type, long triggerTime, PendingIntent pi, boolean unrestricted) { final int flags = unrestricted ? FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED : FLAG_ALLOW_WHILE_IDLE; boolean unrestricted, boolean compat) { assertFalse("Alarm cannot be compat and unrestricted", unrestricted && compat); final int flags; if (unrestricted) { flags = FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; } else if (compat) { flags = FLAG_ALLOW_WHILE_IDLE_COMPAT; } else { flags = FLAG_ALLOW_WHILE_IDLE; } setTestAlarm(type, triggerTime, pi, 0, flags, TEST_CALLING_UID); } Loading Loading @@ -1600,13 +1608,13 @@ public class AlarmManagerServiceTest { final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < quota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent(), false); getNewMockPendingIntent(), false, false); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, getNewMockPendingIntent(), false); getNewMockPendingIntent(), false, false); final long expectedNextTrigger = firstTrigger + mAllowWhileIdleWindow; assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, mTestTimer.getElapsed()); Loading @@ -1618,6 +1626,108 @@ public class AlarmManagerServiceTest { assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed()); } @Test public void allowWhileIdleCompatAlarmsWhileDeviceIdle() throws Exception { setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + window + 1000, getNewMockPendingIntent()); assertNotNull(mService.mPendingIdleUntil); final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < quota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent(), false, true); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, getNewMockPendingIntent(), false, true); final long expectedNextTrigger = firstTrigger + window; assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, mTestTimer.getElapsed()); // Bring the idle until alarm back. setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger - 50, getNewMockPendingIntent()); assertEquals(expectedNextTrigger - 50, mService.mPendingIdleUntil.getWhenElapsed()); assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed()); } @Test public void allowWhileIdleCompatHistorySeparate() throws Exception { when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, TEST_CALLING_PACKAGE)).thenReturn(true); when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); final int fullQuota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; final int compatQuota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; final long fullWindow = mAllowWhileIdleWindow; final long compatWindow = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; final long firstFullTrigger = mNowElapsedTest + 10; for (int i = 0; i < fullQuota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + i, getNewMockPendingIntent(), false, false); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set, as full quota is not available. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + fullQuota, getNewMockPendingIntent(), false, false); final long expectedNextFullTrigger = firstFullTrigger + fullWindow; assertEquals("Incorrect trigger when no quota left", expectedNextFullTrigger, mTestTimer.getElapsed()); mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); // The following should be allowed, as compat quota should be free. for (int i = 0; i < compatQuota; i++) { final long trigger = mNowElapsedTest + 1; setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true); assertEquals(trigger, mTestTimer.getElapsed()); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // Refresh the state mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); // Now test with flipped order final long firstCompatTrigger = mNowElapsedTest + 10; for (int i = 0; i < compatQuota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + i, getNewMockPendingIntent(), false, true); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set, as full quota is not available. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + compatQuota, getNewMockPendingIntent(), false, true); final long expectedNextCompatTrigger = firstCompatTrigger + compatWindow; assertEquals("Incorrect trigger when no quota left", expectedNextCompatTrigger, mTestTimer.getElapsed()); mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); // The following should be allowed, as full quota should be free. for (int i = 0; i < fullQuota; i++) { final long trigger = mNowElapsedTest + 1; setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, false); assertEquals(trigger, mTestTimer.getElapsed()); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } } @Test public void allowWhileIdleUnrestricted() throws Exception { setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); Loading @@ -1634,7 +1744,7 @@ public class AlarmManagerServiceTest { final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < numAlarms; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent(), true); getNewMockPendingIntent(), true, false); } // All of them should fire as expected. for (int i = 0; i < numAlarms; i++) { Loading Loading @@ -1736,7 +1846,7 @@ public class AlarmManagerServiceTest { final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); // Refresh the state mService.removeLocked(TEST_CALLING_UID, Loading @@ -1744,7 +1854,7 @@ public class AlarmManagerServiceTest { mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); trigger, getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); // Refresh the state mService.removeLocked(TEST_CALLING_UID, Loading @@ -1752,7 +1862,36 @@ public class AlarmManagerServiceTest { mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); } @Test public void allowWhileIdleCompatAlarmsInBatterySaver() throws Exception { when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, TEST_CALLING_PACKAGE)).thenReturn(true); when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true), quota, window); // Refresh the state mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true), quota, window); // Refresh the state mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true), quota, window); } @Test Loading Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +26 −7 Original line number Diff line number Diff line Loading @@ -256,6 +256,7 @@ public class AlarmManagerService extends SystemService { AlarmHandler mHandler; AppWakeupHistory mAppWakeupHistory; AppWakeupHistory mAllowWhileIdleHistory; AppWakeupHistory mAllowWhileIdleCompatHistory; private final SparseLongArray mLastPriorityAlarmDispatch = new SparseLongArray(); private final SparseArray<RingBuffer<RemovedAlarm>> mRemovalHistory = new SparseArray<>(); ClockReceiver mClockReceiver; Loading Loading @@ -1633,6 +1634,7 @@ public class AlarmManagerService extends SystemService { mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW); mAllowWhileIdleHistory = new AppWakeupHistory(INTERVAL_HOUR); mAllowWhileIdleCompatHistory = new AppWakeupHistory(INTERVAL_HOUR); mNextWakeup = mNextNonWakeup = 0; Loading Loading @@ -2142,20 +2144,23 @@ public class AlarmManagerService extends SystemService { final int userId = UserHandle.getUserId(alarm.creatorUid); final int quota; final long window; final AppWakeupHistory history; if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) { quota = mConstants.ALLOW_WHILE_IDLE_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_WINDOW; history = mAllowWhileIdleHistory; } else { quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; history = mAllowWhileIdleCompatHistory; } final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow( final int dispatchesInHistory = history.getTotalWakeupsInWindow( alarm.sourcePackage, userId); if (dispatchesInWindow < quota) { if (dispatchesInHistory < quota) { // fine to go out immediately. batterySaverPolicyElapsed = nowElapsed; } else { batterySaverPolicyElapsed = mAllowWhileIdleHistory.getNthLastWakeupForPackage( batterySaverPolicyElapsed = history.getNthLastWakeupForPackage( alarm.sourcePackage, userId, quota) + window; } } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) { Loading Loading @@ -2201,20 +2206,23 @@ public class AlarmManagerService extends SystemService { final int userId = UserHandle.getUserId(alarm.creatorUid); final int quota; final long window; final AppWakeupHistory history; if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) { quota = mConstants.ALLOW_WHILE_IDLE_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_WINDOW; history = mAllowWhileIdleHistory; } else { quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; history = mAllowWhileIdleCompatHistory; } final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow( final int dispatchesInHistory = history.getTotalWakeupsInWindow( alarm.sourcePackage, userId); if (dispatchesInWindow < quota) { if (dispatchesInHistory < quota) { // fine to go out immediately. deviceIdlePolicyTime = nowElapsed; } else { final long whenInQuota = mAllowWhileIdleHistory.getNthLastWakeupForPackage( final long whenInQuota = history.getNthLastWakeupForPackage( alarm.sourcePackage, userId, quota) + window; deviceIdlePolicyTime = Math.min(whenInQuota, mPendingIdleUntil.getWhenElapsed()); } Loading Loading @@ -2502,6 +2510,7 @@ public class AlarmManagerService extends SystemService { Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized"); // The API doesn't allow using both together. flags &= ~FLAG_ALLOW_WHILE_IDLE; // Prioritized alarms don't need any extra permission to be exact. } else if (exact || allowWhileIdle) { final boolean needsPermission; boolean lowerQuota; Loading Loading @@ -2992,6 +3001,10 @@ public class AlarmManagerService extends SystemService { mAllowWhileIdleHistory.dump(pw, nowELAPSED); pw.println(); pw.println("Allow while idle compat history:"); mAllowWhileIdleCompatHistory.dump(pw, nowELAPSED); pw.println(); if (mLastPriorityAlarmDispatch.size() > 0) { pw.println("Last priority alarm dispatches:"); pw.increaseIndent(); Loading Loading @@ -4553,6 +4566,7 @@ public class AlarmManagerService extends SystemService { removeUserLocked(userHandle); mAppWakeupHistory.removeForUser(userHandle); mAllowWhileIdleHistory.removeForUser(userHandle); mAllowWhileIdleCompatHistory.removeForUser(userHandle); } return; case Intent.ACTION_UID_REMOVED: Loading Loading @@ -4588,6 +4602,8 @@ public class AlarmManagerService extends SystemService { // package-removed and package-restarted case mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); mAllowWhileIdleHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); mAllowWhileIdleCompatHistory.removeForPackage(pkg, UserHandle.getUserId(uid)); removeLocked(uid, REMOVE_REASON_UNDEFINED); } else { // external-applications-unavailable case Loading Loading @@ -4965,7 +4981,10 @@ public class AlarmManagerService extends SystemService { if (isAllowedWhileIdleRestricted(alarm)) { // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm while the // device was in doze or battery saver. mAllowWhileIdleHistory.recordAlarmForPackage(alarm.sourcePackage, final AppWakeupHistory history = ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) ? mAllowWhileIdleHistory : mAllowWhileIdleCompatHistory; history.recordAlarmForPackage(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid), nowELAPSED); mAlarmStore.updateAlarmDeliveries(a -> { if (a.creatorUid != alarm.creatorUid || !isAllowedWhileIdleRestricted(a)) { Loading
services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +148 −9 Original line number Diff line number Diff line Loading @@ -514,8 +514,16 @@ public class AlarmManagerServiceTest { } private void setAllowWhileIdleAlarm(int type, long triggerTime, PendingIntent pi, boolean unrestricted) { final int flags = unrestricted ? FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED : FLAG_ALLOW_WHILE_IDLE; boolean unrestricted, boolean compat) { assertFalse("Alarm cannot be compat and unrestricted", unrestricted && compat); final int flags; if (unrestricted) { flags = FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; } else if (compat) { flags = FLAG_ALLOW_WHILE_IDLE_COMPAT; } else { flags = FLAG_ALLOW_WHILE_IDLE; } setTestAlarm(type, triggerTime, pi, 0, flags, TEST_CALLING_UID); } Loading Loading @@ -1600,13 +1608,13 @@ public class AlarmManagerServiceTest { final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < quota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent(), false); getNewMockPendingIntent(), false, false); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, getNewMockPendingIntent(), false); getNewMockPendingIntent(), false, false); final long expectedNextTrigger = firstTrigger + mAllowWhileIdleWindow; assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, mTestTimer.getElapsed()); Loading @@ -1618,6 +1626,108 @@ public class AlarmManagerServiceTest { assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed()); } @Test public void allowWhileIdleCompatAlarmsWhileDeviceIdle() throws Exception { setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + window + 1000, getNewMockPendingIntent()); assertNotNull(mService.mPendingIdleUntil); final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < quota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent(), false, true); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, getNewMockPendingIntent(), false, true); final long expectedNextTrigger = firstTrigger + window; assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, mTestTimer.getElapsed()); // Bring the idle until alarm back. setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger - 50, getNewMockPendingIntent()); assertEquals(expectedNextTrigger - 50, mService.mPendingIdleUntil.getWhenElapsed()); assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed()); } @Test public void allowWhileIdleCompatHistorySeparate() throws Exception { when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, TEST_CALLING_PACKAGE)).thenReturn(true); when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); final int fullQuota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; final int compatQuota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; final long fullWindow = mAllowWhileIdleWindow; final long compatWindow = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; final long firstFullTrigger = mNowElapsedTest + 10; for (int i = 0; i < fullQuota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + i, getNewMockPendingIntent(), false, false); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set, as full quota is not available. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + fullQuota, getNewMockPendingIntent(), false, false); final long expectedNextFullTrigger = firstFullTrigger + fullWindow; assertEquals("Incorrect trigger when no quota left", expectedNextFullTrigger, mTestTimer.getElapsed()); mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); // The following should be allowed, as compat quota should be free. for (int i = 0; i < compatQuota; i++) { final long trigger = mNowElapsedTest + 1; setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true); assertEquals(trigger, mTestTimer.getElapsed()); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // Refresh the state mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); // Now test with flipped order final long firstCompatTrigger = mNowElapsedTest + 10; for (int i = 0; i < compatQuota; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + i, getNewMockPendingIntent(), false, true); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } // This one should get deferred on set, as full quota is not available. setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + compatQuota, getNewMockPendingIntent(), false, true); final long expectedNextCompatTrigger = firstCompatTrigger + compatWindow; assertEquals("Incorrect trigger when no quota left", expectedNextCompatTrigger, mTestTimer.getElapsed()); mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); // The following should be allowed, as full quota should be free. for (int i = 0; i < fullQuota; i++) { final long trigger = mNowElapsedTest + 1; setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, false); assertEquals(trigger, mTestTimer.getElapsed()); mNowElapsedTest = mTestTimer.getElapsed(); mTestTimer.expire(); } } @Test public void allowWhileIdleUnrestricted() throws Exception { setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); Loading @@ -1634,7 +1744,7 @@ public class AlarmManagerServiceTest { final long firstTrigger = mNowElapsedTest + 10; for (int i = 0; i < numAlarms; i++) { setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent(), true); getNewMockPendingIntent(), true, false); } // All of them should fire as expected. for (int i = 0; i < numAlarms; i++) { Loading Loading @@ -1736,7 +1846,7 @@ public class AlarmManagerServiceTest { final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); // Refresh the state mService.removeLocked(TEST_CALLING_UID, Loading @@ -1744,7 +1854,7 @@ public class AlarmManagerServiceTest { mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); trigger, getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); // Refresh the state mService.removeLocked(TEST_CALLING_UID, Loading @@ -1752,7 +1862,36 @@ public class AlarmManagerServiceTest { mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false), quota, mAllowWhileIdleWindow); getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); } @Test public void allowWhileIdleCompatAlarmsInBatterySaver() throws Exception { when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, TEST_CALLING_PACKAGE)).thenReturn(true); when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true), quota, window); // Refresh the state mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true), quota, window); // Refresh the state mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), false, true), quota, window); } @Test Loading