Files
pluriwave/openspec/changes/auto-media-art-quality/specs/android-auto-media/spec.md
T
FreeTLab c193650cc4 fix(auto): fall back to brand art and surface quality on dead/missing favicons
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.
2026-07-19 13:06:18 +02:00

4.3 KiB

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.)

  • 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 MediaItems (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"