You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Following up on the background-ANR fixes in 5.9.5 (SDK-4794 / PR #2664, prewarm at cold-start entry points) and 5.9.6 (SDK-4822, app-state-aware watchdog). We're still seeing chronic background ANRs on FCMBroadcastReceiver, NotificationDismissReceiver, BootUpReceiver, and SyncJobService on the current SDK, and have version-code-sliced Play Vitals data showing the 5.9.5 prewarm did not measurably reduce them for us.
Setup
onesignal_flutter: was 5.6.3, now 5.6.7 (native Android 5.9.5 → 5.9.8) as of this report
App: Flutter, Android minSdk 24 / targetSdk 36
Device mix skews heavily to budget/entry-level hardware: Tecno, Infinix, Honor, entry-level Redmi and Samsung Galaxy A-series
What we measured
We pulled Google Play Vitals (Android Developer Reporting API), sliced by app version code, comparing builds before and after our 5.6.3 upgrade (which shipped 2026-06-29, pulling in native 5.9.5 and the SDK-4794 prewarm):
Component (issue)
users, all builds (7d)
users, builds with 5.6.3+
share unchanged
FCMBroadcastReceiver
16,439
16,008
97.4%
NotificationDismissReceiver
5,963
5,907
99.1%
FCMBroadcastReceiver (2nd issue)
3,024
3,005
99.4%
NotificationDismissReceiver (2nd issue)
2,561
2,536
99.0%
BootUpReceiver
805
794
98.6%
SyncJobService
225
216
96.0%
Normalized against install-base drift (OneSignal's share of all Android ANR reports in the same 7-day window, to control for how many devices are on each build): 34.8% pre-5.6.3 → 62.3% post-5.6.3. The upgrade is fully rolled out on our current builds and the cluster is, if anything, a larger share of our total ANR volume than before.
All four components use goAsync() then suspendifyOnIO { ... } (confirmed by reading the 5.9.8 sources). Every ANR dump in this cluster (100+ per capture) shows the main thread idle in nativePollOnce/epoll_pwait with no Runnable thread other than the ART dump-generation thread — which we understand is expected, since goAsync() does not extend the broadcast/service ANR budget; the clock runs from process start through onReceive()/onStartJob() until PendingResult.finish()/job completion, regardless of whether the work moved to a background dispatcher.
That PR's description explicitly frames prewarming at entry points as the accepted-tradeoff option, over the rejected "durable" option (queue the first dispatch so cold dispatcher construction can never land on a caller thread), specifically because "we have not proven [the race] still fires" in production telemetry, and calls out that "a pathologically slow device could still lose the race."
We believe our fleet is exactly that device population, and the data above is the telemetry that would justify revisiting the durable option — or at minimum, understanding why the prewarm isn't winning the race for us. Happy to share the raw Vitals export (with PII already stripped by the Play Reporting API) if useful for triage.
Ask
Does the prewarm in SDK-4794 have a known gap for devices this slow (e.g., is there a lower bound on how much lead time it needs before the first suspendifyOnIO dispatch, and could that lead time not be met on a cold goAsync() handoff on this hardware class)?
Is there a way to reduce what runs inside initWithContext + the bundle/restore/sync work specifically for cold-background entry points, independent of the dispatcher-construction race?
Happy to provide more detail — version codes, API level breakdown, or raw thread dumps — whatever's useful.
Description
Following up on the background-ANR fixes in 5.9.5 (SDK-4794 / PR #2664, prewarm at cold-start entry points) and 5.9.6 (SDK-4822, app-state-aware watchdog). We're still seeing chronic background ANRs on
FCMBroadcastReceiver,NotificationDismissReceiver,BootUpReceiver, andSyncJobServiceon the current SDK, and have version-code-sliced Play Vitals data showing the 5.9.5 prewarm did not measurably reduce them for us.Setup
onesignal_flutter: was 5.6.3, now 5.6.7 (native Android 5.9.5 → 5.9.8) as of this reportminSdk24 /targetSdk36What we measured
We pulled Google Play Vitals (Android Developer Reporting API), sliced by app version code, comparing builds before and after our
5.6.3upgrade (which shipped 2026-06-29, pulling in native5.9.5and the SDK-4794 prewarm):FCMBroadcastReceiverNotificationDismissReceiverFCMBroadcastReceiver(2nd issue)NotificationDismissReceiver(2nd issue)BootUpReceiverSyncJobServiceNormalized against install-base drift (OneSignal's share of all Android ANR reports in the same 7-day window, to control for how many devices are on each build): 34.8% pre-5.6.3 → 62.3% post-5.6.3. The upgrade is fully rolled out on our current builds and the cluster is, if anything, a larger share of our total ANR volume than before.
All four components use
goAsync()thensuspendifyOnIO { ... }(confirmed by reading the 5.9.8 sources). Every ANR dump in this cluster (100+ per capture) shows the main thread idle innativePollOnce/epoll_pwaitwith no Runnable thread other than the ART dump-generation thread — which we understand is expected, sincegoAsync()does not extend the broadcast/service ANR budget; the clock runs from process start throughonReceive()/onStartJob()untilPendingResult.finish()/job completion, regardless of whether the work moved to a background dispatcher.Relation to PR #2664
That PR's description explicitly frames prewarming at entry points as the accepted-tradeoff option, over the rejected "durable" option (queue the first dispatch so cold dispatcher construction can never land on a caller thread), specifically because "we have not proven [the race] still fires" in production telemetry, and calls out that "a pathologically slow device could still lose the race."
We believe our fleet is exactly that device population, and the data above is the telemetry that would justify revisiting the durable option — or at minimum, understanding why the prewarm isn't winning the race for us. Happy to share the raw Vitals export (with PII already stripped by the Play Reporting API) if useful for triage.
Ask
suspendifyOnIOdispatch, and could that lead time not be met on a coldgoAsync()handoff on this hardware class)?initWithContext+ the bundle/restore/sync work specifically for cold-background entry points, independent of the dispatcher-construction race?Happy to provide more detail — version codes, API level breakdown, or raw thread dumps — whatever's useful.