Loading apex/jobscheduler/framework/java/android/app/AlarmManager.java +31 −4 Original line number Diff line number Diff line Loading @@ -208,10 +208,10 @@ public class AlarmManager { public static final int FLAG_PRIORITIZE = 1 << 6; /** * For apps targeting {@link Build.VERSION_CODES#S} or above, APIs * {@link #setExactAndAllowWhileIdle(int, long, PendingIntent)} and * {@link #setAlarmClock(AlarmClockInfo, PendingIntent)} will require holding a new * permission {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM} * For apps targeting {@link Build.VERSION_CODES#S} or above, any APIs setting exact alarms, * e.g. {@link #setExact(int, long, PendingIntent)}, * {@link #setAlarmClock(AlarmClockInfo, PendingIntent)} and others will require holding a new * permission {@link Manifest.permission#SCHEDULE_EXACT_ALARM} * * @hide */ Loading @@ -219,6 +219,21 @@ public class AlarmManager { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) public static final long REQUIRE_EXACT_ALARM_PERMISSION = 171306433L; /** * For apps targeting {@link Build.VERSION_CODES#S} or above, all inexact alarms will require * to have a minimum window size, expected to be on the order of a few minutes. * * Practically, any alarms requiring smaller windows are the same as exact alarms and should use * the corresponding APIs provided, like {@link #setExact(int, long, PendingIntent)}, et al. * * Inexact alarm with shorter windows specified will have their windows elongated by the system. * * @hide */ @ChangeId @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) public static final long ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS = 185199076L; @UnsupportedAppUsage private final IAlarmManager mService; private final Context mContext; Loading Loading @@ -483,6 +498,11 @@ public class AlarmManager { * modest timeliness requirements for its alarms. * * <p> * Note: Starting with API {@link Build.VERSION_CODES#S}, the system will ensure that the window * specified is at least a few minutes, as smaller windows are considered practically exact * and should use the other APIs provided for exact alarms. * * <p> * This method can also be used to achieve strict ordering guarantees among * multiple alarms by ensuring that the windows requested for each alarm do * not intersect. Loading Loading @@ -532,6 +552,13 @@ public class AlarmManager { * The OnAlarmListener {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * * <p> * Note: Starting with API {@link Build.VERSION_CODES#S}, the system will ensure that the window * specified is at least a few minutes, as smaller windows are considered practically exact * and should use the other APIs provided for exact alarms. * * @see #setWindow(int, long, long, PendingIntent) */ public void setWindow(@AlarmType int type, long windowStartMillis, long windowLengthMillis, String tag, OnAlarmListener listener, Handler targetHandler) { Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +17 −7 Original line number Diff line number Diff line Loading @@ -452,7 +452,8 @@ public class AlarmManagerService extends SystemService { 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 * INTERVAL_DAY; private static final long DEFAULT_MIN_WINDOW = 10_000; // TODO (b/185199076): Tune based on breakage reports. private static final long DEFAULT_MIN_WINDOW = 30 * 60 * 1000; 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; Loading Loading @@ -1688,12 +1689,22 @@ public class AlarmManagerService extends SystemService { windowLength = AlarmManager.WINDOW_EXACT; } // Sanity check the window length. This will catch people mistakenly // trying to pass an end-of-window timestamp rather than a duration. if (windowLength > AlarmManager.INTERVAL_HALF_DAY) { // Snap the window to reasonable limits. if (windowLength > INTERVAL_DAY) { Slog.w(TAG, "Window length " + windowLength + "ms suspiciously long; limiting to 1 hour"); windowLength = AlarmManager.INTERVAL_HOUR; + "ms suspiciously long; limiting to 1 day"); windowLength = INTERVAL_DAY; } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW) { 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 " + mConstants.MIN_WINDOW + "ms."); windowLength = mConstants.MIN_WINDOW; } else { // TODO (b/185199076): Remove log once we have some data about what apps will break Slog.wtf(TAG, "Short window " + windowLength + "ms specified by " + callingPackage); } } // Sanity check the recurrence interval. This will catch people who supply Loading Loading @@ -1737,7 +1748,6 @@ public class AlarmManagerService extends SystemService { // Fix this window in place, so that as time approaches we don't collapse it. windowLength = maxElapsed - triggerElapsed; } else { windowLength = Math.max(windowLength, mConstants.MIN_WINDOW); maxElapsed = triggerElapsed + windowLength; } synchronized (mLock) { Loading services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +25 −1 Original line number Diff line number Diff line Loading @@ -2223,7 +2223,11 @@ public class AlarmManagerServiceTest { } @Test public void minWindow() { public void minWindowChangeEnabled() { 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); Loading @@ -2238,6 +2242,26 @@ public class AlarmManagerServiceTest { } } @Test public void minWindowChangeDisabled() { doReturn(false).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++) { final PendingIntent pi = getNewMockPendingIntent(); setTestAlarm(ELAPSED_REALTIME, 0, window, pi, 0, 0, TEST_CALLING_UID, null); 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/framework/java/android/app/AlarmManager.java +31 −4 Original line number Diff line number Diff line Loading @@ -208,10 +208,10 @@ public class AlarmManager { public static final int FLAG_PRIORITIZE = 1 << 6; /** * For apps targeting {@link Build.VERSION_CODES#S} or above, APIs * {@link #setExactAndAllowWhileIdle(int, long, PendingIntent)} and * {@link #setAlarmClock(AlarmClockInfo, PendingIntent)} will require holding a new * permission {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM} * For apps targeting {@link Build.VERSION_CODES#S} or above, any APIs setting exact alarms, * e.g. {@link #setExact(int, long, PendingIntent)}, * {@link #setAlarmClock(AlarmClockInfo, PendingIntent)} and others will require holding a new * permission {@link Manifest.permission#SCHEDULE_EXACT_ALARM} * * @hide */ Loading @@ -219,6 +219,21 @@ public class AlarmManager { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) public static final long REQUIRE_EXACT_ALARM_PERMISSION = 171306433L; /** * For apps targeting {@link Build.VERSION_CODES#S} or above, all inexact alarms will require * to have a minimum window size, expected to be on the order of a few minutes. * * Practically, any alarms requiring smaller windows are the same as exact alarms and should use * the corresponding APIs provided, like {@link #setExact(int, long, PendingIntent)}, et al. * * Inexact alarm with shorter windows specified will have their windows elongated by the system. * * @hide */ @ChangeId @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) public static final long ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS = 185199076L; @UnsupportedAppUsage private final IAlarmManager mService; private final Context mContext; Loading Loading @@ -483,6 +498,11 @@ public class AlarmManager { * modest timeliness requirements for its alarms. * * <p> * Note: Starting with API {@link Build.VERSION_CODES#S}, the system will ensure that the window * specified is at least a few minutes, as smaller windows are considered practically exact * and should use the other APIs provided for exact alarms. * * <p> * This method can also be used to achieve strict ordering guarantees among * multiple alarms by ensuring that the windows requested for each alarm do * not intersect. Loading Loading @@ -532,6 +552,13 @@ public class AlarmManager { * The OnAlarmListener {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * * <p> * Note: Starting with API {@link Build.VERSION_CODES#S}, the system will ensure that the window * specified is at least a few minutes, as smaller windows are considered practically exact * and should use the other APIs provided for exact alarms. * * @see #setWindow(int, long, long, PendingIntent) */ public void setWindow(@AlarmType int type, long windowStartMillis, long windowLengthMillis, String tag, OnAlarmListener listener, Handler targetHandler) { Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +17 −7 Original line number Diff line number Diff line Loading @@ -452,7 +452,8 @@ public class AlarmManagerService extends SystemService { 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 * INTERVAL_DAY; private static final long DEFAULT_MIN_WINDOW = 10_000; // TODO (b/185199076): Tune based on breakage reports. private static final long DEFAULT_MIN_WINDOW = 30 * 60 * 1000; 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; Loading Loading @@ -1688,12 +1689,22 @@ public class AlarmManagerService extends SystemService { windowLength = AlarmManager.WINDOW_EXACT; } // Sanity check the window length. This will catch people mistakenly // trying to pass an end-of-window timestamp rather than a duration. if (windowLength > AlarmManager.INTERVAL_HALF_DAY) { // Snap the window to reasonable limits. if (windowLength > INTERVAL_DAY) { Slog.w(TAG, "Window length " + windowLength + "ms suspiciously long; limiting to 1 hour"); windowLength = AlarmManager.INTERVAL_HOUR; + "ms suspiciously long; limiting to 1 day"); windowLength = INTERVAL_DAY; } else if (windowLength > 0 && windowLength < mConstants.MIN_WINDOW) { 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 " + mConstants.MIN_WINDOW + "ms."); windowLength = mConstants.MIN_WINDOW; } else { // TODO (b/185199076): Remove log once we have some data about what apps will break Slog.wtf(TAG, "Short window " + windowLength + "ms specified by " + callingPackage); } } // Sanity check the recurrence interval. This will catch people who supply Loading Loading @@ -1737,7 +1748,6 @@ public class AlarmManagerService extends SystemService { // Fix this window in place, so that as time approaches we don't collapse it. windowLength = maxElapsed - triggerElapsed; } else { windowLength = Math.max(windowLength, mConstants.MIN_WINDOW); maxElapsed = triggerElapsed + windowLength; } synchronized (mLock) { Loading
services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +25 −1 Original line number Diff line number Diff line Loading @@ -2223,7 +2223,11 @@ public class AlarmManagerServiceTest { } @Test public void minWindow() { public void minWindowChangeEnabled() { 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); Loading @@ -2238,6 +2242,26 @@ public class AlarmManagerServiceTest { } } @Test public void minWindowChangeDisabled() { doReturn(false).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++) { final PendingIntent pi = getNewMockPendingIntent(); setTestAlarm(ELAPSED_REALTIME, 0, window, pi, 0, 0, TEST_CALLING_UID, null); 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