CVE-2025-0095 AI-generated analysis
platform/packages/apps/Settings, SPA App info page (AppTimeSpentPreference)
Pins the Settings.ACTION_APP_USAGE_SETTINGS intent launched from the App info "time spent" preference to the package named by config_systemWellbeing and resolves it with MATCH_SYSTEM_ONLY, instead of launching an implicit intent after only checking that some system app could handle it.
Root cause
In src/com/android/settings/spa/app/appinfo/AppTimeSpentPreference.kt, AppTimeSpentPresenter built Intent(Settings.ACTION_APP_USAGE_SETTINGS) with only EXTRA_PACKAGE_NAME and no target package. isAvailable() called queryIntentActivitiesAsUser(intent, ResolveInfoFlags.of(0), app.userId) and showed the preference if any resolver's applicationInfo.isSystemApp was true. startActivity() then called context.startActivityAsUser(intent, app.userHandle) with the same implicit intent. So the availability check did not limit which activity actually received the intent at launch time.
How the fix works
- AppTimeSpentPreference.kt: AppTimeSpentPresenter.intent now calls setPackage(context.getString(com.android.internal.R.string.config_systemWellbeing)) before putExtra(Intent.EXTRA_PACKAGE_NAME, ...), which limits the intent to the configured system wellbeing package. startActivity() uses the same intent instance, so the launch is restricted too.
- AppTimeSpentPreference.kt: isAvailable() (queryIntentActivitiesAsUser plus an isSystemApp filter) is replaced by isAvailableFlow, which emits resolveIntent() != null. resolveIntent() calls context.packageManager.resolveActivityAsUser(intent, PackageManager.MATCH_SYSTEM_ONLY, app.userId), so the preference is shown only when the pinned package resolves the action as a system app.
- AppTimeSpentPreference.kt: the AppTimeSpentPreference composable collects isAvailableFlow via collectAsStateWithLifecycle(initialValue = false) and returns early when it is not available. summaryLiveData becomes summaryFlow on Dispatchers.Default, and remember(app) keys the presenter on the app.
- tests/spa_unit/.../AppTimeSpentPreferenceTest.kt: the tests now mock resolveActivityAsUser instead of queryIntentActivitiesAsUser, and the hasIntentHandler_notSystemApp_notDisplay test is removed. The Android 15 version adds tests checking that resolveActivityAsUser and startActivityAsUser receive an intent whose package equals the wellbeing package.
Completeness
- The availability check and the launch path both use the single intent object, which now carries setPackage(config_systemWellbeing). No code path in this file sends the action as an implicit intent anymore.
- MATCH_SYSTEM_ONLY is applied only in resolveIntent() (the availability check). startActivity() does not check again, but the package pin by itself limits the target to the configured package.
- The fix covers only AppTimeSpentPreference.kt. The material does not show whether other Settings code paths send Settings.ACTION_APP_USAGE_SETTINGS without a package.
- The code comment assumes config_systemWellbeing is non-null. The diff does not handle the case where the resource is an empty string.
Behavior changes
- The 'time spent in app' preference is shown only if the package in com.android.internal.R.string.config_systemWellbeing resolves ACTION_APP_USAGE_SETTINGS as a system app for the target user. Before the fix, any system-app resolver was enough.
- Availability is now computed asynchronously on Dispatchers.Default with an initial value of false, so the preference appears after resolution finishes instead of synchronously during composition.
- Summary computation moves from LiveData on Dispatchers.IO to a Flow on Dispatchers.Default.
- Clicking the preference now launches an intent restricted to the wellbeing package instead of an implicit intent.
Per major
- Android 14: same fix: commit 0cd72114e2d8 in android-security-14.0.0_r17 (resolved by change_id). At android-security-14.0.0_r29 the patched region is fully present (8/8 lines).
- Android 15: adapted fix: commit 4b99ae729036 in android-security-15.0.0_r5. It has the same intent pin and MATCH_SYSTEM_ONLY resolution, adapted to the Android 15 code (featureFactory.applicationFeatureProvider, placeholder(), lambda summary/enabled), and adds extended mockito-kotlin tests and FakeFeatureFactory changes. Fully present at android-security-15.0.0_r17.
- Android 16: not affected (not listed by the bulletin). The patched region is present at android-security-16.0.0_r8 (8/8 lines).
- Android 17: not affected (not listed by the bulletin). The patched region is present at android-security-17.0.0_r1 (8/8 lines).
Unknowns
- Whether other Settings components send Settings.ACTION_APP_USAGE_SETTINGS implicitly is not shown.
- Behavior when config_systemWellbeing is empty on a device is not shown.
- The specific EoP impact described by bug 356117796 is not in the material beyond the bulletin rating.
- Why the hasIntentHandler_notSystemApp_notDisplay test was removed is not stated in the material.