Android Auto no longer copies the launcher icon as placeholder art; it rotates through the same 4 on-brand station_art assets the phone UI already uses, keyed by the same per-station hash for visual parity. Malformed or unusable favicon URLs (including a Dart Uri quirk where 'http://' reports hasAuthority=true with an empty host) now fail the validity gate instead of being handed to the OS media browser as-is. Browsable items also show codec/bitrate as a subtitle when known.
78 lines
4.3 KiB
Markdown
78 lines
4.3 KiB
Markdown
# Delta for Android Auto Media
|
|
|
|
## MODIFIED Requirements
|
|
|
|
### 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.
|
|
(Previously: fallback only covered a null/empty favicon and pointed at a bundled default-artwork asset that read as a copy of the launcher icon.)
|
|
|
|
#### Scenario: Station has a valid, reachable remote logo
|
|
|
|
- GIVEN a station has a remote logo URL that resolves to a loadable image
|
|
- WHEN it is mapped to a `MediaItem`
|
|
- THEN `title` is the station name and `artUri` is the station's logo URL
|
|
|
|
#### Scenario: Station has no logo (Case A)
|
|
|
|
- GIVEN a station has no logo (`favicon` is null or empty)
|
|
- WHEN it is mapped to a `MediaItem`
|
|
- THEN `artUri` is set to one of the on-brand `station_art_*` fallback assets instead of being empty or null
|
|
|
|
#### Scenario: Station's logo URL is present but unreachable (Case B)
|
|
|
|
- GIVEN a station has a non-empty `favicon` URL that cannot be loaded (dead link, unreachable host, or non-image response)
|
|
- WHEN it is mapped to (or resolved as) a `MediaItem` in the Android Auto browse tree
|
|
- THEN the system SHALL show the same on-brand fallback art used for Case A instead of broken or blank art
|
|
- AND the car head unit MUST NOT display an empty, broken-image, or indefinitely-loading art tile for that station
|
|
|
|
#### Scenario: Fallback art matches phone-UI per-station selection
|
|
|
|
- GIVEN a station falls back to on-brand art (Case A or Case B)
|
|
- WHEN the fallback asset is chosen for that station
|
|
- THEN the selected asset MUST be one of the same 4 rotating assets used by the phone UI (`station_art_aurora`, `station_art_cosmic`, `station_art_pulse`, `station_art_nova`)
|
|
- AND the same station MUST deterministically resolve to the same asset on both the phone UI and Android Auto (per-station selection parity), not a random or session-varying choice
|
|
|
|
#### Scenario: Fallback art is on-brand, not the launcher icon
|
|
|
|
- GIVEN a station requires fallback art (Case A or Case B)
|
|
- WHEN its `artUri` is resolved
|
|
- THEN it MUST NOT point at a byte-for-byte copy of the app launcher icon
|
|
- AND it MUST point at one of the 4 on-brand `station_art_*` assets
|
|
|
|
### 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) containing playable station items. Playable station items SHOULD carry an audio-quality subtitle when known.
|
|
(Previously: no subtitle requirement; folders and playable items were otherwise unchanged.)
|
|
|
|
#### 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 three folder `MediaItem`s (Favoritos, Todas las emisoras, Mis emisoras), each with `playable: false`
|
|
|
|
#### Scenario: Car requests a folder with no stations
|
|
|
|
- GIVEN the user has zero favorite stations
|
|
- WHEN `getChildren` is called with the Favoritos folder id
|
|
- THEN it returns an empty list, not an error
|
|
|
|
#### Scenario: Browse requested before app state is loaded
|
|
|
|
- GIVEN the audio handler starts cold and station/favorites Provider state has not finished loading
|
|
- WHEN `getChildren` is called (root or any folder)
|
|
- THEN it returns a valid, possibly empty, list without throwing and without blocking or crashing the service
|
|
|
|
#### Scenario: Station has known codec and bitrate
|
|
|
|
- GIVEN a station's `Emisora.codec` and `Emisora.bitrate` are both known (non-null)
|
|
- WHEN it is mapped to a playable `MediaItem`
|
|
- THEN `displaySubtitle` SHALL contain a human-readable quality hint combining bitrate and codec (e.g. "128 kbps · MP3")
|
|
|
|
#### Scenario: Station has unknown codec or bitrate
|
|
|
|
- GIVEN a station's `Emisora.codec` or `Emisora.bitrate` (or both) is null/unknown
|
|
- WHEN it is mapped to a playable `MediaItem`
|
|
- THEN `displaySubtitle` SHALL omit the quality hint gracefully (no subtitle, or a subtitle with no quality fragment)
|
|
- AND the subtitle MUST NOT render literal placeholder text such as "null kbps" or "null · null"
|