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

Commit 349f7886 authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Android (Google) Code Review
Browse files

Merge changes from topic "lock_free_win"

* changes:
  Fix minor issues with new window animations.
  Fix possible race conditions when cancelling animations
  Lock free animations (2/2)
parents c4cded9c 9af095b6
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
@@ -37,8 +38,12 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.view.Surface.OutOfResourcesException;

import com.android.internal.annotations.GuardedBy;

import dalvik.system.CloseGuard;
import libcore.util.NativeAllocationRegistry;

@@ -153,6 +158,13 @@ public class SurfaceControl implements Parcelable {
    private final String mName;
    long mNativeObject; // package visibility only for Surface.java access

    // TODO: Move this to native.
    private final Object mSizeLock = new Object();
    @GuardedBy("mSizeLock")
    private int mWidth;
    @GuardedBy("mSizeLock")
    private int mHeight;

    static Transaction sGlobalTransaction;
    static long sTransactionNestCount = 0;

@@ -567,6 +579,8 @@ public class SurfaceControl implements Parcelable {
        }

        mName = name;
        mWidth = w;
        mHeight = h;
        mNativeObject = nativeCreate(session, name, w, h, format, flags,
            parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
        if (mNativeObject == 0) {
@@ -582,6 +596,8 @@ public class SurfaceControl implements Parcelable {
    // event logging.
    public SurfaceControl(SurfaceControl other) {
        mName = other.mName;
        mWidth = other.mWidth;
        mHeight = other.mHeight;
        mNativeObject = other.mNativeObject;
        other.mCloseGuard.close();
        other.mNativeObject = 0;
@@ -590,6 +606,8 @@ public class SurfaceControl implements Parcelable {

    private SurfaceControl(Parcel in) {
        mName = in.readString();
        mWidth = in.readInt();
        mHeight = in.readInt();
        mNativeObject = nativeReadFromParcel(in);
        if (mNativeObject == 0) {
            throw new IllegalArgumentException("Couldn't read SurfaceControl from parcel=" + in);
@@ -605,6 +623,8 @@ public class SurfaceControl implements Parcelable {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mName);
        dest.writeInt(mWidth);
        dest.writeInt(mHeight);
        nativeWriteToParcel(mNativeObject, dest);
    }

@@ -922,6 +942,18 @@ public class SurfaceControl implements Parcelable {
        }
    }

    public int getWidth() {
        synchronized (mSizeLock) {
            return mWidth;
        }
    }

    public int getHeight() {
        synchronized (mSizeLock) {
            return mHeight;
        }
    }

    @Override
    public String toString() {
        return "Surface(name=" + mName + ")/@0x" +
@@ -1282,6 +1314,7 @@ public class SurfaceControl implements Parcelable {
                nativeGetNativeTransactionFinalizer(), 512);
        private long mNativeObject;

        private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
        Runnable mFreeNativeResources;

        public Transaction() {
@@ -1312,9 +1345,22 @@ public class SurfaceControl implements Parcelable {
         * Jankier version of apply. Avoid use (b/28068298).
         */
        public void apply(boolean sync) {
            applyResizedSurfaces();
            nativeApplyTransaction(mNativeObject, sync);
        }

        private void applyResizedSurfaces() {
            for (int i = mResizedSurfaces.size() - 1; i >= 0; i--) {
                final Point size = mResizedSurfaces.valueAt(i);
                final SurfaceControl surfaceControl = mResizedSurfaces.keyAt(i);
                synchronized (surfaceControl.mSizeLock) {
                    surfaceControl.mWidth = size.x;
                    surfaceControl.mHeight = size.y;
                }
            }
            mResizedSurfaces.clear();
        }

        public Transaction show(SurfaceControl sc) {
            sc.checkNotReleased();
            nativeSetFlags(mNativeObject, sc.mNativeObject, 0, SURFACE_HIDDEN);
@@ -1335,6 +1381,7 @@ public class SurfaceControl implements Parcelable {

        public Transaction setSize(SurfaceControl sc, int w, int h) {
            sc.checkNotReleased();
            mResizedSurfaces.put(sc, new Point(w, h));
            nativeSetSize(mNativeObject, sc.mNativeObject, w, h);
            return this;
        }
@@ -1567,6 +1614,8 @@ public class SurfaceControl implements Parcelable {
         * other transaction as if it had been applied.
         */
        public Transaction merge(Transaction other) {
            mResizedSurfaces.putAll(other.mResizedSurfaces);
            other.mResizedSurfaces.clear();
            nativeMergeTransaction(mNativeObject, other.mNativeObject);
            return this;
        }
+16 −5
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import android.view.IApplicationToken;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Transformation;

import com.android.internal.util.ToBooleanFunction;
import com.android.server.input.InputApplicationHandle;
@@ -75,6 +76,7 @@ import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.LinkedList;

class AppTokenList extends ArrayList<AppWindowToken> {
}
@@ -231,7 +233,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
            // If this initial window is animating, stop it -- we will do an animation to reveal
            // it from behind the starting window, so there is no need for it to also be doing its
            // own stuff.
            winAnimator.clearAnimation();
            win.cancelAnimation();
            if (getController() != null) {
                getController().removeStartingWindow();
            }
@@ -389,7 +391,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
        }

        for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
            if ((mChildren.get(i)).isWindowAnimationSet()) {
            if ((mChildren.get(i)).isSelfOrChildAnimating()) {
                delayed = true;
            }
        }
@@ -610,8 +612,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
     */
    private void destroySurfaces(boolean cleanupOnResume) {
        boolean destroyedSomething = false;
        for (int i = mChildren.size() - 1; i >= 0; i--) {
            final WindowState win = mChildren.get(i);

        // Copying to a different list as multiple children can be removed.
        // TODO: Not sure why this is needed.
        final LinkedList<WindowState> children = new LinkedList<>(mChildren);
        for (int i = children.size() - 1; i >= 0; i--) {
            final WindowState win = children.get(i);
            destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
        }
        if (destroyedSomething) {
@@ -1320,7 +1326,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
                            + " pv=" + w.mPolicyVisibility
                            + " mDrawState=" + winAnimator.drawStateToString()
                            + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
                            + " a=" + winAnimator.mAnimating);
                            + " a=" + winAnimator.isAnimationSet());
                }
            }

@@ -1519,6 +1525,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
        return mAppAnimator.animLayerAdjustment;
    }

    @Override
    boolean isSelfAnimating() {
        return mAppAnimator.isAnimating();
    }

    @Override
    void dump(PrintWriter pw, String prefix) {
        super.dump(pw, prefix);
+41 −33
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ import android.view.InputDevice;
import android.view.MagnificationSpec;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;

import com.android.internal.annotations.VisibleForTesting;
@@ -339,6 +340,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            new ApplySurfaceChangesTransactionState();
    private final ScreenshotApplicationState mScreenshotApplicationState =
            new ScreenshotApplicationState();
    private final Transaction mTmpTransaction = new Transaction();

    // True if this display is in the process of being removed. Used to determine if the removal of
    // the display's direct children should be allowed.
@@ -379,29 +381,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     */
    private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>();

    /** Temporary float array to retrieve 3x3 matrix values. */
    private final float[] mTmpFloats = new float[9];

    private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
        WindowStateAnimator winAnimator = w.mWinAnimator;
        if (winAnimator.hasSurface()) {
            final boolean wasAnimating = winAnimator.mWasAnimating;
            final boolean nowAnimating = winAnimator.stepAnimationLocked(
                    mTmpWindowAnimator.mCurrentTime);
            winAnimator.mWasAnimating = nowAnimating;
            mTmpWindowAnimator.orAnimating(nowAnimating);

            if (DEBUG_WALLPAPER) Slog.v(TAG,
                    w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);

            if (wasAnimating && !winAnimator.mAnimating
                    && mWallpaperController.isWallpaperTarget(w)) {
                mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                if (DEBUG_LAYOUT_REPEATS) {
                    mService.mWindowPlacerLocked.debugLayoutRepeats(
                            "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
                }
            }
        }

        final AppWindowToken atoken = w.mAppToken;
        if (winAnimator.mDrawState == READY_TO_SHOW) {
            if (atoken == null || atoken.allDrawn) {
@@ -434,13 +418,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

        // If this window is animating, make a note that we have an animating window and take
        // care of a request to run a detached wallpaper animation.
        if (winAnimator.mAnimating) {
            if (winAnimator.mAnimation != null) {
                if ((flags & FLAG_SHOW_WALLPAPER) != 0
                        && winAnimator.mAnimation.getDetachWallpaper()) {
        if (winAnimator.isAnimationSet()) {
            final AnimationAdapter anim = w.getAnimation();
            if (anim != null) {
                if ((flags & FLAG_SHOW_WALLPAPER) != 0 && anim.getDetachWallpaper()) {
                    mTmpWindow = w;
                }
                final int color = winAnimator.mAnimation.getBackgroundColor();
                final int color = anim.getBackgroundColor();
                if (color != 0) {
                    final TaskStack stack = w.getStack();
                    if (stack != null) {
@@ -448,7 +432,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                    }
                }
            }
            mTmpWindowAnimator.setAnimating(true);
        }

        // If this window's app token is running a detached wallpaper animation, make a note so
@@ -684,7 +667,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            mWallpaperController.updateWallpaperVisibility();
        }

        w.handleWindowMovedIfNeeded();
        // Use mTmpTransaction instead of mPendingTransaction because we don't want to commit
        // other changes in mPendingTransaction at this point.
        w.handleWindowMovedIfNeeded(mTmpTransaction);
        SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);

        final WindowStateAnimator winAnimator = w.mWinAnimator;

@@ -720,7 +706,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                }
            }
            final TaskStack stack = w.getStack();
            if ((!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening())
            if ((!winAnimator.isWaitingForOpening())
                    || (stack != null && stack.isAnimatingBounds())) {
                // Updates the shown frame before we set up the surface. This is needed
                // because the resizing could change the top-left position (in addition to
@@ -736,6 +722,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                winAnimator.computeShownFrameLocked();
            }
            winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);

            // Since setSurfaceBoundariesLocked applies the clipping, we need to apply the position
            // to the surface of the window container as well. Use mTmpTransaction instead of
            // mPendingTransaction to avoid committing any existing changes in there.
            w.updateSurfacePosition(mTmpTransaction);
            SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
        }

        final AppWindowToken atoken = w.mAppToken;
@@ -2617,8 +2609,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        forAllWindows(w -> {
            if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)
                    && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
                w.mWinAnimator.setAnimation(
                        policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
                w.startAnimation(policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
            }
        }, true /* traverseTopToBottom */);
    }
@@ -3775,13 +3766,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    }

    @Override
    void destroyAfterPendingTransaction(SurfaceControl surface) {
    public void destroyAfterPendingTransaction(SurfaceControl surface) {
        mPendingDestroyingSurfaces.add(surface);
    }

    /**
     * Destroys any surfaces that have been put into the pending list with
     * {@link #destroyAfterTransaction}.
     * {@link #destroyAfterPendingTransaction}.
     */
    void onPendingTransactionApplied() {
        for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) {
@@ -3789,4 +3780,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }
        mPendingDestroyingSurfaces.clear();
    }

    @Override
    void prepareSurfaces() {
        final ScreenRotationAnimation screenRotationAnimation =
                mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
            screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats);
            mPendingTransaction.setMatrix(mWindowingLayer,
                    mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
                    mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
            mPendingTransaction.setPosition(mWindowingLayer,
                    mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]);
            mPendingTransaction.setAlpha(mWindowingLayer,
                    screenRotationAnimation.getEnterTransformation().getAlpha());
        }
        super.prepareSurfaces();
    }
}
+22 −20
Original line number Diff line number Diff line
@@ -751,10 +751,10 @@ public class DockedStackDividerController {

                // There might be an old window delaying the animation start - clear it.
                if (mDelayedImeWin != null) {
                    mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
                    mDelayedImeWin.endDelayingAnimationStart();
                }
                mDelayedImeWin = imeWin;
                imeWin.mWinAnimator.startDelayingAnimationStart();
                imeWin.startDelayingAnimationStart();
            }

            // If we are already waiting for something to be drawn, clear out the old one so it
@@ -765,9 +765,10 @@ public class DockedStackDividerController {
                mService.mWaitingForDrawnCallback.run();
            }
            mService.mWaitingForDrawnCallback = () -> {
                synchronized (mService.mWindowMap) {
                    mAnimationStartDelayed = false;
                    if (mDelayedImeWin != null) {
                    mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
                        mDelayedImeWin.endDelayingAnimationStart();
                    }
                    // If the adjust status changed since this was posted, only notify
                    // the new states and don't animate.
@@ -784,6 +785,7 @@ public class DockedStackDividerController {
                    }
                    notifyAdjustedForImeChanged(
                            mAdjustedForIme || mAdjustedForDivider, duration);
                }
            };
        } else {
            notifyAdjustedForImeChanged(
+59 −45
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import android.util.ArrayMap;
import android.view.Choreographer;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Transformation;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -44,12 +43,19 @@ class SurfaceAnimationRunner {

    private final Object mLock = new Object();

    /**
     * Lock for cancelling animations. Must be acquired on it's own, or after acquiring
     * {@link #mLock}
     */
    private final Object mCancelLock = new Object();

    @VisibleForTesting
    Choreographer mChoreographer;

    private final Runnable mApplyTransactionRunnable = this::applyTransaction;
    private final AnimationHandler mAnimationHandler;
    private final Transaction mFrameTransaction;
    private final AnimatorFactory mAnimatorFactory;
    private boolean mApplyScheduled;

    @GuardedBy("mLock")
@@ -58,15 +64,15 @@ class SurfaceAnimationRunner {

    @GuardedBy("mLock")
    @VisibleForTesting
    final ArrayMap<SurfaceControl, ValueAnimator> mRunningAnimations = new ArrayMap<>();
    final ArrayMap<SurfaceControl, RunningAnimation> mRunningAnimations = new ArrayMap<>();

    SurfaceAnimationRunner() {
        this(null /* callbackProvider */, new Transaction());
        this(null /* callbackProvider */, null /* animatorFactory */, new Transaction());
    }

    @VisibleForTesting
    SurfaceAnimationRunner(@Nullable AnimationFrameCallbackProvider callbackProvider,
            Transaction frameTransaction) {
            AnimatorFactory animatorFactory, Transaction frameTransaction) {
        SurfaceAnimationThread.getHandler().runWithScissors(() -> mChoreographer = getSfInstance(),
                0 /* timeout */);
        mFrameTransaction = frameTransaction;
@@ -74,6 +80,9 @@ class SurfaceAnimationRunner {
        mAnimationHandler.setProvider(callbackProvider != null
                ? callbackProvider
                : new SfVsyncFrameCallbackProvider(mChoreographer));
        mAnimatorFactory = animatorFactory != null
                ? animatorFactory
                : SfValueAnimator::new;
    }

    void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
@@ -94,18 +103,17 @@ class SurfaceAnimationRunner {
        synchronized (mLock) {
            if (mPendingAnimations.containsKey(leash)) {
                mPendingAnimations.remove(leash);
                // TODO: Releasing the leash is problematic if reparenting hasn't happened yet.
                // Fix with transaction
                //leash.release();
                return;
            }
            final ValueAnimator anim = mRunningAnimations.get(leash);
            final RunningAnimation anim = mRunningAnimations.get(leash);
            if (anim != null) {
                mRunningAnimations.remove(leash);
                synchronized (mCancelLock) {
                    anim.mCancelled = true;
                }
                SurfaceAnimationThread.getHandler().post(() -> {
                    anim.cancel();
                    anim.mAnim.cancel();
                    applyTransaction();
                    //leash.release();
                });
            }
        }
@@ -119,54 +127,51 @@ class SurfaceAnimationRunner {
    }

    private void startAnimationLocked(RunningAnimation a) {
        final ValueAnimator result = new SfValueAnimator();
        final ValueAnimator anim = mAnimatorFactory.makeAnimator();

        // Animation length is already expected to be scaled.
        result.overrideDurationScale(1.0f);
        result.setDuration(a.animSpec.getDuration());
        result.addUpdateListener(animation -> {
            applyTransformation(a, mFrameTransaction, result.getCurrentPlayTime());
        anim.overrideDurationScale(1.0f);
        anim.setDuration(a.mAnimSpec.getDuration());
        anim.addUpdateListener(animation -> {
            synchronized (mCancelLock) {
                if (!a.mCancelled) {
                    applyTransformation(a, mFrameTransaction, anim.getCurrentPlayTime());
                }
            }

            // Transaction will be applied in the commit phase.
            scheduleApplyTransaction();
        });
        result.addListener(new AnimatorListenerAdapter() {

            private boolean mCancelled;

        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                mFrameTransaction.show(a.leash);
                synchronized (mCancelLock) {
                    if (!a.mCancelled) {
                        mFrameTransaction.show(a.mLeash);
                    }
                }

            @Override
            public void onAnimationCancel(Animator animation) {
                mCancelled = true;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                synchronized (mLock) {
                    mRunningAnimations.remove(a.leash);
                }
                if (!mCancelled) {
                    mRunningAnimations.remove(a.mLeash);
                    synchronized (mCancelLock) {
                        if (!a.mCancelled) {
                            // Post on other thread that we can push final state without jank.
                    AnimationThread.getHandler().post(() -> {
                        a.finishCallback.run();

                        // Make sure to release the leash after finishCallback has been invoked such
                        // that reparenting is done already when releasing the leash.
                        a.leash.release();
                    });
                            AnimationThread.getHandler().post(a.mFinishCallback);
                        }
                    }
                }
            }
        });
        result.start();
        mRunningAnimations.put(a.leash, result);
        anim.start();
        a.mAnim = anim;
        mRunningAnimations.put(a.mLeash, a);
    }

    private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
        a.animSpec.apply(t, a.leash, currentPlayTime);
        a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
    }

    private void stepAnimation(long frameTimeNanos) {
@@ -189,15 +194,24 @@ class SurfaceAnimationRunner {
    }

    private static final class RunningAnimation {
        final AnimationSpec animSpec;
        final SurfaceControl leash;
        final Runnable finishCallback;
        final AnimationSpec mAnimSpec;
        final SurfaceControl mLeash;
        final Runnable mFinishCallback;
        ValueAnimator mAnim;

        @GuardedBy("mCancelLock")
        private boolean mCancelled;

        RunningAnimation(AnimationSpec animSpec, SurfaceControl leash, Runnable finishCallback) {
            this.animSpec = animSpec;
            this.leash = leash;
            this.finishCallback = finishCallback;
            mAnimSpec = animSpec;
            mLeash = leash;
            mFinishCallback = finishCallback;
        }
    }

    @VisibleForTesting
    interface AnimatorFactory {
        ValueAnimator makeAnimator();
    }

    /**
Loading