Don't let batch coalescing / rewindowing break batch ordering
Bug 9965704
Change-Id: I41819bd1da16cc61c54938ed4ddd421f15b56fbb
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index d7cdb9d..d0b98ae 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -353,15 +353,16 @@
return (index == 0);
}
- Batch attemptCoalesceLocked(long whenElapsed, long maxWhen) {
+ // Return the index of the matching batch, or -1 if none found.
+ int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
final int N = mAlarmBatches.size();
for (int i = 0; i < N; i++) {
Batch b = mAlarmBatches.get(i);
if (!b.standalone && b.canHold(whenElapsed, maxWhen)) {
- return b;
+ return i;
}
}
- return null;
+ return -1;
}
// The RTC clock has moved arbitrarily, so we need to recalculate all the batching
@@ -553,16 +554,23 @@
removeLocked(operation);
final boolean reschedule;
- Batch batch = (isStandalone) ? null : attemptCoalesceLocked(whenElapsed, maxWhen);
- if (batch == null) {
- batch = new Batch(a);
+ int whichBatch = (isStandalone) ? -1 : attemptCoalesceLocked(whenElapsed, maxWhen);
+ if (whichBatch < 0) {
+ Batch batch = new Batch(a);
batch.standalone = isStandalone;
if (DEBUG_BATCH) {
Slog.v(TAG, "Starting new alarm batch " + batch);
}
reschedule = addBatchLocked(mAlarmBatches, batch);
} else {
+ Batch batch = mAlarmBatches.get(whichBatch);
reschedule = batch.add(a);
+ if (reschedule) {
+ // The start time of this batch advanced, so batch ordering may
+ // have just been broken. Move it to where it now belongs.
+ mAlarmBatches.remove(whichBatch);
+ addBatchLocked(mAlarmBatches, batch);
+ }
}
if (reschedule) {
@@ -1058,6 +1066,9 @@
triggerList.clear();
if ((result & TIME_CHANGED_MASK) != 0) {
+ if (DEBUG_BATCH) {
+ Slog.v(TAG, "Time changed notification from kernel");
+ }
remove(mTimeTickSender);
rebatchAllAlarms();
mClockReceiver.scheduleTimeTickEvent();
@@ -1211,7 +1222,10 @@
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
- scheduleTimeTickEvent();
+ if (DEBUG_BATCH) {
+ Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
+ }
+ scheduleTimeTickEvent();
} else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
// Since the kernel does not keep track of DST, we need to
// reset the TZ information at the beginning of each day
@@ -1220,7 +1234,7 @@
TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
int gmtOffset = zone.getOffset(System.currentTimeMillis());
setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
- scheduleDateChangedEvent();
+ scheduleDateChangedEvent();
}
}
@@ -1235,7 +1249,7 @@
set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
0, mTimeTickSender, true);
}
-
+
public void scheduleDateChangedEvent() {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());