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

Commit d0e3c362 authored by wilsonshih's avatar wilsonshih Committed by Wei Sheng Shih
Browse files

Preventing release animation targets due to unsynchronize.

Users can start another animation by reuse existing animation targets
during post-commit animations while canceling a previous animation.
However, because RemoteAnimationFinishedStub can be called from a
binder call, access to these animation targets must be synchronized.
Secondly, since the animation targets remain the same until the
previous animation finishes, we can disregard any previous
RemoteAnimationFinishedStub calls if the animation controller has
already requested another animation.

Flag: EXEMPT bugfix
Bug: 386794627
Test: re-start back animation animation in post-commit, verify the
animation leashes won't be released before animation finish.

Change-Id: I44f16202f08f2ee4144621c55b1bf0e76ea3f815
parent e4046a28
Loading
Loading
Loading
Loading
+49 −17
Original line number Diff line number Diff line
@@ -106,11 +106,12 @@ public class BackAnimationRunner {

    private Runnable mFinishedCallback;
    private RemoteAnimationTarget[] mApps;
    private IRemoteAnimationFinishedCallback mRemoteCallback;
    private RemoteAnimationFinishedStub mRemoteCallback;

    private static class RemoteAnimationFinishedStub extends IRemoteAnimationFinishedCallback.Stub {
        //the binder callback should not hold strong reference to it to avoid memory leak.
        private WeakReference<BackAnimationRunner> mRunnerRef;
        private final WeakReference<BackAnimationRunner> mRunnerRef;
        private boolean mAbandoned;

        private RemoteAnimationFinishedStub(BackAnimationRunner runner) {
            mRunnerRef = new WeakReference<>(runner);
@@ -118,23 +119,29 @@ public class BackAnimationRunner {

        @Override
        public void onAnimationFinished() {
            BackAnimationRunner runner = mRunnerRef.get();
            synchronized (this) {
                if (mAbandoned) {
                    return;
                }
            }
            final BackAnimationRunner runner = mRunnerRef.get();
            if (runner == null) {
                return;
            }
            if (runner.shouldMonitorCUJ(runner.mApps)) {
                InteractionJankMonitor.getInstance().end(runner.mCujType);
            runner.onAnimationFinish(this);
        }

            runner.mFinishedCallback.run();
            for (int i = runner.mApps.length - 1; i >= 0; --i) {
                 SurfaceControl sc = runner.mApps[i].leash;
                 if (sc != null && sc.isValid()) {
                     sc.release();
        void abandon() {
            synchronized (this) {
                mAbandoned = true;
                final BackAnimationRunner runner = mRunnerRef.get();
                if (runner == null) {
                    return;
                }
                if (runner.shouldMonitorCUJ(runner.mApps)) {
                    InteractionJankMonitor.getInstance().end(runner.mCujType);
                }
            }
            runner.mApps = null;
            runner.mFinishedCallback = null;
        }
    }

@@ -144,13 +151,16 @@ public class BackAnimationRunner {
     */
    void startAnimation(RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
            RemoteAnimationTarget[] nonApps, Runnable finishedCallback) {
        InteractionJankMonitor interactionJankMonitor = InteractionJankMonitor.getInstance();
        if (mRemoteCallback != null) {
            mRemoteCallback.abandon();
            mRemoteCallback = null;
        }
        mRemoteCallback = new RemoteAnimationFinishedStub(this);
        mFinishedCallback = finishedCallback;
        mApps = apps;
        if (mRemoteCallback == null) mRemoteCallback = new RemoteAnimationFinishedStub(this);
        mWaitingAnimation = false;
        if (shouldMonitorCUJ(apps)) {
            interactionJankMonitor.begin(
            InteractionJankMonitor.getInstance().begin(
                    apps[0].leash, mContext, mHandler, mCujType);
        }
        try {
@@ -161,6 +171,28 @@ public class BackAnimationRunner {
        }
    }

    void onAnimationFinish(RemoteAnimationFinishedStub finished) {
        mHandler.post(() -> {
            if (mRemoteCallback != null && finished != mRemoteCallback) {
                return;
            }
            if (shouldMonitorCUJ(mApps)) {
                InteractionJankMonitor.getInstance().end(mCujType);
            }

            mFinishedCallback.run();
            for (int i = mApps.length - 1; i >= 0; --i) {
                final SurfaceControl sc = mApps[i].leash;
                if (sc != null && sc.isValid()) {
                    sc.release();
                }
            }
            mApps = null;
            mFinishedCallback = null;
            mRemoteCallback = null;
        });
    }

    @VisibleForTesting
    boolean shouldMonitorCUJ(RemoteAnimationTarget[] apps) {
        return apps.length > 0 && mCujType != NO_CUJ;