Skip to content

fix(android): Improve app start type detection with main thread timing#4999

Open
markushi wants to merge 38 commits intomainfrom
fix/app-start-warm-detection
Open

fix(android): Improve app start type detection with main thread timing#4999
markushi wants to merge 38 commits intomainfrom
fix/app-start-warm-detection

Conversation

@markushi
Copy link
Member

@markushi markushi commented Dec 29, 2025

📜 Description

Improves app start type detection by utilizing the main thread isIdle callback and ApplicationStartInfo APIs on API level 35+

Fixes #4920

The firstPost approach as utilized in the papa library does not seem to work on API level 35+ anymore (See square/papa#63)

The changes include:

  • Use of ApplicationStartInfo APIs on newer devices,
  • a fallback firstIdle mechanism
  • the existing mechanism for older devices
  • Extended app start critical tests for determining warm/cold app start behavior

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

@github-actions
Copy link
Contributor

github-actions bot commented Dec 29, 2025

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 317.49 ms 367.67 ms 50.18 ms
Size 1.58 MiB 2.19 MiB 619.80 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
e59e22a 368.02 ms 432.00 ms 63.98 ms
2124a46 319.19 ms 415.04 ms 95.85 ms
b3d8889 420.46 ms 453.71 ms 33.26 ms
fcec2f2 357.47 ms 447.32 ms 89.85 ms
d15471f 304.55 ms 408.43 ms 103.87 ms
cf708bd 434.73 ms 502.96 ms 68.22 ms
fc5ccaf 276.52 ms 370.46 ms 93.93 ms
3d205d0 352.15 ms 432.53 ms 80.38 ms
b03edbb 352.20 ms 423.69 ms 71.49 ms
a5ab36f 316.83 ms 394.54 ms 77.71 ms

App size

Revision Plain With Sentry Diff
e59e22a 1.58 MiB 2.20 MiB 635.34 KiB
2124a46 1.58 MiB 2.12 MiB 551.51 KiB
b3d8889 1.58 MiB 2.10 MiB 535.07 KiB
fcec2f2 1.58 MiB 2.12 MiB 551.50 KiB
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
cf708bd 1.58 MiB 2.11 MiB 539.71 KiB
fc5ccaf 1.58 MiB 2.13 MiB 557.54 KiB
3d205d0 1.58 MiB 2.10 MiB 532.97 KiB
b03edbb 1.58 MiB 2.13 MiB 557.32 KiB
a5ab36f 1.58 MiB 2.12 MiB 555.26 KiB

Previous results on branch: fix/app-start-warm-detection

Startup times

Revision Plain With Sentry Diff
376c795 307.44 ms 356.18 ms 48.74 ms
eadb118 318.81 ms 365.04 ms 46.23 ms
d05ca28 315.98 ms 357.10 ms 41.12 ms
12d79b2 324.79 ms 404.20 ms 79.41 ms
1911f98 335.29 ms 451.47 ms 116.18 ms
cf6c632 283.92 ms 361.45 ms 77.53 ms
5a370a1 359.02 ms 429.56 ms 70.54 ms
28e7b9d 311.83 ms 366.94 ms 55.11 ms
a0d0a05 303.68 ms 339.38 ms 35.70 ms
224c2d6 311.50 ms 361.40 ms 49.90 ms

App size

Revision Plain With Sentry Diff
376c795 1.58 MiB 2.19 MiB 619.80 KiB
eadb118 1.58 MiB 2.19 MiB 619.66 KiB
d05ca28 1.58 MiB 2.19 MiB 619.66 KiB
12d79b2 1.58 MiB 2.20 MiB 635.40 KiB
1911f98 1.58 MiB 2.19 MiB 619.66 KiB
cf6c632 1.58 MiB 2.19 MiB 619.66 KiB
5a370a1 1.58 MiB 2.19 MiB 619.79 KiB
28e7b9d 1.58 MiB 2.19 MiB 619.78 KiB
a0d0a05 1.58 MiB 2.13 MiB 559.63 KiB
224c2d6 1.58 MiB 2.19 MiB 619.66 KiB

@markushi
Copy link
Member Author

@sentry review

@markushi
Copy link
Member Author

@sentry review

@markushi markushi marked this pull request as ready for review January 16, 2026 11:02

// the first activity determines the app start type
if (activeActivitiesCounter.incrementAndGet() == 1 && !firstDrawDone.get()) {
final long nowUptimeMs = SystemClock.uptimeMillis();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we still need this variable given it's just few microseconds apart from activityCreatedUptimeMillis?

Copy link
Member

@romtsn romtsn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a couple of comments

markushi and others added 2 commits February 3, 2026 10:16
- Add support for ApplicationStartInfo API on Android 15+ (API 35) for more accurate cold/warm start detection
- Add null safety check for ActivityManager service
- Fix detection logic to prevent legacy methods from running when API 35+ already determined start type
- Set app start type to WARM when app moves to background (process stays alive)
- Add comprehensive test coverage with notification-triggered start scenarios

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • (distribution) Add install_groups support by runningcode in #5062
  • (spotlight) Extract SpotlightIntegration to separate module by romtsn in #5064

Bug Fixes 🐛

  • (android) Improve app start type detection with main thread timing by markushi in #4999
  • Establish native exception mechanisms by supervacuus in #5052

Internal Changes 🔧

Deps

  • Bump github/codeql-action from 4.31.11 to 4.32.0 by dependabot in #5067
  • Bump gradle/actions from 5.0.0 to 5.0.1 by dependabot in #5068
  • Bump getsentry/craft from 2.20.0 to 2.20.1 by dependabot in #5069
  • Bump urllib3 from 2.6.0 to 2.6.3 in the pip group across 1 directory by dependabot in #5003
  • Update Native SDK to v0.12.4 by github-actions in #5061
  • Bump getsentry/github-workflows/.github/workflows/updater.yml from 2 to 3 by dependabot in #4884
  • Bump actions/cache from 4 to 5 by dependabot in #4997
  • Bump github/codeql-action from 4.31.10 to 4.31.11 by dependabot in #5057
  • Bump getsentry/craft from 2.19.0 to 2.20.0 by dependabot in #5058

Other

  • (android) Update targetSdk to API 36 (Android 16) by markushi in #5016
  • (ci) Write permission for statuses in changelog preview by supervacuus in #5053
  • (samples) Convert main screen to Jetpack Compose by markushi in #5017

Other

  • No longer fork Sentry Scopes for reactor-kafka consumer poll Runnable by adinauer in #5080
  • Collect database transaction spans (BEGIN, COMMIT, ROLLBACK) by adinauer in #5072

🤖 This preview updates automatically when you update the PR.

@markushi markushi requested a review from romtsn February 3, 2026 10:38
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

CHANGELOG.md Outdated

## Unreleased

### Fixes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have the fixes section down here, could you move it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's actually the third one already lol :D


if (activityManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
final List<ApplicationStartInfo> historicalProcessStartReasons =
activityManager.getHistoricalProcessStartReasons(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so does this return the current (in-progress) app start?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we also double check later to ensure it's the current app launch:

 if (info.getStartupState() == ApplicationStartInfo.STARTUP_STATE_STARTED) {

markushi and others added 4 commits February 6, 2026 13:27
Add custom SentryShadowActivityManager to mock ApplicationStartInfo
for testing cold/warm start detection on Android 15 (API 35).

Tests verify the new getHistoricalProcessStartReasons() code path
and fallback behavior when the list is empty or invalid.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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.

Warm starts potentially reported as cold starts for activities in singleTask launch mode

3 participants