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

Commit 34d20dab authored by Matt Sziklay's avatar Matt Sziklay
Browse files

Disconnect transition test fixes.

To ensure Transition#applyDisplayChangeIfNeeded picks up the display change, flag the DisplayContent as changing existence.

Additionally, create a transition flag for display-level transitions to prevent them from becoming no-op in TransitionController#queueTransition.

Third, add a validator during display removal to ensure the DisplayContent is removed even if the transition fails to complete.

Bug: 391652399
Test: atest, cts
Flag: com.android.window.flags.enable_display_disconnect_interaction
Change-Id: I31abb1d745b0e91abb6017a2068bbb77b63d6ebb
parent 4d60bc1d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -635,6 +635,14 @@ public interface WindowManager extends ViewManager {
     */
    int TRANSIT_FLAG_AVOID_MOVE_TO_FRONT = (1 << 16); // 0x10000

    /**
     * Transition flag: Indicates that the transition involves a display level change
     * (i.e, disconnect).
     * @hide
     */
    int TRANSIT_FLAG_DISPLAY_LEVEL_TRANSITION = (1 << 17); // 0x20000


    /**
     * @hide
     */
@@ -656,6 +664,7 @@ public interface WindowManager extends ViewManager {
            TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH,
            TRANSIT_FLAG_AOD_APPEARING,
            TRANSIT_FLAG_AVOID_MOVE_TO_FRONT,
            TRANSIT_FLAG_DISPLAY_LEVEL_TRANSITION
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface TransitionFlags {}
+21 −5
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PER
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_DISPLAY_LEVEL_TRANSITION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_PIP;
@@ -2802,10 +2803,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                return;
            }
            if (DesktopExperienceFlags.ENABLE_DISPLAY_DISCONNECT_INTERACTION.isTrue()) {
                final Transition transition = new Transition(TRANSIT_CLOSE, 0 /* flags */,
                        mTransitionController, mWmService.mSyncEngine);
                final Transition transition = new Transition(TRANSIT_CLOSE,
                        TRANSIT_FLAG_DISPLAY_LEVEL_TRANSITION, mTransitionController,
                        mWmService.mSyncEngine);
                mTransitionController.startCollectOrQueue(transition, (deferred) -> {
                    transition.collect(displayContent);
                    transition.collectExistenceChange(displayContent);
                    transition.setAllReady();
                    TransitionRequestInfo.DisplayChange displayChange =
                            new TransitionRequestInfo.DisplayChange(displayId);
@@ -2815,12 +2817,26 @@ class RootWindowContainer extends WindowContainer<DisplayContent>

                    mTransitionController.requestStartTransition(transition, null /* startTask */,
                            null /* remoteTransition */, displayChange);
                    mTransitionController.mStateValidators.add(() -> {
                        // Ensure the display content is removed even if the transition does not
                        // successfully finish.
                        removeDisplayContent(displayContent);
                    });
                });
            } else {
                displayContent.remove();
                mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId);
                removeDisplayContent(displayContent);
            }
        }
    }

    private void removeDisplayContent(DisplayContent displayContent) {
        if (displayContent.isRemoving() || displayContent.isRemoved()) {
            Slog.e(TAG, "DisplayContent already removed or removing.");
            return;
        }
        displayContent.remove();
        mWmService.mPossibleDisplayInfoMapper
                .removePossibleDisplayInfos(displayContent.mDisplayId);
    }

    @Override
+5 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_DISPLAY_LEVEL_TRANSITION;
import static android.view.WindowManager.TRANSIT_NONE;

import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
@@ -1513,9 +1514,10 @@ class TransitionController {
    private void queueTransition(Transition transit, OnStartCollect onStartCollect) {
        final QueuedTransition queuedTransition = new QueuedTransition(transit, onStartCollect);

        // If we queue a transition while a collecting transition is still not formally started,
        // then check if collecting transition is changing a display
        if (mCollectingTransition != null && !mCollectingTransition.hasStarted()) {
        // If we queue a non-display transition while a collecting transition is still not
        // formally started, then check if collecting transition is changing a display
        if ((transit.getFlags() & TRANSIT_FLAG_DISPLAY_LEVEL_TRANSITION) == 0
                && mCollectingTransition != null && !mCollectingTransition.hasStarted()) {
            for (int i = 0; i < mCollectingTransition.mParticipants.size(); i++) {
                if (mCollectingTransition.mParticipants.valueAt(i).asDisplayContent() != null) {
                    queuedTransition.mShouldNoopUponDequeue = true;