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

Commit bd34b1b5 authored by Jeremy Sim's avatar Jeremy Sim
Browse files

Fix bug where splitscreen causes unlaunchable camera

This CL changes the way split is dismissed when folding and locking.

Camera launch was broken in two ways:

1) Previously, we checked for occluding apps in onKeyguardStateChanged to determine if we had a SHOW_ABOVE_LOCKED case or not. However, this signal was not exact, and was catching a case where the camera is launched using the power button double-tap feature. Since Camera has the SHOW_ABOVE_LOCKED flag, this was erroneously triggering the "break split" case, breaking split, and preventing the camera from launching (even when Camera had nothing to do with the split pair).

Now, we perform the check instead of StageCoordinator.startAnimation, where we can see more clearly which split apps are being sent TO_BACK or not. If not all the split apps are being sent to back in the same transition, we assume we are in a SHOW_ABOVE_LOCKED case, and break split there.

2) Previously, on device fold, we would check for a wake signal and use it to break split (due to UX-specified behavior that split should break on fold + lock + wake). This was being done in onFinishedWakingUp(), which inadvertently clobbered the Camera launch when the Camera was the wake trigger.

Now we perform the same behavior, but onStartedWakingUp() instead, which happens slightly earlier and does not clobber the Camera.

Fixes: 373477295
Test: Repro steps do not repro anymore
Flag: EXEMPT bugfix
Change-Id: I49b3b104c10cc844caf217e4879eddd3332d1972
parent 14464854
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -110,12 +110,12 @@ public interface SplitScreen {
    void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
    void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
            @NonNull Executor executor);
            @NonNull Executor executor);


    /** Called when device waking up finished. */
    void onFinishedWakingUp();

    /** Called when device starts going to sleep (screen off). */
    /** Called when device starts going to sleep (screen off). */
    void onStartedGoingToSleep();
    void onStartedGoingToSleep();


    /** Called when device wakes up. */
    void onStartedWakingUp();

    /** Called when requested to go to fullscreen from the current active split app. */
    /** Called when requested to go to fullscreen from the current active split app. */
    void goToFullscreenFromSplit();
    void goToFullscreenFromSplit();


+8 −8
Original line number Original line Diff line number Diff line
@@ -471,14 +471,14 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
        mStageCoordinator.onKeyguardStateChanged(visible, occluded);
        mStageCoordinator.onKeyguardStateChanged(visible, occluded);
    }
    }


    public void onFinishedWakingUp() {
        mStageCoordinator.onFinishedWakingUp();
    }

    public void onStartedGoingToSleep() {
    public void onStartedGoingToSleep() {
        mStageCoordinator.onStartedGoingToSleep();
        mStageCoordinator.onStartedGoingToSleep();
    }
    }


    public void onStartedWakingUp() {
        mStageCoordinator.onStartedWakingUp();
    }

    public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
    public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
        mStageCoordinator.exitSplitScreenOnHide(exitSplitScreenOnHide);
        mStageCoordinator.exitSplitScreenOnHide(exitSplitScreenOnHide);
    }
    }
@@ -1073,13 +1073,13 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
        }
        }


        @Override
        @Override
        public void onFinishedWakingUp() {
        public void onStartedGoingToSleep() {
            mMainExecutor.execute(SplitScreenController.this::onFinishedWakingUp);
            mMainExecutor.execute(SplitScreenController.this::onStartedGoingToSleep);
        }
        }


        @Override
        @Override
        public void onStartedGoingToSleep() {
        public void onStartedWakingUp() {
            mMainExecutor.execute(SplitScreenController.this::onStartedGoingToSleep);
            mMainExecutor.execute(SplitScreenController.this::onStartedWakingUp);
        }
        }


        @Override
        @Override
+38 −15
Original line number Original line Diff line number Diff line
@@ -1138,14 +1138,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                "onKeyguardVisibilityChanged: active=%b occludingTaskRunning=%b",
                "onKeyguardVisibilityChanged: active=%b occludingTaskRunning=%b",
                active, occludingTaskRunning);
                active, occludingTaskRunning);
        setDividerVisibility(!mKeyguardActive, null);
        setDividerVisibility(!mKeyguardActive, null);

        if (active && occludingTaskRunning) {
            dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
        }
    }
    }


    void onFinishedWakingUp() {
    void onStartedWakingUp() {
        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinishedWakingUp");
        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onStartedWakingUp");
        if (mBreakOnNextWake) {
        if (mBreakOnNextWake) {
            dismissSplitKeepingLastActiveStage(EXIT_REASON_DEVICE_FOLDED);
            dismissSplitKeepingLastActiveStage(EXIT_REASON_DEVICE_FOLDED);
        }
        }
@@ -2485,6 +2481,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            final int transitType = info.getType();
            final int transitType = info.getType();
            TransitionInfo.Change pipChange = null;
            TransitionInfo.Change pipChange = null;
            int closingSplitTaskId = -1;
            int closingSplitTaskId = -1;
            // This array tracks if we are sending stages TO_BACK in this transition.
            // TODO (b/349828130): Update for n apps
            boolean[] stagesSentToBack = new boolean[2];

            for (int iC = 0; iC < info.getChanges().size(); ++iC) {
            for (int iC = 0; iC < info.getChanges().size(); ++iC) {
                final TransitionInfo.Change change = info.getChanges().get(iC);
                final TransitionInfo.Change change = info.getChanges().get(iC);
                if (change.getMode() == TRANSIT_CHANGE
                if (change.getMode() == TRANSIT_CHANGE
@@ -2552,23 +2552,31 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    }
                    }
                    continue;
                    continue;
                }
                }
                final int taskId = taskInfo.taskId;
                if (isOpeningType(change.getMode())) {
                if (isOpeningType(change.getMode())) {
                    if (!stage.containsTask(taskInfo.taskId)) {
                    if (!stage.containsTask(taskId)) {
                        Log.w(TAG, "Expected onTaskAppeared on " + stage + " to have been called"
                        Log.w(TAG, "Expected onTaskAppeared on " + stage + " to have been called"
                                + " with " + taskInfo.taskId + " before startAnimation().");
                                + " with " + taskId + " before startAnimation().");
                        record.addRecord(stage, true, taskInfo.taskId);
                        record.addRecord(stage, true, taskId);
                    }
                    }
                } else if (change.getMode() == TRANSIT_CLOSE) {
                } else if (change.getMode() == TRANSIT_CLOSE) {
                    if (stage.containsTask(taskInfo.taskId)) {
                    if (stage.containsTask(taskId)) {
                        record.addRecord(stage, false, taskInfo.taskId);
                        record.addRecord(stage, false, taskId);
                        Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
                        Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
                                + " with " + taskInfo.taskId + " before startAnimation().");
                                + " with " + taskId + " before startAnimation().");
                    }
                    }
                }
                }
                if (isClosingType(change.getMode()) &&
                if (isClosingType(change.getMode()) &&
                        getStageOfTask(change.getTaskInfo().taskId) != STAGE_TYPE_UNDEFINED) {
                        getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED) {
                    // If either one of the 2 stages is closing we're assuming we'll break split

                    closingSplitTaskId = change.getTaskInfo().taskId;
                    // Record which stages are getting sent to back
                    if (change.getMode() == TRANSIT_TO_BACK) {
                        stagesSentToBack[getStageOfTask(taskId)] = true;
                    }

                    // (For PiP transitions) If either one of the 2 stages is closing we're assuming
                    // we'll break split
                    closingSplitTaskId = taskId;
                }
                }
            }
            }


@@ -2594,6 +2602,21 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                return true;
                return true;
            }
            }


            // If keyguard is active, check to see if we have our TO_BACK transitions in order.
            // This array should either be all false (no split stages sent to back) or all true
            // (all stages sent to back). In any other case (which can happen with SHOW_ABOVE_LOCKED
            // apps) we should break split.
            if (mKeyguardActive) {
                boolean isFirstStageSentToBack = stagesSentToBack[0];
                for (boolean b : stagesSentToBack) {
                    // Compare each boolean to the first one. If any are different, break split.
                    if (b != isFirstStageSentToBack) {
                        dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
                        break;
                    }
                }
            }

            final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
            final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
            if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0
            if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0
                    || dismissStages.size() == 1) {
                    || dismissStages.size() == 1) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -320,7 +320,7 @@ public class StageCoordinatorTests extends ShellTestCase {


        assertEquals(mStageCoordinator.mLastActiveStage, STAGE_TYPE_MAIN);
        assertEquals(mStageCoordinator.mLastActiveStage, STAGE_TYPE_MAIN);


        mStageCoordinator.onFinishedWakingUp();
        mStageCoordinator.onStartedWakingUp();


        verify(mTaskOrganizer).startNewTransition(eq(TRANSIT_SPLIT_DISMISS), notNull());
        verify(mTaskOrganizer).startNewTransition(eq(TRANSIT_SPLIT_DISMISS), notNull());
    }
    }
+4 −4
Original line number Original line Diff line number Diff line
@@ -281,13 +281,13 @@ public final class WMShell implements
    void initSplitScreen(SplitScreen splitScreen) {
    void initSplitScreen(SplitScreen splitScreen) {
        mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
        mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
            @Override
            @Override
            public void onFinishedWakingUp() {
            public void onStartedGoingToSleep() {
                splitScreen.onFinishedWakingUp();
                splitScreen.onStartedGoingToSleep();
            }
            }


            @Override
            @Override
            public void onStartedGoingToSleep() {
            public void onStartedWakingUp() {
                splitScreen.onStartedGoingToSleep();
                splitScreen.onStartedWakingUp();
            }
            }
        });
        });
        mCommandQueue.addCallback(new CommandQueue.Callbacks() {
        mCommandQueue.addCallback(new CommandQueue.Callbacks() {