Loading services/core/java/com/android/server/wm/RemoteAnimationController.java +40 −7 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.view.SurfaceControl.Transaction; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; import java.lang.ref.WeakReference; import java.util.ArrayList; /** Loading @@ -48,13 +49,7 @@ class RemoteAnimationController { private final ArrayList<RemoteAnimationAdapterWrapper> mPendingAnimations = new ArrayList<>(); private final Rect mTmpRect = new Rect(); private final Handler mHandler; private final IRemoteAnimationFinishedCallback mFinishedCallback = new Stub() { @Override public void onAnimationFinished() throws RemoteException { RemoteAnimationController.this.onAnimationFinished(); } }; private FinishedCallback mFinishedCallback; private final Runnable mTimeoutRunnable = () -> { onAnimationFinished(); Loading Loading @@ -96,6 +91,7 @@ class RemoteAnimationController { // Scale the timeout with the animator scale the controlling app is using. mHandler.postDelayed(mTimeoutRunnable, (long) (TIMEOUT_MS * mService.getCurrentAnimatorScale())); mFinishedCallback = new FinishedCallback(this); final RemoteAnimationTarget[] animations = createAnimations(); mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { Loading Loading @@ -124,6 +120,7 @@ class RemoteAnimationController { private void onAnimationFinished() { mHandler.removeCallbacks(mTimeoutRunnable); synchronized (mService.mWindowMap) { releaseFinishedCallback(); mService.openSurfaceTransaction(); try { for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { Loading @@ -144,6 +141,41 @@ class RemoteAnimationController { } } private void releaseFinishedCallback() { if (mFinishedCallback != null) { mFinishedCallback.release(); mFinishedCallback = null; } } private static final class FinishedCallback extends IRemoteAnimationFinishedCallback.Stub { RemoteAnimationController mOuter; FinishedCallback(RemoteAnimationController outer) { mOuter = outer; } @Override public void onAnimationFinished() throws RemoteException { if (mOuter != null) { mOuter.onAnimationFinished(); // In case the client holds on to the finish callback, make sure we don't leak // RemoteAnimationController which in turn would leak the runner on the client. mOuter = null; } } /** * Marks this callback as not be used anymore by releasing the reference to the outer class * to prevent memory leak. */ void release() { mOuter = null; } }; private class RemoteAnimationAdapterWrapper implements AnimationAdapter { private final AppWindowToken mAppWindowToken; Loading Loading @@ -212,6 +244,7 @@ class RemoteAnimationController { mPendingAnimations.remove(this); if (mPendingAnimations.isEmpty()) { mHandler.removeCallbacks(mTimeoutRunnable); releaseFinishedCallback(); invokeAnimationCancelled(); } } Loading Loading
services/core/java/com/android/server/wm/RemoteAnimationController.java +40 −7 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.view.SurfaceControl.Transaction; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; import java.lang.ref.WeakReference; import java.util.ArrayList; /** Loading @@ -48,13 +49,7 @@ class RemoteAnimationController { private final ArrayList<RemoteAnimationAdapterWrapper> mPendingAnimations = new ArrayList<>(); private final Rect mTmpRect = new Rect(); private final Handler mHandler; private final IRemoteAnimationFinishedCallback mFinishedCallback = new Stub() { @Override public void onAnimationFinished() throws RemoteException { RemoteAnimationController.this.onAnimationFinished(); } }; private FinishedCallback mFinishedCallback; private final Runnable mTimeoutRunnable = () -> { onAnimationFinished(); Loading Loading @@ -96,6 +91,7 @@ class RemoteAnimationController { // Scale the timeout with the animator scale the controlling app is using. mHandler.postDelayed(mTimeoutRunnable, (long) (TIMEOUT_MS * mService.getCurrentAnimatorScale())); mFinishedCallback = new FinishedCallback(this); final RemoteAnimationTarget[] animations = createAnimations(); mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { Loading Loading @@ -124,6 +120,7 @@ class RemoteAnimationController { private void onAnimationFinished() { mHandler.removeCallbacks(mTimeoutRunnable); synchronized (mService.mWindowMap) { releaseFinishedCallback(); mService.openSurfaceTransaction(); try { for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { Loading @@ -144,6 +141,41 @@ class RemoteAnimationController { } } private void releaseFinishedCallback() { if (mFinishedCallback != null) { mFinishedCallback.release(); mFinishedCallback = null; } } private static final class FinishedCallback extends IRemoteAnimationFinishedCallback.Stub { RemoteAnimationController mOuter; FinishedCallback(RemoteAnimationController outer) { mOuter = outer; } @Override public void onAnimationFinished() throws RemoteException { if (mOuter != null) { mOuter.onAnimationFinished(); // In case the client holds on to the finish callback, make sure we don't leak // RemoteAnimationController which in turn would leak the runner on the client. mOuter = null; } } /** * Marks this callback as not be used anymore by releasing the reference to the outer class * to prevent memory leak. */ void release() { mOuter = null; } }; private class RemoteAnimationAdapterWrapper implements AnimationAdapter { private final AppWindowToken mAppWindowToken; Loading Loading @@ -212,6 +244,7 @@ class RemoteAnimationController { mPendingAnimations.remove(this); if (mPendingAnimations.isEmpty()) { mHandler.removeCallbacks(mTimeoutRunnable); releaseFinishedCallback(); invokeAnimationCancelled(); } } Loading