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

Commit 198eb7db authored by Evan Rosky's avatar Evan Rosky Committed by Automerger Merge Worker
Browse files

Merge "Move all transition queueing into transitioncontroller" into udc-dev am: 89a311c2

parents a6745089 89a311c2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3805,6 +3805,12 @@
      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
      "at": "com\/android\/server\/wm\/AppTransitionController.java"
    },
    "1463355909": {
      "message": "Queueing legacy sync-set: %s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN",
      "at": "com\/android\/server\/wm\/TransitionController.java"
    },
    "1469310004": {
      "message": "          SKIP: common mode mismatch. was %s",
      "level": "VERBOSE",
+19 −2
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ class BLASTSyncEngine {
            return mOrphanTransaction;
        }

        private void onSurfacePlacement() {
        private void tryFinish() {
            if (!mReady) return;
            ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: onSurfacePlacement checking %s",
                    mSyncId, mRootMembers);
@@ -223,6 +223,12 @@ class BLASTSyncEngine {
                    }
                });
            }
            // Notify idle listeners
            for (int i = mOnIdleListeners.size() - 1; i >= 0; --i) {
                // If an idle listener adds a sync, though, then stop notifying.
                if (mActiveSyncs.size() > 0) break;
                mOnIdleListeners.get(i).run();
            }
        }

        private void setReady(boolean ready) {
@@ -281,6 +287,8 @@ class BLASTSyncEngine {
     */
    private final ArrayList<PendingSyncSet> mPendingSyncSets = new ArrayList<>();

    private final ArrayList<Runnable> mOnIdleListeners = new ArrayList<>();

    BLASTSyncEngine(WindowManagerService wms) {
        this(wms, wms.mH);
    }
@@ -379,8 +387,13 @@ class BLASTSyncEngine {
    void onSurfacePlacement() {
        // backwards since each state can remove itself if finished
        for (int i = mActiveSyncs.size() - 1; i >= 0; --i) {
            mActiveSyncs.valueAt(i).onSurfacePlacement();
            mActiveSyncs.valueAt(i).tryFinish();
        }
    }

    /** Only use this for tests! */
    void tryFinishForTest(int syncId) {
        getSyncSet(syncId).tryFinish();
    }

    /**
@@ -409,4 +422,8 @@ class BLASTSyncEngine {
    boolean hasPendingSyncSets() {
        return !mPendingSyncSets.isEmpty();
    }

    void addOnIdleListener(Runnable onIdleListener) {
        mOnIdleListeners.add(onIdleListener);
    }
}
+6 −1
Original line number Diff line number Diff line
@@ -104,7 +104,8 @@ import java.util.Objects;
import java.util.function.Predicate;

/**
 * Represents a logical transition.
 * Represents a logical transition. This keeps track of all the changes associated with a logical
 * WM state -> state transition.
 * @see TransitionController
 */
class Transition implements BLASTSyncEngine.TransactionReadyListener {
@@ -416,6 +417,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        return mFinishTransaction;
    }

    boolean isPending() {
        return mState == STATE_PENDING;
    }

    boolean isCollecting() {
        return mState == STATE_COLLECTING || mState == STATE_STARTED;
    }
+93 −19
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.FgThread;
@@ -88,6 +89,7 @@ class TransitionController {

    private WindowProcessController mTransitionPlayerProc;
    final ActivityTaskManagerService mAtm;
    BLASTSyncEngine mSyncEngine;

    final RemotePlayer mRemotePlayer;
    SnapshotController mSnapshotController;
@@ -121,6 +123,26 @@ class TransitionController {

    private final IBinder.DeathRecipient mTransitionPlayerDeath;

    static class QueuedTransition {
        final Transition mTransition;
        final OnStartCollect mOnStartCollect;
        final BLASTSyncEngine.SyncGroup mLegacySync;

        QueuedTransition(Transition transition, OnStartCollect onStartCollect) {
            mTransition = transition;
            mOnStartCollect = onStartCollect;
            mLegacySync = null;
        }

        QueuedTransition(BLASTSyncEngine.SyncGroup legacySync, OnStartCollect onStartCollect) {
            mTransition = null;
            mOnStartCollect = onStartCollect;
            mLegacySync = legacySync;
        }
    }

    private final ArrayList<QueuedTransition> mQueuedTransitions = new ArrayList<>();

    /** The transition currently being constructed (collecting participants). */
    private Transition mCollectingTransition = null;

@@ -158,6 +180,14 @@ class TransitionController {
        mTransitionTracer = wms.mTransitionTracer;
        mIsWaitingForDisplayEnabled = !wms.mDisplayEnabled;
        registerLegacyListener(wms.mActivityManagerAppTransitionNotifier);
        setSyncEngine(wms.mSyncEngine);
    }

    @VisibleForTesting
    void setSyncEngine(BLASTSyncEngine syncEngine) {
        mSyncEngine = syncEngine;
        // Check the queue whenever the sync-engine becomes idle.
        mSyncEngine.addOnIdleListener(this::tryStartCollectFromQueue);
    }

    private void detachPlayer() {
@@ -195,7 +225,7 @@ class TransitionController {
            throw new IllegalStateException("Simultaneous transition collection not supported"
                    + " yet. Use {@link #createPendingTransition} for explicit queueing.");
        }
        Transition transit = new Transition(type, flags, this, mAtm.mWindowManager.mSyncEngine);
        Transition transit = new Transition(type, flags, this, mSyncEngine);
        ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Creating Transition: %s", transit);
        moveToCollecting(transit);
        return transit;
@@ -325,7 +355,7 @@ class TransitionController {
    /** @return {@code true} if a transition is running */
    boolean inTransition() {
        // TODO(shell-transitions): eventually properly support multiple
        return isCollecting() || isPlaying();
        return isCollecting() || isPlaying() || !mQueuedTransitions.isEmpty();
    }

    /** @return {@code true} if a transition is running in a participant subtree of wc */
@@ -453,8 +483,7 @@ class TransitionController {
            // some frames before and after the display projection transaction is applied by the
            // remote player. That may cause some buffers to show in different rotation. So use
            // sync method to pause clients drawing until the projection transaction is applied.
            mAtm.mWindowManager.mSyncEngine.setSyncMethod(displayTransition.getSyncId(),
                    BLASTSyncEngine.METHOD_BLAST);
            mSyncEngine.setSyncMethod(displayTransition.getSyncId(), BLASTSyncEngine.METHOD_BLAST);
        }
        final Rect startBounds = displayChange.getStartAbsBounds();
        final Rect endBounds = displayChange.getEndAbsBounds();
@@ -741,6 +770,31 @@ class TransitionController {
        mStateValidators.clear();
    }

    void tryStartCollectFromQueue() {
        if (mQueuedTransitions.isEmpty()) return;
        // Only need to try the next one since, even when transition can collect in parallel,
        // they still need to serialize on readiness.
        final QueuedTransition queued = mQueuedTransitions.get(0);
        if (mCollectingTransition != null || mSyncEngine.hasActiveSync()) {
            return;
        }
        mQueuedTransitions.remove(0);
        // This needs to happen immediately to prevent another sync from claiming the syncset
        // out-of-order (moveToCollecting calls startSyncSet)
        if (queued.mTransition != null) {
            moveToCollecting(queued.mTransition);
        } else {
            // legacy sync
            mSyncEngine.startSyncSet(queued.mLegacySync);
        }
        // Post this so that the now-playing transition logic isn't interrupted.
        mAtm.mH.post(() -> {
            synchronized (mAtm.mGlobalLock) {
                queued.mOnStartCollect.onCollectStarted(true /* deferred */);
            }
        });
    }

    void moveToPlaying(Transition transition) {
        if (transition != mCollectingTransition) {
            throw new IllegalStateException("Trying to move non-collecting transition to playing");
@@ -749,6 +803,7 @@ class TransitionController {
        mPlayingTransitions.add(transition);
        updateRunningRemoteAnimation(transition, true /* isPlaying */);
        mTransitionTracer.logState(transition);
        // Sync engine should become idle after this, so the idle listener will check the queue.
    }

    void updateAnimatingState(SurfaceControl.Transaction t) {
@@ -758,12 +813,12 @@ class TransitionController {
            t.setEarlyWakeupStart();
            // Usually transitions put quite a load onto the system already (with all the things
            // happening in app), so pause task snapshot persisting to not increase the load.
            mAtm.mWindowManager.mSnapshotController.setPause(true);
            mSnapshotController.setPause(true);
            mAnimatingState = true;
            Transition.asyncTraceBegin("animating", 0x41bfaf1 /* hashcode of TAG */);
        } else if (!animatingState && mAnimatingState) {
            t.setEarlyWakeupEnd();
            mAtm.mWindowManager.mSnapshotController.setPause(false);
            mSnapshotController.setPause(false);
            mAnimatingState = false;
            Transition.asyncTraceEnd(0x41bfaf1 /* hashcode of TAG */);
        }
@@ -793,6 +848,7 @@ class TransitionController {
        transition.abort();
        mCollectingTransition = null;
        mTransitionTracer.logState(transition);
        // abort will call through the normal finish paths and thus check the queue.
    }

    /**
@@ -874,7 +930,7 @@ class TransitionController {
        if (!mPlayingTransitions.isEmpty()) {
            state = LEGACY_STATE_RUNNING;
        } else if ((mCollectingTransition != null && mCollectingTransition.getLegacyIsReady())
                || mAtm.mWindowManager.mSyncEngine.hasPendingSyncSets()) {
                || mSyncEngine.hasPendingSyncSets()) {
            // The transition may not be "ready", but we have a sync-transaction waiting to start.
            // Usually the pending transaction is for a transition, so assuming that is the case,
            // we can't be IDLE for test purposes. Ideally, we should have a STATE_COLLECTING.
@@ -884,26 +940,44 @@ class TransitionController {
        proto.end(token);
    }

    /** Returns {@code true} if it started collecting, {@code false} if it was queued. */
    private void queueTransition(Transition transit, OnStartCollect onStartCollect) {
        mQueuedTransitions.add(new QueuedTransition(transit, onStartCollect));
        ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN,
                "Queueing transition: %s", transit);
    }

    /** Returns {@code true} if it started collecting, {@code false} if it was queued. */
    boolean startCollectOrQueue(Transition transit, OnStartCollect onStartCollect) {
        if (mAtm.mWindowManager.mSyncEngine.hasActiveSync()) {
        if (!mQueuedTransitions.isEmpty()) {
            // Just add to queue since we already have a queue.
            queueTransition(transit, onStartCollect);
            return false;
        }
        if (mSyncEngine.hasActiveSync()) {
            if (!isCollecting()) {
                Slog.w(TAG, "Ongoing Sync outside of transition.");
            }
            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN,
                    "Queueing transition: %s", transit);
            mAtm.mWindowManager.mSyncEngine.queueSyncSet(
                    // Make sure to collect immediately to prevent another transition
                    // from sneaking in before it. Note: moveToCollecting internally
                    // calls startSyncSet.
                    () -> moveToCollecting(transit),
                    () -> onStartCollect.onCollectStarted(true /* deferred */));
            queueTransition(transit, onStartCollect);
            return false;
        } else {
        }
        moveToCollecting(transit);
        onStartCollect.onCollectStarted(false /* deferred */);
        return true;
    }

    /** Returns {@code true} if it started collecting, {@code false} if it was queued. */
    boolean startLegacySyncOrQueue(BLASTSyncEngine.SyncGroup syncGroup, Runnable applySync) {
        if (!mQueuedTransitions.isEmpty() || mSyncEngine.hasActiveSync()) {
            // Just add to queue since we already have a queue.
            mQueuedTransitions.add(new QueuedTransition(syncGroup, (d) -> applySync.run()));
            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN,
                    "Queueing legacy sync-set: %s", syncGroup.mSyncId);
            return false;
        }
        mSyncEngine.startSyncSet(syncGroup);
        applySync.run();
        return true;
    }

    interface OnStartCollect {
+19 −12
Original line number Diff line number Diff line
@@ -231,6 +231,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                 */
                final BLASTSyncEngine.SyncGroup syncGroup = prepareSyncWithOrganizer(callback);
                final int syncId = syncGroup.mSyncId;
                if (mTransitionController.isShellTransitionsEnabled()) {
                    mTransitionController.startLegacySyncOrQueue(syncGroup, () -> {
                        applyTransaction(t, syncId, null /*transition*/, caller);
                        setSyncReady(syncId);
                    });
                } else {
                    if (!mService.mWindowManager.mSyncEngine.hasActiveSync()) {
                        mService.mWindowManager.mSyncEngine.startSyncSet(syncGroup);
                        applyTransaction(t, syncId, null /*transition*/, caller);
@@ -245,6 +251,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                                    setSyncReady(syncId);
                                });
                    }
                }
                return syncId;
            }
        } finally {
Loading