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
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index e8f4545..c1ef395 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 @@
// 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 @@
}
try {
- mRunner.asBinder().linkToDeath(this, 0);
+ linkToDeathOfRunner();
} catch (RemoteException e) {
cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
return;
@@ -374,7 +376,7 @@
}
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 @@
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 3be7b235..16f4cd0 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 @@
private FinishedCallback mFinishedCallback;
private boolean mCanceled;
+ private boolean mLinkedToDeathOfRunner;
RemoteAnimationController(WindowManagerService service,
RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) {
@@ -106,7 +107,7 @@
}
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 @@
private void onAnimationFinished() {
mHandler.removeCallbacks(mTimeoutRunnable);
- mRemoteAnimationAdapter.getRunner().asBinder().unlinkToDeath(this, 0);
synchronized (mService.mWindowMap) {
+ unlinkToDeathOfRunner();
releaseFinishedCallback();
mService.openSurfaceTransaction();
try {
@@ -204,6 +205,20 @@
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();