diff options
4 files changed, 53 insertions, 3 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index b6d29aa5641a..5b61f9abc357 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -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; } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java index f1e13dfcab5c..9c167728cff9 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java @@ -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 = diff --git a/services/core/java/com/android/server/utils/AlarmQueue.java b/services/core/java/com/android/server/utils/AlarmQueue.java index 3f4def6d60ab..41373cd6bbe6 100644 --- a/services/core/java/com/android/server/utils/AlarmQueue.java +++ b/services/core/java/com/android/server/utils/AlarmQueue.java @@ -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 diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/AlarmQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/AlarmQueueTest.java index 849e6730ac11..00d7541a79dc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/utils/AlarmQueueTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/utils/AlarmQueueTest.java @@ -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. |