Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +83 −49 Original line number Diff line number Diff line Loading @@ -151,10 +151,10 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Random; import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Predicate; /** Loading Loading @@ -251,7 +251,6 @@ public class AlarmManagerService extends SystemService { Intent mTimeTickIntent; IAlarmListener mTimeTickTrigger; PendingIntent mDateChangeSender; Random mRandom; boolean mInteractive = true; long mNonInteractiveStartTime; long mNonInteractiveTime; Loading Loading @@ -516,6 +515,10 @@ public class AlarmManagerService extends SystemService { static final String KEY_PRIORITY_ALARM_DELAY = "priority_alarm_delay"; @VisibleForTesting static final String KEY_EXACT_ALARM_DENY_LIST = "exact_alarm_deny_list"; @VisibleForTesting static final String KEY_MIN_DEVICE_IDLE_FUZZ = "min_device_idle_fuzz"; @VisibleForTesting static final String KEY_MAX_DEVICE_IDLE_FUZZ = "max_device_idle_fuzz"; private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; Loading Loading @@ -556,6 +559,9 @@ public class AlarmManagerService extends SystemService { private static final long DEFAULT_PRIORITY_ALARM_DELAY = 9 * 60_000; private static final long DEFAULT_MIN_DEVICE_IDLE_FUZZ = 2 * 60_000; private static final long DEFAULT_MAX_DEVICE_IDLE_FUZZ = 15 * 60_000; // Minimum futurity of a new alarm public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; Loading Loading @@ -618,10 +624,23 @@ public class AlarmManagerService extends SystemService { public long PRIORITY_ALARM_DELAY = DEFAULT_PRIORITY_ALARM_DELAY; /** * Set of apps that won't get SCHEDULE_EXACT_ALARM when the app-op mode for * OP_SCHEDULE_EXACT_ALARM is MODE_DEFAULT. * Read-only set of apps that won't get SCHEDULE_EXACT_ALARM when the app-op mode for * OP_SCHEDULE_EXACT_ALARM is MODE_DEFAULT. Since this is read-only and volatile, this can * be accessed without synchronizing on {@link #mLock}. */ public volatile Set<String> EXACT_ALARM_DENY_LIST = Collections.emptySet(); /** * Minimum time interval that an IDLE_UNTIL will be pulled earlier to a subsequent * WAKE_FROM_IDLE alarm. */ public long MIN_DEVICE_IDLE_FUZZ = DEFAULT_MIN_DEVICE_IDLE_FUZZ; /** * Maximum time interval that an IDLE_UNTIL will be pulled earlier to a subsequent * WAKE_FROM_IDLE alarm. */ public Set<String> EXACT_ALARM_DENY_LIST = Collections.emptySet(); public long MAX_DEVICE_IDLE_FUZZ = DEFAULT_MAX_DEVICE_IDLE_FUZZ; private long mLastAllowWhileIdleWhitelistDuration = -1; private int mVersion = 0; Loading Loading @@ -660,6 +679,7 @@ public class AlarmManagerService extends SystemService { @Override public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) { boolean standbyQuotaUpdated = false; boolean deviceIdleFuzzBoundariesUpdated = false; synchronized (mLock) { mVersion++; for (String name : properties.getKeyset()) { Loading Loading @@ -787,6 +807,13 @@ public class AlarmManagerService extends SystemService { updateExactAlarmDenyList(values); } break; case KEY_MIN_DEVICE_IDLE_FUZZ: case KEY_MAX_DEVICE_IDLE_FUZZ: if (!deviceIdleFuzzBoundariesUpdated) { updateDeviceIdleFuzzBoundaries(); deviceIdleFuzzBoundariesUpdated = true; } break; default: if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) { // The quotas need to be updated in order, so we can't just rely Loading Loading @@ -824,6 +851,24 @@ public class AlarmManagerService extends SystemService { mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater); } private void updateDeviceIdleFuzzBoundaries() { final DeviceConfig.Properties properties = DeviceConfig.getProperties( DeviceConfig.NAMESPACE_ALARM_MANAGER, KEY_MIN_DEVICE_IDLE_FUZZ, KEY_MAX_DEVICE_IDLE_FUZZ); MIN_DEVICE_IDLE_FUZZ = properties.getLong(KEY_MIN_DEVICE_IDLE_FUZZ, DEFAULT_MIN_DEVICE_IDLE_FUZZ); MAX_DEVICE_IDLE_FUZZ = properties.getLong(KEY_MAX_DEVICE_IDLE_FUZZ, DEFAULT_MAX_DEVICE_IDLE_FUZZ); if (MAX_DEVICE_IDLE_FUZZ < MIN_DEVICE_IDLE_FUZZ) { Slog.w(TAG, "max_device_idle_fuzz cannot be smaller than" + " min_device_idle_fuzz! Increasing to " + MIN_DEVICE_IDLE_FUZZ); MAX_DEVICE_IDLE_FUZZ = MIN_DEVICE_IDLE_FUZZ; } } private void updateStandbyQuotasLocked() { // The bucket quotas need to be read as an atomic unit but the properties passed to // onPropertiesChanged may only have one key populated at a time. Loading Loading @@ -1133,12 +1178,8 @@ public class AlarmManagerService extends SystemService { if (mNextWakeFromIdle != null && isRtc(mNextWakeFromIdle.type)) { // The next wake from idle got updated due to the rtc time change, so we need // to update the time we have to come out of idle too. final boolean idleUntilUpdated = mAlarmStore.updateAlarmDeliveries(a -> { if (a != mPendingIdleUntil) { return false; } return adjustIdleUntilTime(a); }); final boolean idleUntilUpdated = mAlarmStore.updateAlarmDeliveries( a -> (a == mPendingIdleUntil) && adjustIdleUntilTime(a)); if (idleUntilUpdated) { mAlarmStore.updateAlarmDeliveries( alarm -> adjustDeliveryTimeBasedOnDeviceIdle(alarm)); Loading Loading @@ -1911,23 +1952,30 @@ public class AlarmManagerService extends SystemService { if ((alarm.flags & AlarmManager.FLAG_IDLE_UNTIL) == 0) { return false; } restoreRequestedTime(alarm); long triggerBeforeFuzz = alarm.getRequestedElapsed(); if (mNextWakeFromIdle != null && triggerBeforeFuzz > mNextWakeFromIdle.getWhenElapsed()) { triggerBeforeFuzz = mNextWakeFromIdle.getWhenElapsed(); final boolean changedBeforeFuzz = restoreRequestedTime(alarm); if (mNextWakeFromIdle == null) { // No need to change anything in the absence of a wake-from-idle request. return changedBeforeFuzz; } // Add fuzz to make the alarm go off some time before the actual desired time. final int fuzz = fuzzForDuration(alarm.getWhenElapsed() - mInjector.getElapsedRealtime()); final int delta; if (fuzz > 0) { if (mRandom == null) { mRandom = new Random(); final long upcomingWakeFromIdle = mNextWakeFromIdle.getWhenElapsed(); // Add fuzz to make the alarm go off some time before the next upcoming wake-from-idle, as // these alarms are usually wall-clock aligned. if (alarm.getWhenElapsed() < (upcomingWakeFromIdle - mConstants.MIN_DEVICE_IDLE_FUZZ)) { // No need to fuzz as this is already earlier than the coming wake-from-idle. return changedBeforeFuzz; } delta = mRandom.nextInt(fuzz); final long nowElapsed = mInjector.getElapsedRealtime(); final long futurity = upcomingWakeFromIdle - nowElapsed; if (futurity <= mConstants.MIN_DEVICE_IDLE_FUZZ) { // No point in fuzzing as the minimum fuzz will take the time in the past. alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, nowElapsed); } else { delta = 0; final ThreadLocalRandom random = ThreadLocalRandom.current(); final long upperBoundExcl = Math.min(mConstants.MAX_DEVICE_IDLE_FUZZ, futurity) + 1; final long fuzz = random.nextLong(mConstants.MIN_DEVICE_IDLE_FUZZ, upperBoundExcl); alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, upcomingWakeFromIdle - fuzz); } alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, triggerBeforeFuzz - delta); return true; } Loading Loading @@ -2130,12 +2178,8 @@ public class AlarmManagerService extends SystemService { // If this wake from idle is earlier than whatever was previously scheduled, // and we are currently idling, then the idle-until time needs to be updated. if (mPendingIdleUntil != null) { final boolean updated = mAlarmStore.updateAlarmDeliveries(alarm -> { if (alarm != mPendingIdleUntil) { return false; } return adjustIdleUntilTime(alarm); }); final boolean updated = mAlarmStore.updateAlarmDeliveries( alarm -> (alarm == mPendingIdleUntil) && adjustIdleUntilTime(alarm)); if (updated) { // idle-until got updated, so also update all alarms not allowed while idle. mAlarmStore.updateAlarmDeliveries( Loading Loading @@ -3675,20 +3719,6 @@ public class AlarmManagerService extends SystemService { } } int fuzzForDuration(long duration) { if (duration < 15 * 60 * 1000) { // If the duration until the time is less than 15 minutes, the maximum fuzz // is the duration. return (int) duration; } else if (duration < 90 * 60 * 1000) { // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes, return 15 * 60 * 1000; } else { // Otherwise, we will fuzz by at most half an hour. return 30 * 60 * 1000; } } boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) { if (mInteractive) { return false; Loading Loading @@ -4698,8 +4728,10 @@ public class AlarmManagerService extends SystemService { if (a.creatorUid != alarm.creatorUid || !isAllowedWhileIdleRestricted(a)) { return false; } return (doze && adjustDeliveryTimeBasedOnDeviceIdle(a)) || (batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a)); final boolean dozeAdjusted = doze && adjustDeliveryTimeBasedOnDeviceIdle(a); final boolean batterySaverAdjusted = batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a); return dozeAdjusted || batterySaverAdjusted; }); } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) { mLastPriorityAlarmDispatch.put(alarm.creatorUid, nowELAPSED); Loading @@ -4708,8 +4740,10 @@ public class AlarmManagerService extends SystemService { || (alarm.flags & FLAG_PRIORITIZE) == 0) { return false; } return (doze && adjustDeliveryTimeBasedOnDeviceIdle(a)) || (batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a)); final boolean dozeAdjusted = doze && adjustDeliveryTimeBasedOnDeviceIdle(a); final boolean batterySaverAdjusted = batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a); return dozeAdjusted || batterySaverAdjusted; }); } if (RECORD_DEVICE_IDLE_ALARMS) { Loading apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java +32 −9 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.util.function.Predicate; public class LazyAlarmStore implements AlarmStore { @VisibleForTesting static final String TAG = LazyAlarmStore.class.getSimpleName(); private static final long ALARM_DEADLINE_SLOP = 500; private final ArrayList<Alarm> mAlarms = new ArrayList<>(); private Runnable mOnAlarmClockRemoved; Loading Loading @@ -75,7 +76,7 @@ public class LazyAlarmStore implements AlarmStore { return; } mAlarms.addAll(alarms); Collections.sort(alarms, sDecreasingTimeOrder); Collections.sort(mAlarms, sDecreasingTimeOrder); } @Override Loading Loading @@ -163,25 +164,47 @@ public class LazyAlarmStore implements AlarmStore { @Override public ArrayList<Alarm> removePendingAlarms(long nowElapsed) { final ArrayList<Alarm> pending = new ArrayList<>(); final ArrayList<Alarm> standAlones = new ArrayList<>(); // Only send wake-up alarms if this is the absolutely latest time we can evaluate // for at least one wakeup alarm. This prevents sending other non-wakeup alarms when the // screen is off but the CPU is awake for some reason. boolean sendWakeups = false; // If any alarm with FLAG_STANDALONE is present, we cannot send any alarms without that flag // in the present batch. boolean standalonesOnly = false; for (int i = mAlarms.size() - 1; i >= 0; i--) { final Alarm alarm = mAlarms.get(i); if (alarm.getWhenElapsed() > nowElapsed) { break; } mAlarms.remove(i); pending.add(alarm); if (alarm.wakeup && alarm.getMaxWhenElapsed() <= nowElapsed + ALARM_DEADLINE_SLOP) { // Using some slop as it is better to send the wakeup alarm now, rather than // waking up again a short time later, just to send it. sendWakeups = true; } if ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) { standAlones.add(alarm); standalonesOnly = true; } } if (!standAlones.isEmpty()) { // If there are deliverable standalone alarms, others must not go out yet. mAlarms.removeAll(standAlones); return standAlones; final ArrayList<Alarm> toSend = new ArrayList<>(); for (int i = pending.size() - 1; i >= 0; i--) { final Alarm pendingAlarm = pending.get(i); if (!sendWakeups && pendingAlarm.wakeup) { continue; } if (standalonesOnly && (pendingAlarm.flags & AlarmManager.FLAG_STANDALONE) == 0) { continue; } pending.remove(i); toSend.add(pendingAlarm); } mAlarms.removeAll(pending); return pending; // Perhaps some alarms could not be sent right now. Adding them back for later. addAll(pending); return toSend; } @Override Loading services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +61 −18 Original line number Diff line number Diff line Loading @@ -71,7 +71,9 @@ import static com.android.server.alarm.AlarmManagerService.Constants.KEY_CRASH_N import static com.android.server.alarm.AlarmManagerService.Constants.KEY_EXACT_ALARM_DENY_LIST; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LAZY_BATCHING; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_DEVICE_IDLE_FUZZ; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_INTERVAL; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_DEVICE_IDLE_FUZZ; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_FUTURITY; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_INTERVAL; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_WINDOW; Loading Loading @@ -654,6 +656,8 @@ public class AlarmManagerServiceTest { setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 45); setDeviceConfigLong(KEY_MIN_WINDOW, 50); setDeviceConfigLong(KEY_PRIORITY_ALARM_DELAY, 55); setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, 60); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 65); assertEquals(5, mService.mConstants.MIN_FUTURITY); assertEquals(10, mService.mConstants.MIN_INTERVAL); assertEquals(15, mService.mConstants.MAX_INTERVAL); Loading @@ -665,6 +669,8 @@ public class AlarmManagerServiceTest { assertEquals(45, mService.mConstants.LISTENER_TIMEOUT); assertEquals(50, mService.mConstants.MIN_WINDOW); assertEquals(55, mService.mConstants.PRIORITY_ALARM_DELAY); assertEquals(60, mService.mConstants.MIN_DEVICE_IDLE_FUZZ); assertEquals(65, mService.mConstants.MAX_DEVICE_IDLE_FUZZ); } @Test Loading Loading @@ -736,6 +742,20 @@ public class AlarmManagerServiceTest { mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW); } @Test public void deviceIdleFuzzRangeNonNegative() { final long newMinFuzz = mService.mConstants.MAX_DEVICE_IDLE_FUZZ + 1542; final long newMaxFuzz = mService.mConstants.MIN_DEVICE_IDLE_FUZZ - 131; setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, newMinFuzz); assertTrue("Negative device-idle fuzz range", mService.mConstants.MAX_DEVICE_IDLE_FUZZ >= mService.mConstants.MIN_DEVICE_IDLE_FUZZ); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, newMaxFuzz); assertTrue("Negative device-idle fuzz range", mService.mConstants.MAX_DEVICE_IDLE_FUZZ >= mService.mConstants.MIN_DEVICE_IDLE_FUZZ); } @Test public void testMinFuturity() { setDeviceConfigLong(KEY_MIN_FUTURITY, 10L); Loading Loading @@ -1431,7 +1451,7 @@ public class AlarmManagerServiceTest { @Test public void singleIdleUntil() { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final PendingIntent idleUntilPi6 = getNewMockPendingIntent(); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, idleUntilPi6); Loading Loading @@ -1504,44 +1524,67 @@ public class AlarmManagerServiceTest { assertNull(mService.mNextWakeFromIdle); } private static void assertInRange(String message, long minIncl, long maxIncl, long val) { assertTrue(message, val >= minIncl && val <= maxIncl); } @Test public void idleUntilBeforeWakeFromIdle() { doReturn(0).when(mService).fuzzForDuration(anyLong()); public void idleUntilFuzzedBeforeWakeFromIdle() { final long minFuzz = 6; final long maxFuzz = 17; setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, minFuzz); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, maxFuzz); mNowElapsedTest = 119; // Arbitrary, just to ensure we are not testing on 0. final PendingIntent idleUntilPi = getNewMockPendingIntent(); final long requestedIdleUntil = mNowElapsedTest + 10; final long requestedIdleUntil = mNowElapsedTest + 12; setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, requestedIdleUntil, idleUntilPi); assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle5 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, wakeFromIdle5); assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); // Anything before now, gets snapped to now. It is not necessary for it to fire // immediately, just how it is implemented today for simplicity. assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle8 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, wakeFromIdle8); assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); // Next wake from idle is still the same. assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle12 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 12, wakeFromIdle12); assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle19 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 19, wakeFromIdle19); // Next wake from idle is still the same. assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); mService.removeLocked(wakeFromIdle5, null, REMOVE_REASON_UNDEFINED); assertEquals(mNowElapsedTest + 8, mService.mPendingIdleUntil.getWhenElapsed()); // Next wake from idle is at now + 8. long min = mNowElapsedTest; long max = mNowElapsedTest + 8 - minFuzz; assertInRange("Idle until alarm time not in expected range [" + min + ", " + max + "]", min, max, mService.mPendingIdleUntil.getWhenElapsed()); mService.removeLocked(wakeFromIdle8, null, REMOVE_REASON_UNDEFINED); // Next wake from idle is at now + 19, which is > minFuzz distance from // the requested idle until time: now + 12. assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); mService.removeLocked(idleUntilPi, null, REMOVE_REASON_UNDEFINED); assertNull(mService.mPendingIdleUntil); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 15, idleUntilPi); assertEquals(mNowElapsedTest + 12, mService.mPendingIdleUntil.getWhenElapsed()); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 21, idleUntilPi); // Next wake from idle is at now + 19, which means this alarm should get pulled back. min = mNowElapsedTest + 19 - maxFuzz; max = mNowElapsedTest + 19 - minFuzz; assertInRange("Idle until alarm time not in expected range [" + min + ", " + max + "]", min, max, mService.mPendingIdleUntil.getWhenElapsed()); } @Test public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + mAllowWhileIdleWindow + 1000, getNewMockPendingIntent()); Loading Loading @@ -1571,7 +1614,7 @@ public class AlarmManagerServiceTest { @Test public void allowWhileIdleUnrestricted() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); // Both battery saver and doze are on. setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000, Loading @@ -1597,7 +1640,7 @@ public class AlarmManagerServiceTest { @Test public void deviceIdleDeferralOnSet() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long deviceIdleUntil = mNowElapsedTest + 1234; setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, deviceIdleUntil, getNewMockPendingIntent()); Loading @@ -1622,7 +1665,7 @@ public class AlarmManagerServiceTest { @Test public void deviceIdleStateChanges() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final int numAlarms = 10; final PendingIntent[] pis = new PendingIntent[numAlarms]; Loading Loading @@ -1740,7 +1783,7 @@ public class AlarmManagerServiceTest { @Test public void prioritizedAlarmsInDeviceIdle() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long minDelay = 5; setDeviceConfigLong(KEY_PRIORITY_ALARM_DELAY, minDelay); Loading Loading @@ -1791,7 +1834,7 @@ public class AlarmManagerServiceTest { @Test public void dispatchOrder() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long deviceIdleUntil = mNowElapsedTest + 1234; final PendingIntent idleUntilPi = getNewMockPendingIntent(); Loading Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +83 −49 Original line number Diff line number Diff line Loading @@ -151,10 +151,10 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Random; import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Predicate; /** Loading Loading @@ -251,7 +251,6 @@ public class AlarmManagerService extends SystemService { Intent mTimeTickIntent; IAlarmListener mTimeTickTrigger; PendingIntent mDateChangeSender; Random mRandom; boolean mInteractive = true; long mNonInteractiveStartTime; long mNonInteractiveTime; Loading Loading @@ -516,6 +515,10 @@ public class AlarmManagerService extends SystemService { static final String KEY_PRIORITY_ALARM_DELAY = "priority_alarm_delay"; @VisibleForTesting static final String KEY_EXACT_ALARM_DENY_LIST = "exact_alarm_deny_list"; @VisibleForTesting static final String KEY_MIN_DEVICE_IDLE_FUZZ = "min_device_idle_fuzz"; @VisibleForTesting static final String KEY_MAX_DEVICE_IDLE_FUZZ = "max_device_idle_fuzz"; private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; Loading Loading @@ -556,6 +559,9 @@ public class AlarmManagerService extends SystemService { private static final long DEFAULT_PRIORITY_ALARM_DELAY = 9 * 60_000; private static final long DEFAULT_MIN_DEVICE_IDLE_FUZZ = 2 * 60_000; private static final long DEFAULT_MAX_DEVICE_IDLE_FUZZ = 15 * 60_000; // Minimum futurity of a new alarm public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; Loading Loading @@ -618,10 +624,23 @@ public class AlarmManagerService extends SystemService { public long PRIORITY_ALARM_DELAY = DEFAULT_PRIORITY_ALARM_DELAY; /** * Set of apps that won't get SCHEDULE_EXACT_ALARM when the app-op mode for * OP_SCHEDULE_EXACT_ALARM is MODE_DEFAULT. * Read-only set of apps that won't get SCHEDULE_EXACT_ALARM when the app-op mode for * OP_SCHEDULE_EXACT_ALARM is MODE_DEFAULT. Since this is read-only and volatile, this can * be accessed without synchronizing on {@link #mLock}. */ public volatile Set<String> EXACT_ALARM_DENY_LIST = Collections.emptySet(); /** * Minimum time interval that an IDLE_UNTIL will be pulled earlier to a subsequent * WAKE_FROM_IDLE alarm. */ public long MIN_DEVICE_IDLE_FUZZ = DEFAULT_MIN_DEVICE_IDLE_FUZZ; /** * Maximum time interval that an IDLE_UNTIL will be pulled earlier to a subsequent * WAKE_FROM_IDLE alarm. */ public Set<String> EXACT_ALARM_DENY_LIST = Collections.emptySet(); public long MAX_DEVICE_IDLE_FUZZ = DEFAULT_MAX_DEVICE_IDLE_FUZZ; private long mLastAllowWhileIdleWhitelistDuration = -1; private int mVersion = 0; Loading Loading @@ -660,6 +679,7 @@ public class AlarmManagerService extends SystemService { @Override public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) { boolean standbyQuotaUpdated = false; boolean deviceIdleFuzzBoundariesUpdated = false; synchronized (mLock) { mVersion++; for (String name : properties.getKeyset()) { Loading Loading @@ -787,6 +807,13 @@ public class AlarmManagerService extends SystemService { updateExactAlarmDenyList(values); } break; case KEY_MIN_DEVICE_IDLE_FUZZ: case KEY_MAX_DEVICE_IDLE_FUZZ: if (!deviceIdleFuzzBoundariesUpdated) { updateDeviceIdleFuzzBoundaries(); deviceIdleFuzzBoundariesUpdated = true; } break; default: if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) { // The quotas need to be updated in order, so we can't just rely Loading Loading @@ -824,6 +851,24 @@ public class AlarmManagerService extends SystemService { mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater); } private void updateDeviceIdleFuzzBoundaries() { final DeviceConfig.Properties properties = DeviceConfig.getProperties( DeviceConfig.NAMESPACE_ALARM_MANAGER, KEY_MIN_DEVICE_IDLE_FUZZ, KEY_MAX_DEVICE_IDLE_FUZZ); MIN_DEVICE_IDLE_FUZZ = properties.getLong(KEY_MIN_DEVICE_IDLE_FUZZ, DEFAULT_MIN_DEVICE_IDLE_FUZZ); MAX_DEVICE_IDLE_FUZZ = properties.getLong(KEY_MAX_DEVICE_IDLE_FUZZ, DEFAULT_MAX_DEVICE_IDLE_FUZZ); if (MAX_DEVICE_IDLE_FUZZ < MIN_DEVICE_IDLE_FUZZ) { Slog.w(TAG, "max_device_idle_fuzz cannot be smaller than" + " min_device_idle_fuzz! Increasing to " + MIN_DEVICE_IDLE_FUZZ); MAX_DEVICE_IDLE_FUZZ = MIN_DEVICE_IDLE_FUZZ; } } private void updateStandbyQuotasLocked() { // The bucket quotas need to be read as an atomic unit but the properties passed to // onPropertiesChanged may only have one key populated at a time. Loading Loading @@ -1133,12 +1178,8 @@ public class AlarmManagerService extends SystemService { if (mNextWakeFromIdle != null && isRtc(mNextWakeFromIdle.type)) { // The next wake from idle got updated due to the rtc time change, so we need // to update the time we have to come out of idle too. final boolean idleUntilUpdated = mAlarmStore.updateAlarmDeliveries(a -> { if (a != mPendingIdleUntil) { return false; } return adjustIdleUntilTime(a); }); final boolean idleUntilUpdated = mAlarmStore.updateAlarmDeliveries( a -> (a == mPendingIdleUntil) && adjustIdleUntilTime(a)); if (idleUntilUpdated) { mAlarmStore.updateAlarmDeliveries( alarm -> adjustDeliveryTimeBasedOnDeviceIdle(alarm)); Loading Loading @@ -1911,23 +1952,30 @@ public class AlarmManagerService extends SystemService { if ((alarm.flags & AlarmManager.FLAG_IDLE_UNTIL) == 0) { return false; } restoreRequestedTime(alarm); long triggerBeforeFuzz = alarm.getRequestedElapsed(); if (mNextWakeFromIdle != null && triggerBeforeFuzz > mNextWakeFromIdle.getWhenElapsed()) { triggerBeforeFuzz = mNextWakeFromIdle.getWhenElapsed(); final boolean changedBeforeFuzz = restoreRequestedTime(alarm); if (mNextWakeFromIdle == null) { // No need to change anything in the absence of a wake-from-idle request. return changedBeforeFuzz; } // Add fuzz to make the alarm go off some time before the actual desired time. final int fuzz = fuzzForDuration(alarm.getWhenElapsed() - mInjector.getElapsedRealtime()); final int delta; if (fuzz > 0) { if (mRandom == null) { mRandom = new Random(); final long upcomingWakeFromIdle = mNextWakeFromIdle.getWhenElapsed(); // Add fuzz to make the alarm go off some time before the next upcoming wake-from-idle, as // these alarms are usually wall-clock aligned. if (alarm.getWhenElapsed() < (upcomingWakeFromIdle - mConstants.MIN_DEVICE_IDLE_FUZZ)) { // No need to fuzz as this is already earlier than the coming wake-from-idle. return changedBeforeFuzz; } delta = mRandom.nextInt(fuzz); final long nowElapsed = mInjector.getElapsedRealtime(); final long futurity = upcomingWakeFromIdle - nowElapsed; if (futurity <= mConstants.MIN_DEVICE_IDLE_FUZZ) { // No point in fuzzing as the minimum fuzz will take the time in the past. alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, nowElapsed); } else { delta = 0; final ThreadLocalRandom random = ThreadLocalRandom.current(); final long upperBoundExcl = Math.min(mConstants.MAX_DEVICE_IDLE_FUZZ, futurity) + 1; final long fuzz = random.nextLong(mConstants.MIN_DEVICE_IDLE_FUZZ, upperBoundExcl); alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, upcomingWakeFromIdle - fuzz); } alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, triggerBeforeFuzz - delta); return true; } Loading Loading @@ -2130,12 +2178,8 @@ public class AlarmManagerService extends SystemService { // If this wake from idle is earlier than whatever was previously scheduled, // and we are currently idling, then the idle-until time needs to be updated. if (mPendingIdleUntil != null) { final boolean updated = mAlarmStore.updateAlarmDeliveries(alarm -> { if (alarm != mPendingIdleUntil) { return false; } return adjustIdleUntilTime(alarm); }); final boolean updated = mAlarmStore.updateAlarmDeliveries( alarm -> (alarm == mPendingIdleUntil) && adjustIdleUntilTime(alarm)); if (updated) { // idle-until got updated, so also update all alarms not allowed while idle. mAlarmStore.updateAlarmDeliveries( Loading Loading @@ -3675,20 +3719,6 @@ public class AlarmManagerService extends SystemService { } } int fuzzForDuration(long duration) { if (duration < 15 * 60 * 1000) { // If the duration until the time is less than 15 minutes, the maximum fuzz // is the duration. return (int) duration; } else if (duration < 90 * 60 * 1000) { // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes, return 15 * 60 * 1000; } else { // Otherwise, we will fuzz by at most half an hour. return 30 * 60 * 1000; } } boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) { if (mInteractive) { return false; Loading Loading @@ -4698,8 +4728,10 @@ public class AlarmManagerService extends SystemService { if (a.creatorUid != alarm.creatorUid || !isAllowedWhileIdleRestricted(a)) { return false; } return (doze && adjustDeliveryTimeBasedOnDeviceIdle(a)) || (batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a)); final boolean dozeAdjusted = doze && adjustDeliveryTimeBasedOnDeviceIdle(a); final boolean batterySaverAdjusted = batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a); return dozeAdjusted || batterySaverAdjusted; }); } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) { mLastPriorityAlarmDispatch.put(alarm.creatorUid, nowELAPSED); Loading @@ -4708,8 +4740,10 @@ public class AlarmManagerService extends SystemService { || (alarm.flags & FLAG_PRIORITIZE) == 0) { return false; } return (doze && adjustDeliveryTimeBasedOnDeviceIdle(a)) || (batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a)); final boolean dozeAdjusted = doze && adjustDeliveryTimeBasedOnDeviceIdle(a); final boolean batterySaverAdjusted = batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a); return dozeAdjusted || batterySaverAdjusted; }); } if (RECORD_DEVICE_IDLE_ALARMS) { Loading
apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java +32 −9 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.util.function.Predicate; public class LazyAlarmStore implements AlarmStore { @VisibleForTesting static final String TAG = LazyAlarmStore.class.getSimpleName(); private static final long ALARM_DEADLINE_SLOP = 500; private final ArrayList<Alarm> mAlarms = new ArrayList<>(); private Runnable mOnAlarmClockRemoved; Loading Loading @@ -75,7 +76,7 @@ public class LazyAlarmStore implements AlarmStore { return; } mAlarms.addAll(alarms); Collections.sort(alarms, sDecreasingTimeOrder); Collections.sort(mAlarms, sDecreasingTimeOrder); } @Override Loading Loading @@ -163,25 +164,47 @@ public class LazyAlarmStore implements AlarmStore { @Override public ArrayList<Alarm> removePendingAlarms(long nowElapsed) { final ArrayList<Alarm> pending = new ArrayList<>(); final ArrayList<Alarm> standAlones = new ArrayList<>(); // Only send wake-up alarms if this is the absolutely latest time we can evaluate // for at least one wakeup alarm. This prevents sending other non-wakeup alarms when the // screen is off but the CPU is awake for some reason. boolean sendWakeups = false; // If any alarm with FLAG_STANDALONE is present, we cannot send any alarms without that flag // in the present batch. boolean standalonesOnly = false; for (int i = mAlarms.size() - 1; i >= 0; i--) { final Alarm alarm = mAlarms.get(i); if (alarm.getWhenElapsed() > nowElapsed) { break; } mAlarms.remove(i); pending.add(alarm); if (alarm.wakeup && alarm.getMaxWhenElapsed() <= nowElapsed + ALARM_DEADLINE_SLOP) { // Using some slop as it is better to send the wakeup alarm now, rather than // waking up again a short time later, just to send it. sendWakeups = true; } if ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) { standAlones.add(alarm); standalonesOnly = true; } } if (!standAlones.isEmpty()) { // If there are deliverable standalone alarms, others must not go out yet. mAlarms.removeAll(standAlones); return standAlones; final ArrayList<Alarm> toSend = new ArrayList<>(); for (int i = pending.size() - 1; i >= 0; i--) { final Alarm pendingAlarm = pending.get(i); if (!sendWakeups && pendingAlarm.wakeup) { continue; } if (standalonesOnly && (pendingAlarm.flags & AlarmManager.FLAG_STANDALONE) == 0) { continue; } pending.remove(i); toSend.add(pendingAlarm); } mAlarms.removeAll(pending); return pending; // Perhaps some alarms could not be sent right now. Adding them back for later. addAll(pending); return toSend; } @Override Loading
services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +61 −18 Original line number Diff line number Diff line Loading @@ -71,7 +71,9 @@ import static com.android.server.alarm.AlarmManagerService.Constants.KEY_CRASH_N import static com.android.server.alarm.AlarmManagerService.Constants.KEY_EXACT_ALARM_DENY_LIST; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LAZY_BATCHING; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_DEVICE_IDLE_FUZZ; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_INTERVAL; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_DEVICE_IDLE_FUZZ; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_FUTURITY; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_INTERVAL; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_WINDOW; Loading Loading @@ -654,6 +656,8 @@ public class AlarmManagerServiceTest { setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 45); setDeviceConfigLong(KEY_MIN_WINDOW, 50); setDeviceConfigLong(KEY_PRIORITY_ALARM_DELAY, 55); setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, 60); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 65); assertEquals(5, mService.mConstants.MIN_FUTURITY); assertEquals(10, mService.mConstants.MIN_INTERVAL); assertEquals(15, mService.mConstants.MAX_INTERVAL); Loading @@ -665,6 +669,8 @@ public class AlarmManagerServiceTest { assertEquals(45, mService.mConstants.LISTENER_TIMEOUT); assertEquals(50, mService.mConstants.MIN_WINDOW); assertEquals(55, mService.mConstants.PRIORITY_ALARM_DELAY); assertEquals(60, mService.mConstants.MIN_DEVICE_IDLE_FUZZ); assertEquals(65, mService.mConstants.MAX_DEVICE_IDLE_FUZZ); } @Test Loading Loading @@ -736,6 +742,20 @@ public class AlarmManagerServiceTest { mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW); } @Test public void deviceIdleFuzzRangeNonNegative() { final long newMinFuzz = mService.mConstants.MAX_DEVICE_IDLE_FUZZ + 1542; final long newMaxFuzz = mService.mConstants.MIN_DEVICE_IDLE_FUZZ - 131; setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, newMinFuzz); assertTrue("Negative device-idle fuzz range", mService.mConstants.MAX_DEVICE_IDLE_FUZZ >= mService.mConstants.MIN_DEVICE_IDLE_FUZZ); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, newMaxFuzz); assertTrue("Negative device-idle fuzz range", mService.mConstants.MAX_DEVICE_IDLE_FUZZ >= mService.mConstants.MIN_DEVICE_IDLE_FUZZ); } @Test public void testMinFuturity() { setDeviceConfigLong(KEY_MIN_FUTURITY, 10L); Loading Loading @@ -1431,7 +1451,7 @@ public class AlarmManagerServiceTest { @Test public void singleIdleUntil() { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final PendingIntent idleUntilPi6 = getNewMockPendingIntent(); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, idleUntilPi6); Loading Loading @@ -1504,44 +1524,67 @@ public class AlarmManagerServiceTest { assertNull(mService.mNextWakeFromIdle); } private static void assertInRange(String message, long minIncl, long maxIncl, long val) { assertTrue(message, val >= minIncl && val <= maxIncl); } @Test public void idleUntilBeforeWakeFromIdle() { doReturn(0).when(mService).fuzzForDuration(anyLong()); public void idleUntilFuzzedBeforeWakeFromIdle() { final long minFuzz = 6; final long maxFuzz = 17; setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, minFuzz); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, maxFuzz); mNowElapsedTest = 119; // Arbitrary, just to ensure we are not testing on 0. final PendingIntent idleUntilPi = getNewMockPendingIntent(); final long requestedIdleUntil = mNowElapsedTest + 10; final long requestedIdleUntil = mNowElapsedTest + 12; setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, requestedIdleUntil, idleUntilPi); assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle5 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, wakeFromIdle5); assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); // Anything before now, gets snapped to now. It is not necessary for it to fire // immediately, just how it is implemented today for simplicity. assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle8 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, wakeFromIdle8); assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); // Next wake from idle is still the same. assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle12 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 12, wakeFromIdle12); assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed()); final PendingIntent wakeFromIdle19 = getNewMockPendingIntent(); setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 19, wakeFromIdle19); // Next wake from idle is still the same. assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); mService.removeLocked(wakeFromIdle5, null, REMOVE_REASON_UNDEFINED); assertEquals(mNowElapsedTest + 8, mService.mPendingIdleUntil.getWhenElapsed()); // Next wake from idle is at now + 8. long min = mNowElapsedTest; long max = mNowElapsedTest + 8 - minFuzz; assertInRange("Idle until alarm time not in expected range [" + min + ", " + max + "]", min, max, mService.mPendingIdleUntil.getWhenElapsed()); mService.removeLocked(wakeFromIdle8, null, REMOVE_REASON_UNDEFINED); // Next wake from idle is at now + 19, which is > minFuzz distance from // the requested idle until time: now + 12. assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); mService.removeLocked(idleUntilPi, null, REMOVE_REASON_UNDEFINED); assertNull(mService.mPendingIdleUntil); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 15, idleUntilPi); assertEquals(mNowElapsedTest + 12, mService.mPendingIdleUntil.getWhenElapsed()); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 21, idleUntilPi); // Next wake from idle is at now + 19, which means this alarm should get pulled back. min = mNowElapsedTest + 19 - maxFuzz; max = mNowElapsedTest + 19 - minFuzz; assertInRange("Idle until alarm time not in expected range [" + min + ", " + max + "]", min, max, mService.mPendingIdleUntil.getWhenElapsed()); } @Test public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + mAllowWhileIdleWindow + 1000, getNewMockPendingIntent()); Loading Loading @@ -1571,7 +1614,7 @@ public class AlarmManagerServiceTest { @Test public void allowWhileIdleUnrestricted() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); // Both battery saver and doze are on. setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000, Loading @@ -1597,7 +1640,7 @@ public class AlarmManagerServiceTest { @Test public void deviceIdleDeferralOnSet() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long deviceIdleUntil = mNowElapsedTest + 1234; setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, deviceIdleUntil, getNewMockPendingIntent()); Loading @@ -1622,7 +1665,7 @@ public class AlarmManagerServiceTest { @Test public void deviceIdleStateChanges() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final int numAlarms = 10; final PendingIntent[] pis = new PendingIntent[numAlarms]; Loading Loading @@ -1740,7 +1783,7 @@ public class AlarmManagerServiceTest { @Test public void prioritizedAlarmsInDeviceIdle() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long minDelay = 5; setDeviceConfigLong(KEY_PRIORITY_ALARM_DELAY, minDelay); Loading Loading @@ -1791,7 +1834,7 @@ public class AlarmManagerServiceTest { @Test public void dispatchOrder() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); final long deviceIdleUntil = mNowElapsedTest + 1234; final PendingIntent idleUntilPi = getNewMockPendingIntent(); Loading