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

Commit 3fc49ae1 authored by Riddle Hsu's avatar Riddle Hsu Committed by Robin Lee
Browse files

Improve surface visibility recovering with transition

For example:
 1. A transition contains an incorrect info which will set X
    to be invisible.
 2. When the transition is playing, set the surface of X to
    visible directly if there is no collecting transition.
 3. The transition of step 1 finishes, which applies invisible
    to X, then the recovering of step 2 doesn't help.

So it will be more robust to recover until the playing transitions
are finished. Then it can also cover some cases of other visibility
validators.

Bug: 303613521
Test: Finish several activities when switching display.
      The surface of foreground activity and its parent should
      keep visible.
Change-Id: I2ecb714ef0eaf94f8950bd4cd3857abfb1c46fbc
parent 2f4e88a2
Loading
Loading
Loading
Loading
+4 −11
Original line number Diff line number Diff line
@@ -5367,18 +5367,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                // rather than just direct membership.
                inFinishingTransition = mTransitionController.inFinishingTransition(this);
                if (!inFinishingTransition && (visible || !mDisplayContent.isSleeping())) {
                    Slog.e(TAG, "setVisibility=" + visible
                            + " while transition is not collecting or finishing "
                            + this + " caller=" + Debug.getCallers(8));
                    // Force showing the parents because they may be hidden by previous transition.
                    if (visible) {
                        final Transaction t = getSyncTransaction();
                        for (WindowContainer<?> p = getParent(); p != null && p != mDisplayContent;
                                p = p.getParent()) {
                            if (p.mSurfaceControl != null) {
                                t.show(p.mSurfaceControl);
                            }
                        }
                        mTransitionController.onVisibleWithoutCollectingTransition(this,
                                Debug.getCallers(1, 1));
                    } else {
                        Slog.w(TAG, "Set invisible without transition " + this);
                    }
                }
            }
+0 −24
Original line number Diff line number Diff line
@@ -1391,7 +1391,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
            dc.handleCompleteDeferredRemoval();
        }
        validateKeyguardOcclusion();
        validateVisibility();

        mState = STATE_FINISHED;
        // Rotation change may be deferred while there is a display change transition, so check
@@ -2766,29 +2765,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        }
    }

    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()
                        || change.mContainer.mSurfaceControl == null) {
                    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();
            }
        });
    }

    /**
     * Returns {@code true} if the transition and the corresponding transaction should be applied
     * on display thread. Currently, this only checks for display rotation change because the order
+30 −0
Original line number Diff line number Diff line
@@ -960,6 +960,36 @@ class TransitionController {
        mValidateDisplayVis.clear();
    }

    void onVisibleWithoutCollectingTransition(WindowContainer<?> wc, String caller) {
        final boolean isPlaying = !mPlayingTransitions.isEmpty();
        Slog.e(TAG, "Set visible without transition " + wc + " playing=" + isPlaying
                + " caller=" + caller);
        if (!isPlaying) {
            enforceSurfaceVisible(wc);
            return;
        }
        // Update surface visibility after the playing transitions are finished, so the last
        // visibility won't be replaced by the finish transaction of transition.
        mStateValidators.add(() -> {
            if (wc.isVisibleRequested()) {
                enforceSurfaceVisible(wc);
            }
        });
    }

    private void enforceSurfaceVisible(WindowContainer<?> wc) {
        if (wc.mSurfaceControl == null) return;
        wc.getSyncTransaction().show(wc.mSurfaceControl);
        // Force showing the parents because they may be hidden by previous transition.
        for (WindowContainer<?> p = wc.getParent(); p != null && p != wc.mDisplayContent;
                p = p.getParent()) {
            if (p.mSurfaceControl != null) {
                p.getSyncTransaction().show(p.mSurfaceControl);
            }
        }
        wc.scheduleAnimation();
    }

    /**
     * Called when the transition has a complete set of participants for its operation. In other
     * words, it is when the transition is "ready" but is still waiting for participants to draw.