Documentation

VHAL Property Investigation History & Rationale

Technical record of reverse-engineering findings, decompile analyses, and empirical hardware validations establishing the property mappings documented in field-catalog.md.


1. Climate Control (HVAC) Actuation Mechanics

Airflow Direction Damper Validation

Testing across physical damper modes verified the standard AOSP bitmask representation on property 557846560 (and alias 356517121):

FACE = 1
FLOOR = 2
FACE | FLOOR = 3
DEFROST = 4
DEFROST | FLOOR = 6

2. Cruise Control & Driver Assist State Decoding

Dash Cluster State Progression

Directed differential state sweeps comparing stationary baseline vs. active highway driving established the state values on 557884450 (float) and 557887630 (int):

Vehicle State Property Value Cluster Indicator
OFF 0.0 / 0 Cruise indicator dark
ARMED 1.0 / 1 Cruise icon illuminated (white)
ACTIVE 7.0 / 7 Cruise icon illuminated (green), vehicle regulating speed

3. High-Voltage Energy Flow & Instantaneous Power Analysis

VHAL Energy Flow Properties (ITripData)

Investigation of candidate properties 559982313, 559982315, and 559982316 via decompilation of com.flyme.auto.energy resolved them to:

Percentage Normalization

Empirical testing confirmed that these properties represent a percentage breakdown of cumulative energy consumption rather than instantaneous power: \(ext{Driving \%} + ext{Battery Thermal \%} + ext{Other \%} pprox 100.0\%\) Reads cross-checked identically with the factory “Trip Statistics” UI card (com.flyme.auto.energy.MILEAGESTATISTICS).

Lack of Native VHAL Instant Power Register

Decompilation of third-party telemetry services and OEM energy management binaries confirmed that instantaneous powertrain power (kW) is not exposed as a native VHAL property on the IHU629G. Real-time powertrain power must be acquired via the direct OBD2 CAN diagnostic interface (0x7E2) or estimated from rolling battery SoC differentials.


4. Property Sweep Coverage & Accessor Architecture

Transition from Generic to Typed Property Accessors

Initial discovery sweeps using CarPropertyManager.getProperty(Object.class, ...) dropped properties failing STATUS_AVAILABLE, falsely reporting populated registers as dead.

Refactoring the discovery harness (Discovery.snapshot) to fall back to typed accessors (getFloatProperty, getIntProperty) expanded detected active properties from 179 to 1,700 out of 1,909 declared candidates:

Discovery Pass Resolution:
  Initial Generic Scan:   179 ok / 1631 fail (of 1810)
  Typed Accessor Scan:   1700 ok /  209 fail (of 1909)

Lesson: Certain vehicle registers (including DOOR_POS and seatbelt switches) answer validly through typed getters despite failing generic Object deserialization.


5. Seat & Occupant Sensor Harness Isolation

Front Seat Telemetry

Rear Seat Hardware Topology

Exhaustive testing across all area bitmasks (1 to 16777216) with physical occupants verified that rear seat occupancy sensors and seatbelt buckles do not route to the Android head unit:


6. Body Electronics & Windows

Door Position and Locking

Window Actuation & Automated Pressure Relief

Writing directly to WINDOW_POS (322964416) actuates the mechanical window motor without requiring auxiliary commands:


7. Bluetooth OBD2 Pairing & RFCOMM Architecture

Pairing PIN Override

The factory Android 9 Bluetooth stack on the IHU629G enforces an automated background pairing sequence hardcoded to PIN "0000" in /system/etc/bluetooth/btDefSetting.json. Because standard ELM327 adapters require PIN "1234", pairing attempts initiated from the stock UI fail silently with UNBOND_REASON_AUTH_FAILED.

For the tested vLinker MC+, temporarily modifying /system/etc/bluetooth/btDefSetting.json to "pairingCode": "1234", or dispatching modehelper’s privileged BtPairReceiver broadcast, enables pairing without user prompts. The system-file method is optional, global while active, and must be reverted immediately after bonding; it is not part of normal Drive Assist installation.

RFCOMM Socket Architecture

Android’s standard SDP-based device.createRfcommSocketToServiceRecord(MY_UUID) fails on this head unit due to non-standard Bluetooth middleware shims. Communication requires direct channel-1 RFCOMM socket allocation via reflection:

Method m = device.getClass().getMethod("createRfcommSocket", int.class);
BluetoothSocket socket = (BluetoothSocket) m.invoke(device, 1);