From fe89198905bd09daa0e45ea39364a13b02937fb7 Mon Sep 17 00:00:00 2001 From: Mariia Sandrikova Date: Wed, 7 Oct 2020 23:10:18 +0100 Subject: [PATCH] Refactor task listeners mapping in ShellTaskOrganiser Stop using windowing modes as keys for task listerners mapping to allow adding multiple listeners for one windowing mode. Fix: 170209272 Test: go/wm-smoke Change-Id: I31c20a00f8747a8510a5fab9e54efa63173aab6a --- .../Shell/res/raw/wm_shell_protolog.json | 12 +- .../android/wm/shell/ShellTaskOrganizer.java | 103 +++++++++++++----- .../wm/shell/pip/PipTaskOrganizer.java | 3 +- .../splitscreen/SplitScreenTaskOrganizer.java | 10 +- .../wm/shell/ShellTaskOrganizerTests.java | 17 +-- 5 files changed, 98 insertions(+), 47 deletions(-) diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json index 227eec2adc874..bcef154beeb3a 100644 --- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json +++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json @@ -1,6 +1,12 @@ { "version": "1.0.0", "messages": { + "-1823823103": { + "message": "Add listener for types=%s listener=%s", + "level": "VERBOSE", + "group": "WM_SHELL_TASK_ORG", + "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" + }, "-1534364071": { "message": "onTransitionReady %s: %s", "level": "VERBOSE", @@ -37,12 +43,6 @@ "group": "WM_SHELL_TASK_ORG", "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" }, - "-242812822": { - "message": "Add listener for modes=%s listener=%s", - "level": "VERBOSE", - "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" - }, "-191422040": { "message": "Transition animations finished, notifying core %s", "level": "VERBOSE", 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 4f610efd55232..7ce65fd633346 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -16,9 +16,17 @@ package com.android.wm.shell; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import android.annotation.IntDef; import android.app.ActivityManager.RunningTaskInfo; +import android.app.WindowConfiguration.WindowingMode; import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -33,7 +41,6 @@ import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.protolog.ShellProtoLogGroup; -import java.util.ArrayList; import java.util.Arrays; /** @@ -42,6 +49,23 @@ import java.util.Arrays; */ public class ShellTaskOrganizer extends TaskOrganizer { + // Intentionally using negative numbers here so the positive numbers can be used + // for task id specific listeners that will be added later. + public static final int TASK_LISTENER_TYPE_UNDEFINED = -1; + public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2; + public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3; + public static final int TASK_LISTENER_TYPE_PIP = -4; + public static final int TASK_LISTENER_TYPE_SPLIT_SCREEN = -5; + + @IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = { + TASK_LISTENER_TYPE_UNDEFINED, + TASK_LISTENER_TYPE_FULLSCREEN, + TASK_LISTENER_TYPE_MULTI_WINDOW, + TASK_LISTENER_TYPE_PIP, + TASK_LISTENER_TYPE_SPLIT_SCREEN, + }) + public @interface TaskListenerType {} + private static final String TAG = "ShellTaskOrganizer"; /** @@ -54,7 +78,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {} } - private final SparseArray mListenerByWindowingMode = new SparseArray<>(); + private final SparseArray mTaskListenersByType = new SparseArray<>(); // Keeps track of all the tasks reported to this organizer (changes in windowing mode will // require us to report to both old and new listeners) @@ -73,29 +97,29 @@ public class ShellTaskOrganizer extends TaskOrganizer { SyncTransactionQueue syncQueue, TransactionPool transactionPool, ShellExecutor mainExecutor, ShellExecutor animExecutor) { super(taskOrganizerController); - addListener(new FullscreenTaskListener(syncQueue), WINDOWING_MODE_FULLSCREEN); + addListener(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN); mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor); if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions); } /** - * Adds a listener for tasks in a specific windowing mode. + * Adds a listener for tasks with given types. */ - public void addListener(TaskListener listener, int... windowingModes) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for modes=%s listener=%s", - Arrays.toString(windowingModes), listener); - for (int winMode : windowingModes) { - if (mListenerByWindowingMode.get(winMode) != null) { - throw new IllegalArgumentException("Listener for winMode=" + winMode + public void addListener(TaskListener listener, @TaskListenerType int... taskListenerTypes) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for types=%s listener=%s", + Arrays.toString(taskListenerTypes), listener); + for (int listenerType : taskListenerTypes) { + if (mTaskListenersByType.get(listenerType) != null) { + throw new IllegalArgumentException("Listener for listenerType=" + listenerType + " already exists"); } - mListenerByWindowingMode.put(winMode, listener); + mTaskListenersByType.put(listenerType, listener); - // Notify the listener of all existing tasks in that windowing mode + // Notify the listener of all existing tasks with the given type. for (int i = mTasks.size() - 1; i >= 0; i--) { Pair data = mTasks.valueAt(i); - int taskWinMode = data.first.configuration.windowConfiguration.getWindowingMode(); - if (taskWinMode == winMode) { + final @TaskListenerType int taskListenerType = getTaskListenerType(data.first); + if (taskListenerType == listenerType) { listener.onTaskAppeared(data.first, data.second); } } @@ -107,12 +131,12 @@ public class ShellTaskOrganizer extends TaskOrganizer { */ public void removeListener(TaskListener listener) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Remove listener=%s", listener); - final int index = mListenerByWindowingMode.indexOfValue(listener); + final int index = mTaskListenersByType.indexOfValue(listener); if (index == -1) { Log.w(TAG, "No registered listener found"); return; } - mListenerByWindowingMode.removeAt(index); + mTaskListenersByType.removeAt(index); } @Override @@ -120,7 +144,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task appeared taskId=%d", taskInfo.taskId); mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, leash)); - final TaskListener listener = mListenerByWindowingMode.get(getWindowingMode(taskInfo)); + final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo)); if (listener != null) { listener.onTaskAppeared(taskInfo, leash); } @@ -131,23 +155,23 @@ public class ShellTaskOrganizer extends TaskOrganizer { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId); final Pair data = mTasks.get(taskInfo.taskId); - final int winMode = getWindowingMode(taskInfo); - final int prevWinMode = getWindowingMode(data.first); + final @TaskListenerType int listenerType = getTaskListenerType(taskInfo); + final @TaskListenerType int prevListenerType = getTaskListenerType(data.first); mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, data.second)); - if (prevWinMode != -1 && prevWinMode != winMode) { - // TODO: We currently send vanished/appeared as the task moves between win modes, but + if (prevListenerType != listenerType) { + // TODO: We currently send vanished/appeared as the task moves between types, but // we should consider adding a different mode-changed callback - TaskListener listener = mListenerByWindowingMode.get(prevWinMode); + TaskListener listener = mTaskListenersByType.get(prevListenerType); if (listener != null) { listener.onTaskVanished(taskInfo); } - listener = mListenerByWindowingMode.get(winMode); + listener = mTaskListenersByType.get(listenerType); if (listener != null) { SurfaceControl leash = data.second; listener.onTaskAppeared(taskInfo, leash); } } else { - final TaskListener listener = mListenerByWindowingMode.get(winMode); + final TaskListener listener = mTaskListenersByType.get(listenerType); if (listener != null) { listener.onTaskInfoChanged(taskInfo); } @@ -158,7 +182,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId); - final TaskListener listener = mListenerByWindowingMode.get(getWindowingMode(taskInfo)); + final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo)); if (listener != null) { listener.onBackPressedOnTaskRoot(taskInfo); } @@ -168,15 +192,38 @@ public class ShellTaskOrganizer extends TaskOrganizer { public void onTaskVanished(RunningTaskInfo taskInfo) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId); - final int prevWinMode = getWindowingMode(mTasks.get(taskInfo.taskId).first); + final @TaskListenerType int prevListenerType = + getTaskListenerType(mTasks.get(taskInfo.taskId).first); mTasks.remove(taskInfo.taskId); - final TaskListener listener = mListenerByWindowingMode.get(prevWinMode); + final TaskListener listener = mTaskListenersByType.get(prevListenerType); if (listener != null) { listener.onTaskVanished(taskInfo); } } - private int getWindowingMode(RunningTaskInfo taskInfo) { + @TaskListenerType + private static int getTaskListenerType(RunningTaskInfo runningTaskInfo) { + // Right now it's N:1 mapping but in the future different task listerners + // may be triggered by one windowing mode depending on task parameters. + switch (getWindowingMode(runningTaskInfo)) { + case WINDOWING_MODE_FULLSCREEN: + return TASK_LISTENER_TYPE_FULLSCREEN; + case WINDOWING_MODE_MULTI_WINDOW: + return TASK_LISTENER_TYPE_MULTI_WINDOW; + case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: + case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: + return TASK_LISTENER_TYPE_SPLIT_SCREEN; + case WINDOWING_MODE_PINNED: + return TASK_LISTENER_TYPE_PIP; + case WINDOWING_MODE_FREEFORM: + case WINDOWING_MODE_UNDEFINED: + default: + return TASK_LISTENER_TYPE_UNDEFINED; + } + } + + @WindowingMode + private static int getWindowingMode(RunningTaskInfo taskInfo) { return taskInfo.configuration.windowConfiguration.getWindowingMode(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 05877d4b172dc..846da0a77bca9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA; import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS; import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP; @@ -282,7 +283,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, if (!PipUtils.hasSystemFeature(context)) { Log.w(TAG, "Device not support PIP feature"); } else { - mTaskOrganizer.addListener(this, WINDOWING_MODE_PINNED); + mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_PIP); displayController.addDisplayWindowListener(this); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java index 30bc43b0292f1..8660702a25099 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java @@ -23,8 +23,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_SPLIT_SCREEN; + import android.app.ActivityManager.RunningTaskInfo; -import android.app.WindowConfiguration; import android.graphics.Rect; import android.os.RemoteException; import android.util.Log; @@ -56,17 +57,16 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener { ShellTaskOrganizer shellTaskOrganizer) { mSplitScreenController = splitScreenController; mTaskOrganizer = shellTaskOrganizer; - mTaskOrganizer.addListener(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_SPLIT_SCREEN); } void init() throws RemoteException { synchronized (this) { try { mPrimary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, - WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); mSecondary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, - WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); } catch (Exception e) { // teardown to prevent callbacks mTaskOrganizer.removeListener(this); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index 6ce4d3795f855..f01fc517d5baf 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -19,6 +19,9 @@ package com.android.wm.shell; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW; +import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP; + import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -102,10 +105,10 @@ public class ShellTaskOrganizerTests { } @Test - public void testOneListenerPerMode() { - mOrganizer.addListener(new TrackingTaskListener(), WINDOWING_MODE_MULTI_WINDOW); + public void testOneListenerPerType() { + mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW); try { - mOrganizer.addListener(new TrackingTaskListener(), WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW); fail("Expected exception due to already registered listener"); } catch (Exception e) { // Expected failure @@ -116,7 +119,7 @@ public class ShellTaskOrganizerTests { public void testAppearedVanished() { RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW); TrackingTaskListener listener = new TrackingTaskListener(); - mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW); mOrganizer.onTaskAppeared(taskInfo, null); assertTrue(listener.appeared.contains(taskInfo)); @@ -130,7 +133,7 @@ public class ShellTaskOrganizerTests { mOrganizer.onTaskAppeared(taskInfo, null); TrackingTaskListener listener = new TrackingTaskListener(); - mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW); assertTrue(listener.appeared.contains(taskInfo)); } @@ -139,8 +142,8 @@ public class ShellTaskOrganizerTests { RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW); TrackingTaskListener mwListener = new TrackingTaskListener(); TrackingTaskListener pipListener = new TrackingTaskListener(); - mOrganizer.addListener(mwListener, WINDOWING_MODE_MULTI_WINDOW); - mOrganizer.addListener(pipListener, WINDOWING_MODE_PINNED); + mOrganizer.addListener(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW); + mOrganizer.addListener(pipListener, TASK_LISTENER_TYPE_PIP); mOrganizer.onTaskAppeared(taskInfo, null); assertTrue(mwListener.appeared.contains(taskInfo)); assertTrue(pipListener.appeared.isEmpty());