From 653c6c1100d9093d0850dc21365b0b91db8cfffb Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Mon, 9 Apr 2018 14:12:46 -0700 Subject: [PATCH] AnimationControllers: Only unlinkToDeath if previously linked Fixes crashes when we unlink to the runners if the animation was cancelled prior to linking to the death of the runners. Change-Id: Ic52c8bea0985bce8a2abfd61d8b54ab6fff9e288 Fixes: 77756198 Test: make --- .../server/wm/RecentsAnimationController.java | 22 ++++++++++++++++--- .../server/wm/RemoteAnimationController.java | 19 ++++++++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index e8f4545e1c27a..c1ef395f37258 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -110,7 +110,9 @@ public class RecentsAnimationController implements DeathRecipient { // minimized private boolean mSplitScreenMinimized; - private Rect mTmpRect = new Rect(); + private final Rect mTmpRect = new Rect(); + + private boolean mLinkedToDeathOfRunner; public interface RecentsAnimationCallbacks { void onAnimationFinished(@ReorderMode int reorderMode); @@ -266,7 +268,7 @@ public class RecentsAnimationController implements DeathRecipient { } try { - mRunner.asBinder().linkToDeath(this, 0); + linkToDeathOfRunner(); } catch (RemoteException e) { cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); return; @@ -374,7 +376,7 @@ public class RecentsAnimationController implements DeathRecipient { } mPendingAnimations.clear(); - mRunner.asBinder().unlinkToDeath(this, 0); + unlinkToDeathOfRunner(); // Clear associated input consumers mService.mInputMonitor.updateInputWindowsLw(true /*force*/); mService.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION); @@ -384,6 +386,20 @@ public class RecentsAnimationController implements DeathRecipient { mService.mH.postDelayed(mFailsafeRunnable, FAILSAFE_DELAY); } + private void linkToDeathOfRunner() throws RemoteException { + if (!mLinkedToDeathOfRunner) { + mRunner.asBinder().linkToDeath(this, 0); + mLinkedToDeathOfRunner = true; + } + } + + private void unlinkToDeathOfRunner() { + if (mLinkedToDeathOfRunner) { + mRunner.asBinder().unlinkToDeath(this, 0); + mLinkedToDeathOfRunner = false; + } + } + @Override public void binderDied() { cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index 3be7b23590e58..16f4cd0d50ed8 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -61,6 +61,7 @@ class RemoteAnimationController implements DeathRecipient { private FinishedCallback mFinishedCallback; private boolean mCanceled; + private boolean mLinkedToDeathOfRunner; RemoteAnimationController(WindowManagerService service, RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) { @@ -106,7 +107,7 @@ class RemoteAnimationController implements DeathRecipient { } mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { try { - mRemoteAnimationAdapter.getRunner().asBinder().linkToDeath(this, 0); + linkToDeathOfRunner(); mRemoteAnimationAdapter.getRunner().onAnimationStart(animations, mFinishedCallback); } catch (RemoteException e) { Slog.e(TAG, "Failed to start remote animation", e); @@ -164,8 +165,8 @@ class RemoteAnimationController implements DeathRecipient { private void onAnimationFinished() { mHandler.removeCallbacks(mTimeoutRunnable); - mRemoteAnimationAdapter.getRunner().asBinder().unlinkToDeath(this, 0); synchronized (mService.mWindowMap) { + unlinkToDeathOfRunner(); releaseFinishedCallback(); mService.openSurfaceTransaction(); try { @@ -204,6 +205,20 @@ class RemoteAnimationController implements DeathRecipient { mService.sendSetRunningRemoteAnimation(pid, running); } + private void linkToDeathOfRunner() throws RemoteException { + if (!mLinkedToDeathOfRunner) { + mRemoteAnimationAdapter.getRunner().asBinder().linkToDeath(this, 0); + mLinkedToDeathOfRunner = true; + } + } + + private void unlinkToDeathOfRunner() { + if (mLinkedToDeathOfRunner) { + mRemoteAnimationAdapter.getRunner().asBinder().unlinkToDeath(this, 0); + mLinkedToDeathOfRunner = false; + } + } + @Override public void binderDied() { cancelAnimation();