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 7f370367187c9..8e98b82088dc5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -216,6 +216,14 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } } + @Override + public void unregisterOrganizer() { + super.unregisterOrganizer(); + if (mStartingWindow != null) { + mStartingWindow.clearAllWindows(); + } + } + public void createRootTask(int displayId, int windowingMode, TaskListener listener) { ProtoLog.v(WM_SHELL_TASK_ORG, "createRootTask() displayId=%d winMode=%d listener=%s", displayId, windowingMode, listener.toString()); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index a9c81b3f3c1f7..73f65b08a7eb6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -134,7 +134,8 @@ public class StartingSurfaceDrawer { mDisplayManager.getDisplay(DEFAULT_DISPLAY); } - private final SparseArray mStartingWindowRecords = new SparseArray<>(); + @VisibleForTesting + final SparseArray mStartingWindowRecords = new SparseArray<>(); /** * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is @@ -459,8 +460,23 @@ public class StartingSurfaceDrawer { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, "Task start finish, remove starting surface for task: %d", removalInfo.taskId); - removeWindowSynced(removalInfo); + removeWindowSynced(removalInfo, false /* immediately */); + } + /** + * Clear all starting windows immediately. + */ + public void clearAllWindows() { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, + "Clear all starting windows immediately"); + final int taskSize = mStartingWindowRecords.size(); + final int[] taskIds = new int[taskSize]; + for (int i = taskSize - 1; i >= 0; --i) { + taskIds[i] = mStartingWindowRecords.keyAt(i); + } + for (int i = taskSize - 1; i >= 0; --i) { + removeWindowNoAnimate(taskIds[i]); + } } /** @@ -542,7 +558,8 @@ public class StartingSurfaceDrawer { return shouldSaveView; } - private void saveSplashScreenRecord(IBinder appToken, int taskId, View view, + @VisibleForTesting + void saveSplashScreenRecord(IBinder appToken, int taskId, View view, @StartingWindowType int suggestType) { final StartingWindowRecord tView = new StartingWindowRecord(appToken, view, null/* TaskSnapshotWindow */, suggestType); @@ -551,19 +568,18 @@ public class StartingSurfaceDrawer { private void removeWindowNoAnimate(int taskId) { mTmpRemovalInfo.taskId = taskId; - removeWindowSynced(mTmpRemovalInfo); + removeWindowSynced(mTmpRemovalInfo, true /* immediately */); } void onImeDrawnOnTask(int taskId) { final StartingWindowRecord record = mStartingWindowRecords.get(taskId); if (record != null && record.mTaskSnapshotWindow != null && record.mTaskSnapshotWindow.hasImeSurface()) { - record.mTaskSnapshotWindow.removeImmediately(); + removeWindowNoAnimate(taskId); } - mStartingWindowRecords.remove(taskId); } - protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) { + protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, boolean immediately) { final int taskId = removalInfo.taskId; final StartingWindowRecord record = mStartingWindowRecords.get(taskId); if (record != null) { @@ -571,7 +587,8 @@ public class StartingSurfaceDrawer { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, "Removing splash screen window for task: %d", taskId); if (record.mContentView != null) { - if (record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { + if (immediately + || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { removeWindowInner(record.mDecorView, false); } else { if (removalInfo.playRevealAnimation) { @@ -594,8 +611,12 @@ public class StartingSurfaceDrawer { if (record.mTaskSnapshotWindow != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, "Removing task snapshot window for %d", taskId); - record.mTaskSnapshotWindow.scheduleRemove( - () -> mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme); + if (immediately) { + record.mTaskSnapshotWindow.removeImmediately(); + } else { + record.mTaskSnapshotWindow.scheduleRemove(() -> + mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme); + } } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index b62360ee45c59..487eb7055e40a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -193,6 +193,18 @@ public class StartingWindowController implements RemoteCallable { + mStartingSurfaceDrawer.clearAllWindows(); + synchronized (mTaskBackgroundColors) { + mTaskBackgroundColors.clear(); + } + }); + } + /** * The interface for calls from outside the Shell, within the host process. */ diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index 70b7c67934926..d92b12e60780c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -31,6 +31,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -117,16 +118,19 @@ public class StartingSurfaceDrawerTests { WindowManager.LayoutParams params, int suggestType) { // listen for addView mAddWindowForTask = taskId; + saveSplashScreenRecord(appToken, taskId, view, suggestType); // Do not wait for background color return false; } @Override - protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) { + protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, + boolean immediately) { // listen for removeView if (mAddWindowForTask == removalInfo.taskId) { mAddWindowForTask = 0; } + mStartingWindowRecords.remove(removalInfo.taskId); } } @@ -179,7 +183,7 @@ public class StartingSurfaceDrawerTests { removalInfo.taskId = windowInfo.taskInfo.taskId; mStartingSurfaceDrawer.removeStartingWindow(removalInfo); waitHandlerIdle(mTestHandler); - verify(mStartingSurfaceDrawer).removeWindowSynced(any()); + verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(false)); assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0); } @@ -267,11 +271,32 @@ public class StartingSurfaceDrawerTests { // Verify the task snapshot with IME snapshot will be removed when received the real IME // drawn callback. + // makeTaskSnapshotWindow shall call removeWindowSynced before there add a new + // StartingWindowRecord for the task. mStartingSurfaceDrawer.onImeDrawnOnTask(1); - verify(mockSnapshotWindow).removeImmediately(); + verify(mStartingSurfaceDrawer, times(2)) + .removeWindowSynced(any(), eq(true)); } } + @Test + public void testClearAllWindows() { + final int taskId = 1; + final StartingWindowInfo windowInfo = + createWindowInfo(taskId, android.R.style.Theme); + mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, + STARTING_WINDOW_TYPE_SPLASH_SCREEN); + waitHandlerIdle(mTestHandler); + verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(), + eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN)); + assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId); + + mStartingSurfaceDrawer.clearAllWindows(); + waitHandlerIdle(mTestHandler); + verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(true)); + assertEquals(mStartingSurfaceDrawer.mStartingWindowRecords.size(), 0); + } + private StartingWindowInfo createWindowInfo(int taskId, int themeResId) { StartingWindowInfo windowInfo = new StartingWindowInfo(); final ActivityInfo info = new ActivityInfo();