am 5c3e277f: Fix bad alarm delivery
* commit '5c3e277fb42bd799287936c5aee0d30fbcc7e65c': Fix bad alarm delivery
This commit is contained in:
@@ -61,7 +61,6 @@ import java.util.Date;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import static android.app.AlarmManager.RTC_WAKEUP;
|
import static android.app.AlarmManager.RTC_WAKEUP;
|
||||||
@@ -109,12 +108,8 @@ class AlarmManagerService extends SystemService {
|
|||||||
final Object mLock = new Object();
|
final Object mLock = new Object();
|
||||||
|
|
||||||
long mNativeData;
|
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;
|
private long mNextNonWakeup;
|
||||||
|
|
||||||
int mBroadcastRefCount = 0;
|
int mBroadcastRefCount = 0;
|
||||||
PowerManager.WakeLock mWakeLock;
|
PowerManager.WakeLock mWakeLock;
|
||||||
boolean mLastWakeLockUnimportantForLogging;
|
boolean mLastWakeLockUnimportantForLogging;
|
||||||
@@ -366,27 +361,14 @@ class AlarmManagerService extends SystemService {
|
|||||||
|
|
||||||
static class BatchTimeOrder implements Comparator<Batch> {
|
static class BatchTimeOrder implements Comparator<Batch> {
|
||||||
public int compare(Batch b1, Batch b2) {
|
public int compare(Batch b1, Batch b2) {
|
||||||
final long start1 = b1.start;
|
long when1 = b1.start;
|
||||||
final long start2 = b2.start;
|
long when2 = b2.start;
|
||||||
if (start1 > start2) {
|
if (when1 - when2 > 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (start1 < start2) {
|
if (when1 - when2 < 0) {
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -609,7 +591,7 @@ class AlarmManagerService extends SystemService {
|
|||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
mNativeData = init();
|
mNativeData = init();
|
||||||
mNextWakeup = mNextWakeupBatchStart = mNextNonWakeup = 0;
|
mNextWakeup = mNextNonWakeup = 0;
|
||||||
|
|
||||||
// We have to set current TimeZone info to kernel
|
// We have to set current TimeZone info to kernel
|
||||||
// because kernel doesn't keep this after reboot
|
// because kernel doesn't keep this after reboot
|
||||||
@@ -804,7 +786,6 @@ class AlarmManagerService extends SystemService {
|
|||||||
"AlarmManager.set");
|
"AlarmManager.set");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exact alarms are standalone; inexact get batched together
|
|
||||||
setImpl(type, triggerAtTime, windowLength, interval, operation,
|
setImpl(type, triggerAtTime, windowLength, interval, operation,
|
||||||
windowLength == AlarmManager.WINDOW_EXACT, workSource, alarmClock);
|
windowLength == AlarmManager.WINDOW_EXACT, workSource, alarmClock);
|
||||||
}
|
}
|
||||||
@@ -877,7 +858,7 @@ class AlarmManagerService extends SystemService {
|
|||||||
|
|
||||||
pw.print("nowRTC="); pw.print(nowRTC);
|
pw.print("nowRTC="); pw.print(nowRTC);
|
||||||
pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
|
pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
|
||||||
pw.print(" nowELAPSED="); pw.print(nowELAPSED);
|
pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
|
||||||
pw.println();
|
pw.println();
|
||||||
if (!mInteractive) {
|
if (!mInteractive) {
|
||||||
pw.print("Time since non-interactive: ");
|
pw.print("Time since non-interactive: ");
|
||||||
@@ -1083,6 +1064,17 @@ class AlarmManagerService extends SystemService {
|
|||||||
return true;
|
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) {
|
private AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
return mNextAlarmClockForUser.get(userId);
|
return mNextAlarmClockForUser.get(userId);
|
||||||
@@ -1216,48 +1208,16 @@ class AlarmManagerService extends SystemService {
|
|||||||
// prior to that which contains no wakeups, we schedule that as well.
|
// prior to that which contains no wakeups, we schedule that as well.
|
||||||
long nextNonWakeup = 0;
|
long nextNonWakeup = 0;
|
||||||
if (mAlarmBatches.size() > 0) {
|
if (mAlarmBatches.size() > 0) {
|
||||||
// Find the first wakeup alarm and note the following batch as well. We'll be
|
final Batch firstWakeup = findFirstWakeupBatchLocked();
|
||||||
// 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);
|
final Batch firstBatch = mAlarmBatches.get(0);
|
||||||
if (firstWakeup != null && mNextWakeupBatchStart != firstWakeup.start) {
|
if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
|
||||||
mNextWakeupBatchStart = mNextWakeup = firstWakeup.start;
|
mNextWakeup = firstWakeup.start;
|
||||||
final long windowEnd = (nextAfterWakeup == null)
|
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
|
||||||
? 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) {
|
if (firstBatch != firstWakeup) {
|
||||||
nextNonWakeup = firstBatch.start;
|
nextNonWakeup = firstBatch.start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPendingNonWakeupAlarms.size() > 0) {
|
if (mPendingNonWakeupAlarms.size() > 0) {
|
||||||
if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
|
if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
|
||||||
nextNonWakeup = mNextNonWakeupDeliveryTime;
|
nextNonWakeup = mNextNonWakeupDeliveryTime;
|
||||||
|
|||||||
Reference in New Issue
Block a user