Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50c77e2c authored by Ikram Gabiyev's avatar Ikram Gabiyev
Browse files

[PiP2]Send config changes after stop upon PiP-exit

  Context:
In an effort to have PiP2 rely on Transitions as much as possible,
we had it adhere to Transitions policy on lifecycle and config-changes.
More specifically, with PiP2 we just send configuration updates upon
transition start/end as needed.

  Issue:
When an activity's isVisibleRequested=false, Transitions framework skips
the dispatch of config-updates to the client after lifecycle updates
(i.e. onStop). However, PiP needs to follow a contract wherein
onPictureInPictureModeChanged(inPip, newConfig) is dispatched with
the latest new config even after the activity receives onStop.

  Solution:
To send config updates for the activity leaving PiP right after
scheduling its stopping. Unlike how it's done in PiP1 with a
special-case force-hidden, we are doing this at the end of the
transition, as our goal is to keep running the remove-PiP animation
as a part of TRANSIT_REMOVE_PIP while the activity is PAUSED.

We can reuse ActivityRecord#updatePictureInPictureMode() for this.

Bug: 403103525
Flag: com.android.wm.shell.enable_pip2
Test: atest PinnedStackTests#testStopBeforeMultiWindowCallbacksOnDismiss

Change-Id: I2f1f7a11fb44dcbcb582d8693089a0893da3d013
parent 7d18bdd7
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1438,7 +1438,7 @@ final class ActivityRecord extends WindowToken {
            // precede the configuration change from the resize.)
            mLastReportedPictureInPictureMode = inPictureInPictureMode;
            mLastReportedMultiWindowMode = inPictureInPictureMode;
            if (!isPip2ExperimentEnabled()) {
            if (forceUpdate || !isPip2ExperimentEnabled()) {
                // PiP2 should handle sending out the configuration as a part of Shell Transitions.
                ensureActivityConfiguration(true /* ignoreVisibility */);
            }
@@ -6377,6 +6377,15 @@ final class ActivityRecord extends WindowToken {
            isSuccessful = false;
        }
        if (isSuccessful) {
            final int lastReportedWinMode = mLastReportedConfiguration.getMergedConfiguration()
                    .windowConfiguration.getWindowingMode();
            if (isPip2ExperimentEnabled()
                    && lastReportedWinMode == WINDOWING_MODE_PINNED && !inPinnedWindowingMode()) {
                // If an activity that was previously reported as pinned has a different windowing
                // mode, then send the latest activity configuration even if this activity is
                // stopping. This ensures that app gets onPictureInPictureModeChanged after onStop.
                updatePictureInPictureMode(null /* targetRootTaskBounds */, true /* forceUpdate */);
            }
            mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
        } else {
            // Just in case, assume it to be stopped.
+8 −3
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_SUPERVISOR_TASK_MSG;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.isPip2ExperimentEnabled;
import static com.android.server.wm.ClientLifecycleManager.shouldDispatchLaunchActivityItemIndependently;
import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED;
import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE;
@@ -1684,9 +1685,13 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
         */
        rootTask.cancelAnimation();
        rootTask.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */);
        if (!isPip2ExperimentEnabled()) {
            // In PiP2, as the transition finishes the lifecycle updates will be sent to the app
            // along with the configuration changes as a part of the transition lifecycle.
            rootTask.ensureActivitiesVisible(null /* starting */);
            activityIdleInternal(null /* idleActivity */, false /* fromTimeout */,
                    true /* processPausingActivities */, null /* configuration */);
        }

        if (rootTask.getParent() == null) {
            // The activities in the task may already be finishing. Then the task could be removed