Skip to content

[Bug]: FCMBroadcastReceiver ANR on cold start — 2-thread IO pool starved by init HTTP (Samsung/Motorola) #2751

Open

Description

@soumen-crypto

What happened?

Play Console shows many ANRs after upgrading to OneSignal 5.x (we saw this after shipping with ~5.9.8 / later 5.10.0). Mostly Samsung and Motorola.

User-facing dialog: “App isn’t responding” on random screens (home, live session, etc.). Those screens are not the root cause.

What actually happens:

  1. A push arrives and starts a cold process (FCMBroadcastReceiver).
  2. Android gives the broadcast ~10s (goAsync).
  3. OneSignal’s IO pool has only 2 threads. On process start both can be busy with SDK init HTTP (and any early OneSignal.login() / other startup network).
  4. Push handling sits in the queue. After ~10s Android reports an ANR on whatever Activity is visible.
  5. Main thread is often idle in dumps — this is broadcast timeout, not UI jank.

Thread dumps commonly show:

  • Timeout of broadcast ... FCMBroadcastReceiver
  • OneSignal-IO-* busy with HTTP / waiting
  • Sometimes Firebase Performance wrapping OneSignal HttpURLConnection (InstrHttpsURLConnection), which makes TLS slower and worsens the race

Related upstream discussion: #2709 / #2722 (dedicated pool / cold-start FCM contention).

Our mitigations (app-side):

  • Keep OneSignal.init early; do not call OneSignal.login() from Application.onCreate (defer until after splash / auth)
  • Disable Firebase Performance HTTP instrumentation for these calls
  • Avoid other heavy SDK init on push-wakeup process starts
  • Defer requestPermission until Home (not splash)

These reduce load on the 2 IO threads, but ANRs can still happen if init HTTP alone exceeds ~10s. A dedicated OneSignal dispatcher / not sharing the same 2-thread pool with FCM work would fix this properly in the SDK.

Steps to reproduce?

1. Install app with OneSignal Android SDK 5.10.0 (also reproduced on 5.9.8).
2. Call OneSignal.initWithContext in Application.onCreate (and optionally OneSignal.login early — that makes it worse).
3. Kill the process **without Force Stop** (`adb shell am kill <package>` or swipe from Recents).
4. Send a OneSignal / FCM test push so the process cold-starts from `FCMBroadcastReceiver`.
5. Optionally open the app and send another push while on a foreground screen.
6. Observe Play Console / logcat ANR: timeout of broadcast `...FCMBroadcastReceiver` within ~10s.
7. Thread dump: main often idle; `OneSignal-IO-1` / `OneSignal-IO-2` busy with init or other HTTP.

What did you expect to happen?

A cold-start push should be handled within the FCMBroadcastReceiver / goAsync budget (~10s) even when OneSignal is initializing.

Expected:

  • OneSignal init (and any internal HTTP) should not starve FCM / notification processing on the same tiny IO pool
  • Push delivery and broadcast completion should not ANR the app when the main thread is idle
  • Optionally: a dedicated dispatcher / more IO capacity for push work so init HTTP cannot block FCM handling

In short: receiving a notification on a killed process should not produce Play Console ANRs (“app isn’t responding”) on random screens.

OneSignal Android SDK version

5.10.0 (also observed after shipping with 5.9.8; leftover 5.7.6 was present earlier and has been removed)

Android version

12, 15, 13, 14

Specific Android models

Primarily OEM-specific clusters in Play Console:
- Samsung (various Galaxy models; highest volume)
- Motorola

Not limited to a single SKU — pattern matches cold-start FCM + OneSignal IO contention rather than one device bug.

Relevant log output

Timeout of broadcast BroadcastRecord{...} - receiver=android.content.BroadcastReceiver$PendingResult@...
com.google.firebase.iid.FirebaseInstanceIdReceiver / FCMBroadcastReceiver related ANR

ANR in <package> (...): Input dispatching timed out / Broadcast of Intent { act=com.google.android.c2dm.intent.RECEIVE ... }

Thread dump highlights (typical):
- main: idle / native poll once (not blocked on our UI)
- OneSignal-IO-1: HTTP / SSL (init or identity)
- OneSignal-IO-2: waiting or also in HTTP
- Sometimes InstrHttpsURLConnection when Firebase Performance instrumentation wraps OneSignal HttpURLConnection

Note: Force Stop prevents FCM delivery entirely. Reproduce with process kill (am kill / swipe Recents), not Force Stop.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions