CVE-2025-48527 AI-generated analysis
platform/packages/apps/Settings, notification history UI (src/com/android/settings/notification/history)
Settings' Notification History screen now replaces the title and text of history, snoozed and dismissed notifications with the generic "notification_hidden_text" string for any profile that is securely locked and has LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS disabled, instead of rendering the full content.
Root cause
NotificationHistoryAdapter.onBindViewHolder and NotificationSbnAdapter.onBindViewHolder unconditionally called holder.setTitle()/holder.setSummary() with the notification's title and text (hn.getTitle()/hn.getText() and getTitleString()/getTextString()). NotificationHistoryActivity never consulted the per-user LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS setting or the lock state of the profiles whose notifications it lists. As a result, content from a locked profile (e.g. a work profile with a separate PIN, per the commit message) that had chosen to hide sensitive content when locked was displayed in full when the history screen was opened from the profile group.
How the fix works
- NotificationHistoryActivity.java: adds a field mContentRestrictedUsers (ArrayList<Integer>). In onCreate, after mUm is obtained, it iterates mUm.getProfiles(getUserId()). A profile's user id is added to mContentRestrictedUsers when Settings.Secure.getIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, default 0, user.id) == 0 and new LockPatternUtils(this).isSecure(user.id) && KeyguardManager.isDeviceLocked(user.id).
- NotificationHistoryActivity.java: the list is passed to three adapter constructions: new NotificationHistoryAdapter(NotificationHistoryActivity.this, mNm, rv, listener, mUiEventLogger, mContentRestrictedUsers) for the per-package history lists, and new NotificationSbnAdapter(..., true/false, mUiEventLogger, mContentRestrictedUsers) for the snoozed (mSnoozedRv) and dismissed (mDismissedRv) lists.
- NotificationHistoryAdapter.java: the constructor gains Context and ArrayList<Integer> contentRestrictedUsers parameters, stored in mContext and mContentRestrictedUsers. In onBindViewHolder, if mContentRestrictedUsers.contains(hn.getUserId()), it only calls holder.setSummary(mContext.getString(com.android.internal.R.string.notification_hidden_text)). Otherwise the original setTitle/setSummary path runs.
- NotificationSbnAdapter.java: the constructor gains ArrayList<Integer> contentRestrictedUsers, stored in mContentRestrictedUsers. In onBindViewHolder, if mContentRestrictedUsers.contains(sbn.getNormalizedUserId()), it only sets the summary to notification_hidden_text. Otherwise the original getTitleString/getTextString path runs. Icon, background, package label and posted time are still set as before.
Completeness
- Covers all three lists rendered by NotificationHistoryActivity: per-package history via NotificationHistoryAdapter, and snoozed and dismissed via NotificationSbnAdapter.
- Only the title and text are redacted. Package label, app icon, posted time and the per-user handling in NotificationSbnAdapter are unchanged, and so is the item click handler in NotificationHistoryAdapter. The existence of a notification from a given app in the locked profile therefore remains visible.
- The restricted-user set is computed once in onCreate and is not recomputed if a profile locks or unlocks while the activity is alive. The Android 15 variant additionally clears the list in onDestroy but also does not refresh it.
- Redaction applies only when the profile has a secure lock (LockPatternUtils.isSecure), is currently locked (KeyguardManager.isDeviceLocked) and has LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS == 0. Unlocked profiles are shown in full.
- In the restricted branch holder.setTitle() is not called at all, so this code path does not explicitly reset the title view of a recycled ViewHolder. Whether the holder clears it elsewhere is not shown in the material.
- Only profiles returned by mUm.getProfiles(getUserId()) are considered. The adapters' own user handling (mEnabledProfiles, normalizeUserId) is untouched.
Behavior changes
- Notification History entries from a locked, content-restricted profile now show the generic framework string notification_hidden_text as summary and no title.
- The constructor signatures of NotificationHistoryAdapter (new leading Context and trailing ArrayList<Integer>) and NotificationSbnAdapter (new trailing ArrayList<Integer>) changed. Any other instantiation would fail to compile.
- onCreate now performs additional per-profile Settings.Secure reads and LockPatternUtils/KeyguardManager queries.
Per major
- Android 14: same fix: commit cee46cf86cd9 in android-security-14.0.0_r22 (cherry-pick of 9df37c3f8be2). Patched region fully present at android-security-14.0.0_r29 (8/8 lines).
- Android 15: adapted fix: commit d8b1de7a18fc in android-security-15.0.0_r10. Same logic plus explanatory comments, a duplicated mContentRestrictedUsers.clear() before the profile loop in onCreate, and mContentRestrictedUsers.clear() in onDestroy. Fully present at android-security-15.0.0_r17 (8/8 lines).
- Android 16: same fix: commit 504a34c4d4a3 in android-security-16.0.0_r1. Logic identical to Android 14, applied on top of the newer activity/adapter layout (GONE constant, no setDividerVisible). Fully present at android-security-16.0.0_r8 (8/8 lines).
- Android 17: not affected per the bulletin (not listed). The patched region is present at android-security-17.0.0_r1 (8/8 lines).
Unknowns
- Whether NotificationHistoryViewHolder/NotificationSbnViewHolder reset the title view when setTitle is not called for a recycled holder (the holder implementations are not in the material).
- Whether the history activity is reachable from a locked profile's own context or only from the parent user (only the parent-user flow is implied by the commit message).
- Whether notification history must be enabled for the snoozed/dismissed lists to be rendered.
- What the NotificationHistoryAdapter item click handler launches.
- Android 13 is listed as affected by the bulletin, but no Android 13 commit or branch status is provided in the material.