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

Commit 2d6b8384 authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Re-land^2: Execute afterPrepareSurfacesRunnables after committing..." into main

parents c8320565 74239125
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
                mGivenInsetsReady = true;
                ImeTracker.forLogging().onProgress(mStatsToken,
                        ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED);
                mStateController.notifyControlChanged(mControlTarget);
                mStateController.notifyControlChanged(mControlTarget, this);
                setImeShowing(true);
            } else if (wasServerVisible && mServerVisible && mGivenInsetsReady
                    && givenInsetsPending) {
@@ -132,15 +132,15 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
    }

    @Override
    protected boolean isLeashReadyForDispatching() {
    protected boolean isLeashReadyForDispatching(InsetsControlTarget target) {
        if (android.view.inputmethod.Flags.refactorInsetsController()) {
            final WindowState ws =
                    mWindowContainer != null ? mWindowContainer.asWindowState() : null;
            final boolean isDrawn = ws != null && ws.isDrawn();
            return super.isLeashReadyForDispatching() && mServerVisible && isDrawn
                    && mGivenInsetsReady;
            return super.isLeashReadyForDispatching(target)
                    && mServerVisible && isDrawn && mGivenInsetsReady;
        } else {
            return super.isLeashReadyForDispatching();
            return super.isLeashReadyForDispatching(target);
        }
    }

+32 −8
Original line number Diff line number Diff line
@@ -411,7 +411,7 @@ class InsetsSourceProvider {
            changed = true;
        }
        if (changed) {
            mStateController.notifyControlChanged(mControlTarget);
            mStateController.notifyControlChanged(mControlTarget, this);
        }
    }

@@ -556,11 +556,37 @@ class InsetsSourceProvider {
        }
        mControl = new InsetsSourceControl(mSource.getId(), mSource.getType(), leash,
                initiallyVisible, surfacePosition, getInsetsHint());
        mStateController.notifySurfaceTransactionReady(this, getSurfaceTransactionId(leash), true);

        ProtoLog.d(WM_DEBUG_WINDOW_INSETS,
                "InsetsSource Control %s for target %s", mControl, mControlTarget);
    }

    private long getSurfaceTransactionId(SurfaceControl leash) {
        // Here returns mNativeObject (long) as the ID instead of the leash itself so that
        // InsetsStateController won't keep referencing the leash unexpectedly.
        return leash != null ? leash.mNativeObject : 0;
    }

    /**
     * This is called when the surface transaction of the leash initialization has been committed.
     *
     * @param id Indicates which transaction is committed so that stale callbacks can be dropped.
     */
    void onSurfaceTransactionCommitted(long id) {
        if (mIsLeashReadyForDispatching) {
            return;
        }
        if (mControl == null) {
            return;
        }
        if (id != getSurfaceTransactionId(mControl.getLeash())) {
            return;
        }
        mIsLeashReadyForDispatching = true;
        mStateController.notifySurfaceTransactionReady(this, 0, false);
    }

    void startSeamlessRotation() {
        if (!mSeamlessRotating) {
            mSeamlessRotating = true;
@@ -582,10 +608,6 @@ class InsetsSourceProvider {
        return true;
    }

    void onSurfaceTransactionApplied() {
        mIsLeashReadyForDispatching = true;
    }

    void setClientVisible(boolean clientVisible) {
        if (mClientVisible == clientVisible) {
            return;
@@ -612,8 +634,9 @@ class InsetsSourceProvider {
                mServerVisible, mClientVisible);
    }

    protected boolean isLeashReadyForDispatching() {
        return mIsLeashReadyForDispatching;
    protected boolean isLeashReadyForDispatching(InsetsControlTarget target) {
        // If the target is not the control target, we are ready for dispatching a null-leash to it.
        return target != mControlTarget || mIsLeashReadyForDispatching;
    }

    /**
@@ -626,7 +649,7 @@ class InsetsSourceProvider {
    @Nullable
    InsetsSourceControl getControl(InsetsControlTarget target) {
        if (target == mControlTarget) {
            if (!isLeashReadyForDispatching() && mControl != null) {
            if (!isLeashReadyForDispatching(target) && mControl != null) {
                // The surface transaction of preparing leash is not applied yet. We don't send it
                // to the client in case that the client applies its transaction sooner than ours
                // that we could unexpectedly overwrite the surface state.
@@ -799,6 +822,7 @@ class InsetsSourceProvider {
        public void onAnimationCancelled(SurfaceControl animationLeash) {
            if (mAdapter == this) {
                mStateController.notifyControlRevoked(mControlTarget, InsetsSourceProvider.this);
                mStateController.notifySurfaceTransactionReady(InsetsSourceProvider.this, 0, false);
                mControl = null;
                mControlTarget = null;
                mAdapter = null;
+59 −18
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.SparseLongArray;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsSource;
import android.view.InsetsSourceControl;
@@ -59,13 +60,14 @@ class InsetsStateController {
    private final DisplayContent mDisplayContent;

    private final SparseArray<InsetsSourceProvider> mProviders = new SparseArray<>();
    private final SparseLongArray mSurfaceTransactionIds = new SparseLongArray();
    private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
            mControlTargetProvidersMap = new ArrayMap<>();
    private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
            mPendingTargetProvidersMap = new ArrayMap<>();
    private final SparseArray<InsetsControlTarget> mIdControlTargetMap = new SparseArray<>();
    private final SparseArray<InsetsControlTarget> mIdFakeControlTargetMap = new SparseArray<>();

    private final ArraySet<InsetsControlTarget> mPendingControlChanged = new ArraySet<>();

    private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
        if (w.isReadyToDispatchInsetsState()) {
            w.notifyInsetsChanged();
@@ -327,11 +329,11 @@ class InsetsStateController {
        }
        if (lastTarget != null) {
            removeFromControlMaps(lastTarget, provider, fake);
            mPendingControlChanged.add(lastTarget);
            addToPendingControlMaps(lastTarget, provider);
        }
        if (target != null) {
            addToControlMaps(target, provider, fake);
            mPendingControlChanged.add(target);
            addToPendingControlMaps(target, provider);
        }
    }

@@ -364,8 +366,15 @@ class InsetsStateController {
        }
    }

    void notifyControlChanged(InsetsControlTarget target) {
        mPendingControlChanged.add(target);
    private void addToPendingControlMaps(@NonNull InsetsControlTarget target,
            InsetsSourceProvider provider) {
        final ArrayList<InsetsSourceProvider> array =
                mPendingTargetProvidersMap.computeIfAbsent(target, key -> new ArrayList<>());
        array.add(provider);
    }

    void notifyControlChanged(InsetsControlTarget target, InsetsSourceProvider provider) {
        addToPendingControlMaps(target, provider);
        notifyPendingInsetsControlChanged();

        if (android.view.inputmethod.Flags.refactorInsetsController()) {
@@ -376,26 +385,58 @@ class InsetsStateController {
        }
    }

    void notifySurfaceTransactionReady(InsetsSourceProvider provider, long id, boolean ready) {
        if (ready) {
            mSurfaceTransactionIds.put(provider.getSource().getId(), id);
        } else {
            mSurfaceTransactionIds.delete(provider.getSource().getId());
        }
    }

    private void notifyPendingInsetsControlChanged() {
        if (mPendingControlChanged.isEmpty()) {
        if (mPendingTargetProvidersMap.isEmpty()) {
            return;
        }
        final int size = mSurfaceTransactionIds.size();
        final SparseLongArray surfaceTransactionIds = new SparseLongArray(size);
        for (int i = 0; i < size; i++) {
            surfaceTransactionIds.append(
                    mSurfaceTransactionIds.keyAt(i), mSurfaceTransactionIds.valueAt(i));
        }
        mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
            for (int i = mProviders.size() - 1; i >= 0; i--) {
                final InsetsSourceProvider provider = mProviders.valueAt(i);
                provider.onSurfaceTransactionApplied();
            for (int i = 0; i < size; i++) {
                final int sourceId = surfaceTransactionIds.keyAt(i);
                final InsetsSourceProvider provider = mProviders.get(sourceId);
                if (provider == null) {
                    continue;
                }
                provider.onSurfaceTransactionCommitted(surfaceTransactionIds.valueAt(i));
            }
            final ArraySet<InsetsControlTarget> newControlTargets = new ArraySet<>();
            int displayId = mDisplayContent.getDisplayId();
            for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
                final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
                controlTarget.notifyInsetsControlChanged(displayId);
                if (mControlTargetProvidersMap.containsKey(controlTarget)) {
            final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>> pendingControlMap =
                    mPendingTargetProvidersMap;
            for (int i = pendingControlMap.size() - 1; i >= 0; i--) {
                final InsetsControlTarget target = pendingControlMap.keyAt(i);
                final ArrayList<InsetsSourceProvider> providers = pendingControlMap.valueAt(i);
                for (int p = providers.size() - 1; p >= 0; p--) {
                    final InsetsSourceProvider provider = providers.get(p);
                    if (provider.isLeashReadyForDispatching(target)) {
                        // Stop waiting for this provider.
                        providers.remove(p);
                    }
                }
                if (providers.isEmpty()) {
                    pendingControlMap.removeAt(i);

                    // All controls of this target are ready to be dispatched.
                    target.notifyInsetsControlChanged(displayId);
                    if (mControlTargetProvidersMap.containsKey(target)) {
                        // We only collect targets who get controls, not lose controls.
                    newControlTargets.add(controlTarget);
                        newControlTargets.add(target);
                    }
                }
            }
            mPendingControlChanged.clear();

            // This updates the insets visibilities AFTER sending current insets state and controls
            // to the clients, so that the clients can change the current visibilities to the
@@ -424,7 +465,7 @@ class InsetsStateController {
     * @param target the control target to check.
     */
    boolean hasPendingControls(@NonNull InsetsControlTarget target) {
        return mPendingControlChanged.contains(target);
        return mPendingTargetProvidersMap.containsKey(target);
    }

    void dump(String prefix, PrintWriter pw) {
+19 −28
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.content.Context;
import android.os.HandlerExecutor;
import android.os.Trace;
import android.util.Slog;
import android.util.TimeUtils;
@@ -68,6 +69,8 @@ public class WindowAnimator {

    private Choreographer mChoreographer;

    private final HandlerExecutor mExecutor;

    /**
     * Indicates whether we have an animation frame callback scheduled, which will happen at
     * vsync-app and then schedule the animation tick at the right time (vsync-sf).
@@ -79,8 +82,7 @@ public class WindowAnimator {
     * A list of runnable that need to be run after {@link WindowContainer#prepareSurfaces} is
     * executed and the corresponding transaction is closed and applied.
     */
    private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
    private boolean mInExecuteAfterPrepareSurfacesRunnables;
    private ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();

    private final SurfaceControl.Transaction mTransaction;

@@ -91,6 +93,7 @@ public class WindowAnimator {
        mTransaction = service.mTransactionFactory.get();
        service.mAnimationHandler.runWithScissors(
                () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
        mExecutor = new HandlerExecutor(service.mAnimationHandler);

        mAnimationFrameCallback = frameTimeNs -> {
            synchronized (mService.mGlobalLock) {
@@ -198,6 +201,19 @@ public class WindowAnimator {
            updateRunningExpensiveAnimationsLegacy();
        }

        final ArrayList<Runnable> afterPrepareSurfacesRunnables = mAfterPrepareSurfacesRunnables;
        if (!afterPrepareSurfacesRunnables.isEmpty()) {
            mAfterPrepareSurfacesRunnables = new ArrayList<>();
            mTransaction.addTransactionCommittedListener(mExecutor, () -> {
                synchronized (mService.mGlobalLock) {
                    // Traverse in order they were added.
                    for (int i = 0, size = afterPrepareSurfacesRunnables.size(); i < size; i++) {
                        afterPrepareSurfacesRunnables.get(i).run();
                    }
                    afterPrepareSurfacesRunnables.clear();
                }
            });
        }
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "applyTransaction");
        mTransaction.apply();
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -205,7 +221,6 @@ public class WindowAnimator {
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate");

        mService.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
        executeAfterPrepareSurfacesRunnables();

        if (DEBUG_WINDOW_TRACE) {
            Slog.i(TAG, "!!! animate: exit"
@@ -287,34 +302,10 @@ public class WindowAnimator {

    /**
     * Adds a runnable to be executed after {@link WindowContainer#prepareSurfaces} is called and
     * the corresponding transaction is closed and applied.
     * the corresponding transaction is closed, applied, and committed.
     */
    void addAfterPrepareSurfacesRunnable(Runnable r) {
        // If runnables are already being handled in executeAfterPrepareSurfacesRunnable, then just
        // immediately execute the runnable passed in.
        if (mInExecuteAfterPrepareSurfacesRunnables) {
            r.run();
            return;
        }

        mAfterPrepareSurfacesRunnables.add(r);
        scheduleAnimation();
    }

    void executeAfterPrepareSurfacesRunnables() {

        // Don't even think about to start recursing!
        if (mInExecuteAfterPrepareSurfacesRunnables) {
            return;
        }
        mInExecuteAfterPrepareSurfacesRunnables = true;

        // Traverse in order they were added.
        final int size = mAfterPrepareSurfacesRunnables.size();
        for (int i = 0; i < size; i++) {
            mAfterPrepareSurfacesRunnables.get(i).run();
        }
        mAfterPrepareSurfacesRunnables.clear();
        mInExecuteAfterPrepareSurfacesRunnables = false;
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -40,12 +40,19 @@ import java.util.concurrent.Executor;
public class StubTransaction extends SurfaceControl.Transaction {

    private HashSet<Runnable> mWindowInfosReportedListeners = new HashSet<>();
    private HashSet<SurfaceControl.TransactionCommittedListener> mTransactionCommittedListeners =
            new HashSet<>();

    @Override
    public void apply() {
        for (Runnable listener : mWindowInfosReportedListeners) {
            listener.run();
        }
        for (SurfaceControl.TransactionCommittedListener listener
                : mTransactionCommittedListeners) {
            listener.onTransactionCommitted();
        }
        mTransactionCommittedListeners.clear();
    }

    @Override
@@ -239,6 +246,9 @@ public class StubTransaction extends SurfaceControl.Transaction {
    @Override
    public SurfaceControl.Transaction addTransactionCommittedListener(Executor executor,
            SurfaceControl.TransactionCommittedListener listener) {
        SurfaceControl.TransactionCommittedListener listenerInner =
                () -> executor.execute(listener::onTransactionCommitted);
        mTransactionCommittedListeners.add(listenerInner);
        return this;
    }

Loading