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

Commit 8176de2e authored by wilsonshih's avatar wilsonshih
Browse files

Able to remove starting window right after onTransitionReady

If a starting window has participated in a transition but is ready to
be removed before the transition is ready, defer the remove request
right after onTransitionReady sent to Shell. This allows Shell to
handle the removeStartingWindow request earlier and ensures that flags
related to the starting window are correct within TransitionInfo.

Bug: 415696165
Flag: com.android.window.flags.remove_starting_in_transition
Test: atest FlickerTestsActivityEmbedding
Test: atest StartingWindowControllerTests
Change-Id: If0110ab134177c1fd1720aa6238647c6fb7d2786
parent 664cee66
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.window;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
import android.window.StartingWindowRemovalInfo;

/**
 * Implemented by WMShell to initiate and play transition animations.
@@ -63,4 +64,10 @@ oneway interface ITransitionPlayer {
     * @param request Information about this particular request.
     */
    void requestStartTransition(in IBinder transitionToken, in TransitionRequestInfo request);

    /**
     * Allows us to send a remove starting windo request to the transition binder, ensuring this
     * request is invoked after onTransitionReady.
     */
    void removeStartingWindow(in StartingWindowRemovalInfo removalInfo);
}
+10 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.ITransitionPlayer;
import android.window.RemoteTransition;
import android.window.StartingWindowRemovalInfo;
import android.window.TaskFragmentOrganizer;
import android.window.TransitionFilter;
import android.window.TransitionInfo;
@@ -1281,6 +1282,10 @@ public class Transitions implements RemoteCallable<Transitions>,
        mPendingTransitions.add(0, active);
    }

    void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
        mOrganizer.removeStartingWindow(removalInfo);
    }

    /**
     * Start a new transition directly.
     * @param handler if null, the transition will be dispatched to the registered set of transition
@@ -1649,6 +1654,11 @@ public class Transitions implements RemoteCallable<Transitions>,
                TransitionRequestInfo request) throws RemoteException {
            mMainExecutor.execute(() -> Transitions.this.requestStartTransition(iBinder, request));
        }

        @Override
        public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
            mMainExecutor.execute(() -> Transitions.this.removeStartingWindow(removalInfo));
        }
    }

    /**
+25 −4
Original line number Diff line number Diff line
@@ -327,6 +327,7 @@ import android.window.SizeConfigurationBuckets;
import android.window.SplashScreen;
import android.window.SplashScreenView;
import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.StartingWindowRemovalInfo;
import android.window.TaskSnapshot;
import android.window.TaskSnapshotManager;
import android.window.TransitionInfo.AnimationOptions;
@@ -2772,6 +2773,10 @@ final class ActivityRecord extends WindowToken {
                    mStartingData.mPrepareRemoveAnimation = prepareAnimation;
                    return;
                }
            } else if (mSyncState != SYNC_STATE_NONE) {
                mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_REMOVE_DIRECTLY;
                mStartingData.mPrepareRemoveAnimation = prepareAnimation;
                return;
            }
            animate = prepareAnimation && mStartingData.needRevealAnimation()
                    && mStartingWindow.isVisibleByPolicy();
@@ -2780,10 +2785,7 @@ final class ActivityRecord extends WindowToken {
                            + " animate=%b Callers=%s", this, mStartingWindow, animate,
                    Debug.getCallers(5));
            surface = mStartingSurface;
            mStartingData = null;
            mStartingSurface = null;
            mStartingWindow = null;
            mTransitionChangeFlags &= ~FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
            cleanUpStartingInfo();
            if (surface == null) {
                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "startingWindow was set but "
                        + "startingSurface==null, couldn't remove");
@@ -2798,6 +2800,25 @@ final class ActivityRecord extends WindowToken {
        surface.remove(animate, hasImeSurface);
    }

    StartingWindowRemovalInfo getStartingWindowInfo() {
        if (mStartingData == null || mStartingWindow == null) {
            return null;
        }
        final boolean animate = mStartingData.mPrepareRemoveAnimation
                && mStartingData.needRevealAnimation()
                && mStartingWindow.isVisibleByPolicy();
        final boolean hasImeSurface = mStartingData.hasImeSurface();
        return mAtmService.mTaskOrganizerController.getStartingWindowRemovalInfo(
                task, animate, hasImeSurface);
    }

    void cleanUpStartingInfo() {
        mStartingData = null;
        mStartingSurface = null;
        mStartingWindow = null;
        mTransitionChangeFlags &= ~FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
    }

    /**
     * Reparents this activity into {@param newTaskFrag} at the provided {@param position}. The
     * caller should ensure that the {@param newTaskFrag} is not already the parent of this
+15 −8
Original line number Diff line number Diff line
@@ -654,16 +654,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
        return true;
    }

    void removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation,
            boolean hasImeSurface) {
    StartingWindowRemovalInfo getStartingWindowRemovalInfo(Task task,
            boolean prepareAnimation, boolean hasImeSurface) {
        final Task rootTask = task.getRootTask();
        if (rootTask == null) {
            return;
        }
        final ITaskOrganizer lastOrganizer = taskOrganizer != null ? taskOrganizer
                : getTaskOrganizer();
        if (lastOrganizer == null) {
            return;
            return null;
        }
        final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
        removalInfo.taskId = task.mTaskId;
@@ -700,6 +695,18 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
                        mainWindow.mSurfacePosition.y);
            }
        }
        return removalInfo;
    }

    void removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation,
            boolean hasImeSurface) {
        final ITaskOrganizer lastOrganizer = taskOrganizer != null ? taskOrganizer
                : getTaskOrganizer();
        if (lastOrganizer == null) {
            return;
        }
        final StartingWindowRemovalInfo removalInfo =
                getStartingWindowRemovalInfo(task, prepareAnimation, hasImeSurface);
        try {
            lastOrganizer.removeStartingWindow(removalInfo);
        } catch (RemoteException e) {
+28 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_S
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_IDLE;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_REMOVE_DIRECTLY;
import static com.android.server.wm.StartingData.AFTER_TRANSITION_FINISH;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_PREDICT_BACK;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
@@ -109,6 +110,7 @@ import android.view.Display;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.ScreenCapture;
import android.window.StartingWindowRemovalInfo;
import android.window.TaskFragmentAnimationParams;
import android.window.TransitionInfo;
import android.window.WindowContainerTransaction;
@@ -2103,6 +2105,32 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
            mLogger.logOnSendAsync(mController.mLoggerHandler);
            mController.mTransitionTracer.logSentTransition(this, mTargets);
        }
        removeStartingWindowIfAny();
    }

    private void removeStartingWindowIfAny() {
        if (!Flags.removeStartingInTransition()) {
            return;
        }
        for (int i = mParticipants.size() - 1; i >= 0; --i) {
            final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
            if (ar == null || ar.mStartingData == null || ar.mStartingSurface == null
                    || ar.mStartingData.mRemoveAfterTransaction
                    != AFTER_TRANSACTION_REMOVE_DIRECTLY) {
                continue;
            }
            final StartingWindowRemovalInfo removalInfo = ar.getStartingWindowInfo();
            if (removalInfo != null) {
                try {
                    ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS,
                            "Remove Starting Window after transition: %s", ar);
                    mController.getTransitionPlayer().removeStartingWindow(removalInfo);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Unable to remove starting window after transition");
                }
                ar.cleanUpStartingInfo();
            }
        }
    }

    void ensureParticipantSurfaceVisibility() {
Loading