Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10505cdb authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert^2 "Use ConcurrentHashMap to make private maps thread safe"" into main

parents 13ffcc72 4c045988
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import com.android.systemui.shared.system.TaskStackChangeListeners;
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 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
    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 class RecentsModel implements RecentTasksDataSource, IconChangeListener,
    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 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
    @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);
        }
    }

+36 −36
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.quickstep.recents.data.TaskVisualsChangedDelegate.TaskThumbna
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 @@ interface TaskVisualsChangedDelegate :
    /** 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 @@ interface TaskVisualsChangedDelegate :
    /** 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 @@ class TaskVisualsChangedDelegateImpl(
    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 @@ class TaskVisualsChangedDelegateImpl(

    override fun registerTaskIconChangedCallback(
        taskKey: Task.TaskKey,
        taskIconChangedCallback: TaskIconChangedCallback
        taskIconChangedCallback: TaskIconChangedCallback,
    ) {
        updateCallbacks {
            taskIconChangedCallbacks[taskKey.id] = taskKey to taskIconChangedCallback
        onCallbackRegistered()
        }
    }

    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,
    ) {
        updateCallbacks {
            taskThumbnailChangedCallbacks[taskKey.id] = taskKey to taskThumbnailChangedCallback
        onCallbackRegistered()
        }
    }

    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)
            }
        }
    }
}