From 639fc5a76a05922f380ad74d61e95ea9b32bd09c Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 8 Sep 2022 16:50:10 -0700 Subject: [PATCH] WM: Blame the window from the focus request for ANR If there are no focusable windows, then try to blame the window that was requested to become focused. This will avoid blaming the wrong process when WM requests focus on a window that is placed on top of the focused app and the window fails to become focusable. Test: atest android.server.wm.AnrTests Test: steps from bug Bug: b/23990703 Change-Id: Ibf74086de259a671c77fcee9746048a3a440bcc4 --- .../com/android/server/wm/AnrController.java | 29 +++++++++++++++++++ .../com/android/server/wm/InputMonitor.java | 5 +++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/AnrController.java b/services/core/java/com/android/server/wm/AnrController.java index e0ac37ae0fe43..01098dedea6e1 100644 --- a/services/core/java/com/android/server/wm/AnrController.java +++ b/services/core/java/com/android/server/wm/AnrController.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.server.wm.ActivityRecord.INVALID_PID; +import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutMillisLocked; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.NonNull; @@ -72,6 +73,33 @@ class AnrController { + ". Dropping notifyNoFocusedWindowAnr request"); return; } + + // App is unresponsive, but we are actively trying to give focus to a window. + // Blame the window if possible since the window may not belong to the app. + DisplayContent display = mService.mRoot.getDisplayContent(activity.getDisplayId()); + IBinder focusToken = display == null ? null : display.getInputMonitor().mInputFocus; + InputTarget focusTarget = mService.getInputTargetFromToken(focusToken); + + if (focusTarget != null) { + // Check if we have a recent focus request, newer than the dispatch timeout, then + // ignore the focus request. + WindowState targetWindowState = focusTarget.getWindowState(); + boolean requestIsValid = SystemClock.uptimeMillis() + - display.getInputMonitor().mInputFocusRequestTimeMillis + >= getInputDispatchingTimeoutMillisLocked( + targetWindowState.getActivityRecord()); + + if (requestIsValid) { + if (notifyWindowUnresponsive(focusToken, timeoutRecord)) { + Slog.i(TAG_WM, "Blamed " + focusTarget.getWindowState().getName() + + " using pending focus request. Focused activity: " + + activity.getName()); + return; + } + } + } + + Slog.i(TAG_WM, "ANR in " + activity.getName() + ". Reason: " + timeoutRecord.mReason); dumpAnrStateLocked(activity, null /* windowState */, timeoutRecord.mReason); mUnresponsiveAppByDisplay.put(activity.getDisplayId(), activity); @@ -208,6 +236,7 @@ class AnrController { } } mService.mAmInternal.inputDispatchingResumed(unresponsiveApp.getPid()); + mUnresponsiveAppByDisplay.remove(newFocus.getDisplayId()); } /** diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 610ce35408580..7860b1530e920 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -52,6 +52,7 @@ import android.graphics.Region; import android.os.Handler; import android.os.IBinder; import android.os.InputConfig; +import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; @@ -77,7 +78,8 @@ final class InputMonitor { private final WindowManagerService mService; // Current input focus token for keys and other non-touch events. May be null. - private IBinder mInputFocus = null; + IBinder mInputFocus = null; + long mInputFocusRequestTimeMillis = 0; // When true, need to call updateInputWindowsLw(). private boolean mUpdateInputWindowsNeeded = true; @@ -479,6 +481,7 @@ final class InputMonitor { } mInputFocus = focusToken; + mInputFocusRequestTimeMillis = SystemClock.uptimeMillis(); mInputTransaction.setFocusedWindow(mInputFocus, windowName, mDisplayId); EventLog.writeEvent(LOGTAG_INPUT_FOCUS, "Focus request " + windowName, "reason=UpdateInputWindows");