CVE-2026-0009 AI-generated analysis
platform/packages/providers/MediaProvider, Photopicker (Compose photopicker: MainActivity, SelectionImpl, SelectionBarFeature)
Removes the Photopicker's automatic finish-on-first-selection behaviour in single-select mode and instead always enables the selection bar so the user must explicitly confirm the selected media before it is returned to the calling app.
Root cause
MainActivity.onCreate called listenForSelectionIfSingleSelect(). When configurationManager.configuration.value.selectionLimit == 1, this function collected selection.get().flow and invoked onMediaSelectionConfirmed() as soon as the set reached size 1. SelectionBarFeature.Registration.isEnabled returned config.selectionLimit > 1 (on Android 16/17, only for the ACTIVITY runtime env), so single-select had no confirm UI. On 16/17, MediaGrid also suppressed the selected indicator when selectionLimit was 1. As a result, selecting one media item confirmed the selection and ended the session without a separate confirmation.
How the fix works
- Commit 1 (Revert^2 'Fix: add confirmation step in single select mode': e7bcd640810f on 15, 61808742c17a on 16, bf034ab4e140 on 17), photopicker/src/com/android/photopicker/MainActivity.kt: deletes listenForSelectionIfSingleSelect() and its call in onCreate. The activity no longer calls onMediaSelectionConfirmed() automatically when the selection size becomes 1. Per the removed comment, confirmation comes from the selection bar click handler or Event.MediaSelectionConfirmed.
- photopicker/src/com/android/photopicker/core/selection/SelectionImpl.kt:toggle: replaces the if/else with a when. The new branch `configuration.value.selectionLimit == 1` clears _selection and adds the new item, so in single-select a tap on a different item replaces the current selection instead of failing with FAILURE_SELECTION_LIMIT_EXCEEDED. Removal of an existing item and the ensureSelectionLimitLocked path for multi-select are unchanged.
- photopicker/src/com/android/photopicker/features/selectionbar/SelectionBarFeature.kt:Registration.isEnabled: now always returns true. It previously returned selectionLimit > 1, and on 16/17 it was also gated on PhotopickerRuntimeEnv. The selection bar with its confirm action is now composed in single-select sessions.
- photopicker/src/com/android/photopicker/features/selectionbar/SelectionBar.kt:SelectionBar: on 15, visibility becomes currentSelection.isNotEmpty() || action == MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP. On 16, the local variable is renamed to showSelectionBar. On 17, the EMBEDDED-specific `selectionLimit > 1` gating of `visible` is removed, so the bar follows showSelectionBar in all runtime envs.
- photopicker/src/com/android/photopicker/core/components/mediagrid/MediaGrid.kt:defaultBuildMediaItem and SelectedIconOverlay (16/17 only; the 15 hunk is whitespace): removes shouldIndicateSelected (isSelected && selectionLimit > 1, plus an embedded check on 17). The selected padding, rounded clip and check/number overlay are now drawn in single-select too.
- Tests: SelectionImplTest adds testToggleWithSelectionLimitOneReplacesExistingItem (and testSelectionGetSize on 15/16). SelectionBarFeatureTest renames testSelectionBarNotEnabledForSingleSelect* to testSelectionBarIsEnabledForSingleSelectInActivityMode and now expects true. On 15 it also adds testSelectionBarIsAlwaysEnabledInEmbeddedMode.
- Commit 2 (Remove duplicate MediaSelectionConfirmed event, 6d81d42dbc7a, android-security-15.0.0_r16), photopicker/src/com/android/photopicker/core/events/Event.kt: deletes a duplicate `data class MediaSelectionConfirmed` declaration in the Event interface. It keeps the declaration documented as fired from the preview screen. The commit carries the same bug id.
Completeness
- Covers the activity-mode single-select path. The only auto-confirm code path shown (listenForSelectionIfSingleSelect) is deleted entirely rather than gated, and the selection bar is always enabled. Every configuration now requires the confirm action or Event.MediaSelectionConfirmed.
- Event.MediaSelectionConfirmed still finishes the session and is unchanged. Per the Event.kt doc comment, it is fired when the user confirms the selection from the preview screen.
- On Android 15 the MediaGrid.kt hunk is whitespace only. The r17 context shows padding driven directly by isSelected. The android-15.0.0_r36 release branch still contains the `shouldIndicateSelected = isSelected && selectionLimit > 1` gating in defaultBuildMediaItem (per index search). That affects the visual indicator, not the confirmation step.
- Android 17 also removes the EMBEDDED-mode `selectionLimit > 1` visibility gate in SelectionBar.kt. No such gate appears in the shown 15/16 code.
- The second commit only removes a duplicate declaration and adds no behavioural protection.
Behavior changes
- Single-select Photopicker sessions no longer finish on the first selection. A selection bar with a confirm action is shown, and the result is returned only after the user confirms.
- In single-select mode, tapping a second item replaces the current selection: SelectionImpl.toggle returns SUCCESS instead of FAILURE_SELECTION_LIMIT_EXCEEDED.
- SelectionBarFeature is enabled for every configuration, including selectionLimit == 1 and, on 16/17, both the ACTIVITY and EMBEDDED runtime envs.
- On 16/17, selected items in single-select mode now show the selected visual state: shrink padding, rounded corners, and a check icon or order number.
- The selection bar stays visible with an empty selection for MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP. The 15 commit adds this; 16/17 already had it.
- After the second commit, Event.MediaSelectionConfirmed has a single declaration.
Per major
- Android 14: Not affected per the bulletin; code absent. The patched files (photopicker/src/com/android/photopicker/MainActivity.kt, MediaGrid.kt, SelectionImpl.kt) are not present at android-security-14.0.0_r29.
- Android 15: Adapted fix. Revert^2 e7bcd640810f in android-security-15.0.0_r13 applies the same SelectionImpl and SelectionBarFeature logic. Its MainActivity hunk also inserts the PhotopickerEventLogger start lines, its MediaGrid hunk is whitespace only, and SelectionBar gains the ACTION_USER_SELECT_IMAGES_FOR_APP visibility clause. Follow-up commit 6d81d42dbc7a in android-security-15.0.0_r16 removes the duplicate Event.MediaSelectionConfirmed. At android-security-15.0.0_r17 the code shows the fixed toggle() and isEnabled() = true.
- Android 16: Adapted fix: 61808742c17a in android-security-16.0.0_r4. It also removes shouldIndicateSelected from MediaGrid.kt and the ACTIVITY/EMBEDDED branching from SelectionBarFeature.isEnabled, and renames visible to showSelectionBar in SelectionBar.kt.
- Android 17: Fixed in the base: bf034ab4e140 in android-17.0.0_r1. Same changes as 16, plus removal of the EMBEDDED `selectionLimit > 1` visibility gate in SelectionBar.kt and the isEmbedded checks in MediaGrid.kt.
Unknowns
- The original reverted commit c5d89a70a250, and why its CTS tests failed, are not in the material.
- The material does not show whether the duplicate MediaSelectionConfirmed declaration was introduced by the Revert^2 cherry-pick itself.
- The material does not show why the Android 15 MainActivity hunk also adds the PhotopickerEventLogger start lines.
- The body of onMediaSelectionConfirmed, and what exactly the calling app received, are not described beyond the EoP rating.