Skip to content

Commit

Permalink
Tune delivery and batching of alarms
Browse files Browse the repository at this point in the history
cherry-pick from lmp-mr1-dev

* Inexact alarms no longer coalesce with exact alarms.  The motivation here
is that exact alarms are far more likely to be wall-clock aligned, and in
general pulling all alarms toward wall-clock alignment is a bad idea.

* Wakeup times are now fuzzed within the target batch's allowed window
rather than being hard pinned at the start of the window.

Bug 18631821

Change-Id: Iefaf34eee3f2a6546abefc27e177ee2fdcff935f
(cherry picked from commit 81f9882)
  • Loading branch information
Christopher Tate authored and The Android Automerger committed Dec 12, 2014
1 parent 5a995f9 commit a6e7e6b
Showing 1 changed file with 63 additions and 23 deletions.
86 changes: 63 additions & 23 deletions services/core/java/com/android/server/AlarmManagerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Random;
import java.util.TimeZone;

import static android.app.AlarmManager.RTC_WAKEUP;
Expand Down Expand Up @@ -108,8 +109,12 @@ class AlarmManagerService extends SystemService {
final Object mLock = new Object();

long mNativeData;
private long mNextWakeup;

private final Random mFuzzer = new Random();
private long mNextWakeupBatchStart; // nominal start of next wakeup's delivery window
private long mNextWakeup; // actual scheduled next wakeup within that window
private long mNextNonWakeup;

int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
boolean mLastWakeLockUnimportantForLogging;
Expand Down Expand Up @@ -361,14 +366,27 @@ public String toString() {

static class BatchTimeOrder implements Comparator<Batch> {
public int compare(Batch b1, Batch b2) {
long when1 = b1.start;
long when2 = b2.start;
if (when1 - when2 > 0) {
final long start1 = b1.start;
final long start2 = b2.start;
if (start1 > start2) {
return 1;
}
if (when1 - when2 < 0) {
if (start1 < start2) {
return -1;
}

// Identical trigger times. As a secondary ordering, require that
// the batch with the shorter allowable delivery window sorts first.
final long interval1 = b1.end - b1.start;
final long interval2 = b2.end - b2.start;
if (interval1 > interval2) {
return 1;
}
if (interval2 < interval1) {
return -1;
}

// equal start + delivery window => they're identical
return 0;
}
}
Expand Down Expand Up @@ -591,7 +609,7 @@ static final class BroadcastStats {
@Override
public void onStart() {
mNativeData = init();
mNextWakeup = mNextNonWakeup = 0;
mNextWakeup = mNextWakeupBatchStart = mNextNonWakeup = 0;

// We have to set current TimeZone info to kernel
// because kernel doesn't keep this after reboot
Expand Down Expand Up @@ -786,8 +804,9 @@ public void set(int type, long triggerAtTime, long windowLength, long interval,
"AlarmManager.set");
}

// Exact alarms are standalone; inexact get batched together
setImpl(type, triggerAtTime, windowLength, interval, operation,
false, workSource, alarmClock);
windowLength == AlarmManager.WINDOW_EXACT, workSource, alarmClock);
}

@Override
Expand Down Expand Up @@ -858,7 +877,7 @@ void dumpImpl(PrintWriter pw) {

pw.print("nowRTC="); pw.print(nowRTC);
pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
pw.print(" nowELAPSED="); pw.print(nowELAPSED);
pw.println();
if (!mInteractive) {
pw.print("Time since non-interactive: ");
Expand Down Expand Up @@ -1064,17 +1083,6 @@ private boolean validateConsistencyLocked() {
return true;
}

private Batch findFirstWakeupBatchLocked() {
final int N = mAlarmBatches.size();
for (int i = 0; i < N; i++) {
Batch b = mAlarmBatches.get(i);
if (b.hasWakeups()) {
return b;
}
}
return null;
}

private AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
synchronized (mLock) {
return mNextAlarmClockForUser.get(userId);
Expand Down Expand Up @@ -1208,16 +1216,48 @@ void rescheduleKernelAlarmsLocked() {
// prior to that which contains no wakeups, we schedule that as well.
long nextNonWakeup = 0;
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
// Find the first wakeup alarm and note the following batch as well. We'll be
// choosing a fuzzed delivery time within the first's allowable interval but
// ensuring that it does not encroach on the second's start time, to minimize
// alarm reordering.
Batch firstWakeup = null, nextAfterWakeup = null;
final int N = mAlarmBatches.size();
for (int i = 0; i < N; i++) {
Batch b = mAlarmBatches.get(i);
if (b.hasWakeups()) {
firstWakeup = b;
if (i < N-1) {
nextAfterWakeup = mAlarmBatches.get(i+1);
}
break;
}
}

// There's a subtlety here: we depend on the invariant that if two batches
// exist with the same start time, the one with the shorter delivery window
// is sorted before the other. This guarantees us that we need only look
// at the first [relevant] batch in the queue in order to schedule an alarm
// appropriately.
final Batch firstBatch = mAlarmBatches.get(0);
if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
mNextWakeup = firstWakeup.start;
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
if (firstWakeup != null && mNextWakeupBatchStart != firstWakeup.start) {
mNextWakeupBatchStart = mNextWakeup = firstWakeup.start;
final long windowEnd = (nextAfterWakeup == null)
? firstWakeup.end
: Math.min(firstWakeup.end, nextAfterWakeup.start);
final long interval = windowEnd - firstWakeup.start;
// if the interval is over maxint we're into crazy land anyway, but
// just in case we check and don't fuzz if the conversion to int for
// random-number purposes would blow up
if (interval > 0 && interval < Integer.MAX_VALUE) {
mNextWakeup += mFuzzer.nextInt((int) interval);
}
setLocked(ELAPSED_REALTIME_WAKEUP, mNextWakeup);
}
if (firstBatch != firstWakeup) {
nextNonWakeup = firstBatch.start;
}
}

if (mPendingNonWakeupAlarms.size() > 0) {
if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
nextNonWakeup = mNextNonWakeupDeliveryTime;
Expand Down

0 comments on commit a6e7e6b

Please sign in to comment.