diff options
| author | 2020-06-09 11:23:29 +0200 | |
|---|---|---|
| committer | 2020-06-10 18:11:42 +0200 | |
| commit | 4a46a92e39b867b3e6910cea9c7a5ef15726f4fc (patch) | |
| tree | 0c94887e1082c4af08453b8dd23e3427db4e347a | |
| parent | ab0ffd1d48e5ca54ca80280796ce279edf83e0fc (diff) | |
Fix unexpected closure of the bubble.
WindowManager calls ATMS#notifySingleTaskDisplayEmpty to notify that the
last task is removed from a single task display.
Originally it was called from ActivityStack when Tsak is removed, but
while merging ActivityStack and Task, CL[1] moved the call to Task. As a
result, the lister gets notification when ActivityRecord is removed,
instead of a last Task is removed, which causes unexpected bubble
closure.
[1]: Ifb167129c89a3aba11796daa21a9dee7200913ca
Bug: 157067689
Test: atest TaskStackChangedListnerTest
Change-Id: I93b745ba7fd1bb2fbef7915ddff2316100813187
3 files changed, 29 insertions, 11 deletions
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 3ee7ee7a4276..ce2ae2a42069 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -1436,15 +1436,6 @@ class Task extends WindowContainer<WindowContainer> { mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged(); } - final boolean isRootTask = isRootTask(); - if (isRootTask) { - final DisplayContent display = getDisplayContent(); - if (display.isSingleTaskInstance()) { - mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId); - } - display.mDisplayContent.setLayoutNeeded(); - } - if (hasChild()) { updateEffectiveIntent(); @@ -1465,7 +1456,7 @@ class Task extends WindowContainer<WindowContainer> { } else if (!mReuseTask && !mCreatedByOrganizer) { // Remove entire task if it doesn't have any activity left and it isn't marked for reuse // or created by task organizer. - if (!isRootTask) { + if (!isRootTask()) { getStack().removeChild(this, reason); } EventLogTags.writeWmTaskRemoved(mTaskId, @@ -2817,6 +2808,10 @@ class Task extends WindowContainer<WindowContainer> { if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId); EventLogTags.writeWmTaskRemoved(mTaskId, "removeTask"); + if (mDisplayContent != null && mDisplayContent.isSingleTaskInstance()) { + mAtmService.notifySingleTaskDisplayEmpty(mDisplayContent.mDisplayId); + } + // If applicable let the TaskOrganizer know the Task is vanishing. setTaskOrganizer(null); diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml index 30df0d4b4ad9..4040fa6a675e 100644 --- a/services/tests/wmtests/AndroidManifest.xml +++ b/services/tests/wmtests/AndroidManifest.xml @@ -54,6 +54,8 @@ <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityViewTestActivity" /> <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityInActivityView" android:resizeableActivity="true" /> + <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityLaunchesNewActivityInActivityView" + android:resizeableActivity="true" /> <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$LandscapeActivity" android:screenOrientation="sensorLandscape" android:showWhenLocked="true" diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java index 2c17bbeae498..2bd342420e2c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java @@ -299,6 +299,20 @@ public class TaskStackChangedListenerTest { waitForCallback(singleTaskDisplayDrawnLatch); } + public static class ActivityLaunchesNewActivityInActivityView extends TestActivity { + private boolean mActivityBLaunched = false; + + @Override + protected void onPostResume() { + super.onPostResume(); + if (mActivityBLaunched) { + return; + } + mActivityBLaunched = true; + startActivity(new Intent(this, ActivityB.class)); + } + } + @Test public void testSingleTaskDisplayEmpty() throws Exception { final Instrumentation instrumentation = getInstrumentation(); @@ -335,13 +349,20 @@ public class TaskStackChangedListenerTest { }); waitForCallback(activityViewReadyLatch); + // 1. start ActivityLaunchesNewActivityInActivityView in an ActivityView + // 2. ActivityLaunchesNewActivityInActivityView launches ActivityB + // 3. ActivityB finishes self. + // 4. Verify ITaskStackListener#onSingleTaskDisplayEmpty is not called yet. final Context context = instrumentation.getContext(); - Intent intent = new Intent(context, ActivityInActivityView.class); + Intent intent = new Intent(context, ActivityLaunchesNewActivityInActivityView.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); activityView.startActivity(intent); waitForCallback(singleTaskDisplayDrawnLatch); + UiDevice.getInstance(getInstrumentation()).waitForIdle(); assertEquals(1, singleTaskDisplayEmptyLatch.getCount()); + // 5. Release the container, and ActivityLaunchesNewActivityInActivityView finishes. + // 6. Verify ITaskStackListener#onSingleTaskDisplayEmpty is called. activityView.release(); waitForCallback(activityViewDestroyedLatch); waitForCallback(singleTaskDisplayEmptyLatch); |