am c6dcce24: am c6e2ab79: am 1260584f: Merge "Rework the task affiliate chain validation" into lmp-dev
* commit 'c6dcce24e71ad577287ddb446d7ce83d4e5869be': Rework the task affiliate chain validation
This commit is contained in:
@@ -413,7 +413,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
* List of intents that were used to start the most recent tasks.
|
||||
*/
|
||||
ArrayList<TaskRecord> mRecentTasks;
|
||||
ArraySet<TaskRecord> mTmpRecents = new ArraySet<TaskRecord>();
|
||||
ArrayList<TaskRecord> mTmpRecents = new ArrayList<TaskRecord>();
|
||||
|
||||
/**
|
||||
* For addAppTask: cached of the last activity component that was added.
|
||||
@@ -3857,6 +3857,86 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
mTaskPersister.wakeup(null, true);
|
||||
}
|
||||
|
||||
// Sort by taskId
|
||||
private Comparator<TaskRecord> mTaskRecordComparator = new Comparator<TaskRecord>() {
|
||||
@Override
|
||||
public int compare(TaskRecord lhs, TaskRecord rhs) {
|
||||
return rhs.taskId - lhs.taskId;
|
||||
}
|
||||
};
|
||||
|
||||
// Extract the affiliates of the chain containing mRecentTasks[start].
|
||||
private int processNextAffiliateChain(int start) {
|
||||
final TaskRecord startTask = mRecentTasks.get(start);
|
||||
final int affiliateId = startTask.mAffiliatedTaskId;
|
||||
|
||||
// Quick identification of isolated tasks. I.e. those not launched behind.
|
||||
if (startTask.taskId == affiliateId && startTask.mPrevAffiliate == null &&
|
||||
startTask.mNextAffiliate == null) {
|
||||
// There is still a slim chance that there are other tasks that point to this task
|
||||
// and that the chain is so messed up that this task no longer points to them but
|
||||
// the gain of this optimization outweighs the risk.
|
||||
startTask.inRecents = true;
|
||||
return start + 1;
|
||||
}
|
||||
|
||||
// Remove all tasks that are affiliated to affiliateId and put them in mTmpRecents.
|
||||
mTmpRecents.clear();
|
||||
for (int i = mRecentTasks.size() - 1; i >= start; --i) {
|
||||
final TaskRecord task = mRecentTasks.get(i);
|
||||
if (task.mAffiliatedTaskId == affiliateId) {
|
||||
mRecentTasks.remove(i);
|
||||
mTmpRecents.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort them all by taskId. That is the order they were create in and that order will
|
||||
// always be correct.
|
||||
Collections.sort(mTmpRecents, mTaskRecordComparator);
|
||||
|
||||
// Go through and fix up the linked list.
|
||||
// The first one is the end of the chain and has no next.
|
||||
final TaskRecord first = mTmpRecents.get(0);
|
||||
first.inRecents = true;
|
||||
if (first.mNextAffiliate != null) {
|
||||
Slog.w(TAG, "Link error 1 first.next=" + first.mNextAffiliate);
|
||||
first.setNextAffiliate(null);
|
||||
mTaskPersister.wakeup(first, false);
|
||||
}
|
||||
// Everything in the middle is doubly linked from next to prev.
|
||||
final int tmpSize = mTmpRecents.size();
|
||||
for (int i = 0; i < tmpSize - 1; ++i) {
|
||||
final TaskRecord next = mTmpRecents.get(i);
|
||||
final TaskRecord prev = mTmpRecents.get(i + 1);
|
||||
if (next.mPrevAffiliate != prev) {
|
||||
Slog.w(TAG, "Link error 2 next=" + next + " prev=" + next.mPrevAffiliate +
|
||||
" setting prev=" + prev);
|
||||
next.setPrevAffiliate(prev);
|
||||
mTaskPersister.wakeup(next, false);
|
||||
}
|
||||
if (prev.mNextAffiliate != next) {
|
||||
Slog.w(TAG, "Link error 3 prev=" + prev + " next=" + prev.mNextAffiliate +
|
||||
" setting next=" + next);
|
||||
prev.setNextAffiliate(next);
|
||||
mTaskPersister.wakeup(prev, false);
|
||||
}
|
||||
prev.inRecents = true;
|
||||
}
|
||||
// The last one is the beginning of the list and has no prev.
|
||||
final TaskRecord last = mTmpRecents.get(tmpSize - 1);
|
||||
if (last.mPrevAffiliate != null) {
|
||||
Slog.w(TAG, "Link error 4 last.prev=" + last.mPrevAffiliate);
|
||||
last.setPrevAffiliate(null);
|
||||
mTaskPersister.wakeup(last, false);
|
||||
}
|
||||
|
||||
// Insert the group back into mRecentTasks at start.
|
||||
mRecentTasks.addAll(start, mTmpRecents);
|
||||
|
||||
// Let the caller know where we left off.
|
||||
return start + tmpSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the recent tasks lists: make sure tasks should still be here (their
|
||||
* applications / activities still exist), update their availability, fixup ordering
|
||||
@@ -3969,51 +4049,9 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
|
||||
// Verify the affiliate chain for each task.
|
||||
for (int i = 0; i < N; ) {
|
||||
TaskRecord task = mRecentTasks.remove(i);
|
||||
if (mTmpRecents.contains(task)) {
|
||||
continue;
|
||||
}
|
||||
int affiliatedTaskId = task.mAffiliatedTaskId;
|
||||
while (true) {
|
||||
TaskRecord next = task.mNextAffiliate;
|
||||
if (next == null) {
|
||||
break;
|
||||
}
|
||||
if (next.mAffiliatedTaskId != affiliatedTaskId) {
|
||||
Slog.e(TAG, "Error in Recents: next.affiliatedTaskId=" +
|
||||
next.mAffiliatedTaskId + " affiliatedTaskId=" + affiliatedTaskId);
|
||||
task.setNextAffiliate(null);
|
||||
if (next.mPrevAffiliate == task) {
|
||||
next.setPrevAffiliate(null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (next.mPrevAffiliate != task) {
|
||||
Slog.e(TAG, "Error in Recents chain prev.mNextAffiliate=" +
|
||||
next.mPrevAffiliate + " task=" + task);
|
||||
next.setPrevAffiliate(null);
|
||||
task.setNextAffiliate(null);
|
||||
break;
|
||||
}
|
||||
if (!mRecentTasks.contains(next)) {
|
||||
Slog.e(TAG, "Error in Recents: next=" + next + " not in mRecentTasks");
|
||||
task.setNextAffiliate(null);
|
||||
// We know that next.mPrevAffiliate is always task, from above, so clear
|
||||
// its previous affiliate.
|
||||
next.setPrevAffiliate(null);
|
||||
break;
|
||||
}
|
||||
task = next;
|
||||
}
|
||||
// task is now the end of the list
|
||||
do {
|
||||
mRecentTasks.remove(task);
|
||||
mRecentTasks.add(i++, task);
|
||||
mTmpRecents.add(task);
|
||||
task.inRecents = true;
|
||||
} while ((task = task.mPrevAffiliate) != null);
|
||||
for (int i = 0; i < N; i = processNextAffiliateChain(i)) {
|
||||
}
|
||||
|
||||
mTmpRecents.clear();
|
||||
// mRecentTasks is now in sorted, affiliated order.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user