Merge "Revert^2 "Use ConcurrentHashMap to make private maps thread safe"" into main
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index a01ceb2..d073580 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -56,6 +56,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
@@ -76,7 +77,8 @@
private static final Executor RECENTS_MODEL_EXECUTOR = Executors.newSingleThreadExecutor(
new SimpleThreadFactory("TaskThumbnailIconCache-", THREAD_PRIORITY_BACKGROUND));
- private final List<TaskVisualsChangeListener> mThumbnailChangeListeners = new ArrayList<>();
+ private final ConcurrentLinkedQueue<TaskVisualsChangeListener> mThumbnailChangeListeners =
+ new ConcurrentLinkedQueue<>();
private final Context mContext;
private final RecentTasksList mTaskList;
@@ -239,8 +241,8 @@
public boolean onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
mThumbnailCache.updateTaskSnapShot(taskId, snapshot);
- for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
- Task task = mThumbnailChangeListeners.get(i).onTaskThumbnailChanged(taskId, snapshot);
+ for (TaskVisualsChangeListener listener : mThumbnailChangeListeners) {
+ Task task = listener.onTaskThumbnailChanged(taskId, snapshot);
if (task != null) {
task.thumbnail = snapshot;
}
@@ -269,8 +271,8 @@
@Override
public void onAppIconChanged(String packageName, UserHandle user) {
mIconCache.invalidateCacheEntries(packageName, user);
- for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
- mThumbnailChangeListeners.get(i).onTaskIconChanged(packageName, user);
+ for (TaskVisualsChangeListener listener : mThumbnailChangeListeners) {
+ listener.onTaskIconChanged(packageName, user);
}
}
diff --git a/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt b/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt
index a141e89..a45d194 100644
--- a/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/TaskVisualsChangedDelegate.kt
@@ -23,6 +23,7 @@
import com.android.quickstep.util.TaskVisualsChangeListener
import com.android.systemui.shared.recents.model.Task
import com.android.systemui.shared.recents.model.ThumbnailData
+import java.util.concurrent.ConcurrentHashMap
/** Delegates the checking of task visuals (thumbnails, high res changes, icons) */
interface TaskVisualsChangedDelegate :
@@ -30,7 +31,7 @@
/** Registers a callback for visuals relating to icons */
fun registerTaskIconChangedCallback(
taskKey: Task.TaskKey,
- taskIconChangedCallback: TaskIconChangedCallback
+ taskIconChangedCallback: TaskIconChangedCallback,
)
/** Unregisters a callback for visuals relating to icons */
@@ -39,7 +40,7 @@
/** Registers a callback for visuals relating to thumbnails */
fun registerTaskThumbnailChangedCallback(
taskKey: Task.TaskKey,
- taskThumbnailChangedCallback: TaskThumbnailChangedCallback
+ taskThumbnailChangedCallback: TaskThumbnailChangedCallback,
)
/** Unregisters a callback for visuals relating to thumbnails */
@@ -66,31 +67,9 @@
private val highResLoadingStateNotifier: HighResLoadingStateNotifier,
) : TaskVisualsChangedDelegate {
private val taskIconChangedCallbacks =
- mutableMapOf<Int, Pair<Task.TaskKey, TaskIconChangedCallback>>()
+ ConcurrentHashMap<Int, Pair<Task.TaskKey, TaskIconChangedCallback>>()
private val taskThumbnailChangedCallbacks =
- mutableMapOf<Int, Pair<Task.TaskKey, TaskThumbnailChangedCallback>>()
- private var isListening = false
-
- @Synchronized
- private fun onCallbackRegistered() {
- if (isListening) return
-
- taskVisualsChangeNotifier.addThumbnailChangeListener(this)
- highResLoadingStateNotifier.addCallback(this)
- isListening = true
- }
-
- @Synchronized
- private fun onCallbackUnregistered() {
- if (!isListening) return
-
- if (taskIconChangedCallbacks.size + taskThumbnailChangedCallbacks.size == 0) {
- taskVisualsChangeNotifier.removeThumbnailChangeListener(this)
- highResLoadingStateNotifier.removeCallback(this)
- }
-
- isListening = false
- }
+ ConcurrentHashMap<Int, Pair<Task.TaskKey, TaskThumbnailChangedCallback>>()
override fun onTaskIconChanged(taskId: Int) {
taskIconChangedCallbacks[taskId]?.let { (_, callback) -> callback.onTaskIconChanged() }
@@ -119,27 +98,48 @@
override fun registerTaskIconChangedCallback(
taskKey: Task.TaskKey,
- taskIconChangedCallback: TaskIconChangedCallback
+ taskIconChangedCallback: TaskIconChangedCallback,
) {
- taskIconChangedCallbacks[taskKey.id] = taskKey to taskIconChangedCallback
- onCallbackRegistered()
+ updateCallbacks {
+ taskIconChangedCallbacks[taskKey.id] = taskKey to taskIconChangedCallback
+ }
}
override fun unregisterTaskIconChangedCallback(taskKey: Task.TaskKey) {
- taskIconChangedCallbacks.remove(taskKey.id)
- onCallbackUnregistered()
+ updateCallbacks { taskIconChangedCallbacks.remove(taskKey.id) }
}
override fun registerTaskThumbnailChangedCallback(
taskKey: Task.TaskKey,
- taskThumbnailChangedCallback: TaskThumbnailChangedCallback
+ taskThumbnailChangedCallback: TaskThumbnailChangedCallback,
) {
- taskThumbnailChangedCallbacks[taskKey.id] = taskKey to taskThumbnailChangedCallback
- onCallbackRegistered()
+ updateCallbacks {
+ taskThumbnailChangedCallbacks[taskKey.id] = taskKey to taskThumbnailChangedCallback
+ }
}
override fun unregisterTaskThumbnailChangedCallback(taskKey: Task.TaskKey) {
- taskThumbnailChangedCallbacks.remove(taskKey.id)
- onCallbackUnregistered()
+ updateCallbacks { taskThumbnailChangedCallbacks.remove(taskKey.id) }
+ }
+
+ @Synchronized
+ private fun updateCallbacks(callbackModifier: () -> Unit) {
+ val prevHasCallbacks =
+ taskIconChangedCallbacks.size + taskThumbnailChangedCallbacks.size > 0
+ callbackModifier()
+
+ val currHasCallbacks =
+ taskIconChangedCallbacks.size + taskThumbnailChangedCallbacks.size > 0
+
+ when {
+ prevHasCallbacks && !currHasCallbacks -> {
+ taskVisualsChangeNotifier.removeThumbnailChangeListener(this)
+ highResLoadingStateNotifier.removeCallback(this)
+ }
+ !prevHasCallbacks && currHasCallbacks -> {
+ taskVisualsChangeNotifier.addThumbnailChangeListener(this)
+ highResLoadingStateNotifier.addCallback(this)
+ }
+ }
}
}