Anr Audit And Fix
Android (Google)OfficialCreated by Google LLCDistributed by Android (Google)
- Skill
- Review and audit
- Software development
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The anr-audit-and-fix skill provides a structured methodology for identifying and remediating Application Not Responding (ANR) issues in Android applications. It supports two primary workflows: a static analysis path for auditing source code to detect potential thread-blocking operations or sync barrier leaks, and a trace-driven path for analyzing existing ANR stack dumps to determine root causes and propose fixes.
What it does
- Performs static analysis on Android source code to identify potential main-thread blocking operations.
- Detects Sync Barrier Leak risks caused by off-main-thread mutations of attached Views.
- Systematically diagnoses ANR stack dumps and trace files.
- Categorizes ANR findings into application defects, resource overloads, or external bottlenecks.
- Provides a standardized reporting template for ANR trace analysis.
- Offers guidance on distinguishing between actual ANR risks and non-blocking operations.
When to use it
- When auditing Android source code to proactively find potential ANR-causing code patterns.
- When investigating a reported ANR to determine if it is caused by application code or external factors.
- When analyzing stack dumps to identify specific blocking chains or thread contention issues.
- When verifying if off-main-thread UI access is creating a Sync Barrier Leak risk.
Advantages
- Enforces a rigorous proof-based approach to identifying thread-blocking candidates.
- Distinguishes between critical ANR risks and minor frame drops.
- Provides a clear framework for differentiating between application-level defects and external system bottlenecks.
- Standardizes the documentation and reporting of ANR investigations.
Usage examples
- “Audit this Activity for potential ANR risks.”
- The agent will scan the provided code, verify the executing thread for blocking primitives, and report any confirmed ANR risks or Sync Barrier Leaks.
- “Analyze this ANR stack dump and suggest a fix.”
- The agent will process the trace, identify the unresponsive thread and blocking mechanism, and provide a structured report with a recommended code fix if the issue is an application defect.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/android/anr-audit-and-fix/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip anr-audit-and-fix.zip -d .agents/skills
Documentation by Google LLC
Select the execution path matching the user's request:
1. Path A: Static codebase ANR risk audit
When auditing source files or scanning for thread-blocking operations:
Follow references/risk_analysis_guide.md step by step: list candidates, prove the executing thread (trace callers when the thread depends on them), prove the call blocks, then attribute and grade. Report only candidates that pass these checks; list the dismissed ones separately with a one-line reason.
Evaluate off-main-thread mutations of attached Views not merely as crash risks (
CalledFromWrongThreadException), but as Sync Barrier Leak ANR risks with their own proof (off-main execution plus an attached View).
2. Path B: Trace-driven diagnosis and remediation
When analyzing ANR traces or stack dumps:
Diagnose systematically using references/trace_analysis_guide.md and format the report with references/anr_trace_report_template.md.
Base findings strictly on log evidence. Propose application fixes only for
APP_DEFECTorAPP_RESOURCE_OVERLOAD(never forEXTERNAL_BOTTLENECK).
Files
- ATTRIBUTION.mdAdded by AutoGineer972 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md1.7 KiB
- references/anr_trace_report_template.md1.9 KiB
- references/risk_analysis_guide.md6.9 KiB
- references/trace_analysis_guide.md11.6 KiB
references/risk_analysis_guide.md
Goal: decide whether code in the file under review stalls the main thread (or a Binder thread that a caller waits on synchronously) long enough to cause an ANR, and point to the exact lines. Work through the steps in order. A candidate becomes a finding only if it passes Steps 2, 3, and 5. The one exception is Step 4 (View threading): its proof is off-main execution on an attached View, followed by Step 5.
Step 1: List candidates in the file
Blocking primitives and locks :
runBlocking, blocking futures, latches, monitors,Thread.sleep, RxJavablocking*operators, or locks contended with background work.Synchronous I/O or heavy compute : network, disk, file, or database reads and writes (
SharedPreferences.Editor.commit(),ContentResolver.query, non-suspend DAO calls), bitmap decoding, JSON or XML payload parsing,MediaPlayer.prepare(), or unbounded loops.Synchronous IPC or slow component lifecycle : cross-process Binder or
ContentProvidercalls, or heavy work insideApplication,Activity,Service,BroadcastReceiver, orContentProviderlifecycle callbacks.Off-main mutation of attached Views (Step 4).
Step 2: Prove the executing thread (mandatory)
Establish which thread actually executes each candidate rather than assuming:
Inspect the enclosing scope : check coroutine dispatchers (
lifecycleScopeandviewModelScopedefault to Main), reactive schedulers, executors or handlers, and Android component callbacks (ContentProviderqueries run on a Binder thread cross-process, or the caller's thread in-process).Trace callers when the thread depends on the caller: locate callers in the project (1 to 2 hops) to verify the dispatching thread, and state the verified call chain.
Listeners and callbacks: verify which thread or executor dispatches the callback before assuming it runs on a worker thread.
Dismiss unproven candidates: if you can't show that the candidate runs on the main thread or a synchronously awaited Binder thread (or off the main thread for Step 4 candidates), list it under dismissed as "thread not established".
Step 3: Prove the call blocks
Seeded in-memory reactive reads return immediately :
blockingFirst()orgetValue()on a seededBehaviorRelayorBehaviorSubject,StateFlow.value, orfirst()on aStateFlow/ populatedSharedFlow(replay >= 1) return in-memory state immediately. Check how the source is initialized before flagging.Suspension isn't blocking : suspend functions,
delay, and coroutineMutex/Semaphoresuspend the coroutine without blocking the underlying thread.runBlockingblocks only its calling thread :runBlockingcalled on a background thread (even withDispatchers.Maininside) doesn't block the main thread unless the main thread is waiting on that worker.Short bounded waits aren't findings: a single sleep or wait of roughly a frame to a few frames (tens of milliseconds to about a hundred), not in a loop and not on a hot path, causes minor frame drops, not an ANR. Don't report it as a finding; mention it under dismissed candidates at most.
Latent hazard : a blocking primitive on the main thread whose inner work completes in memory without I/O or suspension is a
LOWfinding. Explain why it doesn't block today and what change would make it block.
Step 4: View threading violations (sync barrier leak)
Treat off-main-thread UI access on an attached View as a Sync Barrier
Leak ANR risk, not merely a CalledFromWrongThreadException crash risk.
Mechanism :
ViewRootImpl.requestLayout()callscheckThread(), but invalidation paths (invalidate()->onDescendantInvalidated()->scheduleTraversals()) don't, allowing a background thread to enterscheduleTraversals()concurrently with the main thread. Both callmHandler.getLooper().getQueue().postSyncBarrier()and overwrite the unsynchronizedmTraversalBarriertoken;doTraversal()removes only one token, leaking an orphaned synchronization barrier inMessageQueue(freezing synchronous main-thread messages between VSYNC frames or throwingIllegalStateExceptionatMessageQueue.removeSyncBarrier). Android 17 fixed this platform race; Android 16 and older remain vulnerable, so apps shipping to those versions must still remove the violation. Creating or configuring a detached View off-main doesn't trigger this race.What to check : View or adapter mutations inside background coroutine scopes (
Dispatchers.Default/IO), background Rx schedulers, executors or threads, or asynchronous callbacks invoked on worker threads (such as network, image-loading, media, sensor, or Binder listeners).Detection : Android 17's
View#registerCalledFromWrongThreadListener(requirescompileSdk 37; guard calls withBuild.VERSION.SDK_INT >= 37),adb shell am compat enable ENFORCE_THREAD_CHECKS_ON_VIEW_ROOT_IMPL_APIS <package>(debuggable builds), or the Robolectric unit-test flag-Drobolectric.enforceViewMethodsCalledOnMainThread=true.Remediation : fix the threading context at the root scope :
Coroutines : start UI flows on
Dispatchers.Main(lifecycleScopeorviewModelScope) and wrap only slow I/O or compute work inwithContext(Dispatchers.IO)orDispatchers.Default.Threads, executors, and callbacks : keep in-memory UI reads and mutations on the main thread before submitting background work, or configure the upstream stream, callback executor, or target API to deliver results on the main thread (
AndroidSchedulers.mainThread(), main-thread UI targets, or main executor).
Step 5: Attribute and grade
Attribute to the file that owns the defect: report a finding only if the blocking statement or off-main View mutation originates in the file under review (or in a concrete dependency that unconditionally blocks when called on the main thread from this file). If this file invokes an abstract callback or listener interface and an external caller or host class chooses to block inside its callback implementation, attribute the defect to that external file and dismiss it here as "owned by caller or host file".
Severity :
HIGH: main-thread I/O or long waits on primary paths (startup, lifecycle, input), or off-main mutation of attached Views.MEDIUM: main-thread blocking on secondary paths, or bounded work stalling for hundreds of milliseconds.LOW: latent hazards that complete in memory today, or Binder-thread blocking reached only from external processes.
Output
One-line verdict first:
ANR risk: yes (<highest severity>)orANR risk: none found in this file.For each finding: line range, executing thread and verified call chain, why it blocks (or, for Step 4, why it leaks the sync barrier), severity, and suggested fix.
Dismissed candidates: one line each with the reason (for example, "thread not established", "seeded relay, returns immediately", "runs on IO through caller X", "owned by caller or host file").
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Google LLC
- Publisher
- Android (Google) (Official)
- Distributed by
- Android (Google)
- Source
- android/skills · performance/anr-audit-and-fix · commit bf68e2d
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.txt)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Google LLC or Android (Google).
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download anr-audit-and-fix.zip