docs(openspec): archive android-auto-local-music Phase 1

Merges its delta requirements into the android-auto-media base spec.
Phases 2 (metadata/sort/filter/art) and 3 (subfolder scoping/shuffle)
remain planned future work.
This commit is contained in:
2026-07-19 20:37:54 +02:00
parent 6ae7e378c4
commit 977cbcd8cc
8 changed files with 185 additions and 3 deletions
+79 -3
View File
@@ -62,14 +62,14 @@ The system MUST produce a browsable tree that never presents a user-selectable f
### Requirement: Browsable Media Tree
`getChildren` MUST return a browsable tree rooted at `AudioService.browsableRootId`, organized into non-playable folders (Favoritos, Todas las emisoras, Mis emisoras, Ecualizador) containing playable items. Playable station items SHOULD carry an audio-quality subtitle when known. The `Favoritos` folder additionally MAY contain non-playable favorite-group sub-folders (see "Favorite Group Sub-Folders"); `Todas las emisoras` and `Mis emisoras` remain flat. The `Ecualizador` folder is flat, non-playable, and contains only the 6 fixed EQ preset items (see "EQ Preset Browsable Folder").
(Previously: root contained exactly 3 folders — Favoritos, Todas las emisoras, Mis emisoras — with no EQ folder; Favoritos was a flat folder of playable station items only, with no sub-folder nesting.)
`getChildren` MUST return a browsable tree rooted at `AudioService.browsableRootId`, organized into non-playable folders (Favoritos, Todas las emisoras, Mis emisoras, Ecualizador, and the local-music root) containing playable items. Playable station items SHOULD carry an audio-quality subtitle when known. The `Favoritos` folder additionally MAY contain non-playable favorite-group sub-folders (see "Favorite Group Sub-Folders"); `Todas las emisoras` and `Mis emisoras` remain flat. The `Ecualizador` folder is flat, non-playable, and contains only the 6 fixed EQ preset items (see "EQ Preset Browsable Folder"). The local-music root folder is non-playable and may itself be nested (see "Local Music Browsable Tree").
(Previously: root contained exactly 3 folders — Favoritos, Todas las emisoras, Mis emisoras — with no EQ or local-music folder; Favoritos was a flat folder of playable station items only, with no sub-folder nesting.)
#### Scenario: Car requests the root
- GIVEN the car head unit connects and requests the root (`AudioService.browsableRootId`)
- WHEN `getChildren` is called with the root id
- THEN it returns four folder `MediaItem`s (Favoritos, Todas las emisoras, Mis emisoras, Ecualizador), each with `playable: false`
- THEN it returns five folder `MediaItem`s (Favoritos, Todas las emisoras, Mis emisoras, Ecualizador, and the local-music root), each with `playable: false`
#### Scenario: Car requests a folder with no stations
@@ -171,6 +171,82 @@ The system MAY indicate the active/principal preset within the `Ecualizador` fol
- WHEN the `Ecualizador` folder's children are built
- THEN all 6 preset rows are returned with their plain preset names, with no partial or inconsistent marking applied
### Requirement: Local Music Root Access and Permission Persistence
The system MUST let the user select a local-music root folder via SAF (`ACTION_OPEN_DOCUMENT_TREE`), persist the granted URI permission, and MUST NOT crash or leave the local-music root folder in a broken state if that permission is later lost or was never granted.
#### Scenario: User picks a local music root folder
- GIVEN the user opens the local-music setup flow
- WHEN they complete the SAF folder picker and grant access
- THEN the selected folder's URI permission is persisted
- AND the local-music root becomes browsable in Android Auto without re-prompting the picker
#### Scenario: Persisted permission survives app restart
- GIVEN a local music root was previously picked and its permission persisted
- WHEN the app is restarted (cold start)
- THEN the local-music root remains browsable in Android Auto without re-prompting the SAF picker
#### Scenario: Permission revoked or never granted
- GIVEN the SAF permission for the local-music root was revoked outside the app, or no root was ever picked
- WHEN the local-music root folder is browsed in Android Auto
- THEN `getChildren` returns an empty or explanatory list, not an error
- AND the audio handler does not throw or crash
### Requirement: Local Music Browsable Tree
The Android Auto browse tree MUST expose a new non-playable local-music root folder alongside the existing station folders. Browsing that root and any nested subfolder MUST recursively mirror the picked SAF folder's structure: subfolders as non-playable `carpeta_local:<id>` items and audio files as playable `pista:<id>` items resolving to `PistaLocal` instances, using the raw filename as the displayed title.
#### Scenario: Car browses the local-music root
- GIVEN a local music root folder was picked and its permission is valid
- WHEN `getChildren` is called with the local-music root folder id
- THEN it returns the root's immediate subfolders as `carpeta_local:<id>` items and audio files as `pista:<id>` playable items
- AND each playable item's title is the file's raw filename
#### Scenario: Car browses a nested subfolder
- GIVEN a `carpeta_local:<id>` folder returned from a prior browse call
- WHEN `getChildren` is called with that folder id
- THEN it returns that subfolder's own contents (nested folders and/or tracks), recursively mirroring the on-device structure
- AND browsing an empty subfolder returns an empty list, not an error
### Requirement: Local Track Playback Reuses Existing Pipeline
Selecting a `pista:<id>` item MUST resolve to the corresponding `PistaLocal` and play it through the existing `playMediaItem`/`PluriWaveAudioHandler` pipeline, unchanged, including the shared EQ signal chain.
#### Scenario: User selects a local track
- GIVEN the user taps a `pista:<id>` playable item on the car head unit
- WHEN `playFromMediaId(id)` is called
- THEN the id resolves to a `PistaLocal` and playback starts through the existing `playMediaItem` internal path
- AND standard transport (play/pause/stop) and fallback album art work as they do for stations
#### Scenario: EQ still applies to local track playback (regression guard)
- GIVEN a non-flat EQ preset is currently the active/principal preset
- WHEN a `pista:<id>` item is played
- THEN the audible output passes through the same shared EQ signal chain used for station playback, with no separate or bypassed path for local tracks
#### Scenario: Unknown or stale track id
- GIVEN `playFromMediaId` is called with a `pista:<id>` that no longer resolves to a known `PistaLocal`
- WHEN resolution fails
- THEN playback does not start and no unhandled exception propagates from the handler
### Requirement: Local Music Folder Item Cap
A local-music folder (root or nested) whose immediate children exceed `_maxItemsPorCarpeta` (50) MUST be capped to that limit rather than returning unbounded results; pagination is out of scope for this delta.
#### Scenario: Folder exceeds the item cap
- GIVEN a picked or nested local-music folder contains more than 50 immediate children (subfolders and/or tracks combined)
- WHEN `getChildren` is called with that folder id
- THEN at most 50 items are returned, consistent with the existing `_maxItemsPorCarpeta` cap applied to station folders
- AND no error or crash occurs as a result of the truncation
### Requirement: Playable Item Metadata
Every playable `MediaItem` (station) MUST include a non-empty `title` and a loadable `artUri`. Stations without a logo MUST fall back to on-brand artwork, and stations whose logo URL cannot actually be loaded MUST degrade to the same on-brand fallback instead of rendering broken or blank art. The fallback MUST be visually consistent with the phone UI's per-station rotation rather than a generic launcher-icon copy.