Quellcode durchsuchen

docs: document configurable buttons and app pinning

Krasimir Kazakov vor 1 Woche
Ursprung
Commit
398915f291

+ 7 - 6
AGENTS.md

@@ -2,7 +2,7 @@
 
 
 ## 1. Project Overview
 ## 1. Project Overview
 
 
-CarDash is a Flutter/Dart Android home-screen launcher for a car tablet. It has one configurable home page (clock, battery/Wi-Fi, media volume, five shortcuts), launches other apps full-screen, and offers light/dark/automatic themes plus an optional four-digit PIN requested only on cold start.
+CarDash is a Flutter/Dart Android home-screen launcher for a car tablet. It has one configurable home page (clock, battery/Wi-Fi, media volume, up to 16 home buttons), launches other apps full-screen, keeps the screen awake while foreground, and offers light/dark/automatic themes plus an optional four-digit PIN requested only on cold start.
 
 
 Stack: Flutter 3.47.8 / Dart 3.13.7, Android minSdk 29 (Android 10), compile/targetSdk 36, Kotlin bridges, AGP 9.1.0, Gradle 9.3.1, JDK 21. Package `com.wasp.cardash_launcher`. Landscape-only, tablet-first (1280×800).
 Stack: Flutter 3.47.8 / Dart 3.13.7, Android minSdk 29 (Android 10), compile/targetSdk 36, Kotlin bridges, AGP 9.1.0, Gradle 9.3.1, JDK 21. Package `com.wasp.cardash_launcher`. Landscape-only, tablet-first (1280×800).
 
 
@@ -36,12 +36,12 @@ ADB lives at `/opt/android-sdk/platform-tools/adb`; the SDK is at `/opt/android-
 - `lib/core/` — theme tokens (`AppColors`, `AppTheme`), `ThemeController`, reusable widgets.
 - `lib/core/` — theme tokens (`AppColors`, `AppTheme`), `ThemeController`, reusable widgets.
 - `lib/data/models/` — `AppEntry`, `SlotType`, `SlotAssignment`, `SystemStatus`, `VolumeInfo`.
 - `lib/data/models/` — `AppEntry`, `SlotType`, `SlotAssignment`, `SystemStatus`, `VolumeInfo`.
 - `lib/data/services/` — `NativeBridge` (platform channels), `PinService`, secure-store adapter.
 - `lib/data/services/` — `NativeBridge` (platform channels), `PinService`, secure-store adapter.
-- `lib/data/repositories/` — `SettingsRepository`, the SSOT for theme, night window and slot assignments.
-- `lib/features/home/` — home screen, `LauncherController` (apps + shortcuts + HOME role), `SystemController` (volume/battery/Wi-Fi polling).
+- `lib/data/repositories/` — `SettingsRepository`, the SSOT for theme, night window, slot assignments, visibility flags and pinned apps.
+- `lib/features/home/` — home screen, `LauncherController` (apps, slots, pinned apps, 16-button cap, HOME role), `SystemController` (volume/battery/Wi-Fi polling).
 - `lib/features/apps/` — All Apps screen and app-picker sheet.
 - `lib/features/apps/` — All Apps screen and app-picker sheet.
 - `lib/features/settings/` — General and Security pages.
 - `lib/features/settings/` — General and Security pages.
 - `lib/features/lock/` — PIN pad, lock screen, cold-start `LockController`.
 - `lib/features/lock/` — PIN pad, lock screen, cold-start `LockController`.
-- `android/app/src/main/kotlin/com/wasp/cardash_launcher/` — `MainActivity`, `LauncherBridge` (package manager, role), `SystemBridge` (battery, Wi-Fi, volume).
+- `android/app/src/main/kotlin/com/wasp/cardash_launcher/` — `MainActivity` (keep-screen-on, volume keys), `LauncherBridge` (package manager, role), `SystemBridge` (battery, Wi-Fi, volume).
 - `tool/` — emulator/install/check scripts. `docs/` — implementation plan and design notes.
 - `tool/` — emulator/install/check scripts. `docs/` — implementation plan and design notes.
 
 
 Rules:
 Rules:
@@ -63,7 +63,7 @@ notifyListeners();
 
 
 - Use `context.colors` / `AppTheme` tokens, not hard-coded colors in widgets.
 - Use `context.colors` / `AppTheme` tokens, not hard-coded colors in widgets.
 - All UI copy is sentence case (except the CarDash name). Keep copy short and functional.
 - All UI copy is sentence case (except the CarDash name). Keep copy short and functional.
-- New shortcut slots: extend `SlotType`, add a picker entry, a home `ShortcutSpec`, and repository coverage.
+- New home buttons: extend `SlotType` for fixed slots or use `LauncherController` pinned-app APIs; enforce the 16-button cap in the controller.
 - New native methods: add them to `LauncherPlatform`, `NativeBridge`, the relevant Kotlin bridge, and the test fake if used.
 - New native methods: add them to `LauncherPlatform`, `NativeBridge`, the relevant Kotlin bridge, and the test fake if used.
 - Tests: fake `LauncherPlatform`/`SecureStore`; `SharedPreferences.setMockInitialValues({})`; widget tests wrap in `MaterialApp(theme: AppTheme.light())`. Test files live in `test/` and end with `_test.dart`.
 - Tests: fake `LauncherPlatform`/`SecureStore`; `SharedPreferences.setMockInitialValues({})`; widget tests wrap in `MaterialApp(theme: AppTheme.light())`. Test files live in `test/` and end with `_test.dart`.
 - Run `dart format lib test` before committing. Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`).
 - Run `dart format lib test` before committing. Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`).
@@ -89,7 +89,8 @@ notifyListeners();
 - The Flutter template uses AGP 9.1 built-in Kotlin support. Do not add the Kotlin Gradle plugin unless the build explicitly requires it.
 - The Flutter template uses AGP 9.1 built-in Kotlin support. Do not add the Kotlin Gradle plugin unless the build explicitly requires it.
 - Immersive mode is reapplied on every `resumed` lifecycle event; Android may restore system bars after dialogs or role prompts.
 - Immersive mode is reapplied on every `resumed` lifecycle event; Android may restore system bars after dialogs or role prompts.
 - The HOME role must be granted for the dashboard to replace the tablet home screen. On the emulator use `cmd role add-role-holder`; the in-app banner and Settings row use `RoleManager`.
 - The HOME role must be granted for the dashboard to replace the tablet home screen. On the emulator use `cmd role add-role-holder`; the in-app banner and Settings row use `RoleManager`.
-- Screen-space is deliberately finite: test at 1280×800 and 1024×600. Avoid unbounded `ListView`s inside `Column`s.
+- Screen-space is deliberately finite: test the 16-button grid at 1280×800 and 1024×600. Avoid unbounded `ListView`s inside `Column`s.
 - `tool/emulator.sh` starts a headless AVD with the **host GPU**; SwiftShader segfaulted on this machine's API 35 image. Use `CARDASH_GPU=swiftshader_indirect` only as a fallback. Use `adb exec-out screencap -p` for screenshots; there may be multiple `adb` binaries on PATH, so use the absolute one.
 - `tool/emulator.sh` starts a headless AVD with the **host GPU**; SwiftShader segfaulted on this machine's API 35 image. Use `CARDASH_GPU=swiftshader_indirect` only as a fallback. Use `adb exec-out screencap -p` for screenshots; there may be multiple `adb` binaries on PATH, so use the absolute one.
 - While CarDash is foreground, `MainActivity` consumes hardware volume keys and adjusts `STREAM_MUSIC` so they match the dashboard. Do not remove that override without providing another sync path; otherwise Android controls the ring stream when no media is playing.
 - While CarDash is foreground, `MainActivity` consumes hardware volume keys and adjusts `STREAM_MUSIC` so they match the dashboard. Do not remove that override without providing another sync path; otherwise Android controls the ring stream when no media is playing.
+- `FLAG_KEEP_SCREEN_ON` in `MainActivity` is intentional. It applies while CarDash is the foreground window; do not move it to a permission-based wake lock.
 - Reinstalling the app can clear its HOME role; re-run `tool/install.sh` or use Settings > Home app.
 - Reinstalling the app can clear its HOME role; re-run `tool/install.sh` or use Settings > Home app.

+ 38 - 19
README.md

@@ -3,15 +3,15 @@
 A calm, configurable Android car dashboard launcher, built with Flutter.
 A calm, configurable Android car dashboard launcher, built with Flutter.
 
 
 CarDash replaces the tablet home screen with one landscape page: a large clock,
 CarDash replaces the tablet home screen with one landscape page: a large clock,
-battery and Wi-Fi status, the main media-volume control, and five shortcuts —
-**Navigation**, **Music**, **Radio**, **Settings** and **All apps**. The first
-three are configurable; a long press picks a different installed app. External
-apps open full-screen using the normal Android launcher mechanism. No overlays,
-no root, no kiosk setup.
+battery and Wi-Fi status, the main media-volume control, and up to 16 buttons —
+**Navigation**, **Music**, **Radio**, **Settings**, **All apps**, plus any apps
+you pin from All Apps. The first three can be shown, hidden and assigned to
+installed apps. External apps open full-screen using the normal Android launcher
+mechanism. No overlays, no root, no kiosk setup.
 
 
 <p align="center">
 <p align="center">
-  <em>Verified on Android 15 and Android 10 tablet emulators at 1280×800.
-  Landscape only.</em>
+  <em>Verified on Android 15 and Android 10 tablet emulators at 1280×800 and
+  1024×600. Runs on a physical Android 17 HyperOS tablet. Landscape only.</em>
 </p>
 </p>
 
 
 ## Screenshots
 ## Screenshots
@@ -20,9 +20,11 @@ no root, no kiosk setup.
 |---|---|
 |---|---|
 | ![CarDash light home](docs/screenshots/home-light.png) | ![CarDash dark home](docs/screenshots/home-dark.png) |
 | ![CarDash light home](docs/screenshots/home-light.png) | ![CarDash dark home](docs/screenshots/home-dark.png) |
 
 
-Also: [All apps](docs/screenshots/all-apps.png) ·
+Also: [16-button home](docs/screenshots/home-16.png) ·
+[16 buttons at 1024×600](docs/screenshots/home-16-1024.png) ·
+[All apps](docs/screenshots/all-apps.png) ·
 [app picker](docs/screenshots/app-picker.png) ·
 [app picker](docs/screenshots/app-picker.png) ·
-[Settings](docs/screenshots/settings.png) ·
+[Settings · home buttons](docs/screenshots/settings-buttons.png) ·
 [PIN lock](docs/screenshots/pin-lock.png) ·
 [PIN lock](docs/screenshots/pin-lock.png) ·
 [1024×600 layout](docs/screenshots/home-compact-1024.png)
 [1024×600 layout](docs/screenshots/home-compact-1024.png)
 
 
@@ -36,9 +38,15 @@ Also: [All apps](docs/screenshots/all-apps.png) ·
   front, the hardware volume keys are routed to the same media stream, so the
   front, the hardware volume keys are routed to the same media stream, so the
   dashboard and the keys always agree. This is the phone's media stream, not a
   dashboard and the keys always agree. This is the phone's media stream, not a
   private volume.
   private volume.
-- **Configurable shortcuts** for Navigation, Music and Radio. Generic icons on
-  the dashboard; real app icons in the picker and All Apps.
+- **Configurable home buttons** — switches in Settings show or hide Navigation,
+  Music and Radio. Settings and All apps are always present. Dashboard icons
+  stay generic; real app icons appear in the picker and All Apps.
+- **Pin any app from All Apps** — long-press an app to add it to Home. The home
+  page holds up to **16 buttons including Settings and All apps**, and the grid
+  shrinks as it fills. Long-press an added app on Home to remove it completely;
+  add it back with another long press in All Apps.
 - **All apps** — searchable grid of every launchable app, launched full-screen.
 - **All apps** — searchable grid of every launchable app, launched full-screen.
+- **Screen stays awake** while CarDash is in the foreground.
 - **Light / Dark / Automatic** theme. Automatic uses a fixed local-time window
 - **Light / Dark / Automatic** theme. Automatic uses a fixed local-time window
   (default 19:00–07:00), editable in Settings.
   (default 19:00–07:00), editable in Settings.
 - **Optional PIN** — four digits, stored as a salted PBKDF2 hash in
 - **Optional PIN** — four digits, stored as a salted PBKDF2 hash in
@@ -112,8 +120,12 @@ same thing. Android will not let an app force itself into the home role silently
 | Tap Navigation / Music / Radio | Open the assigned app full-screen |
 | Tap Navigation / Music / Radio | Open the assigned app full-screen |
 | Long-press Navigation / Music / Radio | Pick a different installed app |
 | Long-press Navigation / Music / Radio | Pick a different installed app |
 | Tap an unassigned shortcut | Open the app picker |
 | Tap an unassigned shortcut | Open the app picker |
-| Settings | Theme, home shortcuts, default-home role, PIN |
-| All apps | Search every launchable app; tap to open |
+| Settings → Home buttons switches | Show or hide Navigation, Music, Radio |
+| Long-press an app in All Apps | Add it to Home (up to 16 buttons) |
+| Long-press an added app on Home | Remove it from Home |
+| Settings | Theme, home buttons, default-home role, PIN |
+| All apps | Search every launchable app; tap to open, hold to pin |
+| Screen | Stays awake while CarDash is in front |
 | Volume ring / mute | Toggle media mute |
 | Volume ring / mute | Toggle media mute |
 | Slider or − / + | Set media volume |
 | Slider or − / + | Set media volume |
 | Hardware volume keys | Adjust the dashboard's media volume; the ring follows |
 | Hardware volume keys | Adjust the dashboard's media volume; the ring follows |
@@ -127,7 +139,8 @@ the app resumes.
 **General**
 **General**
 - Light / Dark / Auto theme.
 - Light / Dark / Auto theme.
 - Auto night window (default dark from 19:00, light from 07:00).
 - Auto night window (default dark from 19:00, light from 07:00).
-- The three home shortcuts.
+- Home buttons: show/hide Navigation, Music, Radio; live count out of 16.
+- Assign the app for each slot; Settings and All apps are fixed.
 - Home role status and shortcut to the system prompt.
 - Home role status and shortcut to the system prompt.
 
 
 **Security**
 **Security**
@@ -171,10 +184,13 @@ flutter test
 ./tool/check.sh
 ./tool/check.sh
 ```
 ```
 
 
-Current tests cover PIN hashing/persistence, settings persistence, theme
-resolution and the shortcut tile widget. Native package enumeration, the HOME
-role, volume, app launching and PIN flows were verified on both API 35 and
-API 29 tablet emulators, including the release APK.
+The 17 tests cover PIN hashing/persistence, settings persistence, theme
+resolution, slot visibility, pinned apps, the 16-button cap and the dense
+shortcut grid. Native package enumeration, the HOME role, volume, app launching
+and PIN flows were verified on API 35 and API 29 emulators, including the release
+APK. The home-button, pinning and keep-awake flows were checked at 1280×800 and
+1024×600. Release 0.2.0 is also installed on a physical Android 17 HyperOS
+tablet.
 
 
 ## Troubleshooting the emulator
 ## Troubleshooting the emulator
 
 
@@ -197,6 +213,10 @@ Android 15 AVD is left running headlessly after development; use
   requires a newer Android release.
   requires a newer Android release.
 - **Landscape only** (`sensorLandscape`). The home page is designed for
 - **Landscape only** (`sensorLandscape`). The home page is designed for
   1280×800 and remains usable at 1024×600.
   1280×800 and remains usable at 1024×600.
+- **16-button cap** includes Settings and All apps. Added apps use the generic
+  dashboard icon and their name; real icons remain in the picker and All Apps.
+- **Screen-on** applies while CarDash is the foreground window. Android can
+  still sleep while another app is in front.
 - **No embedded third-party app UI.** Navigation/Music/Radio are launched in
 - **No embedded third-party app UI.** Navigation/Music/Radio are launched in
   their own full-screen windows.
   their own full-screen windows.
 - **No global play/pause control.** Volume is on the home screen; playback
 - **No global play/pause control.** Volume is on the home screen; playback
@@ -222,7 +242,6 @@ large numerals and quiet line icons. It is not a copy of that UI.
 ## Roadmap
 ## Roadmap
 
 
 - Optional compact now-playing control beside the volume card.
 - Optional compact now-playing control beside the volume card.
-- Configurable home layout or additional shortcut slots.
 - Release signing configuration.
 - Release signing configuration.
 - Real-device soak test on an Android 10 car tablet.
 - Real-device soak test on an Android 10 car tablet.
 
 

+ 42 - 17
docs/IMPLEMENTATION_PLAN.md

@@ -11,13 +11,18 @@ compatibility:
 - One home page. No top bar, no bottom dock, no pages.
 - One home page. No top bar, no bottom dock, no pages.
 - Clock/date, battery/charging and Wi-Fi on the page.
 - Clock/date, battery/charging and Wi-Fi on the page.
 - A prominent media-volume card (ring, slider, −/+, mute).
 - A prominent media-volume card (ring, slider, −/+, mute).
-- Five shortcuts: Navigation, Music, Radio, Settings, All apps.
-- Navigation/Music/Radio are **app slots**. They can be assigned, changed and
-  cleared. Dashboard icons stay generic.
+- Up to **16 home buttons**: Navigation, Music, Radio, Settings, All apps, plus
+  apps pinned from All Apps.
+- Navigation/Music/Radio are **app slots** with show/hide switches. They can be
+  assigned, changed and cleared. Settings and All apps are always present.
+- Pinned apps are added by long-pressing an app in All Apps and removed by
+  long-pressing the added button on Home. Dashboard icons stay generic.
+- The grid adapts from 2 to 6 columns and shrinks its tiles as the count grows.
 - Every external app opens full-screen through a normal Android `Intent`.
 - Every external app opens full-screen through a normal Android `Intent`.
-- Settings: light/dark/automatic theme, fixed night window, slot assignment,
-  HOME-role setup, four-digit PIN.
+- Settings: light/dark/automatic theme, fixed night window, home-button switches,
+  slot assignment, HOME-role setup, four-digit PIN.
 - PIN is requested **only on a cold start**, never on resume or screen-off.
 - PIN is requested **only on a cold start**, never on resume or screen-off.
+- The screen stays awake while CarDash is the foreground window.
 - Landscape-only; tablet-first 1280×800; Android 10 minimum.
 - Landscape-only; tablet-first 1280×800; Android 10 minimum.
 - Package: `com.wasp.cardash_launcher`. Display name: **CarDash**.
 - Package: `com.wasp.cardash_launcher`. Display name: **CarDash**.
 
 
@@ -27,9 +32,12 @@ compatibility:
 |---|---|---|
 |---|---|---|
 | Central app content | Launcher-native; apps open full-screen | Android cannot embed another app; overlay chrome was rejected as fragile and app-obstructing. |
 | 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. |
 | UI chrome | None (no bars) | Removes the mismatch between launcher chrome and full-screen apps; cleaner, more compatible. |
-| Home layout | Single page, info + volume + five shortcuts | Matches the refined brief: one configurable home screen. |
-| App slots | Navigation, Music, Radio | Kept from the original brief; Settings and All apps are fixed. |
-| Icons | Generic for dashboard; real icons in pickers/All Apps | Keeps the car interface consistent while making app identification possible. |
+| 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 | Generic for all Home buttons; real icons in pickers/All Apps | Keeps the car interface consistent; names identify pinned apps. |
+| 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. |
 | 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. |
 | 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. |
 | Min Android | API 29 (Android 10) | Requested minimum; no in-scope API requires newer. |
@@ -45,18 +53,20 @@ compatibility:
 Flutter
 Flutter
   HomeScreen
   HomeScreen
     ClockBlock / StatusCluster / VolumeCard / ShortcutGrid
     ClockBlock / StatusCluster / VolumeCard / ShortcutGrid
-    LauncherController  -> apps, slots, default-home state
+    LauncherController  -> apps, slots, pinned apps, 16-button cap, default-home state
     SystemController    -> battery/Wi-Fi/volume polling
     SystemController    -> battery/Wi-Fi/volume polling
   AllAppsScreen / AppPickerSheet
   AllAppsScreen / AppPickerSheet
   SettingsScreen -> General / Security
   SettingsScreen -> General / Security
   PinSetupScreen / LockScreen -> LockController -> PinService
   PinSetupScreen / LockScreen -> LockController -> PinService
 Android (Kotlin)
 Android (Kotlin)
-  MainActivity -> LauncherBridge (apps, launch, role)
-              -> SystemBridge (battery, Wi-Fi, volume)
+  MainActivity -> keep-screen-on, volume keys
+               -> LauncherBridge (apps, launch, role)
+               -> SystemBridge (battery, Wi-Fi, volume)
 ```
 ```
 
 
-- `SettingsRepository` is the only persistence path for theme, night window and
-  slots. `flutter_secure_storage` holds the salted PIN hash.
+- `SettingsRepository` is the only persistence path for theme, night window,
+  slot visibility/assignments and pinned apps. `flutter_secure_storage` holds
+  the salted PIN hash.
 - Package enumeration and icon rendering happen on a worker thread in Kotlin and
 - Package enumeration and icon rendering happen on a worker thread in Kotlin and
   are returned as PNG bytes.
   are returned as PNG bytes.
 - Timers for volume/status are stopped when the app leaves the foreground.
 - Timers for volume/status are stopped when the app leaves the foreground.
@@ -76,11 +86,12 @@ Android (Kotlin)
 | M5 | Settings, theme auto window, PIN setup/change/remove, cold-start lock | 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 |
 | M6 | Interaction testing, light/dark screenshots, layout polish, API 29 verification | Done |
 | M7 | Release build, final docs, screenshots, last commits | 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 |
 
 
 ## 5. Verification checklist
 ## 5. Verification checklist
 
 
 - [x] `flutter analyze` clean.
 - [x] `flutter analyze` clean.
-- [x] Unit/widget tests pass (PIN, repository, theme, shortcut tile).
+- [x] Unit/widget tests pass (17 tests: PIN, repository, theme, slot visibility, pinned apps, cap, dense grid).
 - [x] Debug APK builds with JDK 21.
 - [x] Debug APK builds with JDK 21.
 - [x] Installs on API 35 1280×800 tablet.
 - [x] Installs on API 35 1280×800 tablet.
 - [x] HOME role granted; Home opens CarDash.
 - [x] HOME role granted; Home opens CarDash.
@@ -94,6 +105,12 @@ Android (Kotlin)
 - [x] Verify 1024×600 compact layout (`adb shell wm size 1024x600`).
 - [x] Verify 1024×600 compact layout (`adb shell wm size 1024x600`).
 - [x] Boot and verify on Android 10 (API 29) AVD, including PIN and release APK.
 - [x] Boot and verify on Android 10 (API 29) AVD, including PIN and release APK.
 - [x] Release APK on both AVDs (54 MB universal APK).
 - [x] Release APK on both AVDs (54 MB universal APK).
+- [x] Navigation/Music/Radio switches hide/show buttons, persist, and preserve assignments.
+- [x] All Apps long-press pins apps; the 16-button cap rejects a 17th button.
+- [x] Long-press on an added app removes it; it can be re-added from All Apps.
+- [x] 16 buttons fit at 1280×800 and 1024×600; the grid uses 2–6 columns.
+- [x] `FLAG_KEEP_SCREEN_ON` is present on the dashboard window.
+- [x] Release 0.2.0 installed on a physical Android 17 HyperOS tablet.
 - [x] Screenshots in `docs/screenshots/`; README/AGENTS/plan updated.
 - [x] Screenshots in `docs/screenshots/`; README/AGENTS/plan updated.
 
 
 ## 6. Known risks and mitigations
 ## 6. Known risks and mitigations
@@ -105,12 +122,16 @@ Android (Kotlin)
    and acceptable for sideloading; a Play distribution needs policy work.
    and acceptable for sideloading; a Play distribution needs policy work.
 3. **PIN security scope**: cold-start only by design; it does not replace the
 3. **PIN security scope**: cold-start only by design; it does not replace the
    Android keyguard or protect against adb/data extraction. README explains it.
    Android keyguard or protect against adb/data extraction. README explains it.
-4. **Emulator stability**: software-rendered headless emulator can be killed by
-   the host; scripts use managed background boot and `swiftshader_indirect`.
+4. **Emulator stability**: headless emulators can be killed by the host; scripts
+   use managed boot and the host GPU. SwiftShader is only a fallback.
 5. **Flutter 3.47 / AGP 9.1 / JDK 21**: works on this machine; Java 27 is not the
 5. **Flutter 3.47 / AGP 9.1 / JDK 21**: works on this machine; Java 27 is not the
    validated toolchain. The emulator uses the host GPU; SwiftShader segfaulted
    validated toolchain. The emulator uses the host GPU; SwiftShader segfaulted
    on the API 35 image, so the helper script defaults to `-gpu host`.
    on the API 35 image, so the helper script defaults to `-gpu host`.
-6. **Uninstall/reinstall** may drop the HOME role; Settings and the installer
+6. **16-button density**: generic icons plus small labels are the trade-off for
+   a single page. The Settings count and grid scaling make the limit explicit.
+7. **Screen-on battery use**: the flag applies only while the dashboard is
+   foreground; it is not a background wake lock.
+8. **Uninstall/reinstall** may drop the HOME role; Settings and the installer
    script can restore it.
    script can restore it.
 
 
 ## 7. Out of scope (for now)
 ## 7. Out of scope (for now)
@@ -130,3 +151,7 @@ Android (Kotlin)
   on the API 35 AVD; then verified the release build and PIN flows on the API 29
   on the API 35 AVD; then verified the release build and PIN flows on the API 29
   AVD. Added hardware volume-key routing and PIN verification progress.
   AVD. Added hardware volume-key routing and PIN verification progress.
   Screenshots captured at 1280×800 and 1024×600.
   Screenshots captured at 1280×800 and 1024×600.
+- 2026-10-29: Added home-button visibility switches, All Apps long-press pinning,
+  a 16-button cap with an adaptive 2–6 column grid, pinned-app removal, and a
+  foreground keep-screen-on flag. Verified 17 tests, 16-button layouts at
+  1280×800 and 1024×600, cap/removal/re-add, and 0.2.0 on the physical tablet.

BIN
docs/screenshots/all-apps.png


BIN
docs/screenshots/home-16-1024.png


BIN
docs/screenshots/home-16.png


BIN
docs/screenshots/settings-buttons.png