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

Commit 9d186163 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Validate visibility when finishing transition

If the transition info doesn't contain any visible modes,
then recover the visible state of surface for the correspond
window container.

This avoids showing blank screen by an incomplete transition
that hides task or display area unexpectedly.

Bug: 273206473
Fix: 269732484
Test: Assume a task X has an Activity A.
      Consecutive steps:
      Start B: X[A, B]
      Start A' with FLAG_ACTIVITY_CLEAR_TOP to finish [A, B]
      Final: X[A']
      The surface of Task X and its parent should be visible.

Change-Id: Id9de134a2ddc04f7ed7fb2d3c67d7337261c5ba7
parent 0177c5f2
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -1012,6 +1012,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
            dc.removeImeSurfaceImmediately();
            dc.handleCompleteDeferredRemoval();
        }
        validateVisibility();

        mState = STATE_FINISHED;
        mController.mTransitionTracer.logState(this);
@@ -1920,6 +1921,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
                change.setLastParent(info.mStartParent.mRemoteToken.toWindowContainerToken());
            }
            change.setMode(info.getTransitMode(target));
            info.mReadyMode = change.getMode();
            change.setStartAbsBounds(info.mAbsoluteBounds);
            change.setFlags(info.getChangeFlags(target));
            change.setDisplayId(info.mDisplayId, getDisplayId(target));
@@ -2177,6 +2179,26 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        return mainWin.getAttrs().rotationAnimation;
    }

    private void validateVisibility() {
        for (int i = mTargets.size() - 1; i >= 0; --i) {
            if (reduceMode(mTargets.get(i).mReadyMode) != TRANSIT_CLOSE) {
                return;
            }
        }
        // All modes are CLOSE. The surfaces may be hidden by the animation unexpectedly.
        // If the window container should be visible, then recover it.
        mController.mStateValidators.add(() -> {
            for (int i = mTargets.size() - 1; i >= 0; --i) {
                final ChangeInfo change = mTargets.get(i);
                if (!change.mContainer.isVisibleRequested()) continue;
                Slog.e(TAG, "Force show for visible " + change.mContainer
                        + " which may be hidden by transition unexpectedly");
                change.mContainer.getSyncTransaction().show(change.mContainer.mSurfaceControl);
                change.mContainer.scheduleAnimation();
            }
        });
    }

    /** Applies the new configuration for the changed displays. */
    void applyDisplayChangeIfNeeded() {
        for (int i = mParticipants.size() - 1; i >= 0; --i) {
@@ -2262,6 +2284,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        SurfaceControl mSnapshot;
        float mSnapshotLuma;

        /** The mode which is set when the transition is ready. */
        @TransitionInfo.TransitionMode
        int mReadyMode;

        ChangeInfo(@NonNull WindowContainer origState) {
            mContainer = origState;
            mVisible = origState.isVisibleRequested();