Skip to content

feat(android): Add ANR warning breadcrumbs on Android 17+ - #6245

Open
markushi wants to merge 12 commits into
mainfrom
markushi/feat/anr-warning-listener
Open

markushi wants to merge 12 commits into
mainfrom
markushi/feat/anr-warning-listener

Conversation

@markushi

@markushi markushi commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

📜 Description

On Android 17 (API 37) and above, AppLifecycleIntegration now subscribes to ActivityManager.registerAnrWarningListener. These usually fire halfway (e.g. input dispatch at 2.5s of the 5s limit, forground service starts at 5s of the 10s limit)

Each warning becomes an app.anr breadcrumb (type: system, level: warning, message: ANR warning) with this data:

  • anr_type: the AnrTypes constant as a readable name (for example input_dispatch, broadcast_of_intent, start_foreground_service). An unknown value is kept as unknown (<n>).
  • anr_id, timeout_ms, consumed_ms
  • description: the description from the system. It is not set if the system gives an empty value.

Details:

  • The listener is registered only when enableAppLifecycleBreadcrumbs is enabled.
  • Registration is a binder call, so it runs on the SDK executor service, not on the thread that calls Sentry.init.
  • The callback runs on the binder thread that delivers it. As breadcrumb creation is cheap, this should be fine.
  • close() unregisters the listener. If the executor drops or rejects the unregister task, it runs inline. A register task that is still in the queue after close() does not register the listener.
  • AppLifecycleIntegration now takes (Context, BuildInfoProvider) in its constructor. The public no-arg constructor is kept as @Deprecated. With it, the ANR warning listener is not installed.

💡 Motivation and Context

The ANR warning arrives before the ANR. If the app then crashes, records an error, or is killed for the ANR, the event breadcrumbs show that the main thread was already slow, and they show which ANR type and how much of the timeout was used.

💚 How did you test it?

  • Added tests

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

  • Docs: add the app.anr breadcrumb to the Android breadcrumbs page.

🤖 Generated with Claude Code

@linear-code

linear-code Bot commented Oct 12, 2026

Copy link
Copy Markdown

JAVA-771

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 6c235cd

@sentry

sentry Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.63.0 (1) release

⚙️ sentry-android Build Distribution Settings

Base automatically changed from build/jdk-21 to main October 21, 2026 09:56
@getsentry getsentry deleted a comment from sentry-junior Bot Nov 9, 2026
@markushi
markushi marked this pull request as ready for review November 9, 2026 08:32
@markushi
markushi requested review from a team and adinauer as code owners November 9, 2026 08:32
@markushi
markushi requested review from 0xadam-brown and runningcode and removed request for a team November 9, 2026 08:32

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a46e24c. Configure here.

final @Nullable String description = result.getDescription();
if (description != null && !description.isEmpty()) {
breadcrumb.setData("description", description);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ANR description may include PII

Medium Severity

The app.anr breadcrumb copies AnrWarningResult.getDescription() into event data with no sendDefaultPii check. For broadcast and similar ANRs the system string is an Intent dump and can include a data URI (phone numbers, mailto, content:// paths, URL query strings). That payload is then attached to later events by default.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bugbot

Reviewed by Cursor Bugbot for commit a46e24c. Configure here.


if (this.options.isEnableAppLifecycleBreadcrumbs()) {
scheduleRegisterAnrWarningListener(scopes, this.options);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ANR breadcrumbs enabled by default

Low Severity

The new app.anr breadcrumbs are installed whenever enableAppLifecycleBreadcrumbs is on, and that option already defaults to true. There is no separate opt-in for ANR warnings, so every Android 17+ app that leaves the existing lifecycle-breadcrumb toggle unchanged starts sending this new signal.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bugbot

Reviewed by Cursor Bugbot for commit a46e24c. Configure here.

}
} catch (RejectedExecutionException e) {
unregisterAnrWarningListener(options);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unregister can miss executor shutdown

Medium Severity

close() only runs unregisterAnrWarningListener inline when submit throws or the returned Future is already cancelled. A task that is queued and later dropped by executorService.close() → shutdownNow() never unregisters. ActivityManager then keeps the Consumer, which captures scopes and can pin the closed SDK until process death.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bugbot

Reviewed by Cursor Bugbot for commit a46e24c. Configure here.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for reporting AnrWarnings

1 participant