Skip to content

[board] Measure session, view and timed event durations on a monotonic clock - #624

Draft
arifBurakDemiray wants to merge 1 commit into
stagingfrom
board/wall-clock-duration-monotonic-countly-sdk-android
Draft

arifBurakDemiray wants to merge 1 commit into
stagingfrom
board/wall-clock-duration-monotonic-countly-sdk-android

Conversation

@arifBurakDemiray

Copy link
Copy Markdown
Member

Board card C-110 (part 1 of 3 of C-108, Android first as the reference for iOS and Web): Session/view/event durations use wall-clock differences on Android, iOS and Web; C++ fixed this on 10-17 (android)

Source: Countly/countly-sdk-cpp#161, which moved session, view and timed event durations to std::chrono::steady_clock and kept request timestamps on the system clock.

What breaks without it

Durations are differences of two System.currentTimeMillis() readings. When the device clock moves between the two (manual change, NTP or carrier time sync, time zone travel with auto time), a backward change gives a zero or negative session_duration, view dur or timed event dur, and a forward change inflates them. Reasoned from code, not reproduced.

What changed

  • UtilsTime.monotonicTimeMs() returns SystemClock.elapsedRealtime() (counts deep sleep, unaffected by clock changes); monotonicTimeSeconds() is its whole-second form.
  • Sessions: prevSessionDurationStartTime_ and roundedSecondsSinceLastSessionDurationUpdate() use the monotonic clock. The halt() sentinel of 0 still works.
  • Views: viewStartTimeSeconds is set and read on the monotonic clock, still in whole seconds, still 0 for a paused view.
  • Timed events: startEvent stores the monotonic start in a new package-private Event.monotonicStartMs (not serialized, not in equals), and endEvent measures the duration from it. The event's timestamp, hour and dow still come from the start's wall-clock instant.
  • Request and event timestamps stay on the device clock.
  • CountlyTests.testRoundedSecondsSinceLastSessionDurationUpdate builds its start values from the monotonic clock; a test comment in ModuleViewsTests names the new call.
  • CHANGELOG entry under ## XX.XX.XX.

Not verified

  • Compiled only: :sdk:compileDebugJavaWithJavac and :sdk:compileDebugAndroidTestJavaWithJavac pass. The instrumented tests were not run: the emulator would not boot on the worker machine (not enough disk).
  • No test simulates a clock change; the existing session, view and timed event duration tests still need a run on CI or a device.
  • A view started within the first second after boot would read as paused (viewStartTimeSeconds == 0). Not handled, as it cannot happen in practice.

🤖 Generated with Claude Code

…lock

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Dependency security scan

Scanned 569 resolved dependencies — 343 buildscript, 14 published, 212 sample.

Findings Count
Blocking (HIGH+ in published/sample) 0
Below HIGH, in dependencies we control 1
Waived via allowlist 2
Build tooling — not upgradeable from this repo 95
Below the HIGH threshold, but ours to upgrade (1)
Severity Dependency Advisory Fixed in Used by
MODERATE com.google.android.gms:play-services-basement:18.0.0 GHSA-cm6r-892j-jv2g — Google Play Services SDK leads to apps having incorrectly set mutability flag 18.0.2 :app
Waived via allowlist (2)
Advisory Dependency Expires Reason
GHSA-r937-wjx7-w2jp org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.10 2026-11-30 Kotlin Gradle plugin build-cache deserialization. First fixed in 2.4.20-Beta1; no stable Kotlin release carries the fix yet. Build-machine only (CVSS AV:L/AC:H/PR:H), never shipped to integrators. Drop this entry once 2.4.20 is stable.
GHSA-r937-wjx7-w2jp org.jetbrains.kotlin:kotlin-gradle-plugin:2.4.10 2026-11-30 Kotlin Gradle plugin build-cache deserialization. First fixed in 2.4.20-Beta1; no stable Kotlin release carries the fix yet. Build-machine only (CVSS AV:L/AC:H/PR:H), never shipped to integrators. Drop this entry once 2.4.20 is stable.

95 further finding(s) in Gradle plugin internals are reported in the job summary and the resolved-dependencies artifact. They ship inside the build plugins and cannot be upgraded from this repository.

Result: passed

Full run log

@github-actions

Copy link
Copy Markdown

Unit Test Results 🚀

1 170 tests  ±0   1 167 ✅ ±0   9m 13s ⏱️ +19s
   69 suites ±0       3 💤 ±0 
    4 files   ±0       0 ❌ ±0 

Results for commit 17ec3f2. ± Comparison against base commit 8a892b5.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant