Skip to content

SystemEventsBreadcrumbsIntegration causes ANR when processing system broadcasts #4907

@kibotu

Description

@kibotu

Integration

sentry-android

Build System

Gradle

AGP Version

8.13.0

Proguard

Enabled

Version

8.26.0

Steps to Reproduce

Description

The SystemEventsBreadcrumbsIntegration causes Application Not Responding (ANR) errors because its BroadcastReceiver's onReceive() method runs synchronously on the main thread when processing system broadcasts (e.g., BATTERY_CHANGED, network events).

Environment

  • Sentry Android SDK Version: 8.26.0
  • Android API Level: 23/35
  • Device:

Pixel 8 Pro 51%
Pixel 9 Pro XL 12%
Pixel 7 Pro 11%
Pixel 9 Pro 10%
Other 14%

  • Kotlin Version: 2.2.21

Steps to Reproduce

  1. Initialize Sentry with enableAllAutoBreadcrumbs(true):

    SentryAndroid.init(context) { options ->
        options.enableAllAutoBreadcrumbs(true)
        // ... other configuration
    }
  2. System broadcasts fire (battery changes, network events, etc.)

  3. ANR occurs because BroadcastReceiver.onReceive() blocks the main thread

Suggested Fix

The SystemEventsBreadcrumbsIntegration should use BroadcastReceiver.goAsync() to process events asynchronously:

override fun onReceive(context: Context, intent: Intent) {
    val pendingResult = goAsync()
    // Process breadcrumb on background thread
    executorService.execute {
        try {
            // Create breadcrumb
            // Add to Sentry
        } finally {
            pendingResult.finish()
        }
    }
}

Or alternatively, the integration should be refactored to use a different approach that doesn't require a BroadcastReceiver that blocks the main thread.

Additional Context

  • The issue is exacerbated when code protection/obfuscation tools (like PairIP VMRunner) add overhead to method execution, making the synchronous processing even slower.
  • This affects apps that receive frequent system broadcasts (battery changes, network state changes, etc.).
  • The ANR timeout occurs even with background processing if the receiver itself blocks the main thread.

Note: This bug report was generated from a production Android application experiencing ANRs in the Sentry SDK's SystemEventsBreadcrumbsIntegration.

Expected Result

System event breadcrumbs should be captured without blocking the main thread. The integration should use BroadcastReceiver.goAsync() or process events asynchronously on a background thread.

Actual Result

ANR occurs when system broadcasts are processed synchronously on the main thread. The stack trace shows:

io.sentry.android.core.ApplicationNotResponding: Background ANR

  libandroid_runtime  0x154f0      null
    at com.pairip.VMRunner.executeVM
    at com.pairip.VMRunner.invoke(VMRunner.java:67)
    at io.sentry.android.core.SystemEventsBreadcrumbsIntegration$SystemEventsBroadcastReceiver.onReceive(SystemEventsBreadcrumbsIntegration.java:358)
    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1698)
    at android.app.LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0.run(unavailable:2)
    at android.os.Handler.handleCallback(Handler.java:978)
    at android.os.Handler.dispatchMessage(Handler.java:104)
    at android.os.Looper.loopOnce(Looper.java:238)
    at android.os.Looper.loop(Looper.java:357)
    at android.app.ActivityThread.main(ActivityThread.java:8090)
    at java.lang.reflect.Method.invoke
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1026)

Breadcrumbs Context

The ANR occurs when processing system events such as:

  • BATTERY_CHANGED broadcasts
  • Network availability events (NETWORK_AVAILABLE)
  • Other system broadcasts

Workaround

Disabling auto breadcrumbs prevents the ANR but loses useful breadcrumbs:

SentryAndroid.init(context) { options ->
    options.enableAllAutoBreadcrumbs(false)
    // Manual breadcrumbs via Sentry.addBreadcrumb() will still work
}

Alternatively, setting a background executor service helps with Sentry's internal processing but doesn't solve the root issue since the BroadcastReceiver itself still runs on the main thread:

options.setExecutorService(Dispatchers.IO.asExecutorService())

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions