信号接入指南
叮
仅以 car-lib (android) 作为(Java)调用说明, 其他语言的数据结构、通信方式与此类似
Car-lib
-
代码地址 Android Code Search
-
重要类 : CarPropertyManager
-
Java-Doc 不额外提供, 可以参考 Android Developer
-
CarPropertyManager#registerCallback(callback, propertyId, rate)
- [callback] - 信号变化的回调
- [propertyId] - 具体信号 ID
- [rate] - 期望信号接受频率, 仅对 MODE_CONTINUOUS 类型信号有效 (比如: 车速、里程、方向盘转角等等)
-
CarPropertyManager#setProperty(clazz, propId, areaId, value)
- 与 setBooleanProperty setFloatProperty setIntProperty 用法类似
- [clazz] - value type
- [propId] - 具体信号 ID
- [areaId] - 方位 ID , 与信号ID组合使用,共同确定一个具体物件, 比如 Hvac#TEMPERATURE (propId) 和 VehicleAreaSeat#SEAT_ROW_1_LEFT (areaId) 可以表示空调在主驾(副驾?) 的目标温度
- [value] - 具体的信号值,支持 Integer, Float, Long, int[], byte[], long[], String 类型
-
CarPropertyManager#getProperty(clazz, propId, areaId)
- 使用 registerCallback 足以覆盖大部分场景
- 与 setProperty 类似, 不做过多说明
-
CarPropertyManager#getPropertyList 与 CarPropertyManager#getCarPropertyConfig
- 获取当前信号配置,包含该信号可用范围, 支持 Area 范围等
- 该配置在 CarService (Vhal) 中目前是静态配置, 不支持运行时动态变化
- 车辆对于某功能的支持与否,支持程度,皆可通过此方法确认
-
Car-lib 使用方法
- Gradle 编译 (参考 : Link)
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.xxx"
minSdkVersion 28
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
// android.car exists since Android 10 (API level 29) Revision 5.
useLibrary 'android.car'
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
// maven { url 'https://pkgs.d.xiaomi.net:443/artifactory/maven-snapshot-virtual/' }
implementation 'mi.car:vehicle.support:0.2.2.9-SNAPSHOT'
}- bp 编译
android_app {
name: "Xxxxx",
srcs: ["src/**/*.java", "src/**/*.aidl"],
libs: [
"android.car"
],
static_libs: [
"mi-car-support-api",
],
}车控信号定义
-
信号构成参考 (PropertyId, AreaId)
-
SOA 服务接口定义表格(初版,未使用)
-
SOA 服务接口定义表格 MS11(E2/E3 备份 | 弃用)(截止 E3 , 已弃用) -
SOA 服务接口定义表格 MS11(当前版本, 定时更新)
-
-
SC 中信号查找参考指南 : 车控SOA信号流程查看说明(感谢小爱部门大力支持)
-
Maven 地址 ( 版本号可从网页上查看):
maven { url 'https://pkgs.d.xiaomi.net:443/artifactory/maven-snapshot-virtual/' }
implementation 'mi.car:vehicle.support:0.1.4-SNAPSHOT'
// https://pkgs.d.xiaomi.net/artifactory/webapp/#/artifacts/browse/tree/General/artifactory-snapshots/mi/car/vehicle.support
// 或者 release
maven { url 'https://pkgs.d.xiaomi.net:443/artifactory/maven-release-virtual/' }
implementation 'mi.car:vehicle.support:0.1.4'
//https://pkgs.d.xiaomi.net/artifactory/webapp/#/artifacts/browse/tree/General/artifactory-releases/mi/car/vehicle.support最新版本查询 : Link
- 信号声明
public class Hvac {
// .......
@PropertyDef(
permission = @RequiresPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE),
areaRef = VehicleAreaSeat.class,
type = float.class,
value = @ValueDef(range = @Range(floatFrom = 18.0, floatTo = 32.0)))
public static final int TEMPERATURE = 0x10a
| MiVehiclePropertyGroup.MI_CAR
| MiVehicleArea.SEAT
| VehiclePropertyType.FLOAT
| MiVehicleZone.HVAC; /*0x6560410a*/
// .......
}以空调温度信号为例
- PropertyId 为 Hvac#TEMPERATURE , 其 int 的构成可参考上述中的 SOA 服务接口定义表格 MS11(E2/E3 备份 | 弃用) 与 Mi AAOS 信号体系实现
- AreaId 为 VehicleAreaSeat 类中的某个枚举值(或组合| 按位或),比如 VehicleAreaSeat#SEAT_ROW_1_LEFT, 具体支持的 Area 范围以及数据以 CarPropertyManager#getCarPropertyConfig 或车型为准,代码中的声明(ValueDef)只作为参考,不能表示具体车型的支持情况
- 注解中还说明了该信号的数据类型 type, 以及读写所需要的权限 permission (标准 Android 权限体系 | Manifest),请开发人员妥善处理
Mock
常见场景切换
分心模式
# 开启分心模式
adb root
# 切换档位至 DRIVE
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --mock_from_car 1631613445 i 3
# 模拟速度到 60
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --mock_from_car 1631613441 i 60# 关闭分心模式
adb root
# 切换档位至 PARK
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --mock_from_car 1631613445 i 0
# 模拟速度到 0
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --mock_from_car 1631613441 i 0模拟信号脚本
# 解析 log , 并执行模拟
python LogPropMonitor.py xxxx.log
# 将 log 中模拟命令转储为 cmd_list.sh 文件
python LogPropMonitor.py xxxx.log --save_only
# 将 log 中模拟命令转换为 cmd_list.sh 文件, 并执行
python LogPropMonitor.py xxxx.log --output output.sh --exec辅助测试用 APP (代码仓库)
车辆信号调试-Q&ACarService与VHAL
adb install -t -g CarDemo4Test.apk
# APP 中打开 Mock 时候点击, 和命令行注入等效
#注入雨刮速度为 间歇高速 (Body#WIPER_SPEED_MODE)
adb shell dumpsys car_service inject-vhal-event 0x63401301 1 2
#注入雨刮维修模式为 ON (Body#WIPER_SERVICE_MODE)
adb shell dumpsys car_service inject-vhal-event 0x63401302 1 1- 开发人员可以直接拉取代码,来更新App (代码仓库 更新vehicle.support 版本即可, 界面是依赖信号自动生成的)

其他
- Mock 功能仅适用于信号通路完成前,debug 使用, 切勿在车辆设备上适用
- 8295 上默认 Mock 关闭, pad 上默认开启
- 目前所有设备在开机后会保持默认状态 (以防有人忘了清理配置) (提交 | 提交2)
# enable mock, 仅为在通路不可用时, 测试 APP 使用
adb shell settings put --user 0 GLOBAL vehicle_mock_data 1
# disable mock, 切换至正常模式
adb shell settings put --user 0 GLOBAL vehicle_mock_data 0注意事项
权限
- 部分信号所需权限级别是 dangerous , 需要运行时授予,或者添加 (system/vendor/xxx) /etc/default-permissions/xxxxxx.xml
android.car.permission.CAR_ENERGY
android.car.permission.CAR_SPEEDCarPropertyManager 相关异常
CarInternalErrorException,
PropertyAccessDeniedSecurityException,
PropertyNotAvailableException,
PropertyNotAvailableAndRetryException,
IllegalStateException,
IllegalArgumentException-
CarPropertyManager#setProperty
- 这里 App 可以处理部分异常, CarService 目前并不会在 setProperty 的时候抛出 ServiceSpecificException, 所以 App 也可以忽略处理
-
CarPropertyManager#getIntProperty, getFloatProperty, getBooleanProperty, getIntArrayProperty
- 触发原因 : CarPropertyManager#handleNullAndPropertyStatus(source)
- 这里需要 App 主动处理下异常, 因为 这部分代码是存在于 car-lib 中的, 而本地修改 car-lib 的代码并不能影响到所有 App, 而且由于这里的异常都是继承自 RuntimeException, 所以 IDE 也不会提示开发人员去主动处理, 是个很容易忽略的问题
// 建议方式 1
int value ;
try {
value = mCarPropertyManager.getIntProperty(propId, areaId);
} catch (CarInternalErrorException
| PropertyNotAvailableAndRetryException
| PropertyNotAvailableException e1) {
// can signal timeout ? hardware fatal ?
value = -1 ;
} catch (PropertyAccessDeniedSecurityException | IllegalArgumentException e2) {
// app cannot access or error call ? 应用可以解决逻辑问题,而不去处理异常
value = -1;
}
// 建议方式 2, 这里在 CarService 中做了处理, getProperty 并不会抛出异常
CarPropertyValue<Integer> carProp = mCarPropertyManager.getProperty(Integer.class, propId, areaId);
int value = carProp != null ? carProp.getValue() : -1;
// 或者对其他车机系统也做兼容处理
int value;
try {
CarPropertyValue<Integer> carProp = mCarPropertyManager.getProperty(Integer.class, propId, areaId);
value = carProp != null /*&& carProp.getStatus() == CarPropertyValue.STATUS_AVAILABLE*/
? carProp.getValue() : -1;
} catch (CarInternalErrorException
| PropertyNotAvailableAndRetryException
| PropertyNotAvailableException e1) {
// can signal timeout ? hardware fatal ?
value = -1;
} catch (PropertyAccessDeniedSecurityException | IllegalArgumentException e2) {
// app cannot access or error call ? 应用可以解决逻辑问题,而不去处理异常
value = -1;
}
// 方式3
// 额外提供方法 TODO
MiCarPropertyManager#getIntPropertySafe(
CarPropertyManager cpm,
int prop,
int area,
int defaultValue)
MiCarPropertyManager#getIntPropertySafe(
CarPropertyManager cpm,
int prop,
int area,
boolean returnOriginIfUnavaliable/**default : true**/,
int defaultValue)-
CarPropertyManager#getProperty(java.lang.Class
, int, int) - 同 setProperty, Service 端也不会主动抛出 ServiceSpecificException ,开发人员可以忽略此问题, 或者使用上述同样方法去处理
目前所有设备在开机后会Mock保持默认状态 (以防有人忘了清理配置) (提交)
Create Car ANR 警告
信号变更通知群

相关链接
E3-SC : https://xiaomi.f.mioffice.cn/drive/folder/fldk4T2KFVJQaRNz9BOm9LkdRRh
E4-SC : https://xiaomi.f.mioffice.cn/drive/folder/fldk4ME4bI9xq0QhfjkBZ95LdQh
E4U-SC : https://xiaomi.f.mioffice.cn/drive/folder/fldk4Bdzf8Hvh3hBlFVlxh7sZec
TODO : Settings 接入信号列表