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
This commit is contained in:
Vishnu Nair
2022-09-08 16:50:10 -07:00
parent ad9195bef6
commit 639fc5a76a
2 changed files with 33 additions and 1 deletions

View File

@@ -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());
}
/**

View File

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