Android IoT, Automotive, & Smart TV Customizations

Creating a Custom VHAL Property: A Tutorial for Advanced Vehicle Data Management

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction: Unlocking Advanced Vehicle Data with Custom VHAL Properties

The Android Vehicle Hardware Abstraction Layer (VHAL) is a critical component in Android Automotive OS, serving as the interface between vehicle-specific hardware and the Android framework. It standardizes access to vehicle properties such as speed, gear, engine status, and climate controls. While the VHAL defines a comprehensive set of standard properties, real-world automotive platforms often require access to unique, custom vehicle data or functionalities not covered by the standard specification. This advanced tutorial will guide you through the process of extending the VHAL to include your own custom property, empowering you to manage bespoke vehicle data within the Android Automotive ecosystem.

Extending the VHAL is essential for integrating proprietary sensors, custom actuators, or unique vehicle features. Imagine a scenario where you have a custom cabin air quality sensor or a unique battery health monitoring system that needs to expose data to Android applications. A custom VHAL property provides the robust, standardized pathway for such integration, ensuring seamless communication between hardware and software.

Understanding VHAL Properties and Their Structure

Before diving into implementation, it’s crucial to understand the anatomy of a VHAL property. Each property is identified by a unique 32-bit integer ID, typically structured as follows:

  • Bits 28-31: Property type (e.g., VehiclePropertyType.INT32, VehiclePropertyType.FLOAT).
  • Bits 24-27: Area type (e.g., VehicleAreaType.GLOBAL, VehicleAreaType.DOOR, VehicleAreaType.SEAT).
  • Bits 0-23: Property ID itself, unique within its type and area. Vendor-specific properties typically use a dedicated range (0x2000 to 0x2FFF in the upper 16 bits of the ID).

For custom properties, you’ll utilize the vendor-specific range to avoid conflicts with standard VHAL properties. You also need to define its data type (e.g., INT32, FLOAT, BYTE_ARRAY) and access mode (READ_ONLY, WRITE_ONLY, READ_WRITE, ON_CHANGE, CONTINUOUS). For our example, we will create a custom CUSTOM_CABIN_AIR_QUALITY property that reports an integer index (0-100), is read-only, and reports on change.

Prerequisites

  • A configured Android Open Source Project (AOSP) build environment.
  • Familiarity with C++ programming.
  • Basic understanding of Android HAL development.
  • Access to an AOSP source tree (e.g., Android 12 or newer).

Step 1: Define Your Custom VHAL Property

The first step is to declare your new property within the VHAL interface definition. This is typically done by extending the existing types.hal file or creating a new vendor-specific .hal file within your HAL module.

Navigate to the default VHAL implementation’s types definition. For Android 12, this is often found at hardware/interfaces/automotive/vehicle/2.0/default/types.hal. In newer versions (e.g., Android 13/14), you might be working with [email protected], [email protected], or [email protected].

Open types.hal and add your custom property ID to the VehicleProperty enum. Ensure you choose an ID within the vendor-specific range (e.g., starting with 0x2100 for a global property with INT32 type).

// In hardware/interfaces/automotive/vehicle/2.0/default/types.hal or similar [email protected] types.hal
enum VehicleProperty: int32_t {
    ...
    // Vendor-specific properties start here
    // Custom Cabin Air Quality Index (INT32, GLOBAL, READ_ONLY, ON_CHANGE)
    CUSTOM_CABIN_AIR_QUALITY = 0x21000001
};

// Define a struct or union if your custom property needs complex data types
// This example uses a simple INT32, so no extra struct is needed.

Here’s a breakdown of the chosen ID:

  • 0x2 (bits 28-31): Represents VehiclePropertyType.INT32.
  • 0x1 (bits 24-27): Represents VehicleAreaType.GLOBAL.
  • 0x000001 (bits 0-23): The unique property ID within the vendor-specific range.

Step 2: Implement the Property in the VHAL Service

Now that the property is defined, you need to implement its behavior within the VHAL service. This involves telling the VHAL about your new property and providing logic for reading its value.

Locate the default VHAL implementation source code, typically hardware/interfaces/automotive/vehicle/2.0/default/VehicleHal.cpp. You will need to modify a few key methods:

2.1. Declare Support for the New Property

In the VehicleHal::getSupportedProperties() method, add an entry for your new property. This method returns a list of all properties supported by your VHAL implementation.

// In hardware/interfaces/automotive/vehicle/2.0/default/VehicleHal.cpp
std::vector<VehiclePropConfig> VehicleHal::getSupportedProperties() {
    std::vector<VehiclePropConfig> configs;

    // Add all standard properties...
    configs.push_back(createGlobalProp(VehicleProperty::PERF_VEHICLE_SPEED, VehiclePropertyType::FLOAT, 0));

    // Add your custom property configuration
    VehiclePropConfig customAirQualityConfig = {};
    customAirQualityConfig.prop = static_cast<int32_t>(VehicleProperty::CUSTOM_CABIN_AIR_QUALITY);
    customAirQualityConfig.access = VehiclePropertyAccess::READ_ONLY;
    customAirQualityConfig.changeMode = VehiclePropertyChangeMode::ON_CHANGE;
    // Add any vendor-specific metadata if needed
    customAirQualityConfig.configArray.push_back(0); // Example: min value (0)
    customAirQualityConfig.configArray.push_back(100); // Example: max value (100)

    configs.push_back(customAirQualityConfig);

    return configs;
}

2.2. Implement `getValue` for Your Custom Property

Since our CUSTOM_CABIN_AIR_QUALITY property is READ_ONLY, we need to provide a value when requested. For a tutorial, we’ll use a simple dummy value. In a real-world scenario, this is where you’d interact with your actual hardware driver to fetch the sensor reading.

Locate the VehicleHal::getValue() method and add a case for your custom property:

// In hardware/interfaces/automotive/vehicle/2.0/default/VehicleHal.cpp
void VehicleHal::getValue(const VehiclePropValue<void>& requestedPropValue,
                          getValueCallback _hidl_cb) {
    VehiclePropValue<void> propValue = requestedPropValue;
    StatusCode status = StatusCode::OK;

    switch (propValue.prop) {
        ...
        case static_cast<int32_t>(VehicleProperty::CUSTOM_CABIN_AIR_QUALITY): {
            // In a real implementation, you would read from a sensor driver
            // For this example, let's return a dummy value (e.g., 75)
            propValue.value.int32Values.resize(1);
            propValue.value.int32Values[0] = 75;
            propValue.timestamp = elapsedRealtimeNano(); // Set current timestamp
            break;
        }
        default:
            status = StatusCode::INVALID_ARG;
            LOG(ERROR) << "Attempt to get unknown property 0x" << std::hex << propValue.prop;
            break;
    }

    // Return the value (or error)
    _hidl_cb(status, propValue);
}

If your property were READ_WRITE, you’d also need to implement logic in the setValue() method to process incoming values and potentially send them to your hardware.

Step 3: Build AOSP with Your Changes

After modifying the VHAL source code, you need to rebuild the relevant modules and apply them to your AOSP build. Assuming you have already sourced your build environment (source build/envsetup.sh) and selected your lunch target (lunch <target>):

# Rebuild the default VHAL implementation
mmma hardware/interfaces/automotive/vehicle/2.0/default

# If you modified types.hal, you might need to rebuild the entire vehicle HAL interface package
# This might be `mmma hardware/interfaces/automotive/vehicle/2.0` or similar depending on setup
# or even a full build if dependencies are complex.

Once the build completes successfully, you’ll need to flash your device or update your emulator image with the new system. If you’re working with an emulator, simply restart it after the build. For a physical device, follow your platform’s flashing instructions.

Step 4: Test Your Custom VHAL Property

With your custom VHAL property implemented and deployed, you can now test it using the adb shell cmd vehicle_hal command. This command provides a simple way to interact with the VHAL service directly.

4.1. Get Your Custom Property Value

Connect to your Android Automotive device or emulator via ADB and use the get command with your custom property ID (in hexadecimal or decimal):

adb shell cmd vehicle_hal get 0x21000001

You should see output similar to this:

Property 0x21000001 (CUSTOM_CABIN_AIR_QUALITY):
  status: OK
  value: { int32Values: [75], floatValues: [], bytes: [], stringValue: "", booleanValues: [], largeAreaValues: []}

This confirms that your VHAL recognizes the property and returns the dummy value you implemented.

4.2. Verify Property Configuration (Optional)

You can also list all supported properties to ensure your custom property appears with the correct configuration:

adb shell cmd vehicle_hal list

Look for your property ID in the extensive list of supported properties and verify its access mode, change mode, and other configurations.

Advanced Considerations and Best Practices

  • Error Handling: Implement robust error handling in your getValue() and setValue() methods, returning appropriate StatusCode values (e.g., INVALID_ARG, NOT_AVAILABLE) to indicate issues.
  • Hardware Integration: The dummy values used in this tutorial must be replaced with actual calls to your hardware drivers (e.g., JNI calls to native C/C++ drivers, or direct kernel device interactions via /dev files) for a production system.
  • Security: Be mindful of the data you expose. Sensitive vehicle data should have appropriate permissions and access controls within the VHAL and Android framework.
  • Performance: For CONTINUOUS properties, ensure your implementation is efficient to avoid performance bottlenecks.
  • AOSP Version Compatibility: VHAL interfaces can evolve between AOSP versions (e.g., [email protected] to [email protected]). Always refer to the specific version’s documentation and source code you are working with.
  • Vendor Extensions: For more complex vendor-specific properties or multiple custom properties, consider creating a separate vendor HAL module instead of directly modifying the default AOSP VHAL implementation. This makes future upgrades and maintenance easier.

Conclusion

Extending the Android VHAL with custom properties is a powerful technique for integrating unique vehicle hardware and data into the Android Automotive OS. By following this tutorial, you’ve learned how to define a new property, implement its behavior within the VHAL service, rebuild AOSP, and verify your implementation. This foundation enables you to create sophisticated, vehicle-specific applications that leverage the full capabilities of your automotive platform, driving innovation in advanced vehicle data management.

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner