diff options
10 files changed, 126 insertions, 61 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index a165af789c95..7dc74716b9d5 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -2375,7 +2375,7 @@ package android.window { public class TaskOrganizer extends android.window.WindowOrganizer { ctor public TaskOrganizer(); - method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.app.ActivityManager.RunningTaskInfo createRootTask(int, int); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.window.TaskAppearedInfo createRootTask(int, int); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean deleteRootTask(@NonNull android.window.WindowContainerToken); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.window.WindowContainerToken getImeTarget(int); diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl index 3a84c1f98ce6..b5a11b1a8136 100644 --- a/core/java/android/window/ITaskOrganizerController.aidl +++ b/core/java/android/window/ITaskOrganizerController.aidl @@ -39,8 +39,12 @@ interface ITaskOrganizerController { */ void unregisterTaskOrganizer(ITaskOrganizer organizer); - /** Creates a persistent root task in WM for a particular windowing-mode. */ - ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode); + /** + * Creates a persistent root task in WM for a particular windowing-mode. + * {@link TaskOrganizer#onTaskAppeared} won't be called since we are returning + * {@link TaskAppearedInfo} here. + */ + TaskAppearedInfo createRootTask(int displayId, int windowingMode); /** Deletes a persistent root task in WM */ boolean deleteRootTask(in WindowContainerToken task); diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index 909bb47bf1a5..5c86e1c124f7 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -99,7 +99,7 @@ public class TaskOrganizer extends WindowOrganizer { /** Creates a persistent root task in WM for a particular windowing-mode. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) @Nullable - public ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) { + public TaskAppearedInfo createRootTask(int displayId, int windowingMode) { try { return mTaskOrganizerController.createRootTask(displayId, windowingMode); } catch (RemoteException e) { diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json index 3f6ca0fc5246..02bf38504725 100644 --- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json +++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json @@ -31,6 +31,12 @@ "group": "WM_SHELL_TASK_ORG", "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" }, + "-1312360667": { + "message": "createRootTask() displayId=%d winMode=%d listener=%s", + "level": "VERBOSE", + "group": "WM_SHELL_TASK_ORG", + "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" + }, "-880817403": { "message": "Task vanished taskId=%d", "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 9f3c83c09507..8bd7193843f7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -128,11 +128,24 @@ public class ShellTaskOrganizer extends TaskOrganizer { 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.getTaskInfo(), info.getLeash()); + onTaskAppeared(info); } 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); + + // 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. */ @@ -216,12 +229,17 @@ public class ShellTaskOrganizer extends TaskOrganizer { @Override public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { - ProtoLog.v(WM_SHELL_TASK_ORG, "Task appeared taskId=%d", taskInfo.taskId); - mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, leash)); + onTaskAppeared(new TaskAppearedInfo(taskInfo, leash)); + } + + private void onTaskAppeared(TaskAppearedInfo info) { + final int taskId = info.getTaskInfo().taskId; + ProtoLog.v(WM_SHELL_TASK_ORG, "Task appeared taskId=%d", taskId); + mTasks.put(taskId, info); final TaskListener listener = - getTaskListener(taskInfo, true /*removeLaunchCookieIfNeeded*/); + getTaskListener(info.getTaskInfo(), true /*removeLaunchCookieIfNeeded*/); if (listener != null) { - listener.onTaskAppeared(taskInfo, leash); + listener.onTaskAppeared(info.getTaskInfo(), info.getLeash()); } } 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 f763d6d714c4..0a1aadc90a62 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 @@ -33,6 +33,7 @@ import android.util.Log; import android.view.Display; import android.view.SurfaceControl; import android.view.SurfaceSession; +import android.window.TaskAppearedInfo; import androidx.annotation.NonNull; @@ -68,10 +69,15 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener { void init() throws RemoteException { synchronized (this) { try { - mPrimary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - mSecondary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + final TaskAppearedInfo primary = mTaskOrganizer.createRootTask( + Display.DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, this); + final TaskAppearedInfo secondary = mTaskOrganizer.createRootTask( + Display.DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, this); + mPrimary = primary.getTaskInfo(); + mPrimarySurface = primary.getLeash(); + mSecondary = secondary.getTaskInfo(); + mSecondarySurface = secondary.getLeash(); + enableSplitScreenSupportIfNeeded(); } catch (Exception e) { // teardown to prevent callbacks mTaskOrganizer.removeListener(this); @@ -92,43 +98,29 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener { mSplitScreenController.mTransactionPool.release(t); } - @Override - public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { - synchronized (this) { - if (mPrimary == null || mSecondary == null) { - Log.w(TAG, "Received onTaskAppeared before creating root tasks " + taskInfo); - return; - } - - if (taskInfo.token.equals(mPrimary.token)) { - mPrimarySurface = leash; - } else if (taskInfo.token.equals(mSecondary.token)) { - mSecondarySurface = leash; - } - - if (!mSplitScreenSupported && mPrimarySurface != null && mSecondarySurface != null) { - mSplitScreenSupported = true; - - // Initialize dim surfaces: - mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession) - .setParent(mPrimarySurface).setColorLayer() - .setName("Primary Divider Dim") - .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared") - .build(); - mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession) - .setParent(mSecondarySurface).setColorLayer() - .setName("Secondary Divider Dim") - .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared") - .build(); - SurfaceControl.Transaction t = getTransaction(); - t.setLayer(mPrimaryDim, Integer.MAX_VALUE); - t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f}); - t.setLayer(mSecondaryDim, Integer.MAX_VALUE); - t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f}); - t.apply(); - releaseTransaction(t); - } - } + private void enableSplitScreenSupportIfNeeded() { + if (mSplitScreenSupported || mPrimarySurface == null || mSecondarySurface == null) return; + + mSplitScreenSupported = true; + + // Initialize dim surfaces: + mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession) + .setParent(mPrimarySurface).setColorLayer() + .setName("Primary Divider Dim") + .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared") + .build(); + mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession) + .setParent(mSecondarySurface).setColorLayer() + .setName("Secondary Divider Dim") + .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared") + .build(); + SurfaceControl.Transaction t = getTransaction(); + t.setLayer(mPrimaryDim, Integer.MAX_VALUE); + t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f}); + t.setLayer(mSecondaryDim, Integer.MAX_VALUE); + t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f}); + t.apply(); + releaseTransaction(t); } @Override diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 6504f00905e7..6486b78eb601 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -389,6 +389,10 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } void onTaskAppeared(ITaskOrganizer organizer, Task task) { + // Don't send onTaskAppeared signal for task created by organizer since we will return it in + // the creation call. + if (task.mCreatedByOrganizer) return; + final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); state.addTask(task); } @@ -401,7 +405,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } @Override - public RunningTaskInfo createRootTask(int displayId, int windowingMode) { + public TaskAppearedInfo createRootTask(int displayId, int windowingMode) { enforceStackPermission("createRootTask()"); final long origId = Binder.clearCallingIdentity(); try { @@ -418,7 +422,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { true /* createdByOrganizer */); RunningTaskInfo out = task.getTaskInfo(); mLastSentTaskInfos.put(task, out); - return out; + final TaskOrganizerState state = + mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder()); + final SurfaceControl outSurfaceControl = state.addTaskWithoutCallback(task, + "TaskOrganizerController.createRootTask"); + return new TaskAppearedInfo(task.getTaskInfo(), outSurfaceControl); } } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index caf8a720e26c..3dc258c51954 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -70,6 +70,8 @@ import android.content.pm.ActivityInfo; import android.os.Binder; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; +import android.view.SurfaceControl; +import android.window.ITaskOrganizer; import androidx.test.filters.SmallTest; @@ -240,6 +242,24 @@ public class ActivityStackTests extends WindowTestsBase { @Test public void testRemoveOrganizedTask_UpdateStackReference() { + ITaskOrganizer listener = new ITaskOrganizer.Stub() { + @Override + public void onTaskAppeared( + ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { } + + @Override + public void onTaskVanished(ActivityManager.RunningTaskInfo container) { } + + @Override + public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { + } + + @Override + public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) { + } + }; + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); + final Task rootHomeTask = mDefaultTaskDisplayArea.getRootHomeTask(); final ActivityRecord homeActivity = new ActivityBuilder(mAtm) .setStack(rootHomeTask) @@ -247,7 +267,7 @@ public class ActivityStackTests extends WindowTestsBase { .build(); final Task secondaryStack = (Task) WindowContainer.fromBinder( mAtm.mTaskOrganizerController.createRootTask(rootHomeTask.getDisplayId(), - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token.asBinder()); + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo().token.asBinder()); rootHomeTask.reparent(secondaryStack, POSITION_TOP); assertEquals(secondaryStack, rootHomeTask.getParent()); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index aac83974eb51..bd586a5f6c76 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -479,16 +479,33 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testCreateDeleteRootTasks() { + ITaskOrganizer listener = new ITaskOrganizer.Stub() { + @Override + public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { } + + @Override + public void onTaskVanished(RunningTaskInfo container) { } + + @Override + public void onTaskInfoChanged(RunningTaskInfo info) { + } + + @Override + public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { + } + }; + mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); + RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask( Display.DEFAULT_DISPLAY, - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo(); assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, info1.configuration.windowConfiguration.getWindowingMode()); assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType); RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask( Display.DEFAULT_DISPLAY, - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo(); assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, info2.configuration.windowConfiguration.getWindowingMode()); assertEquals(ACTIVITY_TYPE_UNDEFINED, info2.topActivityType); @@ -522,7 +539,7 @@ public class WindowOrganizerTests extends WindowTestsBase { }; mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask( - mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo(); final Task stack = createTaskStackOnDisplay( WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent); @@ -580,7 +597,7 @@ public class WindowOrganizerTests extends WindowTestsBase { }; mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask( - mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo(); lastReportedTiles.clear(); called[0] = false; @@ -641,9 +658,9 @@ public class WindowOrganizerTests extends WindowTestsBase { }; mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener); RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask( - mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo(); RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask( - mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo(); final int initialRootTaskCount = mWm.mAtmService.mTaskOrganizerController.getRootTasks( mDisplayContent.mDisplayId, null /* activityTypes */).size(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 6237be0f4b26..924b286a4f8e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -1006,10 +1006,10 @@ class WindowTestsBase extends SystemServiceTestsBase { mDisplayId = displayId; mService.mTaskOrganizerController.registerTaskOrganizer(this); WindowContainerToken primary = mService.mTaskOrganizerController.createRootTask( - displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).token; + displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo().token; mPrimary = WindowContainer.fromBinder(primary.asBinder()).asTask(); WindowContainerToken secondary = mService.mTaskOrganizerController.createRootTask( - displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token; + displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo().token; mSecondary = WindowContainer.fromBinder(secondary.asBinder()).asTask(); } TestSplitOrganizer(ActivityTaskManagerService service) { |