Last updated: 2026-10-29
CarDash is a Flutter/Dart Android home-screen launcher for a landscape car tablet. It deliberately trades the reference head-unit chrome for maximum compatibility:
Intent.com.wasp.cardash_launcher. Display name: CarDash.| Decision | Choice | Rationale |
|---|---|---|
| Central app content | Launcher-native; apps open full-screen | Android cannot embed another app; overlay chrome was rejected as fragile and app-obstructing. |
| UI chrome | None (no bars) | Removes the mismatch between launcher chrome and full-screen apps; cleaner, more compatible. |
| Home layout | Single page, info + volume + up to 16 buttons | Matches the refined brief; tiles scale from 2 to 6 columns. |
| App slots | Navigation, Music, Radio with visibility switches | Kept from the original brief; Settings and All apps are fixed. |
| Pinned apps | All Apps long-press adds, Home long-press removes | Makes any installed app reachable from Home without editing a separate layout screen. |
| Home cap | 16 buttons total, including Settings and All apps | Keeps the single page legible at tablet resolutions; enforced in LauncherController. |
| Icons | User-installed apps use their own icon; system/unassigned slots stay generic | Identification without losing the calm fixed-button language. |
| Accent | Six curated choices, persisted in Settings | Changes the whole theme without a color picker or arbitrary contrast failures. |
| Battery visibility | One switch hides level and charging bolt | One control for both indicators, as requested. |
| Media feedback | Music tile shows the selected app icon + animated bars while media is active | Compact visual feedback without adding a media control surface. |
| Hint lifetime | Two minutes from process start, then fade out | Avoids permanent onboarding chrome; survives widget rebuilds via AppClock. |
| Screen | FLAG_KEEP_SCREEN_ON while foreground |
The dashboard is the car display; no wake-lock permission needed. |
| Theme | Light / Dark / Automatic with fixed 19:00–07:00 window | No location permission or network; time pickers make the window adjustable. |
| PIN | Four digits, salted PBKDF2 hash, cold start only | Matches the explicit instruction; no re-lock while running. |
| Min Android | API 29 (Android 10) | Requested minimum; no in-scope API requires newer. |
| Target/compile | 36 | Current Flutter toolchain defaults; runs on API 29. |
| Orientation | sensorLandscape + Dart orientation lock |
Car/tablet form factor; portrait is intentionally unsupported. |
| AVD | 10.1" WXGA tablet, 1280×800, 160 dpi, API 35 and API 29 | Matches a dashboard tablet and the reference resolution class. |
| HOME role | Standard RoleManager request + Settings row |
A launcher must be chosen as the system home app; never silently forced. |
| Overlay/kiosk/root | Out of scope | Rejected for compatibility. |
Flutter
HomeScreen
ClockBlock / StatusCluster / VolumeCard / ShortcutGrid
LauncherController -> apps, slots, pinned apps, 16-button cap, default-home state
SystemController -> battery/Wi-Fi/volume/media polling
AllAppsScreen / AppPickerSheet
SettingsScreen -> General / Security
PinSetupScreen / LockScreen -> LockController -> PinService
Android (Kotlin)
MainActivity -> keep-screen-on, volume keys
-> LauncherBridge (packages, icons, system flag, role)
-> SystemBridge (battery, Wi-Fi, volume, media activity)
SettingsRepository is the only persistence path for theme, night window,
slot visibility/assignments and pinned apps. flutter_secure_storage holds
the salted PIN hash.runApp, so there is no dashboard flash on a
locked cold start.| # | Milestone | State |
|---|---|---|
| M0 | Local git repo, Flutter scaffold, launcher config, package ID, icons, docs | Done |
| M1 | x86_64 API 35/API 29 images, 1280×800 landscape tablet AVDs, emulator/install scripts | Done |
| M2 | Theme system, single home layout, clock/status, volume card, shortcut grid | Done (initial visual pass) |
| M3 | Kotlin bridges: app list/icons/launch, HOME role, volume, battery/Wi-Fi | Done |
| M4 | App picker, All Apps, slot persistence, long-press flows, launch errors | Done |
| M5 | Settings, theme auto window, PIN setup/change/remove, cold-start lock | Done |
| M6 | Interaction testing, light/dark screenshots, layout polish, API 29 verification | Done |
| M7 | Release build, final docs, screenshots, last commits | Done |
| M8 | Home-button visibility switches, All Apps pinning, 16-button adaptive grid, keep-awake | Done |
| M9 | Accent colors, battery toggle, fading hint, user icons, Media equalizer, install rule | Done |
flutter analyze clean.STREAM_MUSIC while the dashboard is foreground).adb shell wm size 1024x600).FLAG_KEEP_SCREEN_ON is present on the dashboard window.docs/screenshots/; README/AGENTS/plan updated.ContentObserver would remove
the polling. No global play/pause is in scope.QUERY_ALL_PACKAGES is required for a launcher app list. It is documented
and acceptable for sideloading; a Play distribution needs policy work.-gpu host.AudioManager.isMusicActive,
not a specific package. Exact attribution would require notification access.