Android Automotive 自定义 Property

1,732 阅读4分钟

版权声明

凡未经作者授权,任何媒体、网站及个人不得转载、复制、重制、改动、展示或使用局部或全部的内容或服务。如果已转载,请自行删除。同时,我们保留进一步追究相关行为主体的法律责任的权利。

© 2023 小酥肉不加辣,All rights reserved.

本文基于 AOSP android13-release 分支代码进行修改,并采用 AIDL 方式实现。

作为 OEM,在 AOSP Automotive OS 的基础上添加 Vehicle 自定义属性是必须要做的事情。虽然 AOSP 提供了大量的 Vehicle 属性,但是不同品牌和型号的汽车还是有其区别于其他产品的特别功能。在这种场景下,就需要我们修改 AOSP 的源码,增加自定义属性。

1. 添加新属性

  • hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -2839,5 +2839,10 @@ enum VehicleProperty {

     VEHICLE_CURB_WEIGHT = 0x0F46 + 0x10000000 + 0x01000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+
+    VEHICLE_TEST_PROPERTY = 0x0F50 + 0x10000000 + 0x01000000
+            + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
 }

2. 更新 AIDL API

因为修改了系统的AIDL,为了API的稳定,系统要求执行 update-api 的操作,执行命令

make android.hardware.automotive.vehicle-update-api

执行成功之后会在hardware/interfaces/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl中生成更新后的 aidl 定义

@@ -206,4 +206,7 @@ enum VehicleProperty {
   EV_REGENERATIVE_BRAKING_STATE = 289410884,
   TRAILER_PRESENT = 289410885,
   VEHICLE_CURB_WEIGHT = 289410886,
+  VEHICLE_TEST_PROPERTY = 289410896,
 }

注意不要手动修改这个文件

3. 由 AIDL 生成对应的 .h 文件

回到 AOSP 根目录,执行命令

mmm hardware/interfaces/autmotive/vehicle

编译整个 vehicle 模块,成功之后会在 out/soong/.intermediates/hardware/interfaces/automotive/vehicle/aidl/android.hardware.automotive.vehicle-V2-ndk-source/gen/include/aidl/android/hardware/automotive/vehicle/VehicleProperty.h 文件中生成了 VEHICLE_TEST_PROPERTY 相关的代码。

4. 配置属性

  • hardware/interfaces/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -1974,6 +1974,44 @@ const std::vector<ConfigDeclaration> kVehicleProperties = {
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::VEHICLE_TEST_PROPERTY),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {123}},
+        },

这里设置属性 VEHICLE_TEST_PROPERTY 既可读也可写、changeMode 和初始值。如果这个属性的 area 不是global,那么还需要设置 .areaConfig.initialAreaValues,可参考源码中其他属性的设置。

5. 添加 owner 信息

由于修改了系统的 AIDL,需要添加 owner 到 bp 文件中。

  • hardware/interfaces/automotive/vehicle/aidl/Android.bp
@@ -24,6 +24,7 @@ package {
 aidl_interface {
     name: "android.hardware.automotive.vehicle",
     vendor_available: true,
+    owner:"xsr",
     srcs: [
         "android/hardware/automotive/vehicle/**/*.aidl",
     ],

由于 emulator 中的 aidl 直接依赖了 vehicle 中的 aidl,因此也需要在 emulator 的 Android.bp 中添加 owner 信息

  • device/generic/car/emulator/vhal_v2_0/interfaces/aidl/Android.bp
@@ -12,6 +12,7 @@ package {
 aidl_interface {
     name: "device.generic.car.emulator-aidl",
     vendor_available: true,
+    owner: "xsr",
     srcs: ["device/generic/car/emulator/*.aidl"],
     imports: [
         "android.hardware.automotive.vehicle",

6.升级其他模块中的依赖的版本

完成以上步骤之后编译的时候,会报错找不到 VEHICLE_TEST_PROPERTY,这是因为第3步的时候,会生成 android.hardware.automotive.vehicle-V2-ndk,AOSP 中还有很多其他模块依赖它,但是依赖的版本还是 V1。所以我们需要手动修改所有依赖的地方。

  • hardware/interfaces/automotive/vehicle/aidl/impl/Android.bp
@@ -22,7 +22,7 @@ cc_defaults {
     name: "VehicleHalDefaults",
     static_libs: [
         "android-automotive-large-parcelable-lib",
-        "android.hardware.automotive.vehicle-V1-ndk",
+        "android.hardware.automotive.vehicle-V2-ndk",
         "libmath",
     ],
     shared_libs: [
  • device/generic/car/emulator/vhal_aidl/VehicleEmulator/Android.bp
@@ -38,7 +38,7 @@ cc_library {
         "libutils",
         "libprotobuf-cpp-lite",
         "libbinder_ndk",
-        "device.generic.car.emulator-aidl-V1-ndk",
+        "device.generic.car.emulator-aidl-V2-ndk",
     ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
  • device/generic/car/emulator/vhal_aidl/Android.bp
@@ -52,6 +52,6 @@ cc_binary {
         "libutils",
         "libprotobuf-cpp-lite",
         "libbinder_ndk",
-        "device.generic.car.emulator-aidl-V1-ndk",
+        "device.generic.car.emulator-aidl-V2-ndk",
     ],
 }
  • device/generic/car/emulator/vhal_aidl/VehicleEmulator/Android.bp
@@ -38,7 +38,7 @@ cc_library {
         "libutils",
         "libprotobuf-cpp-lite",
         "libbinder_ndk",
-        "device.generic.car.emulator-aidl-V1-ndk",
+        "device.generic.car.emulator-aidl-V2-ndk",
     ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
  • device/generic/car/emulator/vhal_aidl/VehicleEmulator/test/Android.bp
@@ -39,7 +39,7 @@ cc_test {
         "libutils",
         "libprotobuf-cpp-lite",
         "libbinder_ndk",
-        "device.generic.car.emulator-aidl-V1-ndk",
+        "device.generic.car.emulator-aidl-V2-ndk",
     ],
     defaults: [
         "VehicleHalDefaults",

感觉这一步可能没有必要,但是我没有找到修改 AIDL 之后不执行 update-api 的方法。

7. 验证结果

此处以 x86_64 平台为例,以下文件路径中的 x86_64 替换为相应平台即可

方法1 全量编译

回到项目根目录,使用 m 命令重新编译整个项目。

使用 make emu_img_zip 重新编译模拟器镜像。

编译好的镜像文件在 out/target/product/emulator_car_x86_64/sdk-repo-linux-system-images-eng.$(whoami).zip

将生成的 zip 文件复制出来,解压之后替换本地 SDK 中的镜像 ~/Library/Android/sdk/system-images/android-33/android-automotive/x86_64, 然后把模拟器 wipe data 并重新启动模拟器。

打开模拟器

emulator.png

方法2 增量编译

回到项目根目录,使用 mmm device/generic/car 编译这个模块。

编译成功之后可以

找到out/target/product/emulator_car_x86_64/vendor/bin/hw/android.hardware.automotive.vehicle@V1-emulator-service 文件,并 push 到模拟器的 vendor/bin/hw 目录下。

找到 out/target/product/emulator_car_x86_64/vendor/lib64/android.hardware.automotive.vehicle-V2-ndk.so 文件, 并 push 到模拟器 vendor/lib64 目录下。

找到 out/target/product/emulator_car_x86_64/vendor/lib64/device.generic.car.emulator-aidl-V2-ndk.so,将这个文件push到模拟器 vendor/lib64 目录下。

重启模拟器即可生效。

最后

虽然使用这个方法可以自定义 Vehicle Property,也可以在模拟器中读取和设置属性。但是当我们在应用层调用 CarPropertyManagergetIntPropertysetIntProperty 方法时还是会抛出 property id 不存在的异常。 如果想解决这个问题还需要在 CarService 层为自定义属性添加自定义权限。请查看我的关于自定义权限的文章。

如果你对车机开发感兴趣,可以关注我的车机开发专栏