Fix alarm throttling.

Alarm throttling wasn't happening if the queue became empty before a new
alarm was scheduled. This fixes that so the min time between alarms is
always enforced.

Bug: 288975061
Test: atest FrameworksMockingServicesTests:AlarmQueueTest
Change-Id: Id01bcf4e7d53ae7d89c99cb7f97b86163c43ea88
(cherry picked from commit ef46dcbc56)
This commit is contained in:
Kweku Adams
2023-06-28 19:21:04 +00:00
parent d2a48276fe
commit 84235dab59
2 changed files with 29 additions and 1 deletions

View File

@@ -151,6 +151,10 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
@GuardedBy("mLock")
@ElapsedRealtimeLong
private long mTriggerTimeElapsed = NOT_SCHEDULED;
/** The last time an alarm went off (ie. the last time {@link #onAlarm()} was called}). */
@GuardedBy("mLock")
@ElapsedRealtimeLong
private long mLastFireTimeElapsed;
/**
* @param alarmTag The tag to use when scheduling the alarm with AlarmManager.
@@ -284,7 +288,7 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
/** Sets an alarm with {@link AlarmManager} for the earliest alarm in the queue after now. */
@GuardedBy("mLock")
private void setNextAlarmLocked() {
setNextAlarmLocked(mInjector.getElapsedRealtime());
setNextAlarmLocked(mLastFireTimeElapsed + mMinTimeBetweenAlarmsMs);
}
/**
@@ -334,6 +338,7 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
final ArraySet<K> expired = new ArraySet<>();
synchronized (mLock) {
final long nowElapsed = mInjector.getElapsedRealtime();
mLastFireTimeElapsed = nowElapsed;
while (mAlarmPriorityQueue.size() > 0) {
final Pair<K, Long> alarm = mAlarmPriorityQueue.peek();
if (alarm.second <= nowElapsed) {

View File

@@ -258,6 +258,29 @@ public class AlarmQueueTest {
anyInt(), eq(nowElapsed + 5 * HOUR_IN_MILLIS), eq(ALARM_TAG), any(), any());
}
@Test
public void testMinTimeBetweenAlarms_freshAlarm() {
final AlarmQueue<String> alarmQueue = createAlarmQueue(true, 5 * MINUTE_IN_MILLIS);
final long fixedTimeElapsed = mInjector.getElapsedRealtime();
InOrder inOrder = inOrder(mAlarmManager);
final String pkg1 = "com.android.test.1";
final String pkg2 = "com.android.test.2";
alarmQueue.addAlarm(pkg1, fixedTimeElapsed + MINUTE_IN_MILLIS);
inOrder.verify(mAlarmManager, timeout(1000).times(1)).setExact(
anyInt(), eq(fixedTimeElapsed + MINUTE_IN_MILLIS), eq(ALARM_TAG), any(), any());
advanceElapsedClock(MINUTE_IN_MILLIS);
alarmQueue.onAlarm();
// Minimum of 5 minutes between alarms, so the next alarm should be 5 minutes after the
// first.
alarmQueue.addAlarm(pkg2, fixedTimeElapsed + 2 * MINUTE_IN_MILLIS);
inOrder.verify(mAlarmManager, timeout(1000).times(1)).setExact(
anyInt(), eq(fixedTimeElapsed + 6 * MINUTE_IN_MILLIS), eq(ALARM_TAG), any(), any());
}
@Test
public void testOnAlarm() {
final AlarmQueue<String> alarmQueue = createAlarmQueue(true, 0);