Stop restoring tasks added before recent is loaded
Previously we can have duplicated tasks sharing the same taskId in
RecentTasks due to race condition.
1. A task is created before RecentTasks#loadUserRecentsLocked
(e.g. through adb)
2. RecentTasks#notifyTaskPersisterLocked eventually writes the task file
to storage (e.g. XX_task.xml)
3. RecentTasks#loadUserRecentsLocked tries to recover XX_task.xml while
the task has already been added to RecentTasks.
To fix the issue, the CL stops restoring tasks added before recent is
loaded.
Bug: 36796576
Test: Build and boot Android, check the recent is correctly loaded
Change-Id: Ib57977f2a0a63f7bf7db4d3fd70bdcc359e76f7d
(cherry picked from commit b8aeb6f12e51e6d3ecf6a5f40c953dc76ff64884)
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 9deabb3..e56b09d 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -78,9 +78,8 @@
/** Special value for mWriteTime to mean don't wait, just write */
private static final long FLUSH_QUEUE = -1;
- private static final String RECENTS_FILENAME = "_task";
private static final String TASKS_DIRNAME = "recent_tasks";
- private static final String TASK_EXTENSION = ".xml";
+ private static final String TASK_FILENAME_SUFFIX = "_task.xml";
private static final String IMAGES_DIRNAME = "recent_images";
private static final String PERSISTED_TASK_IDS_FILENAME = "persisted_taskIds.txt";
static final String IMAGE_EXTENSION = ".png";
@@ -412,7 +411,7 @@
return null;
}
- List<TaskRecord> restoreTasksForUserLocked(final int userId) {
+ List<TaskRecord> restoreTasksForUserLocked(final int userId, SparseBooleanArray preaddedTasks) {
final ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>();
ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>();
@@ -430,6 +429,24 @@
Slog.d(TAG, "restoreTasksForUserLocked: userId=" + userId
+ ", taskFile=" + taskFile.getName());
}
+
+ if (!taskFile.getName().endsWith(TASK_FILENAME_SUFFIX)) {
+ continue;
+ }
+ try {
+ final int taskId = Integer.parseInt(taskFile.getName().substring(
+ 0 /* beginIndex */,
+ taskFile.getName().length() - TASK_FILENAME_SUFFIX.length()));
+ if (preaddedTasks.get(taskId, false)) {
+ Slog.w(TAG, "Task #" + taskId +
+ " has already been created so we don't restore again");
+ continue;
+ }
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Unexpected task file name", e);
+ continue;
+ }
+
BufferedReader reader = null;
boolean deleteFile = false;
try {
@@ -744,13 +761,11 @@
try {
atomicFile = new AtomicFile(new File(
getUserTasksDir(task.userId),
- String.valueOf(task.taskId) + RECENTS_FILENAME
- + TASK_EXTENSION));
+ String.valueOf(task.taskId) + TASK_FILENAME_SUFFIX));
file = atomicFile.startWrite();
file.write(stringWriter.toString().getBytes());
file.write('\n');
atomicFile.finishWrite(file);
-
} catch (IOException e) {
if (file != null) {
atomicFile.failWrite(file);