opentelemetry-android icon indicating copy to clipboard operation
opentelemetry-android copied to clipboard

`backgroundInactivityTimeout` miscounts on Android due to a clock that pauses in deep sleep

Open Sabaev opened this issue 1 month ago • 1 comments

1) backgroundInactivityTimeout miscounts on Android due to a clock that pauses in deep sleep

Component(s): android-agent, android, SessionManager, SessionConfig
Environment: Android (device enters Doze / deep sleep)

Summary

backgroundInactivityTimeout in SessionConfig behaves incorrectly on Android when devices enter deep sleep. The default Clock uses System.nanoTime() which maps to a monotonic source that does not advance during deep sleep. Background duration is undercounted, so sessions may not rotate when they should.

Expected behavior

Background inactivity should be measured against a time base that continues through device sleep so a configured timeout triggers after the intended real elapsed duration.

Actual behavior

When the app is backgrounded and the device sleeps, System.nanoTime() stops. On resume, SessionIdTimeoutHandler/SessionManager see a shorter elapsed interval than real time, preventing or delaying session rotation.

Why this happens (Android specifics)

  • System.nanoTime()CLOCK_MONOTONIC → pauses during deep sleep.
  • SystemClock.elapsedRealtime() / elapsedRealtimeNanos() → includes deep sleep; correct for elapsed-wall semantics.

Minimal reproduction

  1. Set backgroundInactivityTimeout to a small value (e.g., 5 min).
  2. Background the app; allow the device to enter deep sleep > timeout.
  3. Resume the app.
  4. Observe that the session did not rotate as expected.

Proposed change

  1. Provide an Android-aware Clock that uses SystemClock.elapsedRealtimeNanos() for elapsed measurements.
  2. Pass this Clock to SessionManager and SessionIdTimeoutHandler during init.
  3. Remove the secondary SessionManager constructor (marked “for tests”) and add a factory method to ensure consistent wiring in prod/tests.

Sabaev avatar Nov 06 '25 13:11 Sabaev

related to https://github.com/open-telemetry/opentelemetry-android/issues/1364

Sabaev avatar Nov 06 '25 13:11 Sabaev

@breedx-splk assign this to me

namanONcode avatar Dec 07 '25 18:12 namanONcode

@breedx-splk @atulgpt @fractalwrench plan to implement the fix for an android aware Clock implementation using SystemClock.elapsedRealtimeNanos() that includes deep sleep time. Replace the default Clock.getDefault() which uses System.nanoTime() in SessionIdTimeoutHandler and SessionManager. Update the secondary constructor in SessionIdTimeoutHandler to use a factory method, and wire the new Clock through production initialization in OpenTelemetryRumInitializer.

namanONcode avatar Dec 08 '25 04:12 namanONcode

@namanONcode @atulgpt has offered to implement a fix already in #1364. I'll close out this issue as on reflection it'd be better to track all discussion in the other issue.

fractalwrench avatar Dec 08 '25 09:12 fractalwrench