From 52ef1bf893e27da84c179b91fa864ecb73f809c7 Mon Sep 17 00:00:00 2001 From: lumark Date: Fri, 16 Nov 2018 21:24:51 +0800 Subject: Fix system circular wait during top display focus change ag/5312657 introduced reporting top focus display change mechanism to ViewRootImpl for IME window re-focus on top display. When current focus on external display, system dialog popup on default display, and then dismiss system dialog, System will possible got circular waiting for ViewRootImpl lock <-> WMS global lock during reporting top display focus change to ViewRootImpl & system dialog doing removeWindow for dismissal. Let WindowState.reportFocusChangedSerialized out of WMS global lock to fix the case. Bug: 119658889 Test: manual to verify the issue case can pass Test: atest ActivityManagerMultiDisplayTests Change-Id: Ia30a279441def501e53eeee8913d19ac50a620cd --- .../android/server/wm/WindowManagerService.java | 30 ++++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d7d3e714eb81..c47b22fd4082 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4402,22 +4402,24 @@ public class WindowManagerService extends IWindowManager.Stub lastFocus = displayContent.mLastFocus; newFocus = displayContent.mCurrentFocus; - if (lastFocus == newFocus) { - // Report focus to ViewRootImpl when top focused display changes. - // Or, nothing to do for no window focus change. - if (topFocusedDisplayChanged && newFocus != null) { - if (DEBUG_FOCUS_LIGHT) { - Slog.d(TAG, "Reporting focus: " + newFocus - + " due to top focused display change."); - } - // See {@link IWindow#windowFocusChanged} to know why set - // reportToClient as false. - newFocus.reportFocusChangedSerialized(true, mInTouchMode, - false /* reportToClient */); - notifyFocusChanged(); + } + if (lastFocus == newFocus) { + // Report focus to ViewRootImpl when top focused display changes. + // Or, nothing to do for no window focus change. + if (topFocusedDisplayChanged && newFocus != null) { + if (DEBUG_FOCUS_LIGHT) { + Slog.d(TAG, "Reporting focus: " + newFocus + + " due to top focused display change."); } - return; + // See {@link IWindow#windowFocusChanged} to know why set + // reportToClient as false. + newFocus.reportFocusChangedSerialized(true, mInTouchMode, + false /* reportToClient */); + notifyFocusChanged(); } + return; + } + synchronized (mGlobalLock) { displayContent.mLastFocus = newFocus; if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus + " to " + newFocus + " displayId=" + displayContent.getDisplayId()); -- cgit v1.2.3-59-g8ed1b