Fatih'sMG4 — ABRP telemetry for an MG4 EH32 on SWI69
A fork of malys/EVABRPUploader (itself a fork of Leon Kernan's ABRP_Uploader) carrying the changes that make it work on this car. History starts here: the tree is what matters, and the upstream projects are where the earlier work belongs. EVHardware is vendored rather than tracked as a submodule, so one clone builds. Telemetry. SOC, battery power and range read as unavailable on SWI69 because the vendor fallbacks were gated to SWI68 alone, while the property ids they use are the ones this car publishes — the gates now admit SWI69. Tyre pressure, the odometer and charge status come from the vendor block too, since the generic properties for all three are declared here and never publish. Tyre pressure is confirmed on the vehicle; the other two are not yet. Vehicle page. Every signal the car answers, in a table. One that it does not publish shows a dash: an unimplemented VHAL property returns zero, and "0 °C" would read as a measurement. Wi-Fi page. Joins a network the unit already has saved, so a phone hotspot does not need a trip into Settings on every drive. Tried on the upload tick and from a button, skipped while already associated. This leans on the unit being API 28 and the build being platform-signed — getConfiguredNetworks and enableNetwork are closed to ordinary apps from API 29 — and fails quietly where that does not hold. The OTA updater points at this repository. An APK from upstream is signed with a different key, which Android will not install over a platform-signed build. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
<!-- GENERATED by CatalogueDocTest; do not edit by hand. -->
|
||||
|
||||
# The EVTasker catalogue
|
||||
|
||||
Every condition a rule can test and every action it can run, straight out of `ConditionType` and `ActionType`. *Firmware* is what the entry is annotated for; "any" means it depends on no vehicle firmware at all, not that it needs nothing — a notification still needs the permission, a call still needs a paired phone. The car's own Diagnostic screen stays the only answer for the car in front of you.
|
||||
|
||||
## Conditions
|
||||
|
||||
### Context
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Bluetooth phone connected | `BT_DEVICE_CONNECTED` | a paired phone | any |
|
||||
| Any Bluetooth device connected | `ANY_BT_CONNECTED` | on / off | any |
|
||||
| Phone on board (Bluetooth) | `BT_DEVICE_ONBOARD` | a paired phone | any |
|
||||
| Bluetooth hands-free phone | `BT_DEVICE_HANDSFREE` | a paired phone | any |
|
||||
| Time of day | `TIME_OF_DAY` | a start and an end time | any |
|
||||
| Day of week | `DAY_OF_WEEK` | weekdays | any |
|
||||
| Exact date | `DATE` | a calendar date | any |
|
||||
| Firmware generation | `FIRMWARE_GEN` | a list the app fills in | any |
|
||||
| Near a place | `LOCATION_WITHIN` | a point and a radius (m) | any |
|
||||
| Physical buttons | `PHYSICAL_BUTTON` | a button, short or long press | any |
|
||||
| Wi-Fi network | `WIFI_SSID` | free text | any |
|
||||
| Call in progress | `IN_CALL` | on / off | any |
|
||||
| Drive duration | `DRIVE_DURATION` | 0…600 min (=, <, >) | any |
|
||||
| Random chance | `RANDOM_CHANCE` | 1…100 % | any |
|
||||
| Doors locked | `DOORS_LOCKED` | on / off | SWI68, SWI165 |
|
||||
| Front door open | `FRONT_DOOR_OPEN` | on / off | SWI133 |
|
||||
| Data used today | `DATA_USED_TODAY` | 0…100000 MB (=, <, >) | any |
|
||||
| Data used this month | `DATA_USED_MONTH` | 0…100000 MB (=, <, >) | any |
|
||||
|
||||
### Environment
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Outside temperature | `OUTSIDE_TEMP` | -30…50 °C (=, <, >) | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Weather | `WEATHER_NOW` | Clear, Cloudy, Rain, Snow, Thunderstorm, Fog, Wind | any |
|
||||
|
||||
### Driving
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Ignition state | `IGNITION_STATE` | Locked, Off, Accessory, Running, Starting | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Gear in P | `IN_PARK` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Speed | `SPEED` | 0…200 km/h (=, <, >) | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Drive mode | `DRIVE_MODE` | Eco, Normal, Sport, Snow, Custom | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Regeneration | `REGEN_LEVEL` | Low, Medium, High, Adaptive, Off, One pedal | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Odometer | `ODOMETER` | 0…500000 km (=, <, >) | any |
|
||||
| Energy saving | `ENERGY_SAVING` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
|
||||
### Energy
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Battery level | `BATTERY_LEVEL` | 0…100 % (=, <, >) | SWI68, SWI165 |
|
||||
| Charging | `CHARGING` | on / off | SWI68, SWI165 |
|
||||
| Charge limit | `CHARGE_LIMIT` | 0…100 % (=, <, >) | SWI68, SWI165 |
|
||||
| Charging state | `CHARGING_STATUS` | Unplugged, Charging (AC), Charging (DC), Plugged in, not charging, Charge complete, Charging fault | SWI68, SWI165 |
|
||||
| Scheduled charging on | `CHARGE_SCHEDULE_ENABLED` | on / off | SWI68, SWI165 |
|
||||
| Charging starts at | `CHARGE_WINDOW_START` | a time of day (=, <, >) | SWI68, SWI165 |
|
||||
| Charging stops at | `CHARGE_WINDOW_STOP` | a time of day (=, <, >) | SWI68, SWI165 |
|
||||
| Remaining range | `RANGE_ESTIMATE` | 0…600 km (=, <, >) | SWI68, SWI165 |
|
||||
| Battery pre-heating on | `BATTERY_PREHEAT` | on / off | SWI68, SWI165 |
|
||||
|
||||
### Climate
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Climate on | `CLIMATE_ON` | on / off | SWI68, SWI165 |
|
||||
| Air conditioning on | `AC_ON` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Climate AUTO on | `HVAC_AUTO` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Air recirculation on | `RECIRC` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Fan speed | `FAN_SPEED` | 0…11 (=, <, >) | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Set temperature | `TEMPERATURE_SET` | 17…33 °C (=, <, >) | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Passenger temperature | `PASSENGER_TEMP` | 17…33 °C (=, <, >) | SWI68, SWI165 |
|
||||
| ECON mode on | `ECON_MODE` | on / off | SWI68, SWI165 |
|
||||
| Windscreen defroster on | `FRONT_DEFROST` | on / off | SWI68, SWI165 |
|
||||
| Rear window defroster on | `REAR_DEFROST` | on / off | SWI68, SWI165 |
|
||||
| A window is open | `WINDOW_OPEN` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Window opening | `WINDOW_POSITION` | 0…100 % (=, <, >) | SWI68, SWI165 |
|
||||
| Driver window opening | `WINDOW_DRIVER` | 0…100 % (=, <, >) | SWI68, SWI165 |
|
||||
| Passenger window opening | `WINDOW_PASSENGER` | 0…100 % (=, <, >) | SWI68, SWI165 |
|
||||
| Rear left window opening | `WINDOW_REAR_LEFT` | 0…100 % (=, <, >) | SWI68, SWI165 |
|
||||
| Rear right window opening | `WINDOW_REAR_RIGHT` | 0…100 % (=, <, >) | SWI68, SWI165 |
|
||||
|
||||
### Comfort
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Left seat heating | `SEAT_HEAT_LEFT` | 0…3 (=, <, >) | SWI133, SWI68, SWI165 |
|
||||
| Right seat heating | `SEAT_HEAT_RIGHT` | 0…3 (=, <, >) | SWI133, SWI68, SWI165 |
|
||||
| Steering wheel heating | `STEERING_HEAT` | on / off | SWI133, SWI68, SWI165 |
|
||||
| Screen brightness | `SCREEN_BRIGHTNESS` | 5…100 % (=, <, >) | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
|
||||
### Audio
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Media playing | `MEDIA_PLAYING` | on / off | any |
|
||||
| Radio playing | `RADIO_PLAYING` | on / off | SWI68, SWI165 |
|
||||
| Media volume | `MEDIA_VOLUME` | 0…max (=, <, >) | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
|
||||
### Driver assistance
|
||||
|
||||
| Condition | Entry | Tested against | Firmware |
|
||||
|---|---|---|---|
|
||||
| Emergency braking (AEB) | `AEB_ENABLED` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| AEB mode | `AEB_MODE` | Alert only, Alert + braking | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| AEB sensitivity | `AEB_SENSITIVITY` | Low, Standard, High | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| ELK mode | `ELK_MODE` | Off, Warning (LDW), Assist (LDP), Emergency keeping (ELK) | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| ELK sensitivity | `ELK_SENSITIVITY` | Low, Standard, High | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| ACC / TJA mode | `ACC_TJA_MODE` | Off, Adaptive cruise (ACC), Traffic jam assist (TJA) | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Speed limiter | `LIMITER_MODE` | Off, Manual, Intelligent | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Traffic sign recognition (TSR) | `TSR` | on / off | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Overspeed alarm | `OVERSPEED_ALARM` | on / off | SWI133, SWI132 |
|
||||
| Speed limit tone | `SPEED_LIMIT_TONE` | on / off | SWI133, SWI132 |
|
||||
| ADAS sound warning | `SOUND_WARNING` | on / off | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
|
||||
A reading the car does not answer makes the rule **not evaluable**: it does not fire, and it does not count as false.
|
||||
|
||||
## Actions
|
||||
|
||||
### Profile
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Apply a profile | `APPLY_PROFILE` | an EVProfile profile | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Ask for a profile | `SHOW_PROFILE_PICKER` | — | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
|
||||
### Driving
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Drive mode | `SET_DRIVE_MODE` | Eco, Normal, Sport, Snow, Custom | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Regeneration | `SET_REGEN_LEVEL` | Low, Medium, High, Adaptive, Off, One pedal | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| One pedal driving | `SET_ONE_PEDAL` | on / off | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Energy saving | `SET_ENERGY_SAVING` | on / off | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
|
||||
### Comfort
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Left seat heating | `SET_SEAT_HEAT_LEFT` | 0…3 | — | SWI133, SWI68, SWI165 |
|
||||
| Right seat heating | `SET_SEAT_HEAT_RIGHT` | 0…3 | — | SWI133, SWI68, SWI165 |
|
||||
| Steering wheel heating | `SET_STEERING_HEAT` | on / off | — | SWI133, SWI68, SWI165 |
|
||||
| Screen brightness | `SET_SCREEN_BRIGHTNESS` | 5…100 % | — | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
|
||||
### Climate
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Climate on/off | `SET_CLIMATE_POWER` | on / off | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Cabin temperature | `SET_CABIN_TEMP` | 17…33 °C | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Passenger temperature | `SET_PASSENGER_TEMP` | 17…33 °C | — | SWI68, SWI165 |
|
||||
| Air conditioning | `SET_AC` | on / off | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| ECON mode | `SET_ECON` | on / off | — | SWI68, SWI165 |
|
||||
| Climate AUTO | `SET_CLIMATE_AUTO` | on / off | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Air recirculation | `SET_RECIRCULATION` | on / off | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Fan level | `SET_FAN_LEVEL` | 0…11 | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Windscreen defroster | `SET_FRONT_DEFROST` | on / off | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Rear window defroster | `SET_REAR_DEFROST` | on / off | — | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| All windows ⚠️ | `SET_WINDOWS` | Closed, Open | yes | SWI68, SWI165 |
|
||||
| Driver window ⚠️ | `SET_WINDOW_DRIVER` | Closed, Open | yes | SWI68, SWI165 |
|
||||
| Passenger window ⚠️ | `SET_WINDOW_PASSENGER` | Closed, Open | yes | SWI68, SWI165 |
|
||||
| Rear left window ⚠️ | `SET_WINDOW_REAR_LEFT` | Closed, Open | yes | SWI68, SWI165 |
|
||||
| Rear right window ⚠️ | `SET_WINDOW_REAR_RIGHT` | Closed, Open | yes | SWI68, SWI165 |
|
||||
| Door locks | `SET_DOOR_LOCK` | on / off | — | SWI68, SWI165 |
|
||||
|
||||
### Energy
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Charge limit | `SET_CHARGE_LIMIT` | 40…100 % | — | SWI68, SWI165 |
|
||||
| Allow charging | `SET_CHARGING_ENABLED` | on / off | — | SWI68, SWI165 |
|
||||
| Scheduled charging | `SET_CHARGE_SCHEDULE` | on / off | — | SWI68, SWI165 |
|
||||
| Charging window | `SET_CHARGE_WINDOW` | a start and an end time | — | SWI68, SWI165 |
|
||||
| Battery pre-heating | `SET_BATTERY_PREHEAT` | on / off | — | SWI68, SWI165 |
|
||||
|
||||
### Audio
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Media volume | `SET_MEDIA_VOLUME` | 0…max | — | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Media volume, step | `ADJUST_MEDIA_VOLUME` | -30…30 | — | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Left / right balance | `SET_AUDIO_BALANCE` | -9…9 | — | SWI69, SWI131, SWI132 |
|
||||
| Front / rear fader | `SET_AUDIO_FADER` | -9…9 | — | SWI69, SWI131, SWI132 |
|
||||
| Tone | `SET_TONE_CONTROL` | -9…9 | — | SWI69, SWI131, SWI132 |
|
||||
| Bose sound profile | `SET_BOSE_SOUND_TYPE` | 0…3 | — | SWI69, SWI131, SWI132 |
|
||||
| 3D effect | `SET_3D_EFFECT` | 0…3 | — | SWI69, SWI131, SWI132 |
|
||||
| Speed-adaptive volume | `SET_SPEED_VOLUME` | 0…3 | — | SWI69, SWI131, SWI132 |
|
||||
| Play the radio | `PLAY_RADIO` | — | — | SWI68, SWI165 |
|
||||
| Radio band and station | `TUNE_RADIO` | band (AM, FM, DAB), frequency, play | — | SWI68, SWI165 |
|
||||
| Next radio station | `RADIO_NEXT_STATION` | — | — | SWI68, SWI165 |
|
||||
| Previous radio station | `RADIO_PREV_STATION` | — | — | SWI68, SWI165 |
|
||||
| Silence the radio | `PAUSE_RADIO` | — | — | SWI68, SWI165 |
|
||||
| Radio play/pause | `RADIO_PLAY_PAUSE` | — | — | SWI68, SWI165 |
|
||||
| Open the radio screen | `OPEN_RADIO_SCREEN` | — | yes | SWI68, SWI165 |
|
||||
|
||||
### Driver assistance
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Emergency braking (AEB) | `SET_AEB_ENABLED` | on / off | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| AEB mode | `SET_AEB_MODE` | Alert only, Alert + braking | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| AEB sensitivity | `SET_AEB_SENSITIVITY` | Low, Standard, High | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Stability control (ESC) | `SET_ESC` | on / off | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Drowsiness warning | `SET_DROWSINESS` | on / off | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Drowsiness warning sensitivity | `SET_DROWSINESS_SENSITIVITY` | Low, Standard, High | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| ELK mode | `SET_ELK_MODE` | Off, Warning (LDW), Assist (LDP), Emergency keeping (ELK) | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| ELK sensitivity | `SET_ELK_SENSITIVITY` | Low, Standard, High | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| ACC / TJA mode | `SET_ACC_TJA_MODE` | Off, Adaptive cruise (ACC), Traffic jam assist (TJA) | yes | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Speed limiter | `SET_LIMITER_MODE` | Off, Manual, Intelligent | yes | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Traffic sign recognition (TSR) | `SET_TSR` | on / off | yes | SWI133, SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Overspeed alarm | `SET_OVERSPEED_ALARM` | on / off | yes | SWI133, SWI132 |
|
||||
| Speed limit tone | `SET_SPEED_LIMIT_TONE` | on / off | yes | SWI133, SWI132 |
|
||||
| ADAS sound warning | `SET_SOUND_WARNING` | on / off | yes | SWI68, SWI165, SWI69, SWI131, SWI132 |
|
||||
| Lane departure sound warning | `SET_LAS_WARNING_SOUND` | on / off | — | SWI132 |
|
||||
| Lane departure steering vibration | `SET_LAS_WARNING_VIBRATION` | on / off | — | SWI132 |
|
||||
|
||||
### System
|
||||
|
||||
| Action | Entry | Asks for | When stopped only | Firmware |
|
||||
|---|---|---|:--:|---|
|
||||
| Launch an app | `LAUNCH_APP` | an installed app | — | any |
|
||||
| Show a notification | `SHOW_NOTIFICATION` | free text | — | any |
|
||||
| Speak a message | `SPEAK_TEXT` | free text | — | any |
|
||||
| Navigate to | `NAVIGATE_TO` | an address or coordinates | — | any |
|
||||
| Ask for confirmation | `ASK_CONFIRM` | a question, and how long to wait | — | any |
|
||||
| Send a text message | `SEND_SMS` | a number or a contact, and a message | — | any |
|
||||
| Enable a rule | `ENABLE_RULE` | one of your rules | — | any |
|
||||
| Disable a rule | `DISABLE_RULE` | one of your rules | — | any |
|
||||
| Media control | `MEDIA_CONTROL` | Play / pause, Next track, Previous track | — | any |
|
||||
| Bluetooth | `SET_BLUETOOTH` | on / off | — | any |
|
||||
| Wi-Fi | `SET_WIFI` | on / off | — | any |
|
||||
| Call webhook | `WEBHOOK` | a URL, and an optional body | — | any |
|
||||
| Wait | `DELAY` | 1…60 s | — | any |
|
||||
| Call | `CALL_NUMBER` | a number or a contact | — | SWI68, SWI165 |
|
||||
| Call a contact | `CALL_CONTACT` | a number or a contact | — | SWI68, SWI165 |
|
||||
|
||||
⚠️ — the firmware carries the property, but nothing establishes that writing it does anything (`ActionType.writeProven`). Those actions are hidden from the editor and refused by the executor until one is observed to work.
|
||||
|
||||
The per-generation grid is in [firmware-matrix.md](firmware-matrix.md), generated from the same annotations.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Public energy-signal candidates
|
||||
|
||||
Reviewed 2026-08-28 for CP-004. This review uses only public AOSP catalogues and the
|
||||
project's existing runtime read seam. It does not use proprietary artifacts or non-public
|
||||
property catalogues.
|
||||
|
||||
## Safety and validation boundary
|
||||
|
||||
Every entry below is read-only and starts with `validated: no`. A public property number proves
|
||||
only that AOSP assigned a number and semantics; it does not prove that an MG4 VHAL implements or
|
||||
publishes it. No candidate may enter `EnergySnapshot`, a production fallback or a stable UI until
|
||||
CP-003 records availability, unit, scale, sign and update cadence for every supported firmware
|
||||
generation. An unavailable or non-finite read stays null.
|
||||
|
||||
## Public catalogue findings
|
||||
|
||||
| Signal | Public declaration | Type / area / unit / mode | AOSP coverage | EVSuite disposition | validated |
|
||||
|---|---|---|---|---|---|
|
||||
| `EV_CURRENT_BATTERY_CAPACITY` (`291504909`, `0x1160030D`) | [AOSP snapshot `c80b787`](https://android.googlesource.com/platform/packages/services/Car/+/c80b787d499243d120c2738eb68e7c0520c7238d/car-lib/src/android/car/VehiclePropertyIds.java) | Float / global / Wh / on-change / read-only | Public post-AAOS 9 API; the declaration requires Car UDC with Android 13 or later | Highest-value new candidate: status-aware probe in unstable evidence capture only | no |
|
||||
| `EV_BATTERY_AVERAGE_TEMPERATURE` (`291504910`, `0x1160030E`) | [AOSP change `5b96f99`](https://android.googlesource.com/platform/packages/services/Car/+/5b96f99271e9209774a312c8f0fc1279dccf0678/car-lib/src/android/car/VehiclePropertyIds.java) | Float / global / °C / continuous / read-only | Added to the public API in December 2023 | Already read by the CP-001 baseline as nullable battery temperature; CP-004 adds no duplicate candidate | no |
|
||||
| `EV_BATTERY_INSTANTANEOUS_CHARGE_RATE` (`291504908`, `0x1160030C`) | [Android 9 AOSP snapshot `8686c86`](https://android.googlesource.com/platform/packages/services/Car/+/8686c86b38a590712412fea2dd083181aceba4f2/car-lib/src/android/car/VehiclePropertyIds.java) | Float / global / mW / continuous / read-only | Android 9 public catalogue | Existing CP-001 battery-power input; its live scale and sign still require CP-003 evidence | no |
|
||||
|
||||
All cited files are Copyright Android Open Source Project and licensed Apache-2.0 at the cited
|
||||
commit. The review records public declarations, not copied implementation code. Vehicle coverage
|
||||
remains unknown for SWI68, SWI69, SWI131, SWI132, SWI133 and SWI165 until CP-003 runs on each one.
|
||||
|
||||
## Explicit negative results
|
||||
|
||||
| Requested quantity | Public catalogue result | Consequence |
|
||||
|---|---|---|
|
||||
| HVAC, compressor or PTC electrical power | No Android 9 or reviewed later public vehicle property. `HVAC_POWER_ON` is only a boolean subsystem state. | Climate energy can only be estimated from validated pack power and controlled trials. |
|
||||
| Battery-heater power | No public power or energy property found. Battery temperature is a temperature, not heater consumption. | No direct measurement candidate. |
|
||||
| DC-DC or accessory load | No public power or energy property found. | No direct measurement candidate. |
|
||||
| Cumulative battery discharge | No public cumulative counter found. `EV_BATTERY_LEVEL` is current stored energy. | Integrate validated instantaneous power, retaining uncertainty and gaps. |
|
||||
| Cumulative regeneration | No public cumulative counter found. Later regenerative-braking properties describe a state, not recovered energy. | Integrate only after CP-003 proves the power sign convention. |
|
||||
| Per-trip energy | No public per-trip energy property found. | EVSuite trip totals remain derived from validated samples. |
|
||||
|
||||
The search deliberately stops here: sweeping arbitrary property ids would produce ambiguous data
|
||||
and broaden the runtime surface without provenance.
|
||||
|
||||
## Probe wiring
|
||||
|
||||
`EV_CURRENT_BATTERY_CAPACITY` is read through the same status-aware reflected
|
||||
`CarPropertyManager.getProperty` path as existing telemetry. The read is explicitly branched over
|
||||
the supported firmware generations and returns null for unknown firmware, unavailable status,
|
||||
negative values, exceptions and non-finite values. It is exposed only by
|
||||
`EnergyTelemetryReader.readEvidence()` and recorded as
|
||||
`candidate.evCurrentBatteryCapacityWh`; ordinary `read()` and `EnergySnapshot` are unchanged.
|
||||
@@ -0,0 +1,161 @@
|
||||
<!-- GENERATED by FirmwareMatrix.render(); do not edit by hand. -->
|
||||
|
||||
### Conditions
|
||||
|
||||
| Entry | SWI133 | SWI68 | SWI165 | SWI69 | SWI131 | SWI132 |
|
||||
|---|:--:|:--:|:--:|:--:|:--:|:--:|
|
||||
| BT_DEVICE_CONNECTED | — | — | — | — | — | — |
|
||||
| ANY_BT_CONNECTED | — | — | — | — | — | — |
|
||||
| BT_DEVICE_ONBOARD | — | — | — | — | — | — |
|
||||
| BT_DEVICE_HANDSFREE | — | — | — | — | — | — |
|
||||
| TIME_OF_DAY | — | — | — | — | — | — |
|
||||
| DAY_OF_WEEK | — | — | — | — | — | — |
|
||||
| DATE | — | — | — | — | — | — |
|
||||
| FIRMWARE_GEN | — | — | — | — | — | — |
|
||||
| LOCATION_WITHIN | — | — | — | — | — | — |
|
||||
| PHYSICAL_BUTTON | — | — | — | — | — | — |
|
||||
| WIFI_SSID | — | — | — | — | — | — |
|
||||
| IN_CALL | — | — | — | — | — | — |
|
||||
| DRIVE_DURATION | — | — | — | — | — | — |
|
||||
| RANDOM_CHANCE | — | — | — | — | — | — |
|
||||
| WEATHER_NOW | — | — | — | — | — | — |
|
||||
| ODOMETER | — | — | — | — | — | — |
|
||||
| MEDIA_PLAYING | — | — | — | — | — | — |
|
||||
| DATA_USED_TODAY | — | — | — | — | — | — |
|
||||
| DATA_USED_MONTH | — | — | — | — | — | — |
|
||||
| OUTSIDE_TEMP | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| IGNITION_STATE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| IN_PARK | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SPEED | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| DRIVE_MODE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| REGEN_LEVEL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| ENERGY_SAVING | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| BATTERY_LEVEL | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CHARGING | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CHARGE_LIMIT | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CHARGING_STATUS | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CHARGE_SCHEDULE_ENABLED | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CHARGE_WINDOW_START | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CHARGE_WINDOW_STOP | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| RANGE_ESTIMATE | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| BATTERY_PREHEAT | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CLIMATE_ON | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| AC_ON | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| HVAC_AUTO | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| RECIRC | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| FAN_SPEED | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| TEMPERATURE_SET | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| PASSENGER_TEMP | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| ECON_MODE | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| FRONT_DEFROST | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| REAR_DEFROST | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| WINDOW_OPEN | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| WINDOW_POSITION | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| WINDOW_DRIVER | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| WINDOW_PASSENGER | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| WINDOW_REAR_LEFT | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| WINDOW_REAR_RIGHT | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| DOORS_LOCKED | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| FRONT_DOOR_OPEN | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| SEAT_HEAT_LEFT | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SEAT_HEAT_RIGHT | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| STEERING_HEAT | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SCREEN_BRIGHTNESS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| RADIO_PLAYING | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| MEDIA_VOLUME | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| AEB_ENABLED | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| AEB_MODE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| AEB_SENSITIVITY | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| ELK_MODE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| ELK_SENSITIVITY | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| ACC_TJA_MODE | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| LIMITER_MODE | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| TSR | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| OVERSPEED_ALARM | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| SPEED_LIMIT_TONE | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| SOUND_WARNING | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
|
||||
|
||||
### Actions
|
||||
|
||||
| Entry | SWI133 | SWI68 | SWI165 | SWI69 | SWI131 | SWI132 |
|
||||
|---|:--:|:--:|:--:|:--:|:--:|:--:|
|
||||
| LAUNCH_APP | — | — | — | — | — | — |
|
||||
| SHOW_NOTIFICATION | — | — | — | — | — | — |
|
||||
| SPEAK_TEXT | — | — | — | — | — | — |
|
||||
| NAVIGATE_TO | — | — | — | — | — | — |
|
||||
| ASK_CONFIRM | — | — | — | — | — | — |
|
||||
| SEND_SMS | — | — | — | — | — | — |
|
||||
| ENABLE_RULE | — | — | — | — | — | — |
|
||||
| DISABLE_RULE | — | — | — | — | — | — |
|
||||
| MEDIA_CONTROL | — | — | — | — | — | — |
|
||||
| SET_BLUETOOTH | — | — | — | — | — | — |
|
||||
| SET_WIFI | — | — | — | — | — | — |
|
||||
| WEBHOOK | — | — | — | — | — | — |
|
||||
| DELAY | — | — | — | — | — | — |
|
||||
| APPLY_PROFILE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SHOW_PROFILE_PICKER | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_DRIVE_MODE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_REGEN_LEVEL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_ONE_PEDAL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_ENERGY_SAVING | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_SEAT_HEAT_LEFT | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_SEAT_HEAT_RIGHT | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_STEERING_HEAT | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_SCREEN_BRIGHTNESS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_CLIMATE_POWER | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_CABIN_TEMP | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_PASSENGER_TEMP | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_AC | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_ECON | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_CLIMATE_AUTO | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_RECIRCULATION | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_FAN_LEVEL | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_FRONT_DEFROST | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_REAR_DEFROST | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_WINDOWS ⚠️ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_WINDOW_DRIVER ⚠️ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_WINDOW_PASSENGER ⚠️ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_WINDOW_REAR_LEFT ⚠️ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_WINDOW_REAR_RIGHT ⚠️ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_DOOR_LOCK | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_CHARGE_LIMIT | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_CHARGING_ENABLED | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_CHARGE_SCHEDULE | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_CHARGE_WINDOW | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_BATTERY_PREHEAT | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_MEDIA_VOLUME | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| ADJUST_MEDIA_VOLUME | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_AUDIO_BALANCE | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| SET_AUDIO_FADER | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| SET_TONE_CONTROL | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| SET_BOSE_SOUND_TYPE | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| SET_3D_EFFECT | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| SET_SPEED_VOLUME | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| PLAY_RADIO | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| TUNE_RADIO | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| RADIO_NEXT_STATION | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| RADIO_PREV_STATION | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| PAUSE_RADIO | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| RADIO_PLAY_PAUSE | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| OPEN_RADIO_SCREEN | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| SET_AEB_ENABLED | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_AEB_MODE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_AEB_SENSITIVITY | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_ESC | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_DROWSINESS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_DROWSINESS_SENSITIVITY | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_ELK_MODE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_ELK_SENSITIVITY | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_ACC_TJA_MODE | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_LIMITER_MODE | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_TSR | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_OVERSPEED_ALARM | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| SET_SPEED_LIMIT_TONE | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| SET_SOUND_WARNING | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| SET_LAS_WARNING_SOUND | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| SET_LAS_WARNING_VIBRATION | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| CALL_NUMBER | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
| CALL_CONTACT | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ |
|
||||
|
||||
⚠️ — the firmware carries the property, but nothing establishes that writing it has any effect (`ActionType.writeProven`). These actions are hidden from the editors and refused by the executors until one is observed to work.
|
||||
@@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="120" viewBox="0 0 480 120" role="img" aria-label="EVHardware">
|
||||
<rect x="1" y="1" width="478" height="118" rx="16" fill="#12161a" stroke="#232a31" stroke-width="2"/>
|
||||
<!-- icon: shared launcher style — vehicle hub with four connections -->
|
||||
<g transform="translate(31,27)" fill="none" stroke="#F4F7FA" stroke-width="5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="32" cy="32" r="16"/>
|
||||
<path d="M32 2V12 M32 52V62 M2 32H12 M52 32H62"/>
|
||||
</g>
|
||||
<circle cx="63" cy="59" r="5" fill="#E0424C"/>
|
||||
<text x="128" y="56" font-family="'Segoe UI',Roboto,Helvetica,Arial,sans-serif" font-size="34" font-weight="700" fill="#eef2f5">EV<tspan fill="#E0424C">Hardware</tspan></text>
|
||||
<text x="129" y="82" font-family="'Segoe UI',Roboto,Helvetica,Arial,sans-serif" font-size="15" fill="#9aa4ad">Shared vehicle-access layer · safety gate · catalogue</text>
|
||||
<text x="129" y="101" font-family="'Segoe UI',Roboto,Helvetica,Arial,sans-serif" font-size="12" fill="#5b6670">SAIC MG4 · AAOS 9 · MT2712</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,102 @@
|
||||
# Radio action gap — community references vs the EVSuite catalogue
|
||||
|
||||
Decides every radio candidate raised by the 2026-08-28 community baseline (CR-020). The
|
||||
comparison is against what `SaicRadio`, `SaicMediaPlayer` and `ActionType` already do, not
|
||||
against the initial community audit, which under-counted the existing catalogue.
|
||||
|
||||
**Provenance.** CarMediaPlayer (MIT) and the community DAB+ fix (no explicit license at the
|
||||
baseline review, and it replaces an OEM application) are read as *behaviour* only. No code,
|
||||
resource or replacement strategy from either is used here. What the head unit's own radio
|
||||
app does is the evidence that matters, and the binding contract below comes from the vendor
|
||||
SDK already documented in `SaicMedia.kt`.
|
||||
|
||||
## What already existed
|
||||
|
||||
| Capability | Where | Reachable from a rule |
|
||||
| --- | --- | --- |
|
||||
| Play / resume the tuner (`srcPlayRadio`, tx 27) | `SaicRadio.play` | `PLAY_RADIO` |
|
||||
| Tune FM/AM by frequency (tx 8) | `SaicRadio.tune` | `TUNE_RADIO` |
|
||||
| Next / previous station (tx 13 / 14) | `SaicRadio.nextStation` / `previousStation` | `RADIO_NEXT_STATION`, `RADIO_PREV_STATION` |
|
||||
| Read the tuner's play state (tx 19, `RadioBean.state`) | `SaicRadio.isPlaying` | — (internal) |
|
||||
| Pause / silence the tuner (`srcPauseRadio`, tx 28) | `SaicRadio.pause` | — (internal) |
|
||||
| Open the radio screen (tx 26) | `SaicRadio.openScreen` | — (internal) |
|
||||
| Play/pause of *whatever owns the audio* | `SaicMediaPlayer.command` | `MEDIA_CONTROL` |
|
||||
|
||||
Three primitives existed in the library with no way to ask for them from a rule. That, not
|
||||
a missing service call, is the actual gap.
|
||||
|
||||
## Decisions
|
||||
|
||||
| # | Candidate | Decision | Why |
|
||||
| --- | --- | --- | --- |
|
||||
| A | Pause / stop the radio | **add** — `PAUSE_RADIO` | `srcPauseRadio` is implemented and unreachable. `MEDIA_CONTROL` is not a substitute: it addresses whichever source owns the audio, so it silences Bluetooth when Bluetooth is playing. "Silence the tuner" was not expressible. |
|
||||
| B | Explicit radio play/pause toggle on readable state | **add** — `RADIO_PLAY_PAUSE` | One shortcut for a driver who wants the tuner specifically, whatever the current source. Built on `isPlaying()` (`RadioBean.state`), because `AudioManager.isMusicActive` is **false while the radio plays** — a toggle driven by it would send "play" to a playing radio forever. Unknown state fails closed (see below). |
|
||||
| C | Open the radio screen | **add, gated** — `OPEN_RADIO_SCREEN` | `startRadioActivity` is implemented and unreachable. It is the one radio action that is not audio-only: throwing a full-screen app in front of a driver at speed is a distraction, so it takes the standstill gate and is refused when speed is unreadable. |
|
||||
| D | Select a band | **added** (2026-08-29, reversed), **merged into `TUNE_RADIO`** (2026-09-03) | Originally rejected because the binding contract exposes no band-only call. The owner asked for DAB support anyway, and the rejection turned out to be answering the wrong question: a band action does not need a band-only *call*, because `tune(band, frequencyKhz)` already carries the band as its first argument. `SELECT_RADIO_BAND` composes what is established — read the current band from `RadioBean`, tune into the requested one — and guesses no transaction code. The frequency it lands on is the station this car was last heard on for that band (`RadioBandMemory`), or the band floor followed by one `nextStation()` when it has never been there, so it does not strand the driver on an empty frequency. It shipped as its own `SELECT_RADIO_BAND` entry and was folded into `TUNE_RADIO` a week later — see *Merge* below. |
|
||||
| E | Select a DAB service | **reject** (unchanged) | A DAB service is addressed by ensemble id + service id, not by a frequency, and neither is a stable identifier a driver could enter or a rule could store across a re-scan. No on-vehicle evidence establishes a portable contract. DAB is now reachable as a **band** (candidate D, inside `TUNE_RADIO`) and stepped through with `RADIO_NEXT_STATION` / `RADIO_PREV_STATION`; what stays out is selecting one named service directly. A DAB *block* is a real frequency in Band III, which is what a band switch tunes; a DAB *service* is not. |
|
||||
| F | Restore the last audible radio state at ignition | **already covered** | Composition, not a new action: an ignition trigger plus `PLAY_RADIO`, whose `srcPlayRadio` resumes the last station by itself. A persistent service that remembered and re-asserted state would be a background watchdog the app does not have and does not want. |
|
||||
| G | Radio artwork caching, station metadata display | **reject as an action** | Presentation, not automation. A rule cannot usefully "cache artwork"; a screen can show it. If it is ever wanted it belongs to an app's UI, reading `RadioBean`, not to the action catalogue. |
|
||||
| H | Replace or patch the OEM radio APK (the DAB+ fix's strategy) | **reject** | Out of scope by the ticket and by the suite's boundary: EVSuite talks to the vendor services the car ships. It does not swap the car's applications, and the upstream fix carries no license that would permit reuse anyway. |
|
||||
|
||||
## Failure behaviour of what was added
|
||||
|
||||
- **Missing service.** All three call `SaicRadio`, whose `service.binder()` is null when the
|
||||
radio service is absent or its bind has not landed. Every call reports false; the executor
|
||||
turns that into an error rather than a silent success. EVTasker's diagnostic screen answers
|
||||
`NO_VENDOR_SERVICE` for the whole radio family — including `RADIO_NEXT_STATION` and
|
||||
`RADIO_PREV_STATION`, which were answering for the AOSP car layer instead.
|
||||
- **Unreadable play state.** `RADIO_PLAY_PAUSE` reads `isPlaying()` first and sends
|
||||
**nothing** when it answers null: `ToggleResult.STATE_UNKNOWN`, reported as an error with
|
||||
its reason. It does not fall back to "assume playing" the way `SaicMediaPlayer.radioCommand`
|
||||
does — that fallback is right for a media-key shortcut a driver can press twice, and wrong
|
||||
for a rule that fires unattended and would toggle the audio to the state nobody chose.
|
||||
- **Unsupported firmware.** `@SupportedOn(SWI68, SWI165)` on all three, the generations where
|
||||
the radio service is bound. The A9 generations (SWI69, SWI131, SWI132) have no such service;
|
||||
`ActionCompatibility` refuses the action there before it is attempted, and the editor does
|
||||
not offer it.
|
||||
|
||||
## Reversal, 2026-08-29
|
||||
|
||||
Candidate D was reopened at the owner's request after an on-vehicle diagnostic (SWI68). The
|
||||
original rejection assumed a band action required a band-only transaction, and that assumption
|
||||
was wrong: `tune` takes the band as an argument, so the band is reachable through a call that
|
||||
was already proven. The rejection of candidate E stands unchanged — a DAB service still has no
|
||||
identifier stable across a re-scan, and none was guessed.
|
||||
|
||||
## Merge, 2026-09-03
|
||||
|
||||
Candidate D shipped as an action of its own, and that was one entry too many. Band, frequency
|
||||
and playback are three parts of one instruction — "put the radio on FM 103.5 and play it" — and
|
||||
splitting them left each part unable to say the whole thing: `SELECT_RADIO_BAND` could not name
|
||||
a station, `TUNE_RADIO` could not reach DAB, and a driver who wanted both wrote two rows with a
|
||||
delay between them. They are now one entry, `TUNE_RADIO`, carrying the band in `number`, the
|
||||
frequency in `text` and playback in `flag`.
|
||||
|
||||
Nothing about the vehicle contract changed: a frequency still goes through `tune`, a band with
|
||||
no frequency still goes through `selectBand`, and DAB is still reachable only as a band. What
|
||||
changed is which of the two a rule asks for, and that is now read off the rule rather than off
|
||||
which of two entries it picked. `selectBand` gained `andPlay` so that the merged action's
|
||||
"enable radio" switch means the same thing on both paths.
|
||||
|
||||
Two things are refused rather than resolved. A typed frequency that disagrees with the picked
|
||||
band (`AM 103.5` under an FM picker) parses to nothing, as `AM 103.5` already did on its own —
|
||||
two things were said, and silently keeping one is how a rule lands on a station nobody chose.
|
||||
And DAB takes no frequency at all: the editor removes the field rather than accept a number it
|
||||
would have to ignore.
|
||||
|
||||
Rules and exported files that still name `SELECT_RADIO_BAND` are rewritten on load by
|
||||
EVTasker's `LegacyRuleJson`, keeping their band and their playback — the old band switch always
|
||||
took the audio focus, so dropping playback would have silenced a rule that used to make a
|
||||
sound.
|
||||
|
||||
## On-vehicle evidence
|
||||
|
||||
_(pending — CR-020 requires a run. Record, per firmware: `SaicRadio.isAvailable`, whether
|
||||
`isPlaying()` answered on FM, AM and DAB, whether `PAUSE_RADIO` silenced the tuner, whether
|
||||
`RADIO_PLAY_PAUSE` toggled in the direction the state predicted, whether
|
||||
`OPEN_RADIO_SCREEN` was correctly refused while moving, and whether `TUNE_RADIO` reached **DAB**
|
||||
with its frequency left empty and came back to FM on the station it had left.)_
|
||||
|
||||
Availability is evidenced on SWI68: the 2026-08-29 diagnostic reported every radio action
|
||||
`[ OK ]`, with the radio service bound. What is still missing is the behavioural half — that
|
||||
each one does what its label says.
|
||||
Reference in New Issue
Block a user