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

Commit c33658e5 authored by Robert Carr's avatar Robert Carr
Browse files

Fix auto-pip visibility issues.

In the case that we defer stop for auto-enter picture
in picture, we should also defer changing the visibility. This causes
particularly awkward issues with SurfaceView as the views are left
in a severed state.

Test: Auto-pip Chrome from youtube. Things look alright!
Bug: 36355266
Bug: 36640131
Change-Id: I77de1c3eb9c61b03740cbe49f88dec1af2ed6577
parent 068b429c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -7803,7 +7803,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                // Activity supports picture-in-picture, now check that we can enter PiP at this
                // point, if it is
                if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode",
                        false /* noThrow */)) {
                        false /* noThrow */, false /* beforeStopping */)) {
                    return false;
                }
+13 −3
Original line number Diff line number Diff line
@@ -1156,10 +1156,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
    }

    /**
     * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
     *         the activity has requested to enter PiP when it would otherwise be stopped.
     *
     * @return whether this activity is currently allowed to enter PIP, throwing an exception if
     *         the activity is not currently visible and {@param noThrow} is not set.
     */
    boolean checkEnterPictureInPictureState(String caller, boolean noThrow) {
    boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) {
        // Check app-ops and see if PiP is supported for this package
        if (!checkEnterPictureInPictureAppOpsState()) {
            return false;
@@ -1170,17 +1173,24 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
            return false;
        }

        boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
        boolean isKeyguardLocked = service.isKeyguardLocked();
        boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
        boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null;
        // Don't return early if !isNotLocked, since we want to throw an exception if the activity
        // is in an incorrect state
        boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;

        // We don't allow auto-PiP when something else is already pipped.
        if (beforeStopping && hasPinnedStack) {
            return false;
        }

        switch (state) {
            case RESUMED:
                // When visible, allow entering PiP if the app is not locked.  If it is over the
                // keyguard, then we will prompt to unlock in the caller before entering PiP.
                return !isCurrentAppLocked;
                return !isCurrentAppLocked &&
                        (supportsPictureInPictureWhilePausing || !beforeStopping);
            case PAUSING:
            case PAUSED:
                // When pausing, then only allow enter PiP as in the resume state, and in addition,
+14 −2
Original line number Diff line number Diff line
@@ -1989,10 +1989,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        // keeping the screen frozen.
        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state);
        try {
            r.setVisible(false);
            switch (r.state) {
                case STOPPING:
                case STOPPED:
                    r.setVisible(false);
                    if (r.app != null && r.app.thread != null) {
                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                                "Scheduling invisibility: " + r);
@@ -2011,6 +2011,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
                    // This case created for transitioning activities from
                    // translucent to opaque {@link Activity#convertToOpaque}.
                    if (visibleBehind == r) {
                        r.setVisible(false);
                        releaseBackgroundResources(r);
                    } else {
                        // If this activity is in a state where it can currently enter
@@ -2018,7 +2019,18 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
                        // the activity tries to enterPictureInPictureMode() later. Otherwise,
                        // we will try and stop the activity next time idle is processed.
                        final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
                                "makeInvisible", true /* noThrow */);
                                "makeInvisible", true /* noThrow */, true /* beforeStopping */);

                        if (canEnterPictureInPicture) {
                            // We set r.visible=false so that Stop will later
                            // call setVisible for us. In this case
                            // we don't want to call setVisible(false) to avoid
                            // notifying the client of this intermittent invisible
                            // state.
                            r.visible = false;
                        } else {
                            r.setVisible(false);
                        }
                        addToStopping(r, true /* scheduleIdle */,
                                canEnterPictureInPicture /* idleDelayed */);
                    }