Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +53 −55 Original line number Diff line number Diff line Loading @@ -1684,17 +1684,13 @@ public class AlarmManagerService extends SystemService { } } if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) { // Do not support windows for idle-until alarms. windowLength = AlarmManager.WINDOW_EXACT; } // Snap the window to reasonable limits. if (windowLength > INTERVAL_DAY) { Slog.w(TAG, "Window length " + windowLength + "ms suspiciously long; limiting to 1 day"); windowLength = INTERVAL_DAY; } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW) { } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW && (flags & FLAG_PRIORITIZE) == 0) { if (CompatChanges.isChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, callingPackage, UserHandle.getUserHandleForUid(callingUid))) { Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to " Loading Loading @@ -1741,7 +1737,7 @@ public class AlarmManagerService extends SystemService { final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger; final long maxElapsed; if (windowLength == AlarmManager.WINDOW_EXACT) { if (windowLength == 0) { maxElapsed = triggerElapsed; } else if (windowLength < 0) { maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval); Loading Loading @@ -2145,17 +2141,63 @@ public class AlarmManagerService extends SystemService { + " does not belong to the calling uid " + callingUid); } // Repeating alarms must use PendingIntent, not direct listener if (interval != 0 && directReceiver != null) { throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers"); } if (workSource != null) { getContext().enforcePermission( android.Manifest.permission.UPDATE_DEVICE_STATS, Binder.getCallingPid(), callingUid, "AlarmManager.set"); } if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) { // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm // manager when to come out of idle mode, which is only for DeviceIdleController. if (callingUid != Process.SYSTEM_UID) { // TODO (b/169463012): Throw instead of tolerating this mistake. flags &= ~AlarmManager.FLAG_IDLE_UNTIL; } else { // Do not support windows for idle-until alarms. windowLength = 0; } } // Remove flags reserved for the service, we will apply those later as appropriate. flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED | FLAG_ALLOW_WHILE_IDLE_COMPAT); // If this alarm is for an alarm clock, then it must be exact and we will // use it to wake early from idle if needed. if (alarmClock != null) { flags |= FLAG_WAKE_FROM_IDLE; windowLength = 0; // If the caller is a core system component or on the user's allowlist, and not calling // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED. // This means we will allow these alarms to go off as normal even while idle, with no // timing restrictions. } else if (workSource == null && (UserHandle.isCore(callingUid) || UserHandle.isSameApp(callingUid, mSystemUiUid) || ((mAppStateTracker != null) && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) { flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_PRIORITIZE); } final boolean allowWhileIdle = (flags & FLAG_ALLOW_WHILE_IDLE) != 0; final boolean exact = (windowLength == AlarmManager.WINDOW_EXACT); final boolean exact = (windowLength == 0); // make sure the caller is allowed to use the requested kind of alarm, and also // Make sure the caller is allowed to use the requested kind of alarm, and also // decide what quota and broadcast options to use. Bundle idleOptions = null; if ((flags & FLAG_PRIORITIZE) != 0) { getContext().enforcePermission( Manifest.permission.SCHEDULE_PRIORITIZED_ALARM, Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized"); flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_ALLOW_WHILE_IDLE_COMPAT); // The API doesn't allow using both together. flags &= ~FLAG_ALLOW_WHILE_IDLE; } else if (exact || allowWhileIdle) { final boolean needsPermission; boolean lowerQuota; Loading Loading @@ -2193,55 +2235,11 @@ public class AlarmManagerService extends SystemService { } } // Repeating alarms must use PendingIntent, not direct listener if (interval != 0) { if (directReceiver != null) { throw new IllegalArgumentException( "Repeating alarms cannot use AlarmReceivers"); } } if (workSource != null) { getContext().enforcePermission( android.Manifest.permission.UPDATE_DEVICE_STATS, Binder.getCallingPid(), callingUid, "AlarmManager.set"); } // No incoming callers can request either WAKE_FROM_IDLE or // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate. flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED); // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm // manager when to come out of idle mode, which is only for DeviceIdleController. if (callingUid != Process.SYSTEM_UID) { flags &= ~AlarmManager.FLAG_IDLE_UNTIL; } // If this is an exact time alarm, then it can't be batched with other alarms. if (windowLength == AlarmManager.WINDOW_EXACT) { if (exact) { flags |= AlarmManager.FLAG_STANDALONE; } // If this alarm is for an alarm clock, then it must be standalone and we will // use it to wake early from idle if needed. if (alarmClock != null) { flags |= FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE; // If the caller is a core system component or on the user's whitelist, and not calling // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED. // This means we will allow these alarms to go off as normal even while idle, with no // timing restrictions. } else if (workSource == null && (UserHandle.isCore(callingUid) || UserHandle.isSameApp(callingUid, mSystemUiUid) || ((mAppStateTracker != null) && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) { flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; flags &= ~FLAG_ALLOW_WHILE_IDLE; flags &= ~FLAG_ALLOW_WHILE_IDLE_COMPAT; flags &= ~FLAG_PRIORITIZE; idleOptions = null; } setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, callingPackage, idleOptions); Loading apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java +0 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.alarm; import static com.android.server.alarm.AlarmManagerService.TAG; import static com.android.server.alarm.AlarmManagerService.dumpAlarmList; import static com.android.server.alarm.AlarmManagerService.isTimeTickAlarm; Loading services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +29 −6 Original line number Diff line number Diff line Loading @@ -468,8 +468,9 @@ public class AlarmManagerServiceTest { TEST_CALLING_UID); } private void setPrioritizedAlarm(int type, long triggerTime, IAlarmListener listener) { mService.setImpl(type, triggerTime, WINDOW_EXACT, 0, null, listener, "test", private void setPrioritizedAlarm(int type, long triggerTime, long windowLength, IAlarmListener listener) { mService.setImpl(type, triggerTime, windowLength, 0, null, listener, "test", FLAG_STANDALONE | FLAG_PRIORITIZE, null, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE, null); } Loading Loading @@ -1685,7 +1686,7 @@ public class AlarmManagerServiceTest { final int numAlarms = 10; for (int i = 0; i < numAlarms; i++) { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, new IAlarmListener.Stub() { 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { Loading Loading @@ -1720,7 +1721,7 @@ public class AlarmManagerServiceTest { final int numAlarms = 10; for (int i = 0; i < numAlarms; i++) { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, new IAlarmListener.Stub() { 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { Loading @@ -1738,12 +1739,12 @@ public class AlarmManagerServiceTest { } assertEquals(numAlarms, alarmsFired.get()); setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, new IAlarmListener.Stub() { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { } }); setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, new IAlarmListener.Stub() { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { } Loading Loading @@ -2262,6 +2263,28 @@ public class AlarmManagerServiceTest { } } @Test public void minWindowPriorityAlarm() { doReturn(true).when( () -> CompatChanges.isChangeEnabled( eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS), anyString(), any(UserHandle.class))); final long minWindow = 73; setDeviceConfigLong(KEY_MIN_WINDOW, minWindow); // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC. for (int window = 1; window <= minWindow; window++) { setPrioritizedAlarm(ELAPSED_REALTIME, 0, window, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { } }); assertEquals(1, mService.mAlarmStore.size()); final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); assertEquals(window, a.windowLength); } } @Test public void denyListPackagesAdded() { mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"}); Loading Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +53 −55 Original line number Diff line number Diff line Loading @@ -1684,17 +1684,13 @@ public class AlarmManagerService extends SystemService { } } if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) { // Do not support windows for idle-until alarms. windowLength = AlarmManager.WINDOW_EXACT; } // Snap the window to reasonable limits. if (windowLength > INTERVAL_DAY) { Slog.w(TAG, "Window length " + windowLength + "ms suspiciously long; limiting to 1 day"); windowLength = INTERVAL_DAY; } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW) { } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW && (flags & FLAG_PRIORITIZE) == 0) { if (CompatChanges.isChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, callingPackage, UserHandle.getUserHandleForUid(callingUid))) { Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to " Loading Loading @@ -1741,7 +1737,7 @@ public class AlarmManagerService extends SystemService { final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger; final long maxElapsed; if (windowLength == AlarmManager.WINDOW_EXACT) { if (windowLength == 0) { maxElapsed = triggerElapsed; } else if (windowLength < 0) { maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval); Loading Loading @@ -2145,17 +2141,63 @@ public class AlarmManagerService extends SystemService { + " does not belong to the calling uid " + callingUid); } // Repeating alarms must use PendingIntent, not direct listener if (interval != 0 && directReceiver != null) { throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers"); } if (workSource != null) { getContext().enforcePermission( android.Manifest.permission.UPDATE_DEVICE_STATS, Binder.getCallingPid(), callingUid, "AlarmManager.set"); } if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) { // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm // manager when to come out of idle mode, which is only for DeviceIdleController. if (callingUid != Process.SYSTEM_UID) { // TODO (b/169463012): Throw instead of tolerating this mistake. flags &= ~AlarmManager.FLAG_IDLE_UNTIL; } else { // Do not support windows for idle-until alarms. windowLength = 0; } } // Remove flags reserved for the service, we will apply those later as appropriate. flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED | FLAG_ALLOW_WHILE_IDLE_COMPAT); // If this alarm is for an alarm clock, then it must be exact and we will // use it to wake early from idle if needed. if (alarmClock != null) { flags |= FLAG_WAKE_FROM_IDLE; windowLength = 0; // If the caller is a core system component or on the user's allowlist, and not calling // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED. // This means we will allow these alarms to go off as normal even while idle, with no // timing restrictions. } else if (workSource == null && (UserHandle.isCore(callingUid) || UserHandle.isSameApp(callingUid, mSystemUiUid) || ((mAppStateTracker != null) && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) { flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_PRIORITIZE); } final boolean allowWhileIdle = (flags & FLAG_ALLOW_WHILE_IDLE) != 0; final boolean exact = (windowLength == AlarmManager.WINDOW_EXACT); final boolean exact = (windowLength == 0); // make sure the caller is allowed to use the requested kind of alarm, and also // Make sure the caller is allowed to use the requested kind of alarm, and also // decide what quota and broadcast options to use. Bundle idleOptions = null; if ((flags & FLAG_PRIORITIZE) != 0) { getContext().enforcePermission( Manifest.permission.SCHEDULE_PRIORITIZED_ALARM, Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized"); flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_ALLOW_WHILE_IDLE_COMPAT); // The API doesn't allow using both together. flags &= ~FLAG_ALLOW_WHILE_IDLE; } else if (exact || allowWhileIdle) { final boolean needsPermission; boolean lowerQuota; Loading Loading @@ -2193,55 +2235,11 @@ public class AlarmManagerService extends SystemService { } } // Repeating alarms must use PendingIntent, not direct listener if (interval != 0) { if (directReceiver != null) { throw new IllegalArgumentException( "Repeating alarms cannot use AlarmReceivers"); } } if (workSource != null) { getContext().enforcePermission( android.Manifest.permission.UPDATE_DEVICE_STATS, Binder.getCallingPid(), callingUid, "AlarmManager.set"); } // No incoming callers can request either WAKE_FROM_IDLE or // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate. flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED); // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm // manager when to come out of idle mode, which is only for DeviceIdleController. if (callingUid != Process.SYSTEM_UID) { flags &= ~AlarmManager.FLAG_IDLE_UNTIL; } // If this is an exact time alarm, then it can't be batched with other alarms. if (windowLength == AlarmManager.WINDOW_EXACT) { if (exact) { flags |= AlarmManager.FLAG_STANDALONE; } // If this alarm is for an alarm clock, then it must be standalone and we will // use it to wake early from idle if needed. if (alarmClock != null) { flags |= FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE; // If the caller is a core system component or on the user's whitelist, and not calling // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED. // This means we will allow these alarms to go off as normal even while idle, with no // timing restrictions. } else if (workSource == null && (UserHandle.isCore(callingUid) || UserHandle.isSameApp(callingUid, mSystemUiUid) || ((mAppStateTracker != null) && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) { flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; flags &= ~FLAG_ALLOW_WHILE_IDLE; flags &= ~FLAG_ALLOW_WHILE_IDLE_COMPAT; flags &= ~FLAG_PRIORITIZE; idleOptions = null; } setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver, listenerTag, flags, workSource, alarmClock, callingUid, callingPackage, idleOptions); Loading
apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java +0 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.alarm; import static com.android.server.alarm.AlarmManagerService.TAG; import static com.android.server.alarm.AlarmManagerService.dumpAlarmList; import static com.android.server.alarm.AlarmManagerService.isTimeTickAlarm; Loading
services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +29 −6 Original line number Diff line number Diff line Loading @@ -468,8 +468,9 @@ public class AlarmManagerServiceTest { TEST_CALLING_UID); } private void setPrioritizedAlarm(int type, long triggerTime, IAlarmListener listener) { mService.setImpl(type, triggerTime, WINDOW_EXACT, 0, null, listener, "test", private void setPrioritizedAlarm(int type, long triggerTime, long windowLength, IAlarmListener listener) { mService.setImpl(type, triggerTime, windowLength, 0, null, listener, "test", FLAG_STANDALONE | FLAG_PRIORITIZE, null, null, TEST_CALLING_UID, TEST_CALLING_PACKAGE, null); } Loading Loading @@ -1685,7 +1686,7 @@ public class AlarmManagerServiceTest { final int numAlarms = 10; for (int i = 0; i < numAlarms; i++) { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, new IAlarmListener.Stub() { 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { Loading Loading @@ -1720,7 +1721,7 @@ public class AlarmManagerServiceTest { final int numAlarms = 10; for (int i = 0; i < numAlarms; i++) { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, new IAlarmListener.Stub() { 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { Loading @@ -1738,12 +1739,12 @@ public class AlarmManagerServiceTest { } assertEquals(numAlarms, alarmsFired.get()); setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, new IAlarmListener.Stub() { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { } }); setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, new IAlarmListener.Stub() { setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, 0, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { } Loading Loading @@ -2262,6 +2263,28 @@ public class AlarmManagerServiceTest { } } @Test public void minWindowPriorityAlarm() { doReturn(true).when( () -> CompatChanges.isChangeEnabled( eq(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS), anyString(), any(UserHandle.class))); final long minWindow = 73; setDeviceConfigLong(KEY_MIN_WINDOW, minWindow); // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC. for (int window = 1; window <= minWindow; window++) { setPrioritizedAlarm(ELAPSED_REALTIME, 0, window, new IAlarmListener.Stub() { @Override public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { } }); assertEquals(1, mService.mAlarmStore.size()); final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); assertEquals(window, a.windowLength); } } @Test public void denyListPackagesAdded() { mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"}); Loading