am 33ecc6e0: am b5c55da5: am b88ba912: Merge "Fix alarm delivery-order sorting" into lmp-dev

* commit '33ecc6e0fca154993ffab053f33296537adfb510':
  Fix alarm delivery-order sorting
This commit is contained in:
Christopher Tate
2014-10-03 21:43:16 +00:00
committed by Android Git Automerger

View File

@@ -58,6 +58,7 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.TimeZone;
@@ -141,6 +142,25 @@ class AlarmManagerService extends SystemService {
private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
new SparseArray<>();
// Alarm delivery ordering bookkeeping
static final int PRIO_TICK = 0;
static final int PRIO_WAKEUP = 1;
static final int PRIO_NORMAL = 2;
class PriorityClass {
int seq;
int priority;
PriorityClass() {
seq = mCurrentSeq - 1;
priority = PRIO_NORMAL;
}
}
final HashMap<String, PriorityClass> mPriorities =
new HashMap<String, PriorityClass>();
int mCurrentSeq = 0;
class WakeupEvent {
public long when;
public int uid;
@@ -356,22 +376,62 @@ class AlarmManagerService extends SystemService {
final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
@Override
public int compare(Alarm lhs, Alarm rhs) {
if ((!lhs.operation.getCreatorPackage().equals(rhs.operation.getCreatorPackage()))
&& lhs.wakeup != rhs.wakeup) {
// We want to put wakeup alarms before non-wakeup alarms, since they are
// the things that drive most activity in the alarm manager. However,
// alarms from the same package should always be ordered strictly by time.
return lhs.wakeup ? -1 : 1;
// priority class trumps everything. TICK < WAKEUP < NORMAL
if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
return -1;
} else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
return 1;
}
// within each class, sort by nominal delivery time
if (lhs.whenElapsed < rhs.whenElapsed) {
return -1;
} else if (lhs.whenElapsed > rhs.whenElapsed) {
return 1;
}
// same priority class + same target delivery time
return 0;
}
};
void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
final int N = alarms.size();
for (int i = 0; i < N; i++) {
Alarm a = alarms.get(i);
final int alarmPrio;
if (Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
alarmPrio = PRIO_TICK;
} else if (a.wakeup) {
alarmPrio = PRIO_WAKEUP;
} else {
alarmPrio = PRIO_NORMAL;
}
PriorityClass packagePrio = a.priorityClass;
if (packagePrio == null) packagePrio = mPriorities.get(a.operation.getCreatorPackage());
if (packagePrio == null) {
packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
mPriorities.put(a.operation.getCreatorPackage(), packagePrio);
}
a.priorityClass = packagePrio;
if (packagePrio.seq != mCurrentSeq) {
// first alarm we've seen in the current delivery generation from this package
packagePrio.priority = alarmPrio;
packagePrio.seq = mCurrentSeq;
} else {
// Multiple alarms from this package being delivered in this generation;
// bump the package's delivery class if it's warranted.
// TICK < WAKEUP < NORMAL
if (alarmPrio < packagePrio.priority) {
packagePrio.priority = alarmPrio;
}
}
}
}
// minimum recurrence period or alarm futurity for us to be able to fuzz it
static final long MIN_FUZZABLE_INTERVAL = 10000;
static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
@@ -1381,6 +1441,10 @@ class AlarmManagerService extends SystemService {
}
}
// This is a new alarm delivery set; bump the sequence number to indicate that
// all apps' alarm delivery classes should be recalculated.
mCurrentSeq++;
calculateDeliveryPriorities(triggerList);
Collections.sort(triggerList, mAlarmDispatchComparator);
if (localLOGV) {
@@ -1423,6 +1487,7 @@ class AlarmManagerService extends SystemService {
public long repeatInterval;
public final AlarmManager.AlarmClockInfo alarmClock;
public final int userId;
public PriorityClass priorityClass;
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws,
@@ -1676,6 +1741,7 @@ class AlarmManagerService extends SystemService {
rescheduleKernelAlarmsLocked();
updateNextAlarmClockLocked();
if (mPendingNonWakeupAlarms.size() > 0) {
calculateDeliveryPriorities(mPendingNonWakeupAlarms);
triggerList.addAll(mPendingNonWakeupAlarms);
Collections.sort(triggerList, mAlarmDispatchComparator);
final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
@@ -1889,6 +1955,7 @@ class AlarmManagerService extends SystemService {
if (pkgList != null && (pkgList.length > 0)) {
for (String pkg : pkgList) {
removeLocked(pkg);
mPriorities.remove(pkg);
for (int i=mBroadcastStats.size()-1; i>=0; i--) {
ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
if (uidStats.remove(pkg) != null) {