From 2ba712905fe70d70024912fc27f99dfe0dc4bf94 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Thu, 5 May 2016 09:16:47 -0700 Subject: [PATCH] Fixed deadlock between AM and WM when animating pinned stack. In Ie18cc04ceeabd94093017f79676253e1189f5249 we delay ending the pinned stack animation until app transition is done. However, the signal that app transition is done comes in with the window manager lock held and the we call into AM to do some additional work which requires AM lock to be aquired. Since AM depends on WM we shouldn't be holding the WM lock while calling into AM since AM can call into WM with its lock held. We now post a runnable to finish the pinned stack animation without the WM lock held. Bug: 28564514 Change-Id: I8450123e992e569a74609883de810cdc611ced81 --- .../server/wm/BoundsAnimationController.java | 52 ++++++++++++------- .../server/wm/WindowManagerService.java | 3 +- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index 220a6de1d8888..51c40456c66a5 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -24,6 +24,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.animation.Animator; import android.animation.ValueAnimator; import android.graphics.Rect; +import android.os.Handler; import android.os.IBinder; import android.os.Debug; import android.util.ArrayMap; @@ -40,6 +41,8 @@ import android.view.WindowManagerInternal; * the bounds of the resized object. * * The object that is resized needs to implement {@link AnimateBoundsUser} interface. + * + * NOTE: All calls to methods in this class should be done on the UI thread */ public class BoundsAnimationController { private static final boolean DEBUG_LOCAL = false; @@ -51,28 +54,41 @@ public class BoundsAnimationController { // Only accessed on UI thread. private ArrayMap mRunningAnimations = new ArrayMap<>(); - private final WindowManagerInternal.AppTransitionListener mAppTransitionNotifier - = new WindowManagerInternal.AppTransitionListener() { - public void onAppTransitionCancelledLocked() { - animationFinished(); - } - public void onAppTransitionFinishedLocked(IBinder token) { - animationFinished(); - } - private void animationFinished() { - if (mFinishAnimationAfterTransition) { - for (int i = 0; i < mRunningAnimations.size(); i++) { - BoundsAnimator b = mRunningAnimations.valueAt(i); - b.onAnimationEnd(null); - } - } - } - }; + private final class AppTransitionNotifier + extends WindowManagerInternal.AppTransitionListener implements Runnable { + public void onAppTransitionCancelledLocked() { + animationFinished(); + } + public void onAppTransitionFinishedLocked(IBinder token) { + animationFinished(); + } + private void animationFinished() { + if (mFinishAnimationAfterTransition) { + mHandler.removeCallbacks(this); + // This might end up calling into activity manager which will be bad since we have the + // window manager lock held at this point. Post a message to take care of the processing + // so we don't deadlock. + mHandler.post(this); + } + } + + @Override + public void run() { + for (int i = 0; i < mRunningAnimations.size(); i++) { + final BoundsAnimator b = mRunningAnimations.valueAt(i); + b.onAnimationEnd(null); + } + } + } + + private final Handler mHandler; private final AppTransition mAppTransition; + private final AppTransitionNotifier mAppTransitionNotifier = new AppTransitionNotifier(); private boolean mFinishAnimationAfterTransition = false; - BoundsAnimationController(AppTransition transition) { + BoundsAnimationController(AppTransition transition, Handler handler) { + mHandler = handler; mAppTransition = transition; mAppTransition.registerListenerLocked(mAppTransitionNotifier); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5a5f10c0303b8..7494d1525958a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -979,7 +979,8 @@ public class WindowManagerService extends IWindowManager.Stub mAppTransition = new AppTransition(context, this); mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier); - mBoundsAnimationController = new BoundsAnimationController(mAppTransition); + mBoundsAnimationController = + new BoundsAnimationController(mAppTransition, UiThread.getHandler()); mActivityManager = ActivityManagerNative.getDefault(); mAmInternal = LocalServices.getService(ActivityManagerInternal.class);