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

Commit 5c7327ff authored by Mohamad Mahmoud's avatar Mohamad Mahmoud
Browse files

Move dumpAnrStateAsync calls after inputDispatchingTimedOut and update the durations array

Reorder the calls to dumpAnrStateAsync, placing them after the execution of ActivityManagerService.InputDispatchingTimedOut.
This adjustment prevents a potential race condition that could cause a significant delay in inputDispatchingTimedOut
(and consequently, the generation of the first core dump in the ANR). By making this change, we ensure that the global window
lock is held first by inputDispatchingTimedOut (in the call to  WindowProcessController.getInputDispatchingTimeoutMillis)

Test: Tested manually
Bug: 272292150
Change-Id: If48a9e5e3af38cabe618750b7989318af3fd75c4
parent d31105e0
Loading
Loading
Loading
Loading
+34 −1
Original line number Original line Diff line number Diff line
@@ -120,6 +120,10 @@ public class AnrLatencyTracker implements AutoCloseable {


    private long mPreDumpIfLockTooSlowStartUptime;
    private long mPreDumpIfLockTooSlowStartUptime;
    private long mPreDumpIfLockTooSlowDuration = 0;
    private long mPreDumpIfLockTooSlowDuration = 0;
    private long mNotifyAppUnresponsiveStartUptime;
    private long mNotifyAppUnresponsiveDuration = 0;
    private long mNotifyWindowUnresponsiveStartUptime;
    private long mNotifyWindowUnresponsiveDuration = 0;


    private final int mAnrRecordPlacedOnQueueCookie =
    private final int mAnrRecordPlacedOnQueueCookie =
            sNextAnrRecordPlacedOnQueueCookieGenerator.incrementAndGet();
            sNextAnrRecordPlacedOnQueueCookieGenerator.incrementAndGet();
@@ -425,11 +429,36 @@ public class AnrLatencyTracker implements AutoCloseable {
        anrSkipped("dumpStackTraces");
        anrSkipped("dumpStackTraces");
    }
    }


    /** Records the start of AnrController#notifyAppUnresponsive. */
    public void notifyAppUnresponsiveStarted() {
        mNotifyAppUnresponsiveStartUptime = getUptimeMillis();
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "notifyAppUnresponsive()");
    }

    /** Records the end of AnrController#notifyAppUnresponsive. */
    public void notifyAppUnresponsiveEnded() {
        mNotifyAppUnresponsiveDuration = getUptimeMillis() - mNotifyAppUnresponsiveStartUptime;
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    /** Records the start of AnrController#notifyWindowUnresponsive. */
    public void notifyWindowUnresponsiveStarted() {
        mNotifyWindowUnresponsiveStartUptime = getUptimeMillis();
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "notifyWindowUnresponsive()");
    }

    /** Records the end of AnrController#notifyWindowUnresponsive. */
    public void notifyWindowUnresponsiveEnded() {
        mNotifyWindowUnresponsiveDuration = getUptimeMillis()
                - mNotifyWindowUnresponsiveStartUptime;
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    /**
    /**
     * Returns latency data as a comma separated value string for inclusion in ANR report.
     * Returns latency data as a comma separated value string for inclusion in ANR report.
     */
     */
    public String dumpAsCommaSeparatedArrayWithHeader() {
    public String dumpAsCommaSeparatedArrayWithHeader() {
        return "DurationsV4: " + mAnrTriggerUptime
        return "DurationsV5: " + mAnrTriggerUptime
                /* triggering_to_app_not_responding_duration = */
                /* triggering_to_app_not_responding_duration = */
                + "," + (mAppNotRespondingStartUptime -  mAnrTriggerUptime)
                + "," + (mAppNotRespondingStartUptime -  mAnrTriggerUptime)
                /* app_not_responding_duration = */
                /* app_not_responding_duration = */
@@ -480,6 +509,10 @@ public class AnrLatencyTracker implements AutoCloseable {
                + "," + (mCopyingFirstPidSucceeded ? 1 : 0)
                + "," + (mCopyingFirstPidSucceeded ? 1 : 0)
                /* preDumpIfLockTooSlow_duration = */
                /* preDumpIfLockTooSlow_duration = */
                + "," + mPreDumpIfLockTooSlowDuration
                + "," + mPreDumpIfLockTooSlowDuration
                /* notifyAppUnresponsive_duration = */
                + "," + mNotifyAppUnresponsiveDuration
                /* notifyWindowUnresponsive_duration = */
                + "," + mNotifyWindowUnresponsiveDuration
                + "\n\n";
                + "\n\n";


    }
    }
+13 −13
Original line number Original line Diff line number Diff line
@@ -68,7 +68,7 @@ class AnrController {
    void notifyAppUnresponsive(InputApplicationHandle applicationHandle,
    void notifyAppUnresponsive(InputApplicationHandle applicationHandle,
            TimeoutRecord timeoutRecord) {
            TimeoutRecord timeoutRecord) {
        try {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "notifyAppUnresponsive()");
            timeoutRecord.mLatencyTracker.notifyAppUnresponsiveStarted();
            timeoutRecord.mLatencyTracker.preDumpIfLockTooSlowStarted();
            timeoutRecord.mLatencyTracker.preDumpIfLockTooSlowStarted();
            preDumpIfLockTooSlow();
            preDumpIfLockTooSlow();
            timeoutRecord.mLatencyTracker.preDumpIfLockTooSlowEnded();
            timeoutRecord.mLatencyTracker.preDumpIfLockTooSlowEnded();
@@ -111,7 +111,6 @@ class AnrController {
                if (!blamePendingFocusRequest) {
                if (!blamePendingFocusRequest) {
                    Slog.i(TAG_WM, "ANR in " + activity.getName() + ".  Reason: "
                    Slog.i(TAG_WM, "ANR in " + activity.getName() + ".  Reason: "
                            + timeoutRecord.mReason);
                            + timeoutRecord.mReason);
                    dumpAnrStateAsync(activity, null /* windowState */, timeoutRecord.mReason);
                    mUnresponsiveAppByDisplay.put(activity.getDisplayId(), activity);
                    mUnresponsiveAppByDisplay.put(activity.getDisplayId(), activity);
                }
                }
            }
            }
@@ -123,8 +122,13 @@ class AnrController {
            } else {
            } else {
                activity.inputDispatchingTimedOut(timeoutRecord, INVALID_PID);
                activity.inputDispatchingTimedOut(timeoutRecord, INVALID_PID);
            }
            }

            if (!blamePendingFocusRequest) {
                dumpAnrStateAsync(activity, null /* windowState */, timeoutRecord.mReason);
            }

        } finally {
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            timeoutRecord.mLatencyTracker.notifyAppUnresponsiveEnded();
        }
        }
    }
    }


@@ -139,7 +143,7 @@ class AnrController {
    void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
    void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
            @NonNull TimeoutRecord timeoutRecord) {
            @NonNull TimeoutRecord timeoutRecord) {
        try {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "notifyWindowUnresponsive()");
            timeoutRecord.mLatencyTracker.notifyWindowUnresponsiveStarted();
            if (notifyWindowUnresponsive(token, timeoutRecord)) {
            if (notifyWindowUnresponsive(token, timeoutRecord)) {
                return;
                return;
            }
            }
@@ -150,7 +154,7 @@ class AnrController {
            }
            }
            notifyWindowUnresponsive(pid.getAsInt(), timeoutRecord);
            notifyWindowUnresponsive(pid.getAsInt(), timeoutRecord);
        } finally {
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            timeoutRecord.mLatencyTracker.notifyWindowUnresponsiveEnded();
        }
        }
    }
    }


@@ -168,6 +172,7 @@ class AnrController {
        final int pid;
        final int pid;
        final boolean aboveSystem;
        final boolean aboveSystem;
        final ActivityRecord activity;
        final ActivityRecord activity;
        final WindowState windowState;
        timeoutRecord.mLatencyTracker.waitingOnGlobalLockStarted();
        timeoutRecord.mLatencyTracker.waitingOnGlobalLockStarted();
        synchronized (mService.mGlobalLock) {
        synchronized (mService.mGlobalLock) {
            timeoutRecord.mLatencyTracker.waitingOnGlobalLockEnded();
            timeoutRecord.mLatencyTracker.waitingOnGlobalLockEnded();
@@ -175,7 +180,7 @@ class AnrController {
            if (target == null) {
            if (target == null) {
                return false;
                return false;
            }
            }
            WindowState windowState = target.getWindowState();
            windowState = target.getWindowState();
            pid = target.getPid();
            pid = target.getPid();
            // Blame the activity if the input token belongs to the window. If the target is
            // Blame the activity if the input token belongs to the window. If the target is
            // embedded, then we will blame the pid instead.
            // embedded, then we will blame the pid instead.
@@ -183,13 +188,13 @@ class AnrController {
                    ? windowState.mActivityRecord : null;
                    ? windowState.mActivityRecord : null;
            Slog.i(TAG_WM, "ANR in " + target + ". Reason:" + timeoutRecord.mReason);
            Slog.i(TAG_WM, "ANR in " + target + ". Reason:" + timeoutRecord.mReason);
            aboveSystem = isWindowAboveSystem(windowState);
            aboveSystem = isWindowAboveSystem(windowState);
            dumpAnrStateAsync(activity, windowState, timeoutRecord.mReason);
        }
        }
        if (activity != null) {
        if (activity != null) {
            activity.inputDispatchingTimedOut(timeoutRecord, pid);
            activity.inputDispatchingTimedOut(timeoutRecord, pid);
        } else {
        } else {
            mService.mAmInternal.inputDispatchingTimedOut(pid, aboveSystem, timeoutRecord);
            mService.mAmInternal.inputDispatchingTimedOut(pid, aboveSystem, timeoutRecord);
        }
        }
        dumpAnrStateAsync(activity, windowState, timeoutRecord.mReason);
        return true;
        return true;
    }
    }


@@ -199,15 +204,10 @@ class AnrController {
    private void notifyWindowUnresponsive(int pid, TimeoutRecord timeoutRecord) {
    private void notifyWindowUnresponsive(int pid, TimeoutRecord timeoutRecord) {
        Slog.i(TAG_WM,
        Slog.i(TAG_WM,
                "ANR in input window owned by pid=" + pid + ". Reason: " + timeoutRecord.mReason);
                "ANR in input window owned by pid=" + pid + ". Reason: " + timeoutRecord.mReason);
        timeoutRecord.mLatencyTracker.waitingOnGlobalLockStarted();
        synchronized (mService.mGlobalLock) {
            timeoutRecord.mLatencyTracker.waitingOnGlobalLockEnded();
            dumpAnrStateAsync(null /* activity */, null /* windowState */, timeoutRecord.mReason);
        }

        // We cannot determine the z-order of the window, so place the anr dialog as high
        // We cannot determine the z-order of the window, so place the anr dialog as high
        // as possible.
        // as possible.
        mService.mAmInternal.inputDispatchingTimedOut(pid, true /*aboveSystem*/, timeoutRecord);
        mService.mAmInternal.inputDispatchingTimedOut(pid, true /*aboveSystem*/, timeoutRecord);
        dumpAnrStateAsync(null /* activity */, null /* windowState */, timeoutRecord.mReason);
    }
    }


    /**
    /**