Add a way to disable non-wakeup alarm deferral.
AlarmManager normally delays non-wakeup alarms when the screen is off. However, tests that depend on components that want to use non-wakeup alarms while the screen is off will be flaky with this deferral. Make it possible to disable the deferral for tests. We may also decide to disable this behavior altogether, so use DeviceConfig to allow experimentation. Also fix long comparison overflow issue in AlarmQueue. Bug: 245987711 Test: atest CtsJobSchedulerTestCases:FlexibilityConstraintTest Test: atest FrameworksMockingServicesTests:AlarmQueueTest Change-Id: I35f1299d551eb7099adfecd13449f53fef88de02
This commit is contained in:
@@ -676,6 +676,9 @@ public class AlarmManagerService extends SystemService {
|
||||
private static final String KEY_TIME_TICK_ALLOWED_WHILE_IDLE =
|
||||
"time_tick_allowed_while_idle";
|
||||
|
||||
private static final String KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF =
|
||||
"delay_nonwakeup_alarms_while_screen_off";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_ALLOW_WHILE_IDLE_QUOTA = "allow_while_idle_quota";
|
||||
|
||||
@@ -743,6 +746,8 @@ public class AlarmManagerService extends SystemService {
|
||||
|
||||
private static final int DEFAULT_TEMPORARY_QUOTA_BUMP = 0;
|
||||
|
||||
private static final boolean DEFAULT_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF = true;
|
||||
|
||||
// Minimum futurity of a new alarm
|
||||
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
|
||||
|
||||
@@ -835,6 +840,9 @@ public class AlarmManagerService extends SystemService {
|
||||
*/
|
||||
public int TEMPORARY_QUOTA_BUMP = DEFAULT_TEMPORARY_QUOTA_BUMP;
|
||||
|
||||
public boolean DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF =
|
||||
DEFAULT_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF;
|
||||
|
||||
private long mLastAllowWhileIdleWhitelistDuration = -1;
|
||||
private int mVersion = 0;
|
||||
|
||||
@@ -1011,6 +1019,11 @@ public class AlarmManagerService extends SystemService {
|
||||
TEMPORARY_QUOTA_BUMP = properties.getInt(KEY_TEMPORARY_QUOTA_BUMP,
|
||||
DEFAULT_TEMPORARY_QUOTA_BUMP);
|
||||
break;
|
||||
case KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF:
|
||||
DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF = properties.getBoolean(
|
||||
KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF,
|
||||
DEFAULT_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF);
|
||||
break;
|
||||
default:
|
||||
if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
|
||||
// The quotas need to be updated in order, so we can't just rely
|
||||
@@ -1249,6 +1262,10 @@ public class AlarmManagerService extends SystemService {
|
||||
pw.print(KEY_TEMPORARY_QUOTA_BUMP, TEMPORARY_QUOTA_BUMP);
|
||||
pw.println();
|
||||
|
||||
pw.print(KEY_DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF,
|
||||
DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF);
|
||||
pw.println();
|
||||
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
|
||||
@@ -4360,7 +4377,11 @@ public class AlarmManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
|
||||
if (!mConstants.DELAY_NONWAKEUP_ALARMS_WHILE_SCREEN_OFF) {
|
||||
return false;
|
||||
}
|
||||
if (mInteractive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@ public final class FlexibilityController extends StateController {
|
||||
static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE =
|
||||
FC_CONFIG_PREFIX + "fallback_flexibility_deadline_ms";
|
||||
static final String KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS =
|
||||
FC_CONFIG_PREFIX + "min_alarm_time_flexibility_ms";
|
||||
FC_CONFIG_PREFIX + "min_time_between_flexibility_alarms_ms";
|
||||
static final String KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS =
|
||||
FC_CONFIG_PREFIX + "percents_to_drop_num_flexible_constraints";
|
||||
static final String KEY_MAX_RESCHEDULED_DEADLINE_MS =
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.util.Slog;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -52,6 +53,11 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final long NOT_SCHEDULED = -1;
|
||||
/**
|
||||
* The threshold used to consider a new trigger time to be significantly different from the
|
||||
* currently used trigger time.
|
||||
*/
|
||||
private static final long SIGNIFICANT_TRIGGER_TIME_CHANGE_THRESHOLD_MS = MINUTE_IN_MILLIS;
|
||||
|
||||
/**
|
||||
* Internal priority queue for each key's alarm, ordered by the time the alarm should go off.
|
||||
@@ -59,7 +65,7 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
|
||||
*/
|
||||
private static class AlarmPriorityQueue<Q> extends PriorityQueue<Pair<Q, Long>> {
|
||||
AlarmPriorityQueue() {
|
||||
super(1, (o1, o2) -> (int) (o1.second - o2.second));
|
||||
super(1, Comparator.comparingLong(o -> o.second));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,8 +312,10 @@ public abstract class AlarmQueue<K> implements AlarmManager.OnAlarmListener {
|
||||
// earlier but not significantly so, then we essentially delay the check for some
|
||||
// apps by up to a minute.
|
||||
// 3. The alarm is after the current alarm.
|
||||
final long timeShiftThresholdMs =
|
||||
Math.min(SIGNIFICANT_TRIGGER_TIME_CHANGE_THRESHOLD_MS, mMinTimeBetweenAlarmsMs);
|
||||
if (mTriggerTimeElapsed == NOT_SCHEDULED
|
||||
|| nextTriggerTimeElapsed < mTriggerTimeElapsed - MINUTE_IN_MILLIS
|
||||
|| nextTriggerTimeElapsed < mTriggerTimeElapsed - timeShiftThresholdMs
|
||||
|| mTriggerTimeElapsed < nextTriggerTimeElapsed) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Scheduling alarm at " + nextTriggerTimeElapsed
|
||||
|
||||
@@ -155,6 +155,27 @@ public class AlarmQueueTest {
|
||||
anyInt(), eq(nowElapsed + HOUR_IN_MILLIS), eq(ALARM_TAG), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingLargeAlarmTimes() {
|
||||
final AlarmQueue<String> alarmQueue = createAlarmQueue(true, 0);
|
||||
final long nowElapsed = mInjector.getElapsedRealtime();
|
||||
|
||||
InOrder inOrder = inOrder(mAlarmManager);
|
||||
|
||||
alarmQueue.addAlarm("com.android.test.1", Long.MAX_VALUE - 5);
|
||||
inOrder.verify(mAlarmManager, timeout(1000).times(1))
|
||||
.setExact(anyInt(), eq(Long.MAX_VALUE - 5), eq(ALARM_TAG), any(), any());
|
||||
alarmQueue.addAlarm("com.android.test.2", Long.MAX_VALUE - 4);
|
||||
inOrder.verify(mAlarmManager, never())
|
||||
.setExact(anyInt(), anyLong(), eq(ALARM_TAG), any(), any());
|
||||
alarmQueue.addAlarm("com.android.test.3", nowElapsed + 5);
|
||||
inOrder.verify(mAlarmManager, timeout(1000).times(1))
|
||||
.setExact(anyInt(), eq(nowElapsed + 5), eq(ALARM_TAG), any(), any());
|
||||
alarmQueue.addAlarm("com.android.test.4", nowElapsed + 6);
|
||||
inOrder.verify(mAlarmManager, never())
|
||||
.setExact(anyInt(), anyLong(), eq(ALARM_TAG), any(), any());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that updating the alarm time for a key will result in the AlarmManager alarm changing,
|
||||
* if needed.
|
||||
|
||||
Reference in New Issue
Block a user