am b88ba912: Merge "Fix alarm delivery-order sorting" into lmp-dev
* commit 'b88ba912f6bb2fd0ae16794470cce38ee308b6ea': Fix alarm delivery-order sorting
This commit is contained in:
@@ -58,6 +58,7 @@ import java.util.Calendar;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@@ -141,6 +142,25 @@ class AlarmManagerService extends SystemService {
|
|||||||
private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
|
private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
|
||||||
new SparseArray<>();
|
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 {
|
class WakeupEvent {
|
||||||
public long when;
|
public long when;
|
||||||
public int uid;
|
public int uid;
|
||||||
@@ -356,22 +376,62 @@ class AlarmManagerService extends SystemService {
|
|||||||
final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
|
final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(Alarm lhs, Alarm rhs) {
|
public int compare(Alarm lhs, Alarm rhs) {
|
||||||
if ((!lhs.operation.getCreatorPackage().equals(rhs.operation.getCreatorPackage()))
|
// priority class trumps everything. TICK < WAKEUP < NORMAL
|
||||||
&& lhs.wakeup != rhs.wakeup) {
|
if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
|
||||||
// We want to put wakeup alarms before non-wakeup alarms, since they are
|
return -1;
|
||||||
// the things that drive most activity in the alarm manager. However,
|
} else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
|
||||||
// alarms from the same package should always be ordered strictly by time.
|
return 1;
|
||||||
return lhs.wakeup ? -1 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// within each class, sort by nominal delivery time
|
||||||
if (lhs.whenElapsed < rhs.whenElapsed) {
|
if (lhs.whenElapsed < rhs.whenElapsed) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (lhs.whenElapsed > rhs.whenElapsed) {
|
} else if (lhs.whenElapsed > rhs.whenElapsed) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// same priority class + same target delivery time
|
||||||
return 0;
|
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
|
// minimum recurrence period or alarm futurity for us to be able to fuzz it
|
||||||
static final long MIN_FUZZABLE_INTERVAL = 10000;
|
static final long MIN_FUZZABLE_INTERVAL = 10000;
|
||||||
static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
|
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);
|
Collections.sort(triggerList, mAlarmDispatchComparator);
|
||||||
|
|
||||||
if (localLOGV) {
|
if (localLOGV) {
|
||||||
@@ -1423,6 +1487,7 @@ class AlarmManagerService extends SystemService {
|
|||||||
public long repeatInterval;
|
public long repeatInterval;
|
||||||
public final AlarmManager.AlarmClockInfo alarmClock;
|
public final AlarmManager.AlarmClockInfo alarmClock;
|
||||||
public final int userId;
|
public final int userId;
|
||||||
|
public PriorityClass priorityClass;
|
||||||
|
|
||||||
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
|
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
|
||||||
long _interval, PendingIntent _op, WorkSource _ws,
|
long _interval, PendingIntent _op, WorkSource _ws,
|
||||||
@@ -1676,6 +1741,7 @@ class AlarmManagerService extends SystemService {
|
|||||||
rescheduleKernelAlarmsLocked();
|
rescheduleKernelAlarmsLocked();
|
||||||
updateNextAlarmClockLocked();
|
updateNextAlarmClockLocked();
|
||||||
if (mPendingNonWakeupAlarms.size() > 0) {
|
if (mPendingNonWakeupAlarms.size() > 0) {
|
||||||
|
calculateDeliveryPriorities(mPendingNonWakeupAlarms);
|
||||||
triggerList.addAll(mPendingNonWakeupAlarms);
|
triggerList.addAll(mPendingNonWakeupAlarms);
|
||||||
Collections.sort(triggerList, mAlarmDispatchComparator);
|
Collections.sort(triggerList, mAlarmDispatchComparator);
|
||||||
final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
|
final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
|
||||||
@@ -1889,6 +1955,7 @@ class AlarmManagerService extends SystemService {
|
|||||||
if (pkgList != null && (pkgList.length > 0)) {
|
if (pkgList != null && (pkgList.length > 0)) {
|
||||||
for (String pkg : pkgList) {
|
for (String pkg : pkgList) {
|
||||||
removeLocked(pkg);
|
removeLocked(pkg);
|
||||||
|
mPriorities.remove(pkg);
|
||||||
for (int i=mBroadcastStats.size()-1; i>=0; i--) {
|
for (int i=mBroadcastStats.size()-1; i>=0; i--) {
|
||||||
ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
|
ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
|
||||||
if (uidStats.remove(pkg) != null) {
|
if (uidStats.remove(pkg) != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user