diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index 5c86e1c124f7e..8a58db90d375d 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -29,6 +29,7 @@ import android.view.SurfaceControl; import com.android.internal.annotations.VisibleForTesting; import java.util.List; +import java.util.concurrent.Executor; /** * Interface for ActivityTaskManager/WindowManager to delegate control of tasks. @@ -37,15 +38,19 @@ import java.util.List; @TestApi public class TaskOrganizer extends WindowOrganizer { - private ITaskOrganizerController mTaskOrganizerController; + private final ITaskOrganizerController mTaskOrganizerController; + // Callbacks WM Core are posted on this executor if it isn't null, otherwise direct calls are + // made on the incoming binder call. + private final Executor mExecutor; public TaskOrganizer() { - this(null); + this(null /*taskOrganizerController*/, null /*executor*/); } /** @hide */ @VisibleForTesting - public TaskOrganizer(ITaskOrganizerController taskOrganizerController) { + public TaskOrganizer(ITaskOrganizerController taskOrganizerController, Executor executor) { + mExecutor = executor != null ? executor : command -> command.run(); mTaskOrganizerController = taskOrganizerController != null ? taskOrganizerController : getController(); } @@ -183,22 +188,22 @@ public class TaskOrganizer extends WindowOrganizer { @Override public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { - TaskOrganizer.this.onTaskAppeared(taskInfo, leash); + mExecutor.execute(() -> TaskOrganizer.this.onTaskAppeared(taskInfo, leash)); } @Override public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { - TaskOrganizer.this.onTaskVanished(taskInfo); + mExecutor.execute(() -> TaskOrganizer.this.onTaskVanished(taskInfo)); } @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { - TaskOrganizer.this.onTaskInfoChanged(info); + mExecutor.execute(() -> TaskOrganizer.this.onTaskInfoChanged(info)); } @Override public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) { - TaskOrganizer.this.onBackPressedOnTaskRoot(info); + mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info)); } }; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 8bd7193843f75..28cf8a1910832 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -105,6 +105,8 @@ public class ShellTaskOrganizer extends TaskOrganizer { // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks private final Transitions mTransitions; + private final Object mLock = new Object(); + public ShellTaskOrganizer(SyncTransactionQueue syncQueue, TransactionPool transactionPool, ShellExecutor mainExecutor, ShellExecutor animExecutor) { this(null, syncQueue, transactionPool, mainExecutor, animExecutor); @@ -114,7 +116,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController, SyncTransactionQueue syncQueue, TransactionPool transactionPool, ShellExecutor mainExecutor, ShellExecutor animExecutor) { - super(taskOrganizerController); + super(taskOrganizerController, mainExecutor); addListenerForType(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN); mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor); if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions); @@ -122,68 +124,76 @@ public class ShellTaskOrganizer extends TaskOrganizer { @Override public List registerOrganizer() { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Registering organizer"); - final List taskInfos = super.registerOrganizer(); - for (int i = 0; i < taskInfos.size(); i++) { - final TaskAppearedInfo info = taskInfos.get(i); - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s", - info.getTaskInfo().taskId, info.getTaskInfo().baseIntent); - onTaskAppeared(info); + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "Registering organizer"); + final List taskInfos = super.registerOrganizer(); + for (int i = 0; i < taskInfos.size(); i++) { + final TaskAppearedInfo info = taskInfos.get(i); + ProtoLog.v(WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s", + info.getTaskInfo().taskId, info.getTaskInfo().baseIntent); + onTaskAppeared(info); + } + return taskInfos; } - return taskInfos; } public TaskAppearedInfo createRootTask( int displayId, int windowingMode, TaskListener listener) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, - "createRootTask() displayId=%d winMode=%d listener=%s", - displayId, windowingMode, listener.toString()); - final TaskAppearedInfo info = super.createRootTask(displayId, windowingMode); + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "createRootTask() displayId=%d winMode=%d listener=%s", + displayId, windowingMode, listener.toString()); + final TaskAppearedInfo info = super.createRootTask(displayId, windowingMode); - // Add the listener and send the task appeared signal - mTaskListeners.put(info.getTaskInfo().taskId, listener); - onTaskAppeared(info); - return info; + // Add the listener and send the task appeared signal + mTaskListeners.put(info.getTaskInfo().taskId, listener); + onTaskAppeared(info); + return info; + } } /** * Adds a listener for a specific task id. */ public void addListenerForTaskId(TaskListener listener, int taskId) { - ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId); - if (mTaskListeners.get(taskId) != null) { - throw new IllegalArgumentException("Listener for taskId=" + taskId + " already exists"); - } + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId); + if (mTaskListeners.get(taskId) != null) { + throw new IllegalArgumentException( + "Listener for taskId=" + taskId + " already exists"); + } - final TaskAppearedInfo info = mTasks.get(taskId); - if (info == null) { - throw new IllegalArgumentException("addListenerForTaskId unknown taskId=" + taskId); - } + final TaskAppearedInfo info = mTasks.get(taskId); + if (info == null) { + throw new IllegalArgumentException("addListenerForTaskId unknown taskId=" + taskId); + } - final TaskListener oldListener = getTaskListener(info.getTaskInfo()); - mTaskListeners.put(taskId, listener); - updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener); + final TaskListener oldListener = getTaskListener(info.getTaskInfo()); + mTaskListeners.put(taskId, listener); + updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener); + } } /** * Adds a listener for tasks with given types. */ public void addListenerForType(TaskListener listener, @TaskListenerType int... listenerTypes) { - ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s", - Arrays.toString(listenerTypes), listener); - for (int listenerType : listenerTypes) { - if (mTaskListeners.get(listenerType) != null) { - throw new IllegalArgumentException("Listener for listenerType=" + listenerType - + " already exists"); - } - mTaskListeners.put(listenerType, listener); + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s", + Arrays.toString(listenerTypes), listener); + for (int listenerType : listenerTypes) { + if (mTaskListeners.get(listenerType) != null) { + throw new IllegalArgumentException("Listener for listenerType=" + listenerType + + " already exists"); + } + mTaskListeners.put(listenerType, listener); - // Notify the listener of all existing tasks with the given type. - for (int i = mTasks.size() - 1; i >= 0; --i) { - final TaskAppearedInfo data = mTasks.valueAt(i); - final TaskListener taskListener = getTaskListener(data.getTaskInfo()); - if (taskListener != listener) continue; - listener.onTaskAppeared(data.getTaskInfo(), data.getLeash()); + // Notify the listener of all existing tasks with the given type. + for (int i = mTasks.size() - 1; i >= 0; --i) { + final TaskAppearedInfo data = mTasks.valueAt(i); + final TaskListener taskListener = getTaskListener(data.getTaskInfo()); + if (taskListener != listener) continue; + listener.onTaskAppeared(data.getTaskInfo(), data.getLeash()); + } } } } @@ -192,30 +202,32 @@ public class ShellTaskOrganizer extends TaskOrganizer { * Removes a registered listener. */ public void removeListener(TaskListener listener) { - ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener); - final int index = mTaskListeners.indexOfValue(listener); - if (index == -1) { - Log.w(TAG, "No registered listener found"); - return; - } + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener); + final int index = mTaskListeners.indexOfValue(listener); + if (index == -1) { + Log.w(TAG, "No registered listener found"); + return; + } - // Collect tasks associated with the listener we are about to remove. - final ArrayList tasks = new ArrayList<>(); - for (int i = mTasks.size() - 1; i >= 0; --i) { - final TaskAppearedInfo data = mTasks.valueAt(i); - final TaskListener taskListener = getTaskListener(data.getTaskInfo()); - if (taskListener != listener) continue; - tasks.add(data); - } + // Collect tasks associated with the listener we are about to remove. + final ArrayList tasks = new ArrayList<>(); + for (int i = mTasks.size() - 1; i >= 0; --i) { + final TaskAppearedInfo data = mTasks.valueAt(i); + final TaskListener taskListener = getTaskListener(data.getTaskInfo()); + if (taskListener != listener) continue; + tasks.add(data); + } - // Remove listener - mTaskListeners.removeAt(index); + // Remove listener + mTaskListeners.removeAt(index); - // Associate tasks with new listeners if needed. - for (int i = tasks.size() - 1; i >= 0; --i) { - final TaskAppearedInfo data = tasks.get(i); - updateTaskListenerIfNeeded(data.getTaskInfo(), data.getLeash(), - null /* oldListener already removed*/, getTaskListener(data.getTaskInfo())); + // Associate tasks with new listeners if needed. + for (int i = tasks.size() - 1; i >= 0; --i) { + final TaskAppearedInfo data = tasks.get(i); + updateTaskListenerIfNeeded(data.getTaskInfo(), data.getLeash(), + null /* oldListener already removed*/, getTaskListener(data.getTaskInfo())); + } } } @@ -224,12 +236,16 @@ public class ShellTaskOrganizer extends TaskOrganizer { * appears. */ public void setPendingLaunchCookieListener(IBinder cookie, TaskListener listener) { - mLaunchCookieToListener.put(cookie, listener); + synchronized (mLock) { + mLaunchCookieToListener.put(cookie, listener); + } } @Override public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { - onTaskAppeared(new TaskAppearedInfo(taskInfo, leash)); + synchronized (mLock) { + onTaskAppeared(new TaskAppearedInfo(taskInfo, leash)); + } } private void onTaskAppeared(TaskAppearedInfo info) { @@ -245,35 +261,41 @@ public class ShellTaskOrganizer extends TaskOrganizer { @Override public void onTaskInfoChanged(RunningTaskInfo taskInfo) { - ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId); - final TaskAppearedInfo data = mTasks.get(taskInfo.taskId); - final TaskListener oldListener = getTaskListener(data.getTaskInfo()); - final TaskListener newListener = getTaskListener(taskInfo); - mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash())); - final boolean updated = updateTaskListenerIfNeeded( - taskInfo, data.getLeash(), oldListener, newListener); - if (!updated && newListener != null) { - newListener.onTaskInfoChanged(taskInfo); + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId); + final TaskAppearedInfo data = mTasks.get(taskInfo.taskId); + final TaskListener oldListener = getTaskListener(data.getTaskInfo()); + final TaskListener newListener = getTaskListener(taskInfo); + mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash())); + final boolean updated = updateTaskListenerIfNeeded( + taskInfo, data.getLeash(), oldListener, newListener); + if (!updated && newListener != null) { + newListener.onTaskInfoChanged(taskInfo); + } } } @Override public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { - ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId); - final TaskListener listener = getTaskListener(taskInfo); - if (listener != null) { - listener.onBackPressedOnTaskRoot(taskInfo); + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId); + final TaskListener listener = getTaskListener(taskInfo); + if (listener != null) { + listener.onBackPressedOnTaskRoot(taskInfo); + } } } @Override public void onTaskVanished(RunningTaskInfo taskInfo) { - ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId); - final int taskId = taskInfo.taskId; - final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo()); - mTasks.remove(taskId); - if (listener != null) { - listener.onTaskVanished(taskInfo); + synchronized (mLock) { + ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId); + final int taskId = taskInfo.taskId; + final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo()); + mTasks.remove(taskId); + if (listener != null) { + listener.onTaskVanished(taskInfo); + } } } @@ -368,32 +390,34 @@ public class ShellTaskOrganizer extends TaskOrganizer { } public void dump(@NonNull PrintWriter pw, String prefix) { - final String innerPrefix = prefix + " "; - final String childPrefix = innerPrefix + " "; - pw.println(prefix + TAG); - pw.println(innerPrefix + mTaskListeners.size() + " Listeners"); - for (int i = mTaskListeners.size() - 1; i >= 0; --i) { - final int key = mTaskListeners.keyAt(i); - final TaskListener listener = mTaskListeners.valueAt(i); - pw.println(innerPrefix + "#" + i + " " + taskListenerTypeToString(key)); - listener.dump(pw, childPrefix); - } + synchronized (mLock) { + final String innerPrefix = prefix + " "; + final String childPrefix = innerPrefix + " "; + pw.println(prefix + TAG); + pw.println(innerPrefix + mTaskListeners.size() + " Listeners"); + for (int i = mTaskListeners.size() - 1; i >= 0; --i) { + final int key = mTaskListeners.keyAt(i); + final TaskListener listener = mTaskListeners.valueAt(i); + pw.println(innerPrefix + "#" + i + " " + taskListenerTypeToString(key)); + listener.dump(pw, childPrefix); + } - pw.println(); - pw.println(innerPrefix + mTasks.size() + " Tasks"); - for (int i = mTasks.size() - 1; i >= 0; --i) { - final int key = mTasks.keyAt(i); - final TaskAppearedInfo info = mTasks.valueAt(i); - final TaskListener listener = getTaskListener(info.getTaskInfo()); - pw.println(innerPrefix + "#" + i + " task=" + key + " listener=" + listener); - } + pw.println(); + pw.println(innerPrefix + mTasks.size() + " Tasks"); + for (int i = mTasks.size() - 1; i >= 0; --i) { + final int key = mTasks.keyAt(i); + final TaskAppearedInfo info = mTasks.valueAt(i); + final TaskListener listener = getTaskListener(info.getTaskInfo()); + pw.println(innerPrefix + "#" + i + " task=" + key + " listener=" + listener); + } - pw.println(); - pw.println(innerPrefix + mLaunchCookieToListener.size() + " Launch Cookies"); - for (int i = mLaunchCookieToListener.size() - 1; i >= 0; --i) { - final IBinder key = mLaunchCookieToListener.keyAt(i); - final TaskListener listener = mLaunchCookieToListener.valueAt(i); - pw.println(innerPrefix + "#" + i + " cookie=" + key + " listener=" + listener); + pw.println(); + pw.println(innerPrefix + mLaunchCookieToListener.size() + " Launch Cookies"); + for (int i = mLaunchCookieToListener.size() - 1; i >= 0; --i) { + final IBinder key = mLaunchCookieToListener.keyAt(i); + final TaskListener listener = mLaunchCookieToListener.valueAt(i); + pw.println(innerPrefix + "#" + i + " cookie=" + key + " listener=" + listener); + } } } }