Docs

Android 17 ProfilingManager Anomaly Trigger Tracking

Android 17's ProfilingManager adds anomaly, cold-start, and OOM triggers that capture diagnostics before a kill — what to wire up and track.

Performance

Until Android 17, an app that got OOM-killed or force-stopped for hogging the CPU left almost no trail. Crash reporting logged the fact that the process died and not much else — no call stack, no heap state, nothing that pointed at the actual cause. Android 17’s ProfilingManager closes that gap with a set of new system triggers that capture diagnostic artifacts at the moment something starts going wrong, and — critically — before the system’s own enforcement kills the process. There’s also a new on-device anomaly detection service layered on top, watching for resource-intensive behaviour like excessive binder calls or excessive memory use and firing a trigger the instant it spots one.

The four triggers worth knowing: TRIGGER_TYPE_COLD_START captures a call stack sample and a system trace during app launch; TRIGGER_TYPE_OOM captures a Java heap dump the moment an OutOfMemoryError is thrown; TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE captures a call stack sample when the OS kills an app for abnormal CPU use; and TRIGGER_TYPE_ANOMALY fires on system-detected anomalies — excessive binder calls or excessive memory usage — ahead of any of the above. None of these show up automatically in a crash dashboard. They have to be explicitly registered and piped somewhere, and teams that skip that step will keep seeing the same vague “process died” bucket they always have, right next to competitors now triaging the exact binder call or memory pattern that caused it.

Data Points to Track

  • Trigger type distribution — counts of ANOMALY, COLD_START, OOM, and KILL_EXCESSIVE_CPU_USAGE events, broken down by app version and device tier
  • Anomaly subtype — excessive binder call volume vs. excessive memory usage, since both fire under TRIGGER_TYPE_ANOMALY but point at different fixes
  • Heap dump composition on OOM triggers — size and top retained-object classes, not just the fact that an OOM occurred
  • Cold-start call stack and system trace, correlated against your existing cold-start duration percentiles
  • Device RAM tier against anomaly/OOM rate, since Android 17 also introduces app memory limits based on total device RAM

Setup Steps

  1. Register ProfilingManager listeners for all four trigger types rather than picking one — each captures a different failure mode and none substitutes for another.
  2. Route each artifact by trigger type into your crash/performance backend, tagged distinctly, instead of merging everything into a generic “process died” event.
  3. Move heap dump parsing off the capture path — upload raw dumps and process them in a scheduled batch job so profiling itself doesn’t add overhead to the flow it’s diagnosing.
  4. Cross-reference ANOMALY triggers against existing ANR and crash-rate tracking to find cases the anomaly service caught earlier than your current pipeline would have.
  5. Segment trigger rate by RAM tier now that Android 17 enforces per-device memory limits — low-RAM devices will legitimately trigger anomaly and OOM events more often, and that’s expected, not a regression.

Actionable Insights

Because the anomaly service fires before system enforcement, a rising ANOMALY rate on a specific app version is a leading indicator, not a duplicate of your crash-rate metric — it shows up before the ANR or OOM crash it’s warning about would otherwise be logged. Excessive-binder-call anomalies in particular tend to trace back to one specific IPC-heavy component — a bound service, a chatty broadcast receiver — rather than a diffuse memory leak, so route those triggers straight to the team that owns the flagged component instead of a general performance backlog.

Expert help

Need help tracking this in your app?

Our team sets up analytics pipelines for mobile and web teams every day. Talk to us and get your first events flowing in under an hour.

Talk to an expert