From a2363540475778db4d6351c581dafb8407a50173 Mon Sep 17 00:00:00 2001 From: nttsai Date: Wed, 3 Apr 2019 15:50:06 +0800 Subject: [PATCH] Fix a deadlock WMG->WMS, WMS->WMG In ImmersiveModeConfirmation, the WindowManager operations shouldn't be called while holding the WM lock. Thus, I remove the assigned operation of mWindowManager member in the constructor function. Next, I add a private function to get a valid mWindowManager member in 3 functions (handleHide, handleShow, onAttachedToWindow). The 3 functions are called by a different thread by specific events. It should avoid the deadlock we saw now. Bug: 129101307, 128520392 Test: local build and manually test it for 2 times Test Steps: 1. Boot up the device 2. Start Photo to view a photo in full screen and exit full screen Change-Id: If42f4fd6a31869d5eefa8b445c32665aef1ee07d --- .../server/wm/ImmersiveModeConfirmation.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java index 3d20501222b69..d774dc3fd2f1d 100644 --- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java +++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java @@ -90,8 +90,6 @@ public class ImmersiveModeConfirmation { mShowDelayMs = getNavBarExitDuration() * 3; mPanicThresholdMs = context.getResources() .getInteger(R.integer.config_immersive_mode_confirmation_panic); - mWindowManager = (WindowManager) - mContext.getSystemService(Context.WINDOW_SERVICE); mVrModeEnabled = vrModeEnabled; } @@ -177,7 +175,7 @@ public class ImmersiveModeConfirmation { private void handleHide() { if (mClingWindow != null) { if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation"); - mWindowManager.removeView(mClingWindow); + getWindowManager().removeView(mClingWindow); mClingWindow = null; } } @@ -275,7 +273,7 @@ public class ImmersiveModeConfirmation { super.onAttachedToWindow(); DisplayMetrics metrics = new DisplayMetrics(); - mWindowManager.getDefaultDisplay().getMetrics(metrics); + getWindowManager().getDefaultDisplay().getMetrics(metrics); float density = metrics.density; getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener); @@ -341,6 +339,19 @@ public class ImmersiveModeConfirmation { } } + /** + * DO HOLD THE WINDOW MANAGER LOCK WHEN CALLING THIS METHOD + * The reason why we add this method is to avoid the deadlock of WMG->WMS and WMS->WMG + * when ImmersiveModeConfirmation object is created. + */ + private WindowManager getWindowManager() { + if (mWindowManager == null) { + mWindowManager = (WindowManager) + mContext.getSystemService(Context.WINDOW_SERVICE); + } + return mWindowManager; + } + private void handleShow() { if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation"); @@ -352,7 +363,7 @@ public class ImmersiveModeConfirmation { // show the confirmation WindowManager.LayoutParams lp = getClingWindowLayoutParams(); - mWindowManager.addView(mClingWindow, lp); + getWindowManager().addView(mClingWindow, lp); } private final Runnable mConfirm = new Runnable() {