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

Commit 25c92d92 authored by Evan Rosky's avatar Evan Rosky
Browse files

Fix defer-display-removal logic

WindowAnimator.animate repeatedly calls into
handleCompleteDeferredRemoval() which wasn't checking
the same conditions as removeIfPossible() (which is
the function that actually sets mDeferredRemoval). This
meant that removeImmediately() would be called early
at times and break CTS tests.

Similarly, moved the onDisplayRemoved call in keyguard
controller to removeImmediately() so that it wouldn't
get called prematurely.

Also fix a NPE in DefaultTransitionHandler

Bug: 183993924
Test: atest MultiDisplayPolicyTests (with shell-transitions)
Change-Id: I73b10a290a3b2be6ea4d978190863cc6ce62ef8f
parent 0ef7951d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -419,8 +419,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
                    // hasRoundedCorners is currently only enabled for tasks
                    final Context displayContext =
                            mDisplayController.getDisplayContext(change.getTaskInfo().displayId);
                    cornerRadius =
                            ScreenDecorationsUtils.getWindowCornerRadius(displayContext);
                    cornerRadius = displayContext == null ? 0
                            : ScreenDecorationsUtils.getWindowCornerRadius(displayContext);
                } else {
                    cornerRadius = 0;
                }
+12 −7
Original line number Diff line number Diff line
@@ -3127,12 +3127,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        mDisplayPolicy.switchUser();
    }

    @Override
    void removeIfPossible() {
        if (isAnimating(TRANSITION | PARENTS)
    private boolean shouldDeferRemoval() {
        return isAnimating(TRANSITION | PARENTS)
                // isAnimating is a legacy transition query and will be removed, so also add a
                // check for whether this is in a shell-transition when not using legacy.
                || mTransitionController.inTransition()) {
                || mTransitionController.isTransitionOnDisplay(this);
    }

    @Override
    void removeIfPossible() {
        if (shouldDeferRemoval()) {
            mDeferredRemoval = true;
            return;
        }
@@ -3161,6 +3165,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mInputMonitor.onDisplayRemoved();
            mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
            mWmService.mAccessibilityController.onDisplayRemoved(mDisplayId);
            mRootWindowContainer.mTaskSupervisor
                    .getKeyguardController().onDisplayRemoved(mDisplayId);
        } finally {
            mDisplayReady = false;
        }
@@ -3174,7 +3180,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    /** Returns true if a removal action is still being deferred. */
    @Override
    boolean handleCompleteDeferredRemoval() {
        final boolean stillDeferringRemoval = super.handleCompleteDeferredRemoval();
        final boolean stillDeferringRemoval =
                super.handleCompleteDeferredRemoval() || shouldDeferRemoval();

        if (!stillDeferringRemoval && mDeferredRemoval) {
            removeImmediately();
@@ -5915,8 +5922,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            forAllRootTasks(t -> {t.removeIfPossible("releaseSelfIfNeeded");});
        } else if (getTopRootTask() == null) {
            removeIfPossible();
            mRootWindowContainer.mTaskSupervisor
                    .getKeyguardController().onDisplayRemoved(mDisplayId);
        }
    }

+37 −25
Original line number Diff line number Diff line
@@ -158,8 +158,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
    /** The final animation targets derived from participants after promotion. */
    private ArrayList<WindowContainer> mTargets;

    /** The main display running this transition. */
    private DisplayContent mTargetDisplay;
    /** The displays that this transition is running on. */
    private final ArrayList<DisplayContent> mTargetDisplays = new ArrayList<>();

    /**
     * Set of participating windowtokens (activity/wallpaper) which are visible at the end of
@@ -209,6 +209,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
        return mTransientLaunches != null && mTransientLaunches.contains(activity);
    }

    boolean isOnDisplay(@NonNull DisplayContent dc) {
        return mTargetDisplays.contains(dc);
    }

    void setSeamlessRotation(@NonNull WindowContainer wc) {
        final ChangeInfo info = mChanges.get(wc);
        if (info == null) return;
@@ -280,6 +284,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            mChanges.put(wc, info);
        }
        mParticipants.add(wc);
        if (wc.getDisplayContent() != null && !mTargetDisplays.contains(wc.getDisplayContent())) {
            mTargetDisplays.add(wc.getDisplayContent());
        }
        if (info.mShowWallpaper) {
            // Collect the wallpaper token (for isWallpaper(wc)) so it is part of the sync set.
            final WindowState wallpaper =
@@ -516,15 +523,23 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            dc.getInputMonitor().setActiveRecents(null /* activity */, null /* layer */);
        }

        final AsyncRotationController asyncRotationController =
                mTargetDisplay.getAsyncRotationController();
        for (int i = 0; i < mTargetDisplays.size(); ++i) {
            final DisplayContent dc = mTargetDisplays.get(i);
            final AsyncRotationController asyncRotationController = dc.getAsyncRotationController();
            if (asyncRotationController != null) {
                asyncRotationController.onTransitionFinished();
            }
            if (mTransientLaunches != null) {
                // Transient-launch activities cannot be IME target (WindowState#canBeImeTarget),
                // so re-compute in case the IME target is changed after transition.
        if (mTransientLaunches != null) {
            mTargetDisplay.computeImeTarget(true /* updateImeTarget */);
                for (int t = 0; t < mTransientLaunches.size(); ++t) {
                    if (mTransientLaunches.valueAt(t).getDisplayContent() == dc) {
                        dc.computeImeTarget(true /* updateImeTarget */);
                        break;
                    }
                }
            }
            dc.handleCompleteDeferredRemoval();
        }
    }

@@ -555,19 +570,13 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            Slog.e(TAG, "Unexpected Sync ID " + syncId + ". Expected " + mSyncId);
            return;
        }
        boolean hasWallpaper = false;
        DisplayContent dc = null;
        for (int i = mParticipants.size() - 1; i >= 0; --i) {
            final WindowContainer<?> wc = mParticipants.valueAt(i);
            if (dc == null && wc.mDisplayContent != null) {
                dc = wc.mDisplayContent;
            }
            if (!hasWallpaper && isWallpaper(wc)) {
                hasWallpaper = true;
        if (mTargetDisplays.isEmpty()) {
            mTargetDisplays.add(mController.mAtm.mRootWindowContainer.getDefaultDisplay());
        }
        }
        if (dc == null) dc = mController.mAtm.mRootWindowContainer.getDefaultDisplay();
        mTargetDisplay = dc;
        // While there can be multiple DC's involved. For now, we just use the first one as
        // the "primary" one for most things. Eventually, this will need to change, but, for the
        // time being, we don't have full cross-display transitions so it isn't a problem.
        final DisplayContent dc = mTargetDisplays.get(0);

        if (mState == STATE_ABORT) {
            mController.abort(this);
@@ -577,8 +586,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            return;
        }
        // Ensure that wallpaper visibility is updated with the latest wallpaper target.
        if (hasWallpaper) {
            dc.mWallpaperController.adjustWallpaperWindows();
        for (int i = mParticipants.size() - 1; i >= 0; --i) {
            final WindowContainer<?> wc = mParticipants.valueAt(i);
            if (isWallpaper(wc) && wc.getDisplayContent() != null) {
                wc.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
            }
        }

        mState = STATE_PLAYING;
+11 −0
Original line number Diff line number Diff line
@@ -256,6 +256,17 @@ class TransitionController {
        return false;
    }

    /** @return {@code true} if wc is in a participant subtree */
    boolean isTransitionOnDisplay(@NonNull DisplayContent dc) {
        if (mCollectingTransition != null && mCollectingTransition.isOnDisplay(dc)) {
            return true;
        }
        for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
            if (mPlayingTransitions.get(i).isOnDisplay(dc)) return true;
        }
        return false;
    }

    /**
     * @return {@code true} if {@param ar} is part of a transient-launch activity in an active
     * transition.