CarPropertyService信号配置和调试

本文主要记录property信号添加的操作流程。

以下操作基于HIDL,安卓13:

1.types.hal中更新信号

首先,VHAL需要根据信号矩阵表,更新types.hal中的信号。

文件路径LINUX\android\hardware\interfaces\automotive\vehicle\2.0\types.hal

信号id是8位的16进制数,可分为4个部分,它们通过或运算累加起来。

下面以原生信号为例,进行说明。

    INFO_EV_BATTERY_CAPACITY = (
        0x0106
        | VehiclePropertyGroup:SYSTEM
        | VehiclePropertyType:FLOAT
        | VehicleArea:GLOBAL),

后4位0x0106是信号的id,由信号矩阵表定义,一般是唯一的。

VehiclePropertyGroup是最高位,系统原生的为SYSTEM(0x10000000);一般来说,供应商添加使用VENDOR(0x20000000)。

VehiclePropertyType是第三第四位,定义如下

enum VehiclePropertyType : int32_t {
    STRING          = 0x00100000,
    BOOLEAN         = 0x00200000,
    INT32           = 0x00400000,
    INT32_VEC       = 0x00410000,
    INT64           = 0x00500000,
    INT64_VEC       = 0x00510000,
    FLOAT           = 0x00600000,
    FLOAT_VEC       = 0x00610000,
    BYTES           = 0x00700000,
    MIXED           = 0x00e00000,
    MASK            = 0x00ff0000
};

VehicleArea是第二位,一般大部分信号的area是GLOBAL。

enum VehicleArea : int32_t {
    /**
     * A global property is a property that applies to the entire vehicle and is not associated with
     * a specific area. For example, FUEL_LEVEL, HVAC_STEERING_WHEEL_HEAT are global properties.
     */
    GLOBAL      = 0x01000000,
    /** WINDOW maps to enum VehicleAreaWindow */
    WINDOW      = 0x03000000,
    /** MIRROR maps to enum VehicleAreaMirror */
    MIRROR      = 0x04000000,
    /** SEAT maps to enum VehicleAreaSeat */
    SEAT        = 0x05000000,
    /** DOOR maps to enum VehicleAreaDoor */
    DOOR        = 0x06000000,
    /** WHEEL maps to enum VehicleAreaWheel */
    WHEEL       = 0x07000000,

    MASK        = 0x0f000000,
};

在编译CarService时,会自动先编译VHAL。所以修改types.hal之后,可以不立即编译VHAL。可以等CarService代码完成后,直接编译CarService即可。

2.PropertyHalServiceIds中配置信号的读写权限

PropertyHalServiceIds文件路径LINUX\android\packages\services\Car\service\src\com\android\car\hal\PropertyHalServiceIds.java

参考原生代码添加权限

        mProps.put(VehicleProperty.INFO_EV_BATTERY_CAPACITY, new Pair<>(
                    Car.PERMISSION_CAR_INFO,
                    null));

new Pair<>(,)中,先后添加读权限和写权限。

PropertyHalServiceIds中会使用到types.hal生成的VehicleProperty类,这也是CarService的编译依赖VHAL的原因。

3.VehiclePropertyIds中添加信号id

VehiclePropertyIds在car-lib目录下,是需要打包成jar以后,提供给APP使用的。

VehiclePropertyIds文件路径LINUX\android\packages\services\Car\car-lib\src\android\car\VehiclePropertyIds.java

car-lib目录下的接口文件修改后,要执行make update-api命令。这个命令会更新以下两个current.txt文件:

  • LINUX\android\packages\services\Car\car-lib\api\current.txt
  • LINUX\android\packages\services\Car\car-lib-module\api\current.txt

其实这2个文件的内容是完全一样的,文件内容就是按照字母表顺序,列出了APP可用的公共接口方法和常量。

这2个文件很重要,进行完整编译时,会校验其中的内容。假如VehiclePropertyIds中新增的信号在current.txt中没有,就会报错并终止编译。如果要手动修改current.txt(例如手动同步代码),一定要注意代码写入的位置是否正确,如果没有按照字母表顺序排列,也会报错并导致无法编译image。

4.编译获取产物和使用

添加property的基本步骤就是以上的3个。完成后即可编译。

  1. source build/envsetup.sh
  2. lunch 编译选项
  3. make CarServiceUpdatableNonModule 或者 在Car的对应目录下mm

这里不能make CarService,因为CarService.apk和CarServiceUpdatableNonModule.apk是不同的,具体区别参考这篇博客《CarService的构成和初始化分析》

编译完成后可获取jar包供APP使用。建议APP引用jar包时使用compileOnly,以避免一些库的冲突。对于CarPropertyService来说,APP只要使用接口和常量,所以compileOnly参与编译即可,不需要用implementation参与打包。

提供给APP的jar包路径为/out/soong/.intermediates/packages/services/Car/car-lib/android.car/android_common/javac/android.car.jar

也可以使用/out/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/classes.jar

用MD5计算可得知,上面两个路径的文件,MD5值是完全一样的。

如果是framework使用编译产物进行调试,需要使用到的产物为android.car.jar和CarServiceUpdatableNonModule.apk

注意这里的 android.car.jar和提供的APP的jar包是不同的东西,其路径为out/target/product/qssi/system/framework/android.car.jar。具体的区别可以参考这篇博客《CarService的构成和初始化分析》

将android.car.jar文件push进system/framework/之后,重启即可生效。

代码提交

综上,更新一个信号需要CarService修改4个文件

  • LINUX\android\packages\services\Car\car-lib\api\current.txt
  • LINUX\android\packages\services\Car\car-lib-module\api\current.txt
  • LINUX\android\packages\services\Car\car-lib\src\android\car\VehiclePropertyIds.java
  • LINUX\android\packages\services\Car\service\src\com\android\car\hal\PropertyHalServiceIds.java

站在CarService提交代码的角度来说,VHAL只需要保证修改types.hal并比CarService先合入即可。DefaultConfig.h是VHAL自己的默认值设置,对于CarService编译无影响。

添加枚举值

有些进阶需求还会在car-lib中添加枚举类,来限制信号的具体值。比如,在枚举类中定义常量ON和OFF,这样APP编写代码时使用常量名,至于ON和OFF代表的具体值,APP并不关注。这样当信号值变化时,更新枚举类和生成的jar包即可,APP代码无需变动,对于平台类项目很合适。

添加枚举值时,可以在types.hal中添加enum,参考原生的代码:

enum EvsServiceState : int32_t {
    OFF = 0,
    ON = 1,
};

之后编译VHAL,可得到产物/out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0/android.hardware.automotive.vehicle-V2.0-java_gen_java/gen/srcs/android/hardware/automotive/vehicle/V2_0/EvsServiceState.java

可以把这个java枚举类放入car-lib目录下,例如在car-lib/src/android/car中新建一个文件夹专门放置枚举类。然后打包进jar供APP使用。但java文件中的包名需要修改,还需要添加构造方法,否则会编译报错。枚举类较多时,可以用脚本进行批量修改。

注意在car-lib中修改枚举类之后,要更新current.txt文件。

调试

CarService的调试,涉及上层APP和下层VHAL。

APP侧调试

APP侧,可以写一个测试APP引入android.car.jar,调用set/get/register三种接口。APP应当有系统权限,否则无法set。如果一些信号有设置读写权限,也应当加上。

初始化代码

private Car mCarApi;
private CarPropertyManager mCarPropertyManager;

if (mCarApi != null && mCarApi.isConnected()) {
    mCarApi.disconnect();
    mCarApi = null;
}
mCarApi = Car.createCar(context, null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT, (car, ready) -> {
    if (ready) {
        initManage(car);
    } else {
        // CarService发生异常或断开时,需要client端处理
    }
});

private void initManage(Car car) {
    Log.i(TAG, "init CarPropertyManager");
    mCarPropertyManager = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);
}

注册/注销监听

private final CarPropertyManager.CarPropertyEventCallback mCarPropertyEventListener = new CarPropertyManager.CarPropertyEventCallback() {
    @Override
    public void onChangeEvent(CarPropertyValue carPropertyValue) {
    }

    @Override
    public void onErrorEvent(int var1, int var2) {
    }
};

mCarPropertyManager.registerCallback(mCarPropertyEventListener, propertyId, CarPropertyManager.SENSOR_RATE_ONCHANGE);
mCarPropertyManager.unregisterCallback(mCarPropertyEventListener, propertyId);

set接口。areaId一般使用0(GLOBAL),不是GLOBAL的信号应使用对应的areaId。

    public void setBooleanProperty(int prop, int areaId, boolean val) 
    public void setFloatProperty(int prop, int areaId, float val) 
    public void setIntProperty(int prop, int areaId, int val) 
    public <E> void setProperty(@NonNull Class<E> clazz, int propId, int areaId, @NonNull E val) 

get接口。areaId一般使用0(GLOBAL),不是GLOBAL的信号应使用对应的areaId。

    public boolean getBooleanProperty(int prop, int area) 
    public float getFloatProperty(int prop, int area) 
    public int getIntProperty(int prop, int area) 
    public int[] getIntArrayProperty(int prop, int area) 
    public <E> CarPropertyValue<E> getProperty(@NonNull Class<E> clazz, int propId, int areaId) 

VHAL侧调试

原生提供了命令进行调试。

adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --set 信号id -i 信号值

信号id可以直接写十进制的id,也可以使用0x的十六进制id。-i表示int型,还可以使用f(float),b(byte数组)

byte数组的格式比较特殊

adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --set 信号id -b 0x0102

0x之后,每两位占一个字节。

get命令

adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --get 信号id

  • 24
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安卓应用服务注册解析是指在安卓系统中,通过特定的方法和步骤将应用服务注册到系统中,以便在需要时能够被其他组件或应用程序使用。其中,涉及到了一些具体的实现细节和技术。 首先,需要在AndroidManifest.xml文件中指定服务的注册信息,包括服务的名称、所在的包名、权限以及其他相关的配置。在这个过程中,可以使用FileProvider来获取文件的URI,以确保应用在访问文件时具有合适的权限。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Android 7.0解析包时出现问题 的解决方案(应用内更新)](https://blog.csdn.net/weixin_32638607/article/details/117293174)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [【Android R】车载 Android 核心服务 - CarPropertyService 解析](https://blog.csdn.net/linkwj/article/details/127938242)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值