diff options
11 files changed, 63 insertions, 9 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java index 14ba9df93f24..764e650a807c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootDisplayAreaOrganizer.java @@ -85,6 +85,8 @@ public class RootDisplayAreaOrganizer extends DisplayAreaOrganizer { } mDisplayAreasInfo.remove(displayId); + mLeashes.get(displayId).release(); + mLeashes.remove(displayId); } @Override 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 e9d24fbf4d0a..3f518c77bbc3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -529,7 +529,8 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } final int taskId = taskInfo.taskId; - final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo()); + final TaskAppearedInfo appearedInfo = mTasks.get(taskId); + final TaskListener listener = getTaskListener(appearedInfo.getTaskInfo()); mTasks.remove(taskId); if (listener != null) { listener.onTaskVanished(taskInfo); @@ -539,6 +540,10 @@ public class ShellTaskOrganizer extends TaskOrganizer implements notifyCompatUI(taskInfo, null /* taskListener */); // Notify the recent tasks that a task has been removed mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskRemoved(taskInfo)); + + if (appearedInfo.getLeash() != null) { + appearedInfo.getLeash().release(); + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java index 3f7d78dda037..9478b347653f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java @@ -128,9 +128,10 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { final WindowContainerTransaction wct = new WindowContainerTransaction(); final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - applyBoundsAndOffsets( - displayAreaInfo.token, mDisplayAreaMap.get(displayAreaInfo.token), wct, t); + final SurfaceControl leash = mDisplayAreaMap.get(displayAreaInfo.token); + applyBoundsAndOffsets(displayAreaInfo.token, leash, wct, t); applyTransaction(wct, t); + leash.release(); mDisplayAreaMap.remove(displayAreaInfo.token); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java index f61d1b95bd85..451afa08040c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java @@ -159,6 +159,10 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { @Override public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) { + final SurfaceControl leash = mDisplayAreaTokenMap.get(displayAreaInfo.token); + if (leash != null) { + leash.release(); + } mDisplayAreaTokenMap.remove(displayAreaInfo.token); } 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 22b0ccbc8488..da88c2de6c01 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 @@ -943,6 +943,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mPipBoundsState.setBounds(new Rect()); mPipUiEventLoggerLogger.setTaskInfo(null); mMainExecutor.executeDelayed(() -> mPipMenuController.detach(), 0); + mLeash = null; if (info.displayId != Display.DEFAULT_DISPLAY && mOnDisplayIdChangeCallback != null) { mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 046b1a2541b4..c8ee010e60e0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -486,7 +486,15 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) { - return reparentSplitTasksForAnimation(apps, false /*splitExpectedToBeVisible*/); + try { + return reparentSplitTasksForAnimation(apps, false /*splitExpectedToBeVisible*/); + } finally { + for (RemoteAnimationTarget appTarget : apps) { + if (appTarget.leash != null) { + appTarget.leash.release(); + } + } + } } private RemoteAnimationTarget[] reparentSplitTasksForAnimation(RemoteAnimationTarget[] apps, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 55e7dacc4087..70d728d90b6a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -1024,6 +1024,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } mRootTaskInfo = null; + mRootTaskLeash = null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 99e750629729..cb9e1a39ec52 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -243,6 +243,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { if (mRootTaskInfo.taskId == taskId) { mCallbacks.onRootTaskVanished(); mRootTaskInfo = null; + mRootLeash = null; mSyncQueue.runInSync(t -> { t.remove(mDimLayer); mSplitDecorManager.release(t); 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 0b53c4069c3f..494815850b7c 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 @@ -46,6 +46,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.SparseArray; import android.view.SurfaceControl; +import android.view.SurfaceSession; import android.window.ITaskOrganizer; import android.window.ITaskOrganizerController; import android.window.TaskAppearedInfo; @@ -137,13 +138,25 @@ public class ShellTaskOrganizerTests { } @Test - public void registerOrganizer_sendRegisterTaskOrganizer() throws RemoteException { + public void testRegisterOrganizer_sendRegisterTaskOrganizer() throws RemoteException { mOrganizer.registerOrganizer(); verify(mTaskOrganizerController).registerTaskOrganizer(any(ITaskOrganizer.class)); } @Test + public void testTaskLeashReleasedAfterVanished() throws RemoteException { + RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW); + SurfaceControl taskLeash = new SurfaceControl.Builder(new SurfaceSession()) + .setName("task").build(); + mOrganizer.registerOrganizer(); + mOrganizer.onTaskAppeared(taskInfo, taskLeash); + assertTrue(taskLeash.isValid()); + mOrganizer.onTaskVanished(taskInfo); + assertTrue(!taskLeash.isValid()); + } + + @Test public void testOneListenerPerType() { mOrganizer.addListenerForType(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW); try { diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index c5993e1ef4bc..801665862d29 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -527,11 +527,12 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { mService.mRootWindowContainer.forAllTasks((task) -> { boolean returnTask = !task.mCreatedByOrganizer; task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */); - if (returnTask) { - SurfaceControl outSurfaceControl = state.addTaskWithoutCallback(task, + // It is possible for the task to not yet have a surface control, so ensure that + // the update succeeded in setting the organizer for the task before returning + if (task.isOrganized() && returnTask) { + SurfaceControl taskLeash = state.addTaskWithoutCallback(task, "TaskOrganizerController.registerTaskOrganizer"); - taskInfos.add( - new TaskAppearedInfo(task.getTaskInfo(), outSurfaceControl)); + taskInfos.add(new TaskAppearedInfo(task.getTaskInfo(), taskLeash)); } }); }; 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 9c2aac066084..540741217ae8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -459,6 +459,23 @@ public class WindowOrganizerTests extends WindowTestsBase { } @Test + public void testRegisterTaskOrganizerWithExistingTasks_noSurfaceControl() + throws RemoteException { + final Task rootTask = createRootTask(); + final Task task = createTask(rootTask); + final Task rootTask2 = createRootTask(); + final Task task2 = createTask(rootTask2); + rootTask2.setSurfaceControl(null); + ArrayList<TaskAppearedInfo> existingTasks = new ArrayList<>(); + final ITaskOrganizer organizer = registerMockOrganizer(existingTasks); + assertContainsTasks(existingTasks, rootTask); + + // Verify we don't get onTaskAppeared if we are returned the tasks + verify(organizer, never()) + .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class)); + } + + @Test public void testTaskTransaction() { removeGlobalMinSizeRestriction(); final Task rootTask = new TaskBuilder(mSupervisor) |