diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index fd64cf828f155..50ac4330facd3 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -352,6 +352,12 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { */ private int mVisibilityTransactionDepth; + /** + * Whether to the visibility updates that started from {@code RootWindowContainer} should be + * deferred. + */ + private boolean mDeferRootVisibilityUpdate; + private ActivityMetricsLogger mActivityMetricsLogger; /** Check if placing task or activity on specified display is allowed. */ @@ -2297,6 +2303,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { return mVisibilityTransactionDepth > 0; } + void setDeferRootVisibilityUpdate(boolean deferUpdate) { + mDeferRootVisibilityUpdate = deferUpdate; + } + + boolean isRootVisibilityUpdateDeferred() { + return mDeferRootVisibilityUpdate; + } + /** * Called when the state or visibility of an attached activity is changed. * diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index da3f9839ad1c7..079868d0dec14 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1998,7 +1998,8 @@ class RootWindowContainer extends WindowContainer */ void ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { - if (mTaskSupervisor.inActivityVisibilityUpdate()) { + if (mTaskSupervisor.inActivityVisibilityUpdate() + || mTaskSupervisor.isRootVisibilityUpdateDeferred()) { // Don't do recursive work. return; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index fec7edefd66d1..f6317a49b4d88 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4665,8 +4665,10 @@ class Task extends TaskFragment { mAtmService.continueWindowLayout(); } - mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); - mRootWindowContainer.resumeFocusedTasksTopActivities(); + if (!mTaskSupervisor.isRootVisibilityUpdateDeferred()) { + mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); + mRootWindowContainer.resumeFocusedTasksTopActivities(); + } } void resumeNextFocusAfterReparent() { diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index b5d98a6b0b772..6ce4f8976b26e 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -322,6 +322,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub int effects = 0; ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId); mService.deferWindowLayout(); + mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */); try { if (transition != null) { // First check if we have a display rotation transition and if so, update it. @@ -411,6 +412,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub task.setMainWindowSizeChangeTransaction(sft); } if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) { + mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */); // Already calls ensureActivityConfig mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); mService.mRootWindowContainer.resumeFocusedTasksTopActivities(); @@ -432,6 +434,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub mService.addWindowLayoutReasons(LAYOUT_REASON_CONFIG_CHANGED); } } finally { + mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */); mService.continueWindowLayout(); } } @@ -472,7 +475,15 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub throw new UnsupportedOperationException("Not supported to set multi-window" + " windowing mode during locked task mode."); } + + final int prevMode = container.getWindowingMode(); container.setWindowingMode(windowingMode); + if (prevMode != container.getWindowingMode()) { + // The activity in the container may become focusable or non-focusable due to + // windowing modes changes (such as entering or leaving pinned windowing mode), + // so also apply the lifecycle effects to this transaction. + effects |= TRANSACT_EFFECTS_LIFECYCLE; + } } return effects; } 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 39fe952cc1998..9160109e7e7fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -81,6 +81,7 @@ import android.window.ITaskOrganizer; import android.window.IWindowContainerTransactionCallback; import android.window.StartingWindowInfo; import android.window.TaskAppearedInfo; +import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; @@ -1275,6 +1276,24 @@ public class WindowOrganizerTests extends WindowTestsBase { assertTrue(optionsCaptor.getValue().getOriginalOptions().getTransientLaunch()); } + @Test + public void testResumeTopsWhenLeavingPinned() { + final ActivityRecord record = makePipableActivity(); + final Task rootTask = record.getRootTask(); + + clearInvocations(mWm.mAtmService.mRootWindowContainer); + final WindowContainerTransaction t = new WindowContainerTransaction(); + WindowContainerToken wct = rootTask.mRemoteToken.toWindowContainerToken(); + t.setWindowingMode(wct, WINDOWING_MODE_PINNED); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); + verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities(); + + clearInvocations(mWm.mAtmService.mRootWindowContainer); + t.setWindowingMode(wct, WINDOWING_MODE_FULLSCREEN); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); + verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities(); + } + /** * Verifies that task vanished is called for a specific task. */