summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Suprabh Shukla <suprabh@google.com> 2021-05-03 19:46:34 -0700
committer Suprabh Shukla <suprabh@google.com> 2021-05-04 19:37:40 -0700
commit74b85211fa12e3e0585fb538f313c234c3e0c27b (patch)
treed3caa73bc6175756b01bf665fe8cbf221dc668dd
parent54df750079167360102da81ab7b77582a67190e9 (diff)
Hold wakeup alarms for as long as possible
If the screen is off, but the CPU is awake and epoll_wait returns for a non-wakeup alarm, sending any wakeup alarm within its eligibility window would cause all the held non-wakeup alarms to also fire, which could: 1. Elongate the length of the time the CPU is awake. 2. Cause apps to wake up and perform work. This change defers sending any wakeup alarm as long as it is possible to defer all such eligible alarms to later. Also, fixed a bug in sorting after adding multiple alarms to the store. Test: atest CtsAlarmManagerTestCases atest FrameworksMockingServicesTests:com.android.server.alarm Bug: 161497385 Change-Id: I01f98255091baddf4e7529f88733776e27d090d7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java41
1 files changed, 32 insertions, 9 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java
index 2e12e2f34ea0..0073335a1332 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java
@@ -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;
@@ -75,7 +76,7 @@ public class LazyAlarmStore implements AlarmStore {
return;
}
mAlarms.addAll(alarms);
- Collections.sort(alarms, sDecreasingTimeOrder);
+ Collections.sort(mAlarms, sDecreasingTimeOrder);
}
@Override
@@ -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