Mobile Development 25 min read

Understanding and Analyzing Android ANR (Application Not Responding) Issues

This article explains the causes of Android ANR, details the input dispatching mechanism, presents key code paths in InputDispatcher, and provides a step‑by‑step analysis workflow—including system‑level factors, stack inspection, Binder problems, and memory‑related pitfalls—to help developers diagnose and resolve most ANR cases.

Coolpad Technology Team
Coolpad Technology Team
Coolpad Technology Team
Understanding and Analyzing Android ANR (Application Not Responding) Issues

The article begins by describing that when the UI thread of an Android app is blocked for too long, the system triggers an Application Not Responding (ANR) error and shows a dialog to the user if the app is in the foreground.

It then outlines the motivation for the guide: many developers encounter ANR but lack a solid understanding of the underlying mechanisms such as CPU, RAM, I/O, GC, LMK, and lock fundamentals.

ANR Principle

Most ANRs are input‑dispatch timeouts. The normal input event flow is illustrated by the following code snippet:

InputDispatcher::dispatchOnce()
    -> InputDispatcher::dispatchOnceInnerLocked
    -> InputDispatcher::dispatchKeyLocked
    -> InputDispatcher::findFocusedWindowTargetsLocked
    ...

The function findFocusedWindowTargetsLocked searches for a focused window. If none is found, the event is dropped:

// If there is no currently focused window and no focused application
if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
    ALOGI("Dropping %s event because there is no focused window or focused application in display %" PRId32 ".", NamedEnum::string(entry.type).c_str(), displayId);
    return InputEventInjectionResult::FAILED;
}

When a focused window is missing but a focused application exists, the dispatcher starts an ANR timer:

if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
    if (!mNoFocusedWindowTimeoutTime.has_value()) {
        // Start the ANR timer
        std::chrono::nanoseconds timeout = focusedApplicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
        mNoFocusedWindowTimeoutTime = currentTime + timeout.count();
        // ... log and schedule wake‑up
        return InputEventInjectionResult::PENDING;
    } else if (currentTime > *mNoFocusedWindowTimeoutTime) {
        // Timeout reached, drop the event
        return InputEventInjectionResult::FAILED;
    } else {
        // Still waiting
        return InputEventInjectionResult::PENDING;
    }
}

The timeout can be reset when a valid window is finally found:

// we have a valid, non‑null focused window
resetNoFocusedWindowTimeoutLocked();

Other situations that trigger a reset include changes to the focused application, input dispatch mode changes, and various internal calls such as stopFreezingDisplayLocked or performEnableScreen .

If the window is in an abnormal state (e.g., paused), the event is marked pending, which can also lead to ANR.

Dropping of inbound events occurs in InputDispatcher::dropInboundEventLocked for reasons like policy, disabled dispatch, app switch, blocked, stale, etc.

void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) {
    const char* reason;
    switch (dropReason) {
        case DropReason::POLICY:
            reason = "inbound event was dropped because the policy consumed it";
            break;
        case DropReason::DISABLED:
            reason = "inbound event was dropped because input dispatch is disabled";
            break;
        case DropReason::APP_SWITCH:
            reason = "inbound event was dropped because of pending overdue app switch";
            break;
        case DropReason::BLOCKED:
            reason = "inbound event was dropped because the current application is not responding and the user has started interacting with a different application";
            break;
        case DropReason::STALE:
            reason = "inbound event was dropped because it is stale";
            break;
        // ... other cases
    }
    // log and handle drop
}

The ANR detection loop checks the timeout in InputDispatcher::processAnrsLocked and, if expired, calls onAnrLocked to post a command that notifies the system.

nsecs_t InputDispatcher::processAnrsLocked() {
    const nsecs_t currentTime = now();
    if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
        if (currentTime >= *mNoFocusedWindowTimeoutTime) {
            processNoFocusedWindowAnrLocked();
            // reset state
            return LONG_LONG_MIN;
        } else {
            nextAnrCheck = *mNoFocusedWindowTimeoutTime;
        }
    }
    // ... handle other connections
    return nextAnrCheck;
}

After the technical deep‑dive, the article provides a practical analysis workflow:

Check whether system‑level factors (high load, low memory, kswapd activity) are influencing the ANR.

If not, locate the relevant am_anr line in the event log, find the matching trace file, and examine the stack for the main thread (identified by sysTid ).

Interpret thread states (RUNNING, BLOCKED, WAITING, SLEEPING) and lock owners to spot deadlocks or long‑running operations.

Investigate Binder interactions—client‑side calls, server‑side handling, and possible Binder thread‑pool exhaustion.

Analyze memory‑related causes such as frequent GC, large allocations, or memory leaks that keep the heap above its target size.

Use enhanced logs (e.g., binderinfo, nativePollOnce traces) to uncover hidden latency.

Typical case studies are presented, including:

Main‑thread long‑running tasks.

Blocked or waiting main thread due to lock contention.

Binder blocking and thread‑pool exhaustion.

Invalid stacks that appear on nativePollOnce , indicating the real work happened earlier.

Application memory problems such as excessive temporary objects, severe leaks, or explicit System.gc() calls in onTrimMemory .

The article concludes that ANR is a serious manifestation of performance problems and encourages early detection and systematic debugging using the outlined steps.

debuggingperformanceAndroidANRmemoryBinderInputDispatcher
Coolpad Technology Team
Written by

Coolpad Technology Team

Committed to advancing technology and supporting innovators. The Coolpad Technology Team regularly shares forward‑looking insights, product updates, and tech news. Tech experts are welcome to join; everyone is invited to follow us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.