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");