Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 639fc5a7 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

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
parent ad9195be
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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());
    }

    /**
+4 −1
Original line number Diff line number Diff line
@@ -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");