Kaynağa Gözat

docs: record the real-car volume verification

Krasimir Kazakov 4 gün önce
ebeveyn
işleme
f0ede3fef3
3 değiştirilmiş dosya ile 6 ekleme ve 2 silme
  1. 1 1
      AGENTS.md
  2. 2 1
      README.md
  3. 3 0
      docs/IMPLEMENTATION_PLAN.md

+ 1 - 1
AGENTS.md

@@ -96,7 +96,7 @@ notifyListeners();
 - Screen-space is deliberately finite: test the 16-button grid at 1280×800, 1280×720 and 1024×600. The shortcut grid is bottom-anchored so a short row sits on the bottom edge; keep that behavior when changing layouts. The grid includes All apps; Settings sits in `StatusCluster` and does not consume a slot. Avoid unbounded `ListView`s inside `Column`s.
 - Screen-space is deliberately finite: test the 16-button grid at 1280×800, 1280×720 and 1024×600. The shortcut grid is bottom-anchored so a short row sits on the bottom edge; keep that behavior when changing layouts. The grid includes All apps; Settings sits in `StatusCluster` and does not consume a slot. 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, unless `AudioManager.isVolumeFixed` is true; on fixed-volume car units the keys pass through to the vehicle amplifier and the on-screen slider is disabled with an explanation. `SystemBridge.setVolume` falls back to relative `adjustStreamVolume` steps when a unit ignores absolute `setStreamVolume`, then to a `FLAG_SHOW_UI` write that may reach the vendor's own volume panel. Long-pressing **Media volume** toggles `SystemController.volumeDiagnostics`, which shows the raw `index/max`/`min`, fixed flag, control source, vendor state, all stream levels and the last write result; the native side logs the same data under `CarDashVolume`. Do not remove this path 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, unless `AudioManager.isVolumeFixed` is true; on fixed-volume car units the keys pass through to the vehicle amplifier and the on-screen slider is disabled with an explanation. `SystemBridge.setVolume` falls back to relative `adjustStreamVolume` steps when a unit ignores absolute `setStreamVolume`, then to a `FLAG_SHOW_UI` write that may reach the vendor's own volume panel. Long-pressing **Media volume** toggles `SystemController.volumeDiagnostics`, which shows the raw `index/max`/`min`, fixed flag, control source, vendor state, all stream levels and the last write result; the native side logs the same data under `CarDashVolume`. Do not remove this path without providing another sync path; otherwise Android controls the ring stream when no media is playing.
-- FYT/Syu head units (Joying, Junsun, Teyes, Atoto and similar Chinese firmware) own the amplifier in the MCU, so the Android media stream is not what the driver hears. `SyuVolumeBridge` binds `com.syu.ms` (`app.ToolkitService`, action `com.syu.ms.toolkit`), fetches module 4 (`getRemoteModule`, transaction 1) and sends `cmd(0, [level])` for the absolute master volume (command 0 = `FinalSound.C_VOL`, range 0–36); it also subscribes to update 2 (level) and 3 (mute), so knob changes and slider changes stay in sync. `SystemBridge.readVolume` reports `source = syu` while that bridge is connected. `MainActivity`'s hardware-key path is unchanged: the car's own knob and steering-wheel volume are handled by the MCU, not by injecting extra steps. No permission, root or manifest change is needed; if the package, service or module is missing the bridge stays disconnected and the `AudioManager` path is used. Never make the vendor bind a hard dependency, and never let a failed binder call crash the app.
+- FYT/Syu head units (Joying, Junsun, Teyes, Atoto and similar Chinese firmware) own the amplifier in the MCU, so the Android media stream is not what the driver hears. `SyuVolumeBridge` binds `com.syu.ms` (`app.ToolkitService`, action `com.syu.ms.toolkit`), fetches module 4 (`getRemoteModule`, transaction 1) and sends `cmd(0, [level])` for the absolute master volume (command 0 = `FinalSound.C_VOL`, range 0–36); it also subscribes to update 2 (level) and 3 (mute), so knob changes and slider changes stay in sync. `SystemBridge.readVolume` reports `source = syu` while that bridge is connected. This path is verified on a real Android 13 FYT/Syu unit: the on-screen slider and the car's own volume control agree. `MainActivity`'s hardware-key path is unchanged: the car's own knob and steering-wheel volume are handled by the MCU, not by injecting extra steps. No permission, root or manifest change is needed; if the package, service or module is missing the bridge stays disconnected and the `AudioManager` path is used. Never make the vendor bind a hard dependency, and never let a failed binder call crash the app.
 - A write that the car does not confirm must not snap the slider back to the old value: `SystemController` keeps the requested level for a 1.6 s settle window, then marks it unconfirmed (the card shows `25%?`) until the read changes. Do not restore the old immediate read-back revert; that is the "it always goes back" bug on units whose read does not follow writes.
 - A write that the car does not confirm must not snap the slider back to the old value: `SystemController` keeps the requested level for a 1.6 s settle window, then marks it unconfirmed (the card shows `25%?`) until the read changes. Do not restore the old immediate read-back revert; that is the "it always goes back" bug on units whose read does not follow writes.
 - `FLAG_KEEP_SCREEN_ON` is controlled by `DisplayController` from `display.keepScreenOn` (default on) through `SystemBridge`; do not hard-code it in `MainActivity` or move it to a wake lock.
 - `FLAG_KEEP_SCREEN_ON` is controlled by `DisplayController` from `display.keepScreenOn` (default on) through `SystemBridge`; do not hard-code it in `MainActivity` or move it to a wake lock.
 - The Music and Jellyfin equalizers are exclusive. The Jellyfin tile animates only while `JellyfinPlaybackController.playing`; the Music tile animates only when the system reports media playing, Jellyfin is not playing, and the active system session is not CarDash itself (`system.media.packageName != appPackageName`). The package guard prevents the Music tile flashing while a Jellyfin pause propagates through the 900 ms system poll. Jellyfin title/progress come from the native playback controller even without notification access; other apps use the notification-listener component and active MediaSession. Never read or store notification content.
 - The Music and Jellyfin equalizers are exclusive. The Jellyfin tile animates only while `JellyfinPlaybackController.playing`; the Music tile animates only when the system reports media playing, Jellyfin is not playing, and the active system session is not CarDash itself (`system.media.packageName != appPackageName`). The package guard prevents the Music tile flashing while a Jellyfin pause propagates through the 900 ms system poll. Jellyfin title/progress come from the native playback controller even without notification access; other apps use the notification-listener component and active MediaSession. Never read or store notification content.

+ 2 - 1
README.md

@@ -465,7 +465,8 @@ volume buttons, and includes the 1.2.4 album redesign, the 1.2.3
 recents/normal-app work, the FYT/Syu MCU volume bridge, the no-snap-back volume
 recents/normal-app work, the FYT/Syu MCU volume bridge, the no-snap-back volume
 handling, the streaming-quality setting, Favorites, the playing-album Home
 handling, the streaming-quality setting, Favorites, the playing-album Home
 shortcut and the Jellyfin progress-duration fallback. The emulator has verified
 shortcut and the Jellyfin progress-duration fallback. The emulator has verified
-the in-app update path; the MCU volume path still needs the real-car test.
+the in-app update path, and the MCU volume path is verified on the car: the
+on-screen slider and the car's own volume control now agree.
 
 
 ## Troubleshooting the emulator
 ## Troubleshooting the emulator
 
 

+ 3 - 0
docs/IMPLEMENTATION_PLAN.md

@@ -484,3 +484,6 @@ Android (Kotlin)
   volume card now prefers the FYT/Syu MCU master level, keeps an unconfirmed
   volume card now prefers the FYT/Syu MCU master level, keeps an unconfirmed
   write instead of snapping back, and exposes the control source in diagnostics.
   write instead of snapping back, and exposes the control source in diagnostics.
   149 tests pass; release `releases/cardash-android-1.2.2.apk`.
   149 tests pass; release `releases/cardash-android-1.2.2.apk`.
+- 2026-11-01: Verified the FYT/Syu MCU volume bridge on the real car (Android 13
+  Chinese firmware): the on-screen slider changes the amplifier, follows the
+  car's own volume control, and no longer snaps back to 100%. No code change.