Android-U Vehicle HAL架构
VehicleHAL 简介¶
- 源码位置 : hardware/interfaces/automotive/vehicle/2.0/
- 类图:略
接口文件¶
-
源码位置 : hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle
从 Android T 开始,Vehicle HAL已经改成 stable aidl 的方式了。 如下 Android.bp:
hardware/interfaces/automotive/vehicle/aidl/Android.bp
aidl_interface {
name: "android.hardware.automotive.vehicle",
vendor_available: true,
srcs: [
"android/hardware/automotive/vehicle/*.aidl",
],
frozen: true,
stability: "vintf",
backend: {
cpp: {
enabled: false,
},
java: {
sdk_version: "module_current",
min_sdk_version: "31",
apex_available: [
"//apex_available:platform",
"com.android.car.framework",
],
},
},
versions_with_info: [
{
version: "1",
imports: [],
},
{
version: "2",
imports: [],
},
],
}
- IVehicle.aidl 定义的是从 CarService 往 HAL 调用的接口
- IVehicleCallback.aidl HAL 往 CarService 上报回调的接口
- VehicleHalProto.proto hardware/interfaces/automotive/vehicle/proto/VehicleHalProto.proto 定义的是一些数据结构,在模拟器VHAL和模拟器之间传递消息。
- hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/
IVehicle.aidl¶
hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
@VintfStability
interface IVehicle {
/* 无效的内存ID。 */
const long INVALID_MEMORY_ID = 0;
/* 每个订阅客户端的共享内存文件的最大数量。 */
const int MAX_SHARED_MEMORY_FILES_PER_CLIENT = 3;
/**
* 返回此车辆HAL支持的所有属性配置的列表。
*
* @return 一个可序列化的对象,其中包含配置列表(如果它们符合binder内存限制)或包含配置的共享内存文件。
* 必须使用{@code android-automotive-large-parcelable}库进行解析。
*/
VehiclePropConfigs getAllPropConfigs();
/**
* 返回给定属性的属性配置列表。
*
* 如果未找到请求的VehicleProperty之一,则必须返回{@link StatusCode#INVALID_ARG},
* 否则返回带有{@link StatusCode#OK}的车辆属性配置列表。
*
* @param props 要获取配置的属性ID的列表。
* @return 一个可序列化的对象,其中包含配置列表(如果它们符合binder内存限制)或包含配置的共享内存文件。
* 必须使用{@code android-automotive-large-parcelable}库进行解析。
*/
VehiclePropConfigs getPropConfigs(in int[] props);
/**
* 异步获取车辆属性值。
*
* 当获取到值时,将调用{@link IVehicleCallback#onGetValues}方法。
* 该方法可能会被多次调用,每次调用时都会获取到一部分已获取的属性。
* 例如,如果请求属性[A,B,C],则回调可能会两次调用,一次调用[A,C],一次调用[B]。
* 调用者不应对{@link IVehicleCallback#onGetValues}的顺序有任何期望。
*
* 如果此方法返回错误,则表示未能获取所有属性。
* 如果此方法返回OK,则仍然有可能未能获取某些属性,这些属性由{@link GetValueResult#status}指示。
*
* 对于{@link VehiclePropertyChangeMode#STATIC}属性,此方法必须始终返回相同的值。
* 对于{@link VehiclePropertyChangeMode#ON_CHANGE}属性,它必须返回最新的可用值。
* 对于可缓存的属性,将返回缓存中的值,而无需与实际的车辆总线通信。
*
* 一些属性(如{@code RADIO_PRESET})需要在{@link VehiclePropValue}对象中传递附加数据。
*
* 如果尚无可用数据,这在初始阶段可能发生,{@link GetValueResult#status}将包含{@link StatusCode#TRY_AGAIN}。
*
* 对于每个请求,调用者必须传递唯一的RequestID,如果给定的请求ID与待处理的请求ID之一重复,
* 则此函数必须返回{@link StatusCode#INVALID_ARG}。
*
* 为防止混淆,在单个调用中不允许重复属性(相同的属性ID和相同的区域ID)。
* 对于重复的属性,此函数必须返回{@link StatusCode#INVALID_ARG}。
*
* 请求中的{@link VehiclePropValue#timestamp}字段将被忽略。
* {@link GetValueResult}中的{@link VehiclePropValue#timestamp}字段必须是从启动时的系统运行时间开始计算的,
* 当ON_CHANGE属性的值发生变化或根据轮询速率检查值时。
* 请注意,对于连续属性,VHAL客户端在轮询间隔内多次读取属性将获得相同的时间戳。
*
* @param callback 回调接口,在获取到值后将调用其'onGetValues'方法。
* 调用者应使用{@code android-automotive-large-parcelable}库解析返回的{@link GetValueResult}对象。
* @param requests 包含请求属性列表或包含属性的共享内存文件的对象。
* 必须使用发送方和接收方的辅助库进行解析。
*/
void getValues(IVehicleCallback callback, in GetValueRequests requests);
/**
* 设置车辆属性值。
*
* 在通过车辆总线发送设置值请求或设置失败后,将调用{@link IVehicleCallback#onSetValues}函数。
* 如果总线协议支持确认,将在收到确认后调用回调函数。
*
* 对于某些车辆总线(例如CAN总线),不支持确认,OnSetValues并不意味着值的更改会立即反映在{@link #getValues}中。
*
* 如果输出状态包含错误,则表示我们无法设置所有属性。如果无法设置某些值,则它们将作为非OK的{@link SetValueResult#status}反映出来。
*
* 请求中每个属性的设置顺序不能保证。如果调用者需要确保在设置值时有特定的顺序,调用者应先设置一个值,等待其回调,然后设置另一个值。
*
* 对于设置操作,数据的时间戳必须被忽略。
*
* 设置某些属性需要有初始状态可用。如果初始数据尚不可用,则{@link SetValueResult#status}必须为{@link StatusCode#TRY_AGAIN}。
* 对于具有单独电源控制的属性,如果属性未上电,则{@link SetValueResult#status}必须为{@link StatusCode#NOT_AVAILABLE}。
*
* 调用者必须为每个请求传递一个唯一的RequestID,如果给定的请求ID之一与待处理的请求ID之一重复,则此函数必须返回{@link StatusCode#INVALID_ARG}。
*
* 为防止混淆,在单个调用中不允许重复属性(相同的属性ID和相同的区域ID)。对于重复属性,此函数必须返回{@link StatusCode#INVALID_ARG}。
*
* @param callback 回调函数,在将设置值请求发送到总线后将调用其'onSetValues'。
* @param requests 包含{@link SetValueRequest}列表的对象,或者如果它们超过binder内存限制,则存储请求列表的共享内存文件,必须使用发送方和接收方的辅助库进行解析。
*/
void setValues(IVehicleCallback callback, in SetValueRequests requests);
/**
* 订阅属性事件。
*
* 客户端可以根据选项参数提供的数据订阅多个属性。
*
* 对于一个回调函数,只有一个属性的订阅。
* 使用不同的采样率进行新的订阅会覆盖旧的订阅。
* 一个属性可以多次订阅,用于不同的回调函数。
*
* 如果返回错误,则表示一些属性订阅失败。
* 调用者可以再次尝试,因为对已经订阅的属性进行订阅是可以的。
*
* 指定的采样率只是一个指导。无法保证实际的属性事件速率是否可达到,这取决于轮询刷新率。
* 实际的属性事件速率可能高于或低于指定的采样率。例如,如果轮询速率为每秒5次或每秒10次,
* 订阅采样率为7可能会使用每秒5次的轮询速率,从而生成每秒5个事件。我们只要求在平均情况下,
* 可以实现minSampleRate和maxSampleRate之间的所有采样率,生成的事件速率>=minSampleRate且<=maxSampleRate。
*
* 每个属性事件的{@link VehiclePropValue#timestamp}字段必须是系统启动后的系统运行时间,
* 当值发生变化时,对于ON_CHANGE属性,或者根据轮询速率检查值时,对于CONTINUOUS属性。
* 请注意,对于CONTINUOUS属性,VHAL客户端在轮询间隔内多次读取属性将获得相同的时间戳。
* 例如,如果属性的轮询速率为每秒10次,无论在{@code options}中指定的采样率是多少,
* 时间戳都会以每秒10次更新。
*
* 如果由于某些电源状态关闭而无法读取属性,则可能不会生成属性更改事件,
* 直到属性变为可用为止。对于ON_CHANGE属性,如果属性从NOT_AVAILABLE更改为OKAY,
* 以读取某些或所有区域的某个属性,则对于每个变为可读的区域,必须生成一个属性更改事件。
* 事件必须包含该区域的当前值,并且必须具有{@code AVAILABLE}状态。
*
* @param callback 订阅的回调函数。
* 当新的属性事件到达时,将调用{@link IVehicleCallback#onPropertyEvent}。
* 当属性设置请求失败时,将调用{@link IVehicleCallback#onPropertySetError}。
* 这通常是由车辆总线发送的属性设置失败消息引起的。
* @param options 订阅的选项列表。SubscribeOption包含属性ID、区域ID、采样率等信息。
* 对于连续属性,必须提供采样率。如果采样率小于{@link VehiclePropConfig#minSampleRate},
* 则采样率将为minSampleRate。如果采样率大于{@link VehiclePropValue#maxSampleRate},
* 则采样率将为maxSampleRate。
* @param maxSharedMemoryFileCount 在VHAL中为此订阅分配的共享内存文件的最大数量。
* 当一个内存文件被返回给客户端时,直到通过调用returnSharedMemory将缓冲区返回给VHAL,
* VHAL才能再次使用它来传递另一个事件。较大的maxSharedMemoryFileCount意味着在处理大量数据时性能更好,
* 但也意味着内存占用更大。如果不希望频繁到达事件,建议值为2。值为0表示对于每个新的属性,
* 都会创建一个新的共享内存文件,并且不会重用任何共享内存文件。这仅适用于不频繁到达的事件或内存有限的设备。
* 此值必须>=0且<{@link MAX_SHARED_MEMORY_FILES_PER_CLIENT}。
*/
void subscribe(in IVehicleCallback callback, in SubscribeOptions[] options,
int maxSharedMemoryFileCount);
/**
* 取消订阅属性事件。
*
* 如果'callback'无效,则此方法必须返回{@link StatusCode#INVALID_ARG}。
* 如果之前未订阅指定的propId,则此方法必须忽略该propId。
*
* 如果返回错误,则表示一些属性取消订阅失败。
* 调用者可以再次尝试,因为取消订阅已经取消订阅的属性是可以的。
*
* @param callback 之前订阅时使用的回调函数。
* @param propIds 要取消订阅的属性的ID。
*/
void unsubscribe(in IVehicleCallback callback, in int[] propIds);
/**
* 将共享内存文件返回给VHAL以进行回收。
*
* 在{@link IVehicleCallback#onPropertyEvent}返回的共享内存文件不再被客户端使用时,
* 必须调用此方法。这通常在'onPropertyEvent'的末尾调用。
*
* 如果'callback'无效或'sharedMemoryId'与传递给{@link IVehicleCallback#onPropertyEvent}的
* 'VehiclePropValues'中的任何SharedMemoryId不匹配,则此方法必须返回{@link StatusCode#INVALID_ARG}。
*
* @param callback 订阅时使用的回调函数。
* @param sharedMemoryId 由'onPropertyEvent'返回的表示要返回的已使用共享内存文件的ID。
*/
void returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId);
}
定义了一个名为IVehicle的接口,从 CarService 往 HAL 调用的接口。 该接口用于与车辆硬件交互,提供了获取车辆属性配置、获取车辆属性值、设置车辆属性值、订阅车辆属性事件等功能。
IVehicleCallback.aidl¶
hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl
@VintfStability
interface IVehicleCallback {
/**
* {@link IVehicle#getValues}函数的回调。
*
* 当一些要获取的值准备好时调用。对于一个'getValues'请求,可能会调用一次或多次。
* 每个回调包含请求的值的一部分。保证所有请求的值都会在其中一个回调中返回,但是每个值准备好的顺序不能保证。
*
* @param responses 一个对象,可以包含一个{@link GetValueResult}列表,如果它们符合Binder内存限制,或者包含一个包含响应的共享内存文件。
* 每个{@link GetValueResult}要么包含属性值,要么包含获取值时发生的错误。
*
* {@link GetValueResult}还包含一个requestId,指示此响应所属的请求。响应对象应该由{@code android-automotive-large-parcelable}库解析。
*/
oneway void onGetValues(in GetValueResults responses);
/**
* {@link IVehicle#setValues}函数的回调。
*
* 当VHAL完成处理一些属性设置请求时调用。对于一个'setValues'请求,可能会调用一次或多次。
* 每个回调包含请求的值的一部分。保证所有设置值的状态都会在其中一个回调中返回,但是每个值设置的顺序不能保证。
*
* @param responses 一个{@link SetValueResult}列表。每个SetValueResult包含一个指示设置特定属性状态的状态。
* requestId指示响应所属的请求。
*/
oneway void onSetValues(in SetValueResults responses);
/**
* 当API用户订阅的一个或多个变量需要报告时发生事件回调。这可能是基于阈值和频率(一个常规订阅,参见subscribe调用的参数),
* 或者当调用{@link IVehicle#setValues}方法并且需要报告实际更改时发生。
*
* @param propValues 包装在对象中的更新的属性值。
* 如果属性符合Binder限制,它们将在{@code propValues.payloads}中,否则它们将在一个共享内存文件{@code propValues.sharedMemoryFd}中。
* 共享内存文件由VHAL创建,并在使用后必须通过{@link IVehicle#returnSharedMemory}返回给VHAL。
* 每个订阅只创建有限数量的内存文件,如果客户端不返回共享内存,则客户端可能无法在将来收到事件。
* @param sharedMemoryFileCount 为此订阅分配的共享内存文件数。此值可用于调整{@link IVehicle#subscribe}中的{@code maxSharedMemoryFileCount}。
* 例如,如果通常看到sharedMemoryFileCount等于您设置的maxSharedMemoryFileCount,这意味着您可能需要增加maxSharedMemoryFileCount。
*/
oneway void onPropertyEvent(in VehiclePropValues propValues, int sharedMemoryFileCount);
/**
* 设置属性值通常是异步操作。因此,即使客户端从{@link IVehicle#setValues}接收到{@link StatusCode#OK},
* 或者在{@link #onSetValues}中接收到{@link StatusCode#OK},也不能保证该值已成功传播到车辆网络。
* 如果发生这种罕见事件,必须调用此方法。
*
* @param errors 一个属性设置错误列表。如果VHAL实现没有批处理错误,可能只包含一个错误。
*/
oneway void onPropertySetError(in VehiclePropErrors errors);
}
定义了一个接口IVehicleCallback
,用于处理车辆相关的回调函数(HAL 往 CarService 回调的接口)。它包含了四个回调函数,分别是:
- onGetValues
当获取车辆属性值的请求完成时调用。该回调可能会被调用一次或多次,每次回调都包含部分请求的属性值。所有请求的属性值都会在其中一个回调中返回,但属性值的顺序不保证一致。
-
onSetValues 当设置车辆属性值的请求完成时调用。该回调可能会被调用一次或多次,每次回调都包含部分请求的属性值。所有设置属性值的状态都会在其中一个回调中返回,但属性值的设置顺序不保证一致。
-
onPropertyEvent 当订阅的属性值需要报告时调用。这可能是基于阈值和频率的定期订阅,也可能是在调用了
IVehicle#setValues
方法后需要报告实际更改的情况。 -
onPropertySetError 当设置属性值的操作无法成功传播到车辆网络时调用。这是一个稀有事件,即使客户端从
IVehicle#setValues
或onSetValues
中收到StatusCode#OK
,也不能保证属性值已成功传播。如果发生这种情况,必须调用此方法。
数据类型¶
VehiclePropertyType¶
车辆属性类型
hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehiclePropertyType.aidl
/**
* 枚举支持的车辆属性数据类型。
*
* 用于在VehicleProperty枚举中创建属性ID。
*/
@VintfStability
@Backing(type="int")
enum VehiclePropertyType {
STRING = 0x00100000, // 字符串类型,1048576
BOOLEAN = 0x00200000, // 布尔类型,2097152
INT32 = 0x00400000, // 32位整数类型,4194304
INT32_VEC = 0x00410000, // 32位整数向量类型,4259840
INT64 = 0x00500000, // 64位整数类型,5242880
INT64_VEC = 0x00510000, // 64位整数向量类型,5308416
FLOAT = 0x00600000, // 浮点数类型,6291456
FLOAT_VEC = 0x00610000, // 浮点数向量类型,6356992
BYTES = 0x00700000, // 字节类型,7340032
/**
* 标量或向量类型的任意组合。具体格式必须在属性的描述中提供。
*
* 对于供应商的混合类型属性,configArray需要按照以下结构进行格式化。
*
* configArray[0],1表示属性具有字符串值
* configArray[1],1表示属性具有布尔值。
* configArray[2],1表示属性具有整数值。
* configArray[3],数字表示属性中整数数组的大小。
* configArray[4],1表示属性具有长整数值。
* configArray[5],数字表示属性中长整数数组的大小。
* configArray[6],1表示属性具有浮点数值。
* configArray[7],数字表示属性中浮点数数组的大小。
* configArray[8],数字表示属性中字节数组的大小。
* 例如:
* {@code configArray = {1, 1, 1, 3, 0, 0, 0, 0, 0}} 表示属性具有
* 字符串值、布尔值、整数值和一个包含3个整数的数组。
*/
MIXED = 0x00e00000, // 混合类型,14680064
MASK = 0x00ff0000 // 属性类型掩码,16711680
}
VehicleArea¶
车辆区域类型
hardware/interfaces/automotive/vehicle/2.0/types.hal
/**
* 车辆区域
* 用于构建 VehicleProperty 枚举中的属性ID。
*
* 一些属性可能与特定的车辆区域相关联。例如,VehicleProperty:DOOR_LOCK 属性必须与特定的车门相关联,
* 因此该属性必须标记为 VehicleArea:DOOR 标志。
*
* 其他属性可能与特定的车辆区域无关。这些属性必须具有 VehicleArea:GLOBAL 标志。
*
* [定义] 区域:区域表示 AreaType 的一个唯一元素。例如,如果 AreaType 是 WINDOW ,则一个区域可以是 FRONT_WINDSHIELD 。
*
* [定义] 区域ID:区域ID 是一个或多个区域的组合,使用 Area 枚举的位掩码表示。不同的 AreaType 不能在一个单独的 AreaID 中混合。
* 例如,窗口区域不能与座位区域组合在一个 AreaID 中。
*
* 映射分区属性到区域ID 的规则:
* - 属性必须映射到一个在属性值更改时受影响的 AreaID 数组。
* - 数组中的每个元素必须表示一个 AreaID ,在该 AreaID 中,属性值只能在 AreaID 中的所有区域中同时更改,而不能独立更改。
* 也就是说,当属性值在数组中的一个区域中更改时,它必须自动在 AreaID 中的所有其他区域中更改。
* - 属性值必须在数组中的任意两个不同的 AreaID 中独立可控。
* - 区域在 AreaID 数组中只能出现一次。也就是说,一个区域只能是 AreaID 数组中的一个区域。
*
* [定义] 全局属性:适用于整个车辆并且不与特定区域相关联的属性。例如,FUEL_LEVEL,HVAC_STEERING_WHEEL_HEAT。
*
* 映射全局属性到区域ID 的规则:
* - 全局属性不得映射到区域ID。
*/
enum VehicleArea {
GLOBAL = 0x01000000, // 16777216
WINDOW = 0x03000000, // WINDOW映射到VehicleAreaWindow枚举,50331648
MIRROR = 0x04000000, // MIRROR映射到VehicleAreaMirror枚举,67108864
SEAT = 0x05000000, // SEAT映射到VehicleAreaSeat枚举,83886080
DOOR = 0x06000000, // DOOR映射到VehicleAreaDoor枚举,100663296
WHEEL = 0x07000000, // WHEEL映射到VehicleAreaWheel枚举,117440512
MASK = 0x0f000000, //251658240
};
VehiclePropertyGroup¶
车辆属性分组类型
hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl
/**
* 定义了属性组的枚举类型。
*
* 用于在VehicleProperty枚举中创建属性ID。
*/
enum VehiclePropertyGroup {
/**
*
*/
SYSTEM = 0x10000000, // 在AOSP中声明的属性必须使用此标志, 268435456
/**
*
*/
VENDOR = 0x20000000, // 由供应商声明的属性必须使用此标志, 536870912
MASK = 0xf0000000, // -268435456 ?
}
VehicleAreaWindow¶
车辆窗户区域属性
hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl
/**
* 定义了车辆中的各种挡风玻璃/窗户。
*/
@VintfStability
@Backing(type="int")
enum VehicleAreaWindow {
FRONT_WINDSHIELD = 0x00000001, // 前挡风玻璃,1
REAR_WINDSHIELD = 0x00000002, // 后挡风玻璃,2
ROW_1_LEFT = 0x00000010, // 第一排左侧窗户,16
ROW_1_RIGHT = 0x00000040, // 第一排右侧窗户,64
ROW_2_LEFT = 0x00000100, // 第二排左侧窗户,256
ROW_2_RIGHT = 0x00000400, // 第二排右侧窗户,1024
ROW_3_LEFT = 0x00001000, // 第三排左侧窗户,4096
ROW_3_RIGHT = 0x00004000, // 第三排右侧窗户,16384
ROOF_TOP_1 = 0x00010000, // 顶部1号窗户,65536
ROOF_TOP_2 = 0x00020000, // 顶部2号窗户,131072
};
VehiclePropertyAccess¶
车辆属性访问权限
hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl
/**
* VehiclePropertyAccess是一个枚举类型,用于定义车辆属性的访问权限。
* 用户在使用API之前,必须先获取属性配置,以了解从get()命令获取的输出,
* 并确保set()或事件命令与预期输出同步。
*/
@VintfStability
@Backing(type="int")
enum VehiclePropertyAccess {
/**
* 表示无访问权限
*/
NONE = 0x00,
/**
* 表示只读权限
*/
READ = 0x01,
/**
* 表示只写权限
*/
WRITE = 0x02,
/**
* 表示读写权限
*/
READ_WRITE = 0x03,
}
VehiclePropertyChangeMode¶
hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl
/**
* 描述属性值如何变化的枚举类型
*/
@VintfStability
@Backing(type="int")
enum VehiclePropertyChangeMode {
/**
* 此类型的属性不能被更改。不支持对这些属性进行 subscribe 订阅。只能 IVehicle.get() 获取
*/
STATIC = 0x00,
/**
* ON_CHANGE 这个类型的属性当变化时必须上报
* 此类型的属性在发生变化时必须报告。 IVehicle.get() 调用必须返回当前值。
* 对于此属性的设置操作被假定为异步的。当在 IVehicle.set() 之后读取属性(使用 IVehicle.get() )时,
* 它可能仍然返回旧值,直到支持此属性的底层硬件实际上改变了状态。一旦状态改变,属性必须作为事件分发已更改的值。
*/
ON_CHANGE = 0x01,
/**
* 此类型的属性连续变化,并且需要固定的采样率来检索数据。实现者可以选择在重要的值变化时发送额外的通知。
*/
CONTINUOUS = 0x02,
};
SubscribeOptions¶
车辆属性事件订阅信息
hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl、
/**
* 封装了有关订阅车辆属性事件的信息。
*/
@VintfStability
@JavaDerive(equals=true, toString=true)
parcelable SubscribeOptions {
/**
* 要订阅的属性。
*/
int propId;
/**
* 可选的订阅此属性的区域,如果为空,则订阅为此属性配置的所有区域。
*/
int[] areaIds;
/**
* 采样率,以赫兹(Hz)为单位。
*
* 对于具有 VehiclePropertyChangeMode::CONTINUOUS 的属性,必须提供。
* 该值必须在给定属性的 VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate 范围内。
* 此值表示客户端希望每秒接收多少次更新。
*/
float sampleRate;
}
如果了解 Android S 代码可以知道,在 SubscribeOptions 有一个类型为 SubscribeFlags 的 flags,也就是:
enum SubscribeFlags : int32_t {
UNDEFINED = 0x0,
/**
* 订阅来自车辆HAL的事件
* (很可能是车辆本身产生的事件)。
*/
EVENTS_FROM_CAR = 0x1,
/**
* 使用此标志订阅当车辆HAL的客户端(例如Car Service)调用 IVehicle.set(...) 时的事件。
*/
EVENTS_FROM_ANDROID = 0x2,
};
但是在 Android U 中,已经没有 flags 了。
VehicleAreaSeat¶
车辆座椅属性
hardware/interfaces/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
/**
* 不同的车辆座位。
*/
@VintfStability
@Backing(type="int")
enum VehicleAreaSeat {
ROW_1_LEFT = 0x0001, // 第一排左侧座位, 1
ROW_1_CENTER = 0x0002, // 第一排中间座位, 2
ROW_1_RIGHT = 0x0004, // 第一排右侧座位, 4
ROW_2_LEFT = 0x0010, // 第二排左侧座位, 16
ROW_2_CENTER = 0x0020, // 第二排中间座位, 32
ROW_2_RIGHT = 0x0040, // 第二排右侧座位, 64
ROW_3_LEFT = 0x0100, // 第三排左侧座位, 256
ROW_3_CENTER = 0x0200, // 第三排中间座位, 512
ROW_3_RIGHT = 0x0400 // 第三排右侧座位, 1024
};
StatusCode¶
hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl
/**
* 车辆HAL接口中使用的错误代码。
*/
@VintfStability
@Backing(type="int")
enum StatusCode {
OK = 0, // 表示操作成功
TRY_AGAIN = 1, // 表示调用者应该重试
INVALID_ARG = 2, // 表示提供的参数无效
NOT_AVAILABLE = 3, // 表示属性当前不可用
ACCESS_DENIED = 4, // 表示访问被拒绝
INTERNAL_ERROR = 5, // 表示发生了意外错误
NOT_AVAILABLE_DISABLED = 6, // 表示由于底层功能被禁用而不可用
NOT_AVAILABLE_SPEED_LOW = 7, // 表示由于车速过低而不可用
NOT_AVAILABLE_SPEED_HIGH = 8, // 表示由于车速过高而不可用
NOT_AVAILABLE_POOR_VISIBILITY = 9, // 表示由于相机或传感器的可见性差而不可用
NOT_AVAILABLE_SAFETY = 10, // 表示由于安全原因无法访问
}
2. VehicleHal初始化¶
VehicleService::main()¶
初始化从执行 hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp 的main函数开始:
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
int main(int /* argc */, char* /* argv */[]) {
ALOGI("Starting thread pool...");
if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) {
ALOGE("%s", "failed to set thread pool max thread count");
return 1;
}
ABinderProcess_startThreadPool();
// 创建一个 FakeVehicleHardware 对象的智能指针
std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
// 创建一个 DefaultVehicleHal 对象的共享指针,并传入 FakeVehicleHardware 对象的移动构造函数
std::shared_ptr<DefaultVehicleHal> vhal =
::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
ALOGI("Registering as service...");
// 将 DefaultVehicleHal 对象注册为名为 "android.hardware.automotive.vehicle.IVehicle/default" 的服务
binder_exception_t err = AServiceManager_addService(
vhal->asBinder().get(), "android.hardware.automotive.vehicle.IVehicle/default");
// 如果注册失败,则打印错误日志并返回1
if (err != EX_NONE) {
ALOGE("failed to register android.hardware.automotive.vehicle service, exception: %d", err);
return 1;
}
ALOGI("Vehicle Service Ready");
ABinderProcess_joinThreadPool();
ALOGI("Vehicle Service Exiting");
return 0;
}
FakeVehicleHardware¶
FakeVehicleHardware 继承自 IVehicleHardware 接口。提供了一系列方法来获取和设置车辆属性的值,并提供了一些辅助方法来处理和生成虚拟数据。
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
class FakeVehicleHardware : public IVehicleHardware {
public:
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
getAllPropertyConfigs() const override;
aidl::android::hardware::automotive::vehicle::StatusCode setValues(
std::shared_ptr<const SetValuesCallback> callback,
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
requests) override;
aidl::android::hardware::automotive::vehicle::StatusCode getValues(
std::shared_ptr<const GetValuesCallback> callback,
const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
requests) const override;
...
};
IVehicleHardware 接口如下:
hardware/interfaces/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
/ 一个用于访问车辆硬件的抽象接口。
// 对于虚拟化的 VHAL,GrpcVehicleHardware将通过GRPC与另一个虚拟机中的VehicleHardware实现进行通信。对于非虚拟化的VHAL,VHAL直接通过该接口与VehicleHardware进行通信。
class IVehicleHardware {
public:
using SetValuesCallback = std::function<void(
std::vector<aidl::android::hardware::automotive::vehicle::SetValueResult>)>;
using GetValuesCallback = std::function<void(
std::vector<aidl::android::hardware::automotive::vehicle::GetValueResult>)>;
using PropertyChangeCallback = std::function<void(
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>;
using PropertySetErrorCallback = std::function<void(std::vector<SetValueErrorEvent>)>;
virtual ~IVehicleHardware() = default;
// 获取所有属性的配置。
virtual std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
getAllPropertyConfigs() const = 0;
// 异步设置属性值。服务器可能在属性设置请求发送到车辆总线之前或接收到属性设置确认之前返回。回调函数在函数返回后可以安全地调用,并且可以在不同的线程中调用。
virtual aidl::android::hardware::automotive::vehicle::StatusCode setValues(
std::shared_ptr<const SetValuesCallback> callback,
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
requests) = 0;
// 异步获取属性值。服务器可能在属性值准备好之前返回。回调函数在函数返回后可以安全地调用,并且可以在不同的线程中调用。
virtual aidl::android::hardware::automotive::vehicle::StatusCode getValues(
std::shared_ptr<const GetValuesCallback> callback,
const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
requests) const = 0;
// 如果服务器支持,更新指定属性和指定区域ID(全局属性为0)的采样率。属性必须是连续属性。
// sampleRate表示对于该特定属性,服务器必须每秒生成至少这么多个OnPropertyChange事件。
// sampleRate为0表示不再订阅该属性,服务器不需要为该属性生成任何onPropertyEvent。
// 如果为订阅者更新了采样率、添加了新的订阅者或删除了现有的订阅者,则会调用此函数。例如:
// 1. 对于速度,我们没有订阅者。
// 2. 一个新的订阅者正在以10次/秒的速度订阅速度,updateSampleRate将以10为sampleRate进行调用。实现现在正在以10次/秒的频率从总线轮询车速。
// 3. 一个新的订阅者正在以5次/秒的速度订阅速度,因为它小于10次/秒,不会调用updateSampleRate。
// 4. 删除初始订阅者,updateSampleRate将以5为sampleRate进行调用,因为现在只需要报告5次/秒的事件。实现现在可以以5次/秒的频率轮询车速。如果实现仍然以10次/秒的频率轮询,那是可以的,只要轮询速率大于5次/秒。DefaultVehicleHal将忽略额外的事件。
// 5. 删除第二个订阅者,updateSampleRate将以0为sampleRate进行调用。实现可以选择禁用车速的轮询。
//
// 如果实现始终以配置中指定的maxSampleRate进行轮询,则此函数可以是一个空操作。
virtual aidl::android::hardware::automotive::vehicle::StatusCode updateSampleRate(
[[maybe_unused]] int32_t propId, [[maybe_unused]] int32_t areaId,
[[maybe_unused]] float sampleRate) {
return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
}
// 在服务器中转储调试信息。
virtual DumpResult dump(const std::vector<std::string>& options) = 0;
// 检查系统是否健康,对于健康的情况返回StatusCode::OK。
virtual aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() = 0;
// 注册在有车辆属性变化事件时调用的回调函数。在初始化期间只能调用一次。
virtual void registerOnPropertyChangeEvent(
std::unique_ptr<const PropertyChangeCallback> callback) = 0;
// 注册在有车辆属性设置错误事件时调用的回调函数。在初始化期间只能调用一次。
virtual void registerOnPropertySetErrorEvent(
std::unique_ptr<const PropertySetErrorCallback> callback) = 0;
};
现在我们来看 FakeVehicleHardware 初始化都做了哪些事情。
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
FakeVehicleHardware::FakeVehicleHardware()
: FakeVehicleHardware(DEFAULT_CONFIG_DIR, OVERRIDE_CONFIG_DIR, false) {}
FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
std::string overrideConfigDir, bool forceOverride)
: mValuePool(std::make_unique<VehiclePropValuePool>()), // 创建一个VehiclePropValuePool对象,并使用智能指针进行管理
mServerSidePropStore(new VehiclePropertyStore(mValuePool)), // 创建一个VehiclePropertyStore对象,并使用智能指针进行管理
mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)), // 创建一个FakeObd2Frame对象,并使用智能指针进行管理
mFakeUserHal(new FakeUserHal(mValuePool)), // 创建一个FakeUserHal对象,并使用智能指针进行管理
mRecurrentTimer(new RecurrentTimer()), // 创建一个RecurrentTimer对象,并使用智能指针进行管理
mGeneratorHub(new GeneratorHub(
[this](const VehiclePropValue& value) { eventFromVehicleBus(value); })), // 创建一个GeneratorHub对象,并使用智能指针进行管理,同时传入一个lambda表达式作为参数
mPendingGetValueRequests(this), // 创建一个PendingRequests对象,并使用当前对象的指针进行初始化
mPendingSetValueRequests(this), // 创建一个PendingRequests对象,并使用当前对象的指针进行初始化
mDefaultConfigDir(defaultConfigDir), // 初始化mDefaultConfigDir成员变量
mOverrideConfigDir(overrideConfigDir), // 初始化mOverrideConfigDir成员变量
mForceOverride(forceOverride) { // 初始化mForceOverride成员变量
init(); // 调用init()函数进行初始化操作
}
-
mValuePool 创建 VehiclePropValuePool 对象,并使用智能指针进行管理。
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
-
mServerSidePropStore 创建一个 VehiclePropertyStore 对象,并使用智能指针进行管理。 创建 VehiclePropertyStore 时,把 mValuePool 传进去。
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
-
mFakeObd2Frame FakeObd2Frame 提供了一些方法来填充和操作 OBD-II(On-Board Diagnostics)传感器数据。
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp
-
mFakeUserHal 用于模拟真实的用户HAL行为。如:检查模拟器是否支持某个属性、允许模拟器设置属性、从模拟器获取属性值等。
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
-
mRecurrentTimer 实现了一个线程安全的循环定时器。
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
-
mGeneratorHub 所有VHAL事件生成器的调度器。管理所有生成器,并使用优先级队列来维护按时间戳排序的生成的事件。调度器使用单个线程来查询和更新事件队列,以确保所有生成器的事件按顺序产生。
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
-
mPendingGetValueRequests 使用线程安全的方式处理 getValue 请求。
-
mPendingSetValueRequests 使用线程安全的方式处理 setValue 请求。
-
mDefaultConfigDir /vendor/etc/automotive/vhalconfig/
-
mOverrideConfigDir /vendor/etc/automotive/vhaloverride/
-
init() 目录 mDefaultConfigDir (或者 mOverrideConfigDir )读取 json 配置文件,并全部加载。
在 Android S 中。是把 hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h 里声明的 kVehicleProperties 配置全部加载。
Android U (没看过 Android T,也行是在 T 上就改了)改成目录下的文件,自定义度高。
下面我们先来分析关键的部分。
VehiclePropertyValue¶
VehiclePropertyValue 是线程安全的。用户可以在一个线程中获取一个对象,并将其传递给另一个线程。 它只有一个重载的公共方法 - obtain(...),当需要一个新的对象时,用户必须调用此方法,并提供 VehiclePropertyType 和 vector 大小(对于vector属性)。 示例用法:
VehiclePropValuePool pool;
auto v = pool.obtain(VehiclePropertyType::INT32);
v->propId = VehicleProperty::HVAC_FAN_SPEED;
v->areaId = VehicleAreaSeat::ROW_1_LEFT;
v->timestamp = elapsedRealtimeNano();
v->value->int32Values[0] = 42;
VehiclePropertyStore¶
VehiclePropertyStore的类,用于存储和访问车辆属性的配置和值。
- registerProperty:注册车辆属性的配置。
- writeValue:存储提供的属性值。
- removeValue:删除指定的属性值。
- removeValuesForProperty:删除指定属性的所有值。
- readAllValues:读取所有属性的值。
- readValuesForProperty:读取指定属性的所有值。
- readValue:读取指定属性的属性值。
- getAllConfigs:获取所有属性的配置信息。
- getConfig:获取指定属性的配置信息。
- setOnValueChangeCallback:设置属性值更新时的回调函数。
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
class VehiclePropertyStore final {
public:
...
void registerProperty(
const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config,
TokenFunction tokenFunc = nullptr);
VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
bool updateStatus = false,
EventMode mode = EventMode::ON_VALUE_CHANGE);
void removeValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
void removeValuesForProperty(int32_t propId);
std::vector<VehiclePropValuePool::RecyclableType> readAllValues() const;
ValuesResultType readValuesForProperty(int32_t propId) const;
ValueResultType readValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const;
ValueResultType readValue(int32_t prop, int32_t area = 0, int64_t token = 0) const;
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllConfigs()
const;
android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*,
VhalError>
getConfig(int32_t propId) const;
void setOnValueChangeCallback(const OnValueChangeCallback& callback);
inline std::shared_ptr<VehiclePropValuePool> getValuePool() { return mValuePool; }
...
}
FakeUserHal¶
FakeUserHal 用于模拟用户 HAL 的行为,通过使用 lshal 调试请求来实现。
对应的是 Android S 的 EmulatedUserHal
- isSupported():检查模拟器是否支持给定的属性。
- onSetProperty():允许模拟器设置属性,并返回更新后的属性和状态码。
- onGetProperty():从模拟器获取属性值,并返回属性值和状态码。
- dump():lshal 命令 dump
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
// 用于通过lshal调试请求模拟真实User HAL行为的类。
class FakeUserHal final {
public:
...
// 检查模拟器是否能处理该属性。
static bool isSupported(int32_t prop);
// 允许模拟器设置属性。
//
// @return 更新后的属性和StatusCode
ValueResultType onSetProperty(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
// 从模拟器获取属性值。
//
// @return 属性值和StatusCode
ValueResultType onGetProperty(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
// 显示User HAL模拟帮助。
std::string showDumpHelp() const;
// 转储其内容。
std::string dump() const;
...
}
FakeVehicleHardware::init()¶
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
std::unordered_map<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId);
if (mForceOverride ||
android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false)) {
loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId);
}
return configsByPropId;
}
// 从指定目录加载属性配置文件
void FakeVehicleHardware::loadPropConfigsFromDir(
const std::string& dirPath,
std::unordered_map<int32_t, ConfigDeclaration>* configsByPropId) {
ALOGI("loading properties from %s", dirPath.c_str());
if (auto dir = opendir(dirPath.c_str()); dir != NULL) {
// 创建一个正则表达式,用于匹配以.json结尾的文件
std::regex regJson(".*[.]json", std::regex::icase);
// 遍历目录中的文件
while (auto f = readdir(dir)) {
// 如果文件名不匹配正则表达式,则跳过该文件
if (!std::regex_match(f->d_name, regJson)) {
continue;
}
// 构建文件的完整路径
std::string filePath = dirPath + "/" + std::string(f->d_name);
ALOGI("loading properties from %s", filePath.c_str());
// 调用mLoader对象的loadPropConfig方法加载属性配置文件
auto result = mLoader.loadPropConfig(filePath);
if (!result.ok()) {
ALOGE("failed to load config file: %s, error: %s", filePath.c_str(),
result.error().message().c_str());
continue; // 继续处理下一个文件
}
// 遍历加载成功的属性配置
for (auto& [propId, configDeclaration] : result.value()) {
// 将属性配置添加到configsByPropId中
(*configsByPropId)[propId] = std::move(configDeclaration);
}
}
closedir(dir); // 关闭目录
}
}
void FakeVehicleHardware::init() {
// 加载配置声明并遍历
for (auto& [_, configDeclaration] : loadConfigDeclarations()) {
VehiclePropConfig cfg = configDeclaration.config;
VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
// 如果属性是 AP_POWER_STATE_REQ
if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
// 获取 POWER_STATE_REQ_CONFIG_PROPERTY 的值作为配置
int config = GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0);
cfg.configArray[0] = config;
}
// 如果属性是 OBD2_FREEZE_FRAME
else if (cfg.prop == OBD2_FREEZE_FRAME) {
// 设置 tokenFunction 为一个 lambda 函数,返回 propValue 的时间戳
tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
}
// 注册属性到 mServerSidePropStore
mServerSidePropStore->registerProperty(cfg, tokenFunction);
// 如果是诊断属性,则忽略存储默认值,因为它们有特殊的get/set逻辑
if (obd2frame::FakeObd2Frame::isDiagnosticProperty(cfg)) {
continue;
}
// 存储属性的初始值
storePropInitialValue(configDeclaration);
}
// OBD2_LIVE_FRAME 和 OBD2_FREEZE_FRAME 必须在默认配置中进行配置
auto maybeObd2LiveFrame = mServerSidePropStore->getConfig(OBD2_LIVE_FRAME);
if (maybeObd2LiveFrame.has_value()) {
// 初始化mFakeObd2Frame 的O BD2_LIVE_FRAME
mFakeObd2Frame->initObd2LiveFrame(*maybeObd2LiveFrame.value());
}
auto maybeObd2FreezeFrame = mServerSidePropStore->getConfig(OBD2_FREEZE_FRAME);
if (maybeObd2FreezeFrame.has_value()) {
// 初始化 mFakeObd2Frame 的 OBD2_FREEZE_FRAME
mFakeObd2Frame->initObd2FreezeFrame(*maybeObd2FreezeFrame.value());
}
// 设置 mServerSidePropStore 的值改变回调函数
mServerSidePropStore->setOnValueChangeCallback(
[this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
}
-
从目录 mDefaultConfigDir (或者 mOverrideConfigDir )读取 json 配置文件,解析后存在 configsByPropId 。
-
遍历 configsByPropId
-
针对 AP_POWER_STATE_REQ 、OBD2_FREEZE_FRAME 做一些特殊处理
-
注册属性到 mServerSidePropStore(也就是 VehiclePropertyStore )
void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
VehiclePropertyStore::TokenFunction tokenFunc) {
std::scoped_lock<std::mutex> g(mLock);
mRecordsByPropId[config.prop] = Record{
.propConfig = config,
.tokenFunction = tokenFunc,
};
}
-
如果是 OBD-II(On-Board Diagnostics),则忽略存储默认值,因为它们有特殊的get/set逻辑
-
OBD2_LIVE_FRAME 、OBD2_FREEZE_FRAME 必须在默认配置中进行配置
-
存储属性的初始值 storePropInitialValue() 函数做关键的部分其实就是调 mServerSidePropStore->writeValue(mValuePool->obtain(prop), true) 。
-
设置回调函数,如果 VehiclePropertyStore 值变化,回调到 FakeVehicleHardware::onValueChangeCallback() 。
DefaultVehicleHal¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehicle::BnVehicle {
public:
// 定义回调类型
using CallbackType =
std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
// 构造函数,接受一个指向IVehicleHardware对象的unique_ptr
explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
// 获取所有属性配置的方法,返回一个VehiclePropConfigs对象
ndk::ScopedAStatus getAllPropConfigs(
aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
override;
// 获取属性值的方法,接受一个回调函数和GetValueRequests对象
ndk::ScopedAStatus getValues(
const CallbackType& callback,
const aidl::android::hardware::automotive::vehicle::GetValueRequests& requests)
override;
// 设置属性值的方法,接受一个回调函数和SetValueRequests对象
ndk::ScopedAStatus setValues(
const CallbackType& callback,
const aidl::android::hardware::automotive::vehicle::SetValueRequests& requests)
override;
// 获取指定属性配置的方法,接受一个属性ID的vector和一个VehiclePropConfigs对象
ndk::ScopedAStatus getPropConfigs(
const std::vector<int32_t>& props,
aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
override;
// 订阅属性值变化的方法,接受一个回调函数、SubscribeOptions对象的vector和最大共享内存文件数
ndk::ScopedAStatus subscribe(
const CallbackType& callback,
const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
options,
int32_t maxSharedMemoryFileCount) override;
// 取消订阅属性值变化的方法,接受一个回调函数和属性ID的vector
ndk::ScopedAStatus unsubscribe(const CallbackType& callback,
const std::vector<int32_t>& propIds) override;
// 返回共享内存的方法,接受一个回调函数和共享内存ID
ndk::ScopedAStatus returnSharedMemory(const CallbackType& callback,
int64_t sharedMemoryId) override;
// 输出调试信息的方法,接受一个文件描述符、参数数组和参数数量
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
// 获取IVehicleHardware对象的方法
IVehicleHardware* getHardware();
};
下面我们来看 DefaultVehicleHal 的构造函数。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
// DefaultVehicleHal类的构造函数
DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
: mVehicleHardware(std::move(vehicleHardware)),
mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
// 从 VehiclePropertyStore 的 mRecordsByPropId 成员变量里获取属性
if (!getAllPropConfigsFromHardware()) {
return;
}
// 初始化 mSubscriptionClients 成员变量
mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool);
// 创建 subscribeIdByClient 智能指针
auto subscribeIdByClient = std::make_shared<SubscribeIdByClient>();
// 获取 mVehicleHardware 的原始指针
IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
// 初始化 mSubscriptionManager 成员变量
mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
// 创建 subscriptionManagerCopy 弱指针,指向 mSubscriptionManager
std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
// 调用 mVehicleHardware 的 registerOnPropertyChangeEvent 函数,传入一个 PropertyChangeCallback 对象
mVehicleHardware->registerOnPropertyChangeEvent(
std::make_unique<IVehicleHardware::PropertyChangeCallback>(
[subscriptionManagerCopy](std::vector<VehiclePropValue> updatedValues) { // PropertyChangeCallback 的构造函数接收一个 lambda 表达式作为参数
onPropertyChangeEvent(subscriptionManagerCopy, updatedValues); // 调用 onPropertyChangeEvent 函数,传入 subscriptionManagerCopy 和 updatedValues
}));
// 注册心跳事件
mRecurrentAction = std::make_shared<std::function<void()>>(
[vehicleHardwarePtr, subscriptionManagerCopy]() { // 创建一个 lambda 表达式作为 mRecurrentAction 的值
checkHealth(vehicleHardwarePtr, subscriptionManagerCopy); // 调用 checkHealth 函数,传入 vehicleHardwarePtr 和 subscriptionManagerCopy
});
// 注册定时器回调函数
mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
// 创建 mBinderLifecycleHandler对象
mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
// 创建一个新的线程,调用 onBinderDiedUnlinkedHandler 函数
mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
mDeathRecipient = ScopedAIBinder_DeathRecipient(
// 创建 mDeathRecipient 对象,并设置 onBinderDied 函数为回调函数
AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
// 设置 mDeathRecipient 的 onBinderUnlinked 函数为回调函数
AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
&DefaultVehicleHal::onBinderUnlinked);
}
-
mVehicleHardware 就是 VehicleService::main() 创建的 FakeVehicleHardware 对象。
-
mPendingRequestPool 线程安全的待处理请求池,用于跟踪每个请求是否超时。
-
mSubscriptionClients 用于存储所有订阅客户端。
-
subscribeIdByClient 为每个订阅客户端维护一个递增的请求ID。
-
mSubscriptionManager 线程安全的订阅管理器,用于管理所有VHAL订阅。
-
VehicleHardware::registerOnPropertyChangeEvent() 调用 mVehicleHardware 的 registerOnPropertyChangeEvent 函数,传入一个 PropertyChangeCallback 对象。 PropertyChangeCallback 的构造函数接收一个 lambda 表达式作为参数,调用 onPropertyChangeEvent 函数,传入 subscriptionManagerCopy 和 updatedValues。
-
VehicleHardware::checkHealth() 通过 RecurrentTimer 计时器注册 3S 的心跳事件。
-
根据 Binder 生命周期 从 mSubscriptionClients、mSubscriptionManager、mSetValuesClients、mGetValuesClients 移除掉相应的客户端id 。
PendingRequestPool¶
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
// 一个线程安全的待处理请求池,用于跟踪每个请求是否超时。
class PendingRequestPool final {
public:
// 定义超时回调函数类型
using TimeoutCallbackFunc = std::function<void(const std::unordered_set<int64_t>&)>;
// 构造函数,传入超时时间(纳秒)
explicit PendingRequestPool(int64_t timeoutInNano);
// 将一组请求添加到请求池中。
// clientId是所有请求的键。它可以是一个数字或表示客户端的数据结构的地址。调用者必须维护此数据结构。
// 所有请求的requestId必须对于一个客户端是唯一的,如果任何一个requestId与客户端的任何待处理请求的requestId重复,
// 则此函数返回错误,并且不会添加任何请求。否则,它们将被添加到请求池中。
// 如果请求在{@code mTimeoutInNano}秒内未完成,则会调用回调函数。
VhalResult<void> addRequests(const void* clientId,
const std::unordered_set<int64_t>& requestIds,
std::shared_ptr<const TimeoutCallbackFunc> callback);
// 检查请求当前是否处于待处理状态。
bool isRequestPending(const void* clientId, int64_t requestId) const;
// 尝试标记请求为已完成并从池中删除,如果请求当前处于待处理状态。返回已成功完成的待处理请求列表。
// 即使一些requestIds无效,此函数也会尝试完成任何有效的requestIds。
std::unordered_set<int64_t> tryFinishRequests(const void* clientId,
const std::unordered_set<int64_t>& requestIds);
// 返回池中待处理请求的数量,用于测试目的。
size_t countPendingRequests(const void* clientId) const;
// 返回池中所有待处理请求的数量,用于测试目的。
size_t countPendingRequests() const;
};
SubscriptionClients¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
// 一个线程安全的类,用于存储所有订阅客户端。这个类在异步回调中传递是安全的。
class SubscriptionClients {
public:
// 构造函数,接受一个共享指针类型的PendingRequestPool对象作为参数
SubscriptionClients(std::shared_ptr<PendingRequestPool> pool) : mPendingRequestPool(pool) {}
// 可能添加一个客户端到订阅列表中,并返回一个共享指针类型的SubscriptionClient对象
std::shared_ptr<SubscriptionClient> maybeAddClient(const CallbackType& callback);
// 根据回调函数获取一个客户端,并返回一个共享指针类型的SubscriptionClient对象
std::shared_ptr<SubscriptionClient> getClient(const CallbackType& callback);
// 根据客户端ID移除一个客户端
void removeClient(const AIBinder* clientId);
// 返回当前订阅客户端的数量
size_t countClients();
...
};
SubscribeIdByClient¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
// 一个线程安全的类,用于为每个订阅客户端维护一个递增的请求ID。该类可以安全地传递给异步回调函数。
class SubscribeIdByClient {
public:
// 获取给定回调函数的ID
int64_t getId(const CallbackType& callback);
private:
// 互斥锁,用于保护mIds的并发访问
std::mutex mLock;
// 使用AIBinder指针作为键,将回调函数的ID存储在unordered_map中
std::unordered_map<const AIBinder*, int64_t> mIds GUARDED_BY(mLock);
};
SubscriptionManager¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
// 一个线程安全的订阅管理器,用于管理所有VHAL订阅。
class SubscriptionManager final {
public:
// 定义ClientIdType为const AIBinder*类型
using ClientIdType = const AIBinder*;
using CallbackType =
std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
// 构造函数,接受一个IVehicleHardware指针参数
explicit SubscriptionManager(IVehicleHardware* vehicleHardware);
// 根据{@code SubscribeOptions}订阅属性。注意,所有选项必须包含非空的areaIds字段,其中包含要订阅的所有区域ID。
// 因此,这里的选项与从VHAL客户端传递的选项不同。
// 如果任何订阅选项无效或一个属性订阅失败,则返回错误。如果此函数返回错误,则部分属性可能已成功订阅。
// 调用者可以安全地重试,因为订阅已经订阅的属性是可以的。
// 如果所有选项都正确解析并且所有属性都已订阅,则返回ok。
VhalResult<void> subscribe(
const CallbackType& callback, // 回调函数
const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
options, // 订阅选项
bool isContinuousProperty); // 是否是连续属性
// 取消订阅客户端的属性。
// 如果客户端之前未订阅,或者给定的属性之一未订阅,或者一个属性取消订阅失败,则返回错误。
// 调用者可以安全地重试,因为取消订阅已取消订阅的属性是可以的(将被忽略)。
// 如果客户端的所有请求属性都已取消订阅,则返回ok。
VhalResult<void> unsubscribe(ClientIdType client, const std::vector<int32_t>& propIds);
// 取消订阅客户端的所有属性。
// 如果客户端之前未订阅,或者客户端的一个已订阅属性取消订阅失败,则返回错误。调用者可以安全地重试。
// 如果客户端的所有属性都已取消订阅,则返回ok。
VhalResult<void> unsubscribe(ClientIdType client);
// 对于更新的属性列表,返回一个将订阅更新的客户端映射到更新值列表的映射。
// 这只会返回应该通知给定更新值的on-change属性客户端。
std::unordered_map<
CallbackType,
std::vector<const aidl::android::hardware::automotive::vehicle::VehiclePropValue*>>
getSubscribedClients(
const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
updatedValues);
// 检查采样率是否有效。
static bool checkSampleRateHz(float sampleRateHz);
...
}
DefaultVehicleHal::onPropertyChangeEvent()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
// 调用 mVehicleHardware 的 registerOnPropertyChangeEvent 函数,传入一个 PropertyChangeCallback 对象
mVehicleHardware->registerOnPropertyChangeEvent(
std::make_unique<IVehicleHardware::PropertyChangeCallback>(
[subscriptionManagerCopy](std::vector<VehiclePropValue> updatedValues) { // PropertyChangeCallback 的构造函数接收一个 lambda 表达式作为参数
onPropertyChangeEvent(subscriptionManagerCopy, updatedValues); // 调用 onPropertyChangeEvent 函数,传入 subscriptionManagerCopy 和 updatedValues
}));
在 DefaultVehicleHal 的构造函数里调用 mVehicleHardware 的 registerOnPropertyChangeEvent 函数,传入一个 PropertyChangeCallback 对象。PropertyChangeCallback 的构造函数接收一个 lambda 表达式作为参数,调用 onPropertyChangeEvent 函数,传入 subscriptionManagerCopy 和 updatedValues 。
mVehicleHardware 就是 FakeVehicleHardware。
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
using PropertyChangeCallback = std::function<void(
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>;
// Only allowed to set once.
std::unique_ptr<const PropertyChangeCallback> mOnPropertyChangeCallback;
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
void FakeVehicleHardware::registerOnPropertyChangeEvent(
std::unique_ptr<const PropertyChangeCallback> callback) {
if (mOnPropertyChangeCallback != nullptr) {
ALOGE("registerOnPropertyChangeEvent must only be called once");
return;
}
mOnPropertyChangeCallback = std::move(callback);
}
继续在 FakeVehicleHardware 找 mOnPropertyChangeCallback 在哪里用:
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
// 检查是否存在属性变化回调函数
if (mOnPropertyChangeCallback == nullptr) {
return;
}
// 创建一个存储 VehiclePropValue 类型的向量 updatedValues
std::vector<VehiclePropValue> updatedValues;
// 将传入的 value 添加到 updatedValues 向量中
updatedValues.push_back(value);
// 调用 mOnPropertyChangeCallback 函数,并将 updatedValues 向量作为参数传递给它
(*mOnPropertyChangeCallback)(std::move(updatedValues));
}
前面分析到 FakeVehicleHardware::init() 的时候,有说到过:
// 设置 mServerSidePropStore 的值改变回调函数
mServerSidePropStore->setOnValueChangeCallback(
[this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
mServerSidePropStore 就是 VehiclePropertyStore 。
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
// Callback when a property value has been updated or a new value added.
using OnValueChangeCallback = std::function<void(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue&)>;
OnValueChangeCallback mOnValueChangeCallback GUARDED_BY(mLock);
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
void VehiclePropertyStore::setOnValueChangeCallback(
const VehiclePropertyStore::OnValueChangeCallback& callback) {
std::scoped_lock<std::mutex> g(mLock);
mOnValueChangeCallback = callback;
}
继续在 VehiclePropertyStore 找 mOnValueChangeCallback 在哪里用:
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
VhalResult<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
bool updateStatus,
VehiclePropertyStore::EventMode eventMode) {
...
if ((eventMode == EventMode::ALWAYS || valueUpdated) && mOnValueChangeCallback != nullptr) {
mOnValueChangeCallback(*(record->values[recId]));
}
return {};
}
很清晰了,就是在写属性的时候回调回去的。
VehiclePropertyStore::writeValue() --->
FakeVehicleHardware::onValueChangeCallback() --->
DefaultVehicleHal::onPropertyChangeEvent()
我们这边暂且不分析 DefaultVehicleHal::onPropertyChangeEvent() 的具体功能。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
void DefaultVehicleHal::onPropertyChangeEvent(
std::weak_ptr<SubscriptionManager> subscriptionManager,
const std::vector<VehiclePropValue>& updatedValues) {
// subscriptionManager 是订阅管理器的弱引用
// 获取订阅管理器的强引用
auto manager = subscriptionManager.lock();
if (manager == nullptr) {
ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
return;
}
// 获取订阅了更新属性值的客户端
auto updatedValuesByClients = manager->getSubscribedClients(updatedValues);
for (const auto& [callback, valuePtrs] : updatedValuesByClients) {
std::vector<VehiclePropValue> values;
for (const VehiclePropValue* valuePtr : valuePtrs) {
values.push_back(*valuePtr);
}
// 发送更新的属性值给客户端
SubscriptionClient::sendUpdatedValues(callback, std::move(values));
}
}
RecurrentTimer¶
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
// 一个线程安全的循环定时器。
class RecurrentTimer final {
public:
// 用于循环调用的函数的类。
using Callback = std::function<void()>;
// 注册一个循环回调,指定时间间隔。
// 重复注册相同的回调会覆盖之前提供的时间间隔。
void registerTimerCallback(int64_t intervalInNano, std::shared_ptr<Callback> callback);
// 取消之前注册的循环回调。
void unregisterTimerCallback(std::shared_ptr<Callback> callback);
}
具体实现请参考 hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
DefaultVehicleHal::checkHealth()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
// Only initialized once.
std::shared_ptr<std::function<void()>> mRecurrentAction;
// RecurrentTimer is thread-safe.
RecurrentTimer mRecurrentTimer;
// heart beat event interval: 3s
static constexpr int64_t HEART_BEAT_INTERVAL_IN_NANO = 3'000'000'000;
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
// 注册心跳事件
mRecurrentAction = std::make_shared<std::function<void()>>(
[vehicleHardwarePtr, subscriptionManagerCopy]() { // 创建一个 lambda 表达式作为 mRecurrentAction 的值
checkHealth(vehicleHardwarePtr, subscriptionManagerCopy); // 调用 checkHealth 函数,传入 vehicleHardwarePtr 和 subscriptionManagerCopy
});
// 注册定时器回调函数
mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
由前面的构造函数可以知道,通过 RecurrentTimer 计时器注册 3S 的心跳事件。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
std::weak_ptr<SubscriptionManager> subscriptionManager) {
// 调用车辆硬件接口的checkHealth方法,获取状态码
StatusCode status = vehicleHardware->checkHealth();
if (status != StatusCode::OK) {
ALOGE("VHAL check health returns non-okay status");
return;
}
// 创建一个包含车辆属性值的向量
std::vector<VehiclePropValue> values = {{
.prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
.areaId = 0,
.status = VehiclePropertyStatus::AVAILABLE,
.value.int64Values = {uptimeMillis()},
}};
// 调用onPropertyChangeEvent方法,传入订阅管理器和属性值向量
onPropertyChangeEvent(subscriptionManager, values);
return;
}
vehicleHardware 就是 FakeVehicleHardware。 有跟前面的一样调到了 onPropertyChangeEvent() 函数。
VehicleHal 获取(设置)属性¶
subscribe 订阅属性¶
CarService.onCreate()¶
packages/services/Car/service-builtin/src/com/android/car/CarService.java
/** Proxy service for CarServciceImpl */
public class CarService extends ServiceProxy {
...
public CarService() {
super(UpdatablePackageDependency.CAR_SERVICE_IMPL_CLASS);
...
}
...
}
CarService.onCreate()¶
packages/services/Car/service-builtin/src/com/android/car/ServiceProxy.java
public class ServiceProxy extends Service {
private final String mRealServiceClassName;
private ProxiedService mRealService;
public ServiceProxy(String realServiceClassName) {
mRealServiceClassName = realServiceClassName;
}
@Override
public void onCreate() {
init();
mRealService.onCreate();
}
private void init() {
mUpdatablePackageContext = UpdatablePackageContext.create(this);
try {
mRealServiceClass = mUpdatablePackageContext.getClassLoader().loadClass(
mRealServiceClassName);
// Use default constructor always
Constructor constructor = mRealServiceClass.getConstructor();
mRealService = (ProxiedService) constructor.newInstance();
mRealService.doAttachBaseContext(mUpdatablePackageContext);
mRealService.setBuiltinPackageContext(this);
} catch (Exception e) {
throw new RuntimeException("Cannot load class:" + mRealServiceClassName, e);
}
}
}
mRealServiceClassName 就是 UpdatablePackageDependency.CAR_SERVICE_IMPL_CLASS ,也就是 "com.android.car.CarServiceImpl" 。
所以 mRealService 其实也就是 CarServiceImpl;那么 mRealService.onCreate() 就是 CarServiceImpl.onCreate()
CarServiceImpl.onCreate()¶
packages/services/Car/service/src/com/android/car/CarServiceImpl.java
@Keep
public class CarServiceImpl extends ProxiedService {
@Override
public void onCreate() {
LimitedTimingsTraceLog initTiming = new LimitedTimingsTraceLog(CAR_SERVICE_INIT_TIMING_TAG,
TraceHelper.TRACE_TAG_CAR_SERVICE, CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);
initTiming.traceBegin("CarService.onCreate");
initTiming.traceBegin("getVehicle");
mVehicle = VehicleStub.newVehicleStub();
initTiming.traceEnd(); // "getVehicle"
EventLogHelper.writeCarServiceCreate(/* hasVhal= */ mVehicle.isValid());
mVehicleInterfaceName = mVehicle.getInterfaceDescriptor();
Slogf.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
EventLogHelper.writeCarServiceConnected(mVehicleInterfaceName);
mICarImpl = new ICarImpl(this,
getBuiltinPackageContext(),
mVehicle,
SystemInterface.Builder.defaultSystemInterface(this).build(),
mVehicleInterfaceName);
mICarImpl.init();
mVehicle.linkToDeath(mVehicleDeathRecipient);
ServiceManagerHelper.addService("car_service", mICarImpl);
SystemPropertiesHelper.set("boot.car_service_created", "1");
super.onCreate();
initTiming.traceEnd(); // "CarService.onCreate"
}
}
CarServiceImpl.onCreate() 主要做了三件事: - 通过 VehicleStub 获取到 IVehicle - 创建 SystemInterface ,实现了多个接口(ActivityManagerInterface, DisplayInterface, IOInterface, StorageMonitoringInterface, SystemStateInterface, TimeInterface, WakeLockInterface)。 - 创建 ICarImpl ,并把 mVehicle 传进去,也就是 IVehicle 。 - ICarImpl.init()
下面我们先来分析 VehicleStub.newVehicleStub() 。
VehicleStub.newVehicleStub()¶
packages/services/Car/service/src/com/android/car/VehicleStub.java
/**
* 创建一个新的VehicleStub以连接到Vehicle HAL。
*
* 根据可用的后端(AIDL或HIDL),创建一个新的VehicleStub以连接到Vehicle HAL。
* 如果没有可用的vehicle HAL,则此函数将抛出IllegalStateException。
*
* @return 用于连接到Vehicle HAL的vehicle stub。
*/
public static VehicleStub newVehicleStub() throws IllegalStateException {
VehicleStub stub = new AidlVehicleStub();
if (stub.isValid()) {
if ((BuildHelper.isUserDebugBuild() || BuildHelper.isEngBuild())
&& FakeVehicleStub.doesEnableFileExist()) {
try {
return new FakeVehicleStub(stub);
} catch (Exception e) {
Slogf.e(CarLog.TAG_SERVICE, e, "Failed to create FakeVehicleStub. "
+ "Fallback to using real VehicleStub.");
}
}
return stub;
}
Slogf.i(CarLog.TAG_SERVICE, "No AIDL vehicle HAL found, fall back to HIDL version");
stub = new HidlVehicleStub();
if (!stub.isValid()) {
throw new IllegalStateException("Vehicle HAL service is not available.");
}
return stub;
}
根据可用的后端(AIDL或HIDL),创建一个新的VehicleStub以连接到Vehicle HAL。
属性 "ro.build.type" 是 userdebug 或者是 eng ;并且 /data/system/car/fake_vhal_config/ENABLE 存在 则使用 FakeVehicleStub 参考 packages/services/Car/service/src/com/android/car/hal/fakevhal/README.md
AidlVehicleStub¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
final class AidlVehicleStub extends VehicleStub {
private static final String AIDL_VHAL_SERVICE =
"android.hardware.automotive.vehicle.IVehicle/default";
AidlVehicleStub() {
this(getAidlVehicle());
}
@VisibleForTesting
AidlVehicleStub(IVehicle aidlVehicle) {
this(aidlVehicle,
CarServiceUtils.getHandlerThread(AidlVehicleStub.class.getSimpleName()));
}
@VisibleForTesting
AidlVehicleStub(IVehicle aidlVehicle, HandlerThread handlerThread) {
mAidlVehicle = aidlVehicle;
mPropValueBuilder = new HalPropValueBuilder(/*isAidl=*/true);
mHandlerThread = handlerThread;
mHandler = new Handler(mHandlerThread.getLooper());
mGetSetValuesCallback = new GetSetValuesCallback();
mPendingAsyncRequestPool = new PendingAsyncRequestPool(mHandler.getLooper());
}
@Nullable
private static IVehicle getAidlVehicle() {
try {
return IVehicle.Stub.asInterface(
ServiceManagerHelper.waitForDeclaredService(AIDL_VHAL_SERVICE));
} catch (RuntimeException e) {
Slogf.w(TAG, "Failed to get \"" + AIDL_VHAL_SERVICE + "\" service", e);
}
return null;
}
}
packages/services/Car/car-builtin-lib/src/android/car/builtin/os/ServiceManagerHelper.java
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class ServiceManagerHelper {
/** Check {@link ServiceManager#waitForDeclaredService(String)} */
@Nullable
@AddedIn(PlatformVersion.TIRAMISU_0)
public static IBinder waitForDeclaredService(@NonNull String name) {
return ServiceManager.waitForDeclaredService(name);
}
}
- 通过 ServiceManager.waitForDeclaredService() 获取到服务名为:"android.hardware.automotive.vehicle.IVehicle/default" 的代理对象。
- 创建线程,并使用线程安全处理异步请求池。
- GetSetValuesCallback 继承 IVehicleCallback ,用来监听 hal 回调事件。
- 创建 HalPropValueBuilder ,并标记为 aidl
HidlVehicleStub¶
packages/services/Car/service/src/com/android/car/HidlVehicleStub.java
final class HidlVehicleStub extends VehicleStub {
HidlVehicleStub() {
this(getHidlVehicle());
}
@VisibleForTesting
HidlVehicleStub(IVehicle hidlVehicle) {
mHidlVehicle = hidlVehicle;
mPropValueBuilder = new HalPropValueBuilder(/*isAidl=*/false);
}
@Nullable
private static IVehicle getHidlVehicle() {
String instanceName = SystemProperties.get("ro.vehicle.hal", "default");
try {
return IVehicle.getService(instanceName);
} catch (RemoteException e) {
Slogf.e(TAG, e, "Failed to get IVehicle/" + instanceName + " service");
} catch (NoSuchElementException e) {
Slogf.e(TAG, "IVehicle/" + instanceName + " service not registered yet");
}
return null;
}
}
通过 IVehicle.getService() 回去到 hidl 服务的代理对象。 现在我们返回到 CarServiceImpl.onCreate() 中,拿到 IVehicle 后,接着创建 ICarImpl。
ICarImpl构造函数¶
packages/services/Car/service/src/com/android/car/ICarImpl.java
public class ICarImpl extends ICar.Stub {
public ICarImpl(Context serviceContext, Context builtinContext, VehicleStub vehicle,
SystemInterface systemInterface, String vehicleInterfaceName) {
this(serviceContext, builtinContext, vehicle, systemInterface, vehicleInterfaceName,
/* carUserService= */ null, /* carWatchdogService= */ null,
/* carPerformanceService= */ null, /* garageModeService= */ null,
/* powerPolicyDaemon= */ null, /* carTelemetryService= */ null,
/* carRemoteAccessService= */ null, /* doPriorityInitInConstruction= */ true);
}
@VisibleForTesting
ICarImpl(Context serviceContext, @Nullable Context builtinContext, VehicleStub vehicle,
SystemInterface systemInterface, String vehicleInterfaceName,
@Nullable CarUserService carUserService,
@Nullable CarWatchdogService carWatchdogService,
@Nullable CarPerformanceService carPerformanceService,
@Nullable GarageModeService garageModeService,
@Nullable ICarPowerPolicySystemNotification powerPolicyDaemon,
@Nullable CarTelemetryService carTelemetryService,
@Nullable CarRemoteAccessService carRemoteAccessService,
boolean doPriorityInitInConstruction) {
...
mContext = serviceContext;
if (builtinContext == null) {
mCarServiceBuiltinPackageContext = serviceContext;
} else {
mCarServiceBuiltinPackageContext = builtinContext;
}
mCarServiceHelperWrapper = CarServiceHelperWrapper.create();
// 创建一个容量为40的ArrayList,用于存储所有的 CarSystemService
List<CarSystemService> allServices = new ArrayList<>(40);
// 构造CarOemProxyService实例,并将其添加到allServices中
mCarOemService = constructWithTrace(t, CarOemProxyService.class,
() -> new CarOemProxyService(serviceContext), allServices);
mSystemInterface = systemInterface;
CarLocalServices.addService(SystemInterface.class, mSystemInterface);
// 构造VehicleHal实例,并将其添加到allServices中
mHal = constructWithTrace(t, VehicleHal.class,
() -> new VehicleHal(serviceContext, vehicle), allServices);
...
if (mDoPriorityInitInConstruction) {
Slogf.i(TAG, "VHAL Priority Init Enabled");
Slogf.i(TAG, "Car User Service Priority Init Enabled");
priorityInit();
}
...
// 构造 mCarPowerManagementService 实例,并将其添加到allServices
mCarPowerManagementService = constructWithTrace(
t, CarPowerManagementService.class,
() -> new CarPowerManagementService(mContext, mHal.getPowerHal(),
systemInterface, mCarUserService, powerPolicyDaemon), allServices);
...
mAllServices = allServices.toArray(new CarSystemService[allServices.size()]);
mICarSystemServerClientImpl = new ICarSystemServerClientImpl();
t.traceEnd(); // "ICarImpl.constructor"
}
}
/**
* 构造带有跟踪日志的CarSystemService对象
* @param t 跟踪日志对象
* @param cls CarSystemService的Class对象
* @param callable 用于构造CarSystemService对象的可调用对象
* @param allServices 所有CarSystemService对象的列表
* @param <T> CarSystemService的类型参数
* @return 构造完成的CarSystemService对象
*/
private <T extends CarSystemService> T constructWithTrace(LimitedTimingsTraceLog t,
Class<T> cls, Callable<T> callable, List<CarSystemService> allServices) {
t.traceBegin(cls.getSimpleName()); // 开始跟踪日志
T constructed;
try {
constructed = callable.call(); // 调用可调用对象构造CarSystemService对象
CarLocalServices.addService(cls, constructed); // 将构造的CarSystemService对象添加到CarLocalServices中
} catch (Exception e) {
throw new RuntimeException("Crash while constructing:" + cls.getSimpleName(), e); // 构造过程中发生异常,抛出运行时异常
} finally {
t.traceEnd(); // 结束跟踪日志
}
allServices.add(constructed); // 将构造的CarSystemService对象添加到所有服务列表中
return constructed; // 返回构造完成的CarSystemService对象
}
/* package */ void priorityInit() {
mHal.priorityInit();
mCarUserService.priorityInit();
}
ICarImpl构造函数做了很多工作,我们只关心两件事: - 构造 VehicleHal 实例,并将其添加到 mAllServices 中。 - 创建各个 java Service,并将其添加到 mAllServices 中。
我们从 constructWithTrace() 函数里看到一个细节,所有加到 mAllServices 的服务都加到 CarLocalServices 中了。 熟悉 framework 的同学都知道,framework 里的 LocalServices 是什么,怎么用。其实 CarLocalServices 就是把 LocalServices 的代码 copy 过来使用的。 好了,有了 CarLocalServices 之后,后面在各个 service 之间调用方便多了。
VehicleHal构造函数¶
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public VehicleHal(Context context, VehicleStub vehicle) {
this(context, /* powerHal= */ null, /* propertyHal= */ null,
/* inputHal= */ null, /* vmsHal= */ null, /* userHal= */ null,
/* diagnosticHal= */ null, /* clusterHalService= */ null,
/* timeHalService= */ null,
CarServiceUtils.getHandlerThread(VehicleHal.class.getSimpleName()), vehicle);
}
/**
* Constructs a new {@link VehicleHal} object given the services passed as parameters.
* This method must be used by tests only.
*/
@VisibleForTesting
VehicleHal(Context context,
PowerHalService powerHal,
PropertyHalService propertyHal,
InputHalService inputHal,
VmsHalService vmsHal,
UserHalService userHal,
DiagnosticHalService diagnosticHal,
ClusterHalService clusterHalService,
TimeHalService timeHalService,
HandlerThread handlerThread,
VehicleStub vehicle) {
// Must be initialized before HalService so that HalService could use this.
mPropValueBuilder = vehicle.getHalPropValueBuilder();
mHandlerThread = handlerThread;
mHandler = new Handler(mHandlerThread.getLooper());
mPowerHal = powerHal != null ? powerHal : new PowerHalService(context, this);
mPropertyHal = propertyHal != null ? propertyHal : new PropertyHalService(this);
mInputHal = inputHal != null ? inputHal : new InputHalService(this);
mVmsHal = vmsHal != null ? vmsHal : new VmsHalService(context, this);
mUserHal = userHal != null ? userHal : new UserHalService(this);
mDiagnosticHal = diagnosticHal != null ? diagnosticHal : new DiagnosticHalService(this);
mClusterHalService = clusterHalService != null
? clusterHalService : new ClusterHalService(this);
mEvsHal = new EvsHalService(this);
mTimeHalService = timeHalService != null
? timeHalService : new TimeHalService(context, this);
mAllServices = List.of(
mPowerHal,
mInputHal,
mDiagnosticHal,
mVmsHal,
mUserHal,
mClusterHalService,
mEvsHal,
mTimeHalService,
// mPropertyHal must be the last so that on init/release it can be used for all
// other HAL services properties.
mPropertyHal);
mVehicleStub = vehicle;
mSubscriptionClient = vehicle.newSubscriptionClient(this);
}
VehicleHal构造函数里 new各个HalService(继承于 HalServiceBase ),并且保存到 mAllServices 成员变量中。 通过 VehicleStub 获取到 SubscriptionClient,为后面的注册监听事件做准备。
在 ICarImpl构造函数中还调用 mHal.priorityInit() 初始化属性。
VehicleHal.priorityInit()¶
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public void priorityInit() {
fetchAllPropConfigs();
// PropertyHalService will take most properties, so make it big enough.
ArrayMap<HalServiceBase, ArrayList<HalPropConfig>> configsForAllServices;
synchronized (mLock) {
configsForAllServices = new ArrayMap<>(mAllServices.size());
for (int i = 0; i < mAllServices.size(); i++) {
ArrayList<HalPropConfig> configsForService = new ArrayList();
HalServiceBase service = mAllServices.get(i);
configsForAllServices.put(service, configsForService);
int[] supportedProps = service.getAllSupportedProperties();
if (supportedProps.length == 0) {
for (int j = 0; j < mAllProperties.size(); j++) {
Integer propId = mAllProperties.keyAt(j);
if (service.isSupportedProperty(propId)) {
HalPropConfig config = mAllProperties.get(propId);
mPropertyHandlers.append(propId, service);
configsForService.add(config);
}
}
} else {
for (int prop : supportedProps) {
HalPropConfig config = mAllProperties.get(prop);
if (config == null) {
continue;
}
mPropertyHandlers.append(prop, service);
configsForService.add(config);
}
}
}
}
for (Map.Entry<HalServiceBase, ArrayList<HalPropConfig>> entry
: configsForAllServices.entrySet()) {
HalServiceBase service = entry.getKey();
ArrayList<HalPropConfig> configsForService = entry.getValue();
service.takeProperties(configsForService);
service.init();
}
}
这里主要做了两件事: - 获取所有的属性。 - 给每个服务更新对应的属性,并初始化服务。
getAllPropConfigs()¶
mVehicleStub.getAllPropConfigs() 从 Vehicle HAL(IVehicle.aidl) 获取所有的属性。 调用到 DefaultVehicleHal::getAllPropConfigs() 函数。
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
private void fetchAllPropConfigs() {
synchronized (mLock) {
if (mAllProperties.size() != 0) { // already set
Slogf.i(CarLog.TAG_HAL, "fetchAllPropConfigs already fetched");
return;
}
}
HalPropConfig[] configs;
try {
configs = mVehicleStub.getAllPropConfigs();
if (configs == null || configs.length == 0) {
Slogf.e(CarLog.TAG_HAL, "getAllPropConfigs returned empty configs");
return;
}
} catch (RemoteException | ServiceSpecificException e) {
throw new RuntimeException("Unable to retrieve vehicle property configuration", e);
}
synchronized (mLock) {
// Create map of all properties
for (HalPropConfig p : configs) {
if (DBG) {
Slogf.i(CarLog.TAG_HAL, "Add config for prop: 0x%x config: %s", p.getPropId(),
p.toString());
}
mAllProperties.put(p.getPropId(), p);
}
}
}
HalServiceBase.inti()¶
在 init() 中调用 fetchAllPropConfigs() 获取到所有的属性,并保存在 mAllProperties 变量中。 接着还有一件很重要的事情是,给每个服务更新对应的属性。
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public void priorityInit() {
fetchAllPropConfigs();
// PropertyHalService will take most properties, so make it big enough.
ArrayMap<HalServiceBase, ArrayList<HalPropConfig>> configsForAllServices;
synchronized (mLock) {
configsForAllServices = new ArrayMap<>(mAllServices.size());
for (int i = 0; i < mAllServices.size(); i++) {
ArrayList<HalPropConfig> configsForService = new ArrayList();
HalServiceBase service = mAllServices.get(i);
configsForAllServices.put(service, configsForService);
int[] supportedProps = service.getAllSupportedProperties();
if (supportedProps.length == 0) {
for (int j = 0; j < mAllProperties.size(); j++) {
Integer propId = mAllProperties.keyAt(j);
if (service.isSupportedProperty(propId)) {
HalPropConfig config = mAllProperties.get(propId);
mPropertyHandlers.append(propId, service);
configsForService.add(config);
}
}
} else {
for (int prop : supportedProps) {
HalPropConfig config = mAllProperties.get(prop);
if (config == null) {
continue;
}
mPropertyHandlers.append(prop, service);
configsForService.add(config);
}
}
}
}
for (Map.Entry<HalServiceBase, ArrayList<HalPropConfig>> entry
: configsForAllServices.entrySet()) {
HalServiceBase service = entry.getKey();
ArrayList<HalPropConfig> configsForService = entry.getValue();
service.takeProperties(configsForService);
service.init();
}
}
根据签名的构造函数,我们知道 mAllServices 就是各个 HalServiceBase,这里我们拿 PowerHalService 举例。
PowerHalService.getAllSupportedProperties()¶
PowerHalService支持的所有属性是: - AP_POWER_STATE_REQ - AP_POWER_STATE_REPORT - DISPLAY_BRIGHTNESS - PER_DISPLAY_BRIGHTNESS - VEHICLE_IN_USE
packages/services/Car/service/src/com/android/car/hal/PowerHalService.java
public class PowerHalService extends HalServiceBase {
private static final int[] SUPPORTED_PROPERTIES = new int[]{
AP_POWER_STATE_REQ,
AP_POWER_STATE_REPORT,
DISPLAY_BRIGHTNESS,
PER_DISPLAY_BRIGHTNESS,
VEHICLE_IN_USE,
};
@Override
public int[] getAllSupportedProperties() {
return SUPPORTED_PROPERTIES;
}
}
在回到前面的 priorityInit() 函数,从 PowerHalService.getAllSupportedProperties() 是有获取到支持属性的;所以接着从 mAllProperties 去寻找是否有配置,最后调用 PowerHalService.takeProperties(configsForService) 更新。
PowerHalService.takeProperties()¶
packages/services/Car/service/src/com/android/car/hal/PowerHalService.java
public class PowerHalService extends HalServiceBase {
@GuardedBy("mLock")
private final SparseArray<HalPropConfig> mProperties = new SparseArray<>();
@Override
public void takeProperties(Collection<HalPropConfig> properties) {
if (properties.isEmpty()) {
return;
}
synchronized (mLock) {
for (HalPropConfig config : properties) {
mProperties.put(config.getPropId(), config);
}
}
}
}
PowerHalService.init()¶
调用 mHal.subscribeProperty(this, config.getPropId()); 订阅属性。
packages/services/Car/service/src/com/android/car/hal/PowerHalService.java
public class PowerHalService extends HalServiceBase {
@Override
public void init() {
synchronized (mLock) {
for (int i = 0; i < mProperties.size(); i++) {
HalPropConfig config = mProperties.valueAt(i);
if (VehicleHal.isPropertySubscribable(config)) {
mHal.subscribeProperty(this, config.getPropId());
}
}
HalPropConfig brightnessProperty = mProperties.get(PER_DISPLAY_BRIGHTNESS);
mPerDisplayBrightnessSupported = brightnessProperty != null;
if (brightnessProperty == null) {
brightnessProperty = mProperties.get(DISPLAY_BRIGHTNESS);
}
if (brightnessProperty != null) {
HalAreaConfig[] areaConfigs = brightnessProperty.getAreaConfigs();
mMaxDisplayBrightness = areaConfigs.length > 0
? areaConfigs[0].getMaxInt32Value() : 0;
if (mMaxDisplayBrightness <= 0) {
Slogf.w(CarLog.TAG_POWER, "Max display brightness from vehicle HAL is invalid:"
+ mMaxDisplayBrightness);
mMaxDisplayBrightness = 1;
}
}
}
}
}
VehicleHal.subscribeProperty()¶
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
/**
* Subscribes given properties with sampling rate defaults to 0 and no special flags provided.
*
* @throws IllegalArgumentException thrown if property is not supported by VHAL
* @see #subscribeProperty(HalServiceBase, int, float)
*/
public void subscribeProperty(HalServiceBase service, int property)
throws IllegalArgumentException {
subscribeProperty(service, property, /* samplingRateHz= */ 0f);
}
/**
* Subscribe given property. Only Hal service owning the property can subscribe it.
*
* @param service HalService that owns this property
* @param property property id (VehicleProperty)
* @param samplingRateHz sampling rate in Hz for continuous properties
* @throws IllegalArgumentException thrown if property is not supported by VHAL
*/
public void subscribeProperty(HalServiceBase service, int property, float samplingRateHz)
throws IllegalArgumentException {
subscribeProperty(service, property, samplingRateHz, new int[0]);
}
/**
* Subscribe given property. Only Hal service owning the property can subscribe it.
*
* @param service HalService that owns this property
* @param property property id (VehicleProperty)
* @param samplingRateHz sampling rate in Hz for continuous properties
* @param areaIds The areaId that is being subscribed to, if empty subscribe to all areas
* @throws IllegalArgumentException thrown if property is not supported by VHAL
*/
public void subscribeProperty(HalServiceBase service, int property, float samplingRateHz,
int[] areaIds) {
if (DBG) {
Slogf.d(CarLog.TAG_HAL, "subscribeProperty, service, areaIds, SamplingRateHz:"
+ toCarPropertyLog(property) + ", " + service + ", "
+ CarServiceUtils.asList(areaIds) + ", " + samplingRateHz);
}
HalPropConfig config;
synchronized (mLock) {
config = mAllProperties.get(property);
}
if (config == null) {
throw new IllegalArgumentException(
String.format("subscribe error: config is null for property 0x%x", property));
} else if (isPropertySubscribable(config)) {
if (areaIds.length == 0) {
areaIds = getAllAreaIdsFromPropertyId(config);
}
SubscribeOptions opts = new SubscribeOptions();
opts.propId = property;
opts.sampleRate = samplingRateHz;
int[] filteredAreaIds = checkAlreadySubscribed(property, areaIds, samplingRateHz);
opts.areaIds = filteredAreaIds;
if (opts.areaIds.length == 0) {
Slogf.w(CarLog.TAG_HAL, "property: " + VehiclePropertyIds.toString(property)
+ " is already subscribed at rate: " + samplingRateHz + " hz");
return;
}
synchronized (mLock) {
assertServiceOwnerLocked(service, property);
for (int i = 0; i < filteredAreaIds.length; i++) {
mUpdateRateByPropIdAreadId.put(Pair.create(property,
filteredAreaIds[i]), samplingRateHz);
}
}
try {
mSubscriptionClient.subscribe(new SubscribeOptions[]{opts});
} catch (RemoteException | ServiceSpecificException e) {
Slogf.w(CarLog.TAG_HAL, "Failed to subscribe to " + toCarPropertyLog(property),
e);
}
} else {
Slogf.w(CarLog.TAG_HAL, "Cannot subscribe to " + toCarPropertyLog(property));
}
}
前面分析 VehicleHal 构造函数提到过:mSubscriptionClient = vehicle.newSubscriptionClient(this),为后面的注册监听事件做准备。 这里的 this 是谁呢?看下 VehicleHal 类:
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public class VehicleHal implements VehicleHalCallback, CarSystemService {
...
}
packages/services/Car/service/src/com/android/car/hal/VehicleHalCallback.java
public interface VehicleHalCallback {
/**
* Called when new property events happen.
*/
void onPropertyEvent(ArrayList<HalPropValue> values);
/**
* Called when property set errors happen.
*/
void onPropertySetError(ArrayList<VehiclePropError> errors);
}
那就是 VehicleHalCallback 了。我们先接着看 mSubscriptionClient 到底是啥,到后面我们再分析 VehicleHal 回调函数都干啥。
Android U 使用的是 Stable AIDL,使用我们这里的 SubscriptionClient 其实是 AidlSubscriptionClient。
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
@Override
public SubscriptionClient newSubscriptionClient(VehicleHalCallback callback) {
return new AidlSubscriptionClient(callback, mPropValueBuilder);
}
AidlSubscriptionClient.subscribe()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private class AidlSubscriptionClient extends IVehicleCallback.Stub
implements SubscriptionClient {
private final VehicleHalCallback mCallback;
private final HalPropValueBuilder mBuilder;
AidlSubscriptionClient(VehicleHalCallback callback, HalPropValueBuilder builder) {
mCallback = callback;
mBuilder = builder;
}
...
@Override
public void onPropertyEvent(VehiclePropValues propValues, int sharedMemoryFileCount)
throws RemoteException {
VehiclePropValues origPropValues = (VehiclePropValues)
LargeParcelable.reconstructStableAIDLParcelable(propValues,
/* keepSharedMemory= */ false);
ArrayList<HalPropValue> values = new ArrayList<>(origPropValues.payloads.length);
for (VehiclePropValue value : origPropValues.payloads) {
values.add(mBuilder.build(value));
}
mCallback.onPropertyEvent(values);
}
@Override
public void onPropertySetError(VehiclePropErrors errors) throws RemoteException {
VehiclePropErrors origErrors = (VehiclePropErrors)
LargeParcelable.reconstructStableAIDLParcelable(errors,
/* keepSharedMemory= */ false);
ArrayList<VehiclePropError> errorList = new ArrayList<>(origErrors.payloads.length);
for (VehiclePropError error : origErrors.payloads) {
errorList.add(error);
}
mCallback.onPropertySetError(errorList);
}
@Override
public void subscribe(SubscribeOptions[] options)
throws RemoteException, ServiceSpecificException {
mAidlVehicle.subscribe(this, options, /* maxSharedMemoryFileCount= */ 2);
}
@Override
public void unsubscribe(int prop) throws RemoteException, ServiceSpecificException {
mAidlVehicle.unsubscribe(this, new int[]{prop});
}
}
调用 mAidlVehicle.subscribe() ,监听 IVehicleCallback 的回调。 在 IVehicleCallback 的回调函数 onPropertyEvent() 继续回调 mCallback.onPropertyEvent() ,而 mCallback 就是 VehicleHal 构造函数 传进来的 this。
所以 IVehicleCallback 的回调事件会从 AidlSubscriptionClient 到 VehicleHal 。
VehicleHal.onPropertyEvent()¶
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public class VehicleHal implements VehicleHalCallback, CarSystemService {
@Override
public void onPropertyEvent(ArrayList<HalPropValue> propValues) {
mHandler.post(() -> handleOnPropertyEvent(propValues));
}
@Override
public void onPropertySetError(ArrayList<VehiclePropError> errors) {
mHandler.post(() -> handleOnPropertySetError(errors));
}
private void handleOnPropertyEvent(List<HalPropValue> propValues) {
synchronized (mLock) {
for (int i = 0; i < propValues.size(); i++) {
HalPropValue v = propValues.get(i);
int propId = v.getPropId();
// 在前面的 priorityInit() 会把 属性id 跟 service 关联起来
// mPropertyHandlers.append(propId, service);
HalServiceBase service = mPropertyHandlers.get(propId);
if (service == null) {
Slogf.e(CarLog.TAG_HAL,
"handleOnPropertyEvent: HalService not found for prop: 0x%x", propId);
continue;
}
service.getDispatchList().add(v);
// 把需要通知的 service 都添加到 mServicesToDispatch
mServicesToDispatch.add(service);
VehiclePropertyEventInfo info = mEventLog.get(propId);
if (info == null) {
info = new VehiclePropertyEventInfo(v);
mEventLog.put(propId, info);
} else {
info.addNewEvent(v);
}
}
}
for (HalServiceBase s : mServicesToDispatch) {
s.onHalEvents(s.getDispatchList());
s.getDispatchList().clear();
}
mServicesToDispatch.clear();
}
}
接到回调后,调用 handleOnPropertyEvent() 函数处理: - 根据 propId 从 mPropertyHandlers 里获取到 service,并把 HalPropValue 添加到 service 的 mDispatchList 中。 - 把获取到的 service 添加到将要派发的 mServicesToDispatch 列表中。 - 遍历 mServicesToDispatch 列表,调用 service 的 onHalEvents() 函数。 - 最后清除 mServicesToDispatch 。
这里我们依然使用 PowerHalService 来举例。
PowerHalService.onHalEvents()¶
packages/services/Car/service/src/com/android/car/hal/PowerHalService.java
@Override
public void onHalEvents(List<HalPropValue> values) {
PowerEventListener listener;
synchronized (mLock) {
if (mListener == null) {
if (mQueuedEvents == null) {
mQueuedEvents = new ArrayList<>(values.size());
}
mQueuedEvents.addAll(values);
return;
}
listener = mListener;
}
dispatchEvents(values, listener);
}
在 PowerHalService.onHalEvents() 中,调用 dispatchEvents() 处理事件。
java 这边流程清楚了,现在再回到 AidlSubscriptionClient.subscribe() 中,调了 mAidlVehicle.subscribe() 。就走到 Vehicle Hal 端了。
从前面 VehicleHal 初始化流程的分析可知,最终会调到 DefaultVehicleHal::subscribe()。
DefaultVehicleHal::subscribe()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
const std::vector<SubscribeOptions>& options,
[[maybe_unused]] int32_t maxSharedMemoryFileCount) {
if (callback == nullptr) {
return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
}
// 检查订阅选项是否有效,如果无效则返回异常状态
if (auto result = checkSubscribeOptions(options); !result.ok()) {
ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
return toScopedAStatus(result);
}
// 存储需要订阅的属性变化和连续属性的选项
std::vector<SubscribeOptions> onChangeSubscriptions;
std::vector<SubscribeOptions> continuousSubscriptions;
// 遍历所有选项
for (const auto& option : options) {
int32_t propId = option.propId;
// 已经验证配置存在
const VehiclePropConfig& config = mConfigsByPropId[propId];
SubscribeOptions optionCopy = option;
// 如果areaIds为空,则订阅所有区域
if (optionCopy.areaIds.empty() && !isGlobalProp(propId)) {
for (const auto& areaConfig : config.areaConfigs) {
optionCopy.areaIds.push_back(areaConfig.areaId);
}
}
if (isGlobalProp(propId)) {
optionCopy.areaIds = {0};
}
// 如果属性变化模式为连续模式,则设置采样率为默认采样率,并将选项添加到连续属性的订阅列表中
if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
optionCopy.sampleRate = getDefaultSampleRateHz(
optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate);
continuousSubscriptions.push_back(std::move(optionCopy));
} else {
// 否则将选项添加到属性变化的订阅列表中
onChangeSubscriptions.push_back(std::move(optionCopy));
}
}
{
// 加锁以确保不会并发调用onBinderDied
std::scoped_lock lockGuard(mLock);
// 如果监视的Binder生命周期失败,则返回异常状态
if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
"client died");
}
// 如果不存在现有的SubscriptionClient,则创建一个新的SubscriptionClient
mSubscriptionClients->maybeAddClient(callback);
// 由于已经检查了采样率,以下函数必须成功
// 如果属性变化的订阅列表不为空,则调用订阅管理器的subscribe函数进行订阅
if (!onChangeSubscriptions.empty()) {
return toScopedAStatus(mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
/*isContinuousProperty=*/false));
}
// 如果连续属性的订阅列表不为空,则调用订阅管理器的subscribe函数进行订阅
if (!continuousSubscriptions.empty()) {
return toScopedAStatus(mSubscriptionManager->subscribe(callback,
continuousSubscriptions,
/*isContinuousProperty=*/true));
}
}
// 返回正常状态
return ScopedAStatus::ok();
}
这个函数最重要的一点其实就是调用 SubscriptionManager::subscribe() 。
SubscriptionManager::subscribe()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
VhalResult<void> SubscriptionManager::subscribe(const std::shared_ptr<IVehicleCallback>& callback,
const std::vector<SubscribeOptions>& options,
bool isContinuousProperty) {
std::scoped_lock<std::mutex> lockGuard(mLock);
// 遍历options向量中的每个SubscribeOptions对象
for (const auto& option : options) {
// 获取当前SubscribeOptions对象的采样率
float sampleRateHz = option.sampleRate;
// 如果isContinuousProperty为true
if (isContinuousProperty) {
// 调用getIntervalNanos函数获取采样间隔时间
if (auto result = getIntervalNanos(sampleRateHz); !result.ok()) {
return StatusError(StatusCode::INVALID_ARG) << result.error().message();
}
}
// 如果当前SubscribeOptions对象的areaIds向量为空
if (option.areaIds.empty()) {
ALOGE("area IDs to subscribe must not be empty");
return StatusError(StatusCode::INVALID_ARG)
<< "area IDs to subscribe must not be empty";
}
}
// 获取callback对象的Binder ID
ClientIdType clientId = callback->asBinder().get();
// 遍历options向量中的每个SubscribeOptions对象
for (const auto& option : options) {
// 获取当前SubscribeOptions对象的属性ID
int32_t propId = option.propId;
// 获取当前SubscribeOptions对象的区域ID向量
const std::vector<int32_t>& areaIds = option.areaIds;
// 遍历区域ID向量中的每个区域ID
for (int32_t areaId : areaIds) {
PropIdAreaId propIdAreaId = {
.propId = propId,
.areaId = areaId,
};
// 如果isContinuousProperty为true
if (isContinuousProperty) {
// 调用addContinuousSubscriberLocked函数添加连续属性的订阅者
if (auto result = addContinuousSubscriberLocked(clientId, propIdAreaId,
option.sampleRate);
!result.ok()) {
return result;
}
}
// 将propIdAreaId插入到mSubscribedPropsByClient的clientId键对应的集合中
mSubscribedPropsByClient[clientId].insert(propIdAreaId);
// 将callback插入到mClientsByPropIdArea的propIdAreaId键对应的clientId键对应的值中
mClientsByPropIdArea[propIdAreaId][clientId] = callback;
}
}
return {};
}
看到了 callback 存放在 mClientsByPropIdArea,我们看下 mClientsByPropIdArea 是什么?
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
mutable std::mutex mLock;
std::unordered_map<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
PropIdAreaIdHash> mClientsByPropIdArea GUARDED_BY(mLock);
从这里我们看出来了,如果知道了 propIdAreaId ,就可以从 mClientsByPropIdArea 查到 callback 了。
SubscriptionManager::getSubscribedClients()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<const VehiclePropValue*>>
SubscriptionManager::getSubscribedClients(const std::vector<VehiclePropValue>& updatedValues) {
std::scoped_lock<std::mutex> lockGuard(mLock);
std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<const VehiclePropValue*>>
clients;
// 遍历updatedValues中的每个元素,元素类型为VehiclePropValue
for (const auto& value : updatedValues) {
PropIdAreaId propIdAreaId{
.propId = value.prop,
.areaId = value.areaId,
};
// 如果mClientsByPropIdArea中不存在propIdAreaId键
if (mClientsByPropIdArea.find(propIdAreaId) == mClientsByPropIdArea.end()) {
continue; // 跳过当前循环,继续下一次循环
}
// 遍历mClientsByPropIdArea[propIdAreaId]中的每个元素,元素类型为std::pair<const std::shared_ptr<IVehicleCallback>, bool>
for (const auto& [_, client] : mClientsByPropIdArea[propIdAreaId]) {
// 将value的地址添加到clients[client]的末尾
clients[client].push_back(&value);
}
}
// 返回clients
return clients;
}
跟我们前面的猜想是一样的。
SubscriptionClient::sendUpdatedValues()¶
在之前的流程,我们说先不分析 DefaultVehicleHal::onPropertyChangeEvent() 的具体功能。 现在我们拿出来继续分析。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
void DefaultVehicleHal::onPropertyChangeEvent(
std::weak_ptr<SubscriptionManager> subscriptionManager,
const std::vector<VehiclePropValue>& updatedValues) {
// subscriptionManager 是订阅管理器的弱引用
// 获取订阅管理器的强引用
auto manager = subscriptionManager.lock();
if (manager == nullptr) {
ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
return;
}
// 获取订阅了更新属性值的客户端
auto updatedValuesByClients = manager->getSubscribedClients(updatedValues);
for (const auto& [callback, valuePtrs] : updatedValuesByClients) {
std::vector<VehiclePropValue> values;
for (const VehiclePropValue* valuePtr : valuePtrs) {
values.push_back(*valuePtr);
}
// 发送更新的属性值给客户端
SubscriptionClient::sendUpdatedValues(callback, std::move(values));
}
}
manager 就是 mSubscriptionManager,也就是 SubscriptionManager::getSubscribedClients() 。也就是说要注册监听的客户端了。 真正发起 ipc 回调的一个就是这里了 SubscriptionClient::sendUpdatedValues(callback, std::move(values));
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
void SubscriptionClient::sendUpdatedValues(std::shared_ptr<IVehicleCallback> callback,
std::vector<VehiclePropValue>&& updatedValues) {
if (updatedValues.empty()) {
return;
}
// 在这里使用内存池,并填充sharedMemoryId。
// 创建一个VehiclePropValues对象
VehiclePropValues vehiclePropValues;
// 共享内存文件计数器初始化为0
int32_t sharedMemoryFileCount = 0;
// 将更新的值转换为稳定的大型可序列化对象
ScopedAStatus status =
vectorToStableLargeParcelable(std::move(updatedValues), &vehiclePropValues);
if (!status.isOk()) {
// 如果转换失败,则打印错误信息并返回
int statusCode = status.getServiceSpecificError();
ALOGE("subscribe: failed to marshal result into large parcelable, error: "
"%s, code: %d",
status.getMessage(), statusCode);
return;
}
// 调用回调函数,将vehiclePropValues和sharedMemoryFileCount作为参数传递
if (ScopedAStatus callbackStatus =
callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount);
!callbackStatus.isOk()) {
ALOGE("subscribe: failed to call UpdateValues callback, client ID: %p, error: %s, "
"exception: %d, service specific error: %d",
callback->asBinder().get(), callbackStatus.getMessage(),
callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
}
}
以上我们只是拿 PowerHalService ,在 VehicleHal.priorityInit() 中会遍历所以的 HalService 去做同样的事情,所以 所有属性都subscribe,CarService就可以所有接收到Vehicle HAL发上来的所有属性变化
同理,unsubscribe注销订阅。
set 设置属性¶
在 Android S 中,我们拿 CarHvacManager 来举例,而在 Android U ( 没看过 T 的代码,也许在 T 中已经是这样子了 ) 建议都使用 CarPropertyManager 了。
CarPropertyManager.setProperty()¶
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
@AddedInOrBefore(majorVersion = 33)
public <E> void setProperty(@NonNull Class<E> clazz, int propertyId, int areaId,
@NonNull E val) {
...
try {
runSyncOperation(() -> {
mService.setProperty(new CarPropertyValue<>(propertyId, areaId, val),
mCarPropertyEventToService);
return null;
});
...
}
这里的 mService 就是 CarPropertyService 。
CarPropertyService.setProperty()¶
packages/services/Car/service/src/com/android/car/CarPropertyService.java
@Override
public void setProperty(CarPropertyValue carPropertyValue,
ICarPropertyEventListener iCarPropertyEventListener)
throws IllegalArgumentException, ServiceSpecificException {
requireNonNull(iCarPropertyEventListener);
validateSetParameters(carPropertyValue);
runSyncOperationCheckLimit(() -> {
mPropertyHalService.setProperty(carPropertyValue);
return null;
});
IBinder listenerBinder = iCarPropertyEventListener.asBinder();
synchronized (mLock) {
Client client = mClientMap.get(listenerBinder);
if (client == null) {
client = new Client(iCarPropertyEventListener);
}
if (client.isDead()) {
Slogf.w(TAG, "the ICarPropertyEventListener is already dead");
return;
}
mClientMap.put(listenerBinder, client);
updateSetOperationRecorderLocked(carPropertyValue.getPropertyId(),
carPropertyValue.getAreaId(), client);
}
}
mPropertyHalService 就是 PropertyHalService。
PropertyHalService.setProperty()¶
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
public void setProperty(CarPropertyValue carPropertyValue)
throws IllegalArgumentException, ServiceSpecificException {
HalPropValue valueToSet;
synchronized (mLock) {
valueToSet = carPropertyValueToHalPropValueLocked(carPropertyValue);
}
// CarPropertyManager catches and rethrows exception, no need to handle here.
mVehicleHal.set(valueToSet);
}
mVehicleHal 就是 VehicleHal 。
VehicleHal.set()¶
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public void set(HalPropValue propValue)
throws IllegalArgumentException, ServiceSpecificException {
setValueWithRetry(propValue);
}
private void setValueWithRetry(HalPropValue value) {
invokeRetriable((requestValue) -> {
Trace.traceBegin(TRACE_TAG, "VehicleStub#set");
mVehicleStub.set(requestValue);
Trace.traceEnd(TRACE_TAG);
return null;
}, "set", value, mMaxDurationForRetryMs, mSleepBetweenRetryMs, /* maxRetries= */ 0);
}
mVehicleStub 是 AidlVehicleStub。
AidlVehicleStub.set()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
@Override
public void set(HalPropValue requestedPropValue) throws RemoteException,
ServiceSpecificException {
getOrSetSync(requestedPropValue, mPendingSyncSetValueRequestPool,
new AsyncSetRequestsHandler(),
(result) -> {
if (result.status != StatusCode.OK) {
throw new ServiceSpecificException(result.status,
"failed to set value for " + printPropIdAreaId(requestedPropValue));
}
return null;
});
}
private <VhalResultType> HalPropValue getOrSetSync(
HalPropValue requestedPropValue,
PendingSyncRequestPool<VhalResultType> pendingSyncRequestPool,
AsyncRequestsHandler requestsHandler,
Function<VhalResultType, HalPropValue> resultHandler)
throws RemoteException, ServiceSpecificException {
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub#getOrSetSync");
long vhalRequestId = mRequestId.getAndIncrement();
AndroidFuture<VhalResultType> resultFuture = pendingSyncRequestPool.addRequest(
vhalRequestId);
requestsHandler.allocateVhalRequestSize(1);
requestsHandler.addVhalRequest(vhalRequestId, requestedPropValue);
requestsHandler.sendRequestsToVhal(mAidlVehicle, mGetSetValuesCallback);
boolean gotResult = false;
try {
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub#waitingForSyncResult");
VhalResultType result = resultFuture.get(mSyncOpTimeoutInMs,
TimeUnit.MILLISECONDS);
gotResult = true;
return resultHandler.apply(result);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore the interrupted status
throw new ServiceSpecificException(StatusCode.INTERNAL_ERROR,
"thread interrupted, possibly exiting the thread");
} catch (ExecutionException e) {
throw new ServiceSpecificException(StatusCode.INTERNAL_ERROR,
"failed to resolve future, error: " + e);
} catch (TimeoutException e) {
throw new ServiceSpecificException(StatusCode.INTERNAL_ERROR,
"get/set value request timeout for: " + printPropIdAreaId(requestedPropValue));
} finally {
Trace.traceEnd(TRACE_TAG);
if (!gotResult) {
resultFuture = pendingSyncRequestPool.finishRequestIfFound(vhalRequestId);
// Something wrong happened, the future is guaranteed not to be used again.
resultFuture.cancel(/* mayInterruptIfRunning= */ false);
}
Trace.traceEnd(TRACE_TAG);
}
}
首先,我们先了解 set() 函数调用 getOrSetSync() 传了什么参数。
- requestsHandler 是 new AsyncSetRequestsHandler()
- Function
resultHandler 是 一个 lambda 表达式作为参数,这里只是判断是否设置成功而已。
这里比较关键的代码是:
requestsHandler.allocateVhalRequestSize(1);
requestsHandler.addVhalRequest(vhalRequestId, requestedPropValue);
requestsHandler.sendRequestsToVhal(mAidlVehicle, mGetSetValuesCallback);
mGetSetValuesCallback 是 AidlVehicleStub 构造函数里 创建的。
AsyncSetRequestsHandler.sendRequestsToVhal()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private static final class AsyncSetRequestsHandler
extends AsyncRequestsHandler<SetValueRequest, SetValueRequests> {
...
@Override
public void sendRequestsToVhal(IVehicle iVehicle, GetSetValuesCallback callbackForVhal)
throws RemoteException, ServiceSpecificException {
SetValueRequests largeParcelableRequest = new SetValueRequests();
largeParcelableRequest.payloads = mVhalRequestItems;
largeParcelableRequest = (SetValueRequests) LargeParcelable.toLargeParcelable(
largeParcelableRequest, () -> {
SetValueRequests newRequests = new SetValueRequests();
newRequests.payloads = new SetValueRequest[0];
return newRequests;
});
iVehicle.setValues(callbackForVhal, largeParcelableRequest);
}
...
}
iVehicle 是 VehicleHAL 服务,所以调到对端接口了。 这里的 callbackForVhal 是 GetSetValuesCallback 。
GetSetValuesCallback.onSetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private final class GetSetValuesCallback extends IVehicleCallback.Stub {
@Override
public void onSetValues(SetValueResults responses) throws RemoteException {
AidlVehicleStub.this.onSetValues(responses);
}
}
AidlVehicleStub.onSetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private void onSetValues(SetValueResults responses) {
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub#onSetValues");
SetValueResults origResponses = (SetValueResults)
LargeParcelable.reconstructStableAIDLParcelable(responses,
/* keepSharedMemory= */ false);
onGetSetValues(origResponses.payloads, new AsyncSetResultsHandler(),
mPendingSyncSetValueRequestPool);
Trace.traceEnd(TRACE_TAG);
}
这里传进去的 AsyncResultsHandler 是 AsyncSetResultsHandler 。
AidlVehicleStub.onGetSetValues()¶
/**
* 用于处理 onGetValues / onSetValues 的通用函数。
*/
private <VhalResultType> void onGetSetValues(VhalResultType[] vhalResults,
AsyncResultsHandler asyncResultsHandler,
PendingSyncRequestPool<VhalResultType> pendingSyncRequestPool) {
synchronized (mLock) {
for (VhalResultType result : vhalResults) {
long vhalRequestId = asyncResultsHandler.getVhalRequestId(result);
if (!mPendingAsyncRequestPool.contains(vhalRequestId)) {
// 如果在异步映射中找不到请求ID,则假设它是用于同步请求。
completePendingSyncRequestLocked(pendingSyncRequestPool, vhalRequestId, result);
continue;
}
AsyncRequestInfo requestInfo = mPendingAsyncRequestPool.finishRequestIfFound(
vhalRequestId);
if (requestInfo == null) {
Slogf.w(TAG,
"No pending request for ID: %s, possibly already timed out, "
+ "or cancelled, or the client already died", vhalRequestId);
continue;
}
asyncResultsHandler.addVhalResult(requestInfo.getClientCallback(),
requestInfo.getServiceRequestId(), result);
}
}
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub call async result callback");
asyncResultsHandler.callVehicleStubCallback();
Trace.traceEnd(TRACE_TAG);
}
哈哈,分析到这里发现用这里例子举例好像不太好。因为这里是 同步 设置的。所以这里分析不下去了,换个例子。
[异步] CarPropertyManager.setPropertiesAsync()¶
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
public void setPropertiesAsync(
@NonNull List<SetPropertyRequest<?>> setPropertyRequests,
long timeoutInMs,
@Nullable CancellationSignal cancellationSignal,
@Nullable Executor callbackExecutor,
@NonNull SetPropertyCallback setPropertyCallback) {
...
try {
..
mService.setPropertiesAsync(new AsyncPropertyServiceRequestList(
setPropertyServiceRequests), mAsyncPropertyResultCallback, timeoutInMs);
...
...
}
mAsyncPropertyResultCallback 是
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
private final AsyncPropertyResultCallback mAsyncPropertyResultCallback = new AsyncPropertyResultCallback();
private class AsyncPropertyResultCallback extends IAsyncPropertyResultCallback.Stub {
@Override
public IBinder asBinder() {
return this;
}
@Override
public void onGetValueResults(GetSetValueResultList getValueResults) {
...
}
@Override
public void onSetValueResults(GetSetValueResultList setValueResults) {
...
}
@SuppressLint("WrongConstant")
private <RequestType extends AsyncPropertyRequest, CallbackType, ResultType> void onResults(
List<GetSetValueResult> results,
PropertyResultCallback<CallbackType, ResultType> propertyResultCallback) {
...
}
}
[异步] CarPropertyService.setPropertiesAsync()¶
packages/services/Car/service/src/com/android/car/CarPropertyService.java
public void setPropertiesAsync(AsyncPropertyServiceRequestList setPropertyServiceRequests,
IAsyncPropertyResultCallback asyncPropertyResultCallback,
long timeoutInMs) {
...
mPropertyHalService.setCarPropertyValuesAsync(setPropertyServiceRequestList,
asyncPropertyResultCallback, timeoutInMs);
}
[异步] PropertyHalService.setCarPropertyValuesAsync()¶
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
/**
* Sets car property values asynchronously.
*/
public void setCarPropertyValuesAsync(
List<AsyncPropertyServiceRequest> serviceRequests,
IAsyncPropertyResultCallback asyncPropertyResultCallback,
long timeoutInMs) {
List<AsyncPropRequestInfo> pendingSetRequestInfo = new ArrayList<>();
VehicleStubCallback vehicleStubCallback = createVehicleStubCallback(
asyncPropertyResultCallback);
List<AsyncGetSetRequest> setValueRequests = prepareVehicleStubRequests(
SET, serviceRequests, timeoutInMs, vehicleStubCallback,
/* assocSetValueRequestInfo= */ null, /* outRequestInfo= */ pendingSetRequestInfo);
List<AsyncPropRequestInfo> waitForUpdateSetRequestInfo = filterWaitForUpdateRequests(
pendingSetRequestInfo, (request) -> request.isWaitForPropertyUpdate());
if (waitForUpdateSetRequestInfo.size() != 0) {
List<AsyncPropertyServiceRequest> waitForUpdateServiceRequests =
filterWaitForUpdateRequests(serviceRequests,
(request) -> request.isWaitForPropertyUpdate());
sendGetInitialValueAndSubscribeUpdateEvent(waitForUpdateServiceRequests,
vehicleStubCallback, timeoutInMs, waitForUpdateSetRequestInfo);
}
sendVehicleStubRequests(SET, setValueRequests, vehicleStubCallback);
}
IAsyncPropertyResultCallback asyncPropertyResultCallback 是 CarPropertyManager 的 成员变量 mAsyncPropertyResultCallback ( AsyncPropertyResultCallback )。
再找下 vehicleStubCallback 是谁。
asyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback 。
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
@GuardedBy("mLock")
private final Map<IBinder, VehicleStubCallback> mResultBinderToVehicleStubCallback = new ArrayMap<>();
VehicleStubCallback createVehicleStubCallback(
IAsyncPropertyResultCallback asyncPropertyResultCallback) {
IBinder asyncPropertyResultBinder = asyncPropertyResultCallback.asBinder();
VehicleStubCallback callback;
synchronized (mLock) {
if (mResultBinderToVehicleStubCallback.get(asyncPropertyResultBinder) == null) {
callback = new VehicleStubCallback(asyncPropertyResultCallback);
try {
callback.linkToDeath(() -> onBinderDied(asyncPropertyResultBinder));
} catch (RemoteException e) {
throw new IllegalStateException("Linking to binder death recipient failed, "
+ "the client might already died", e);
}
mResultBinderToVehicleStubCallback.put(asyncPropertyResultBinder, callback);
} else {
callback = mResultBinderToVehicleStubCallback.get(asyncPropertyResultBinder);
}
}
return callback;
}
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
private class VehicleStubCallback extends VehicleStubCallbackInterface {
private final IAsyncPropertyResultCallback mAsyncPropertyResultCallback;
private final IBinder mClientBinder;
VehicleStubCallback(
IAsyncPropertyResultCallback asyncPropertyResultCallback) {
// mAsyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback
mAsyncPropertyResultCallback = asyncPropertyResultCallback;
mClientBinder = asyncPropertyResultCallback.asBinder();
}
private void sendGetValueResults(List<GetSetValueResult> results) {
if (results.isEmpty()) {
return;
}
try {
mAsyncPropertyResultCallback.onGetValueResults(new GetSetValueResultList(results));
} catch (RemoteException e) {
Slogf.w(TAG, "sendGetValueResults: Client might have died already", e);
}
}
void sendSetValueResults(List<GetSetValueResult> results) {
if (results.isEmpty()) {
return;
}
try {
mAsyncPropertyResultCallback.onSetValueResults(new GetSetValueResultList(results));
} catch (RemoteException e) {
Slogf.w(TAG, "sendSetValueResults: Client might have died already", e);
}
}
...
}
packages/services/Car/service/src/com/android/car/VehicleStub.java
public abstract static class VehicleStubCallbackInterface {
/**
* Method called when {@link getAsync} returns results.
*/
public abstract void onGetAsyncResults(
List<GetVehicleStubAsyncResult> getVehicleStubAsyncResults);
/**
* Method called when {@link setAsync} returns results.
*/
public abstract void onSetAsyncResults(
List<SetVehicleStubAsyncResult> setVehicleStubAsyncResults);
/**
* Register a callback that will be called when the callback binder died.
*/
public abstract void linkToDeath(DeathRecipient recipient) throws RemoteException;
/**
* Method called when async requests timed-out.
*
* If the callback's binder is already dead, this function will not be called.
*/
public abstract void onRequestsTimeout(List<Integer> serviceRequestIds);
}
mResultBinderToVehicleStubCallback 是通过 IBinder 和 VehicleStubCallback 关联起来。所以只有通过 CarPropertyManager 拿到传进来的 AsyncPropertyResultCallback ( asBinder() ),就可以知道在 PropertyHalService 里其对应的 VehicleStubCallback。
这里还有一个比较重要的点:VehicleStubCallback 的成员变量 mAsyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback 。
不知道 setValueRequests 有没有用,先不分析。sendVehicleStubRequests 会根据 requestType 来调用 VehicleHal 接口。
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
private void sendVehicleStubRequests(@AsyncRequestType int requestType,
List<AsyncGetSetRequest> vehicleStubRequests, VehicleStubCallback callback) {
switch (requestType) {
case GET: // fallthrough
case GET_INITIAL_VALUE_FOR_SET:
mVehicleHal.getAsync(vehicleStubRequests, callback);
break;
case SET:
mVehicleHal.setAsync(vehicleStubRequests, callback);
break;
}
}
我们这里例子是 SET 。
[异步] VehicleHal.setAsync()¶
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public void setAsync(List<VehicleStub.AsyncGetSetRequest> setVehicleStubAsyncRequests,
VehicleStub.VehicleStubCallbackInterface setVehicleStubAsyncCallback) {
mVehicleStub.setAsync(setVehicleStubAsyncRequests, setVehicleStubAsyncCallback);
}
这里的 mVehicleStub 依然是 AidlVehicleStub 。 setVehicleStubAsyncCallback 就是 PropertyHalService 的 VehicleStubCallback 。
[异步] AidlVehicleStub.setAsync()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
@Override
public void setAsync(List<AsyncGetSetRequest> setVehicleStubAsyncRequests,
VehicleStubCallbackInterface setCallback) {
getOrSetAsync(setVehicleStubAsyncRequests, setCallback, new AsyncSetRequestsHandler(),
new AsyncSetResultsHandler());
}
[异步] AidlVehicleStub.getOrSetAsync()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private <VhalRequestType, VhalRequestsType> void getOrSetAsync(
List<AsyncGetSetRequest> vehicleStubAsyncRequests,
VehicleStubCallbackInterface vehicleStubCallback,
AsyncRequestsHandler<VhalRequestType, VhalRequestsType> asyncRequestsHandler,
AsyncResultsHandler asyncResultsHandler) {
prepareAndConvertAsyncRequests(vehicleStubAsyncRequests, vehicleStubCallback,
asyncRequestsHandler);
try {
asyncRequestsHandler.sendRequestsToVhal(mAidlVehicle, mGetSetValuesCallback);
...
}
VehicleStubCallbackInterface vehicleStubCallback 就是 PropertyHalService 的 VehicleStubCallback 。 asyncRequestsHandler 就是 new AsyncSetRequestsHandler() 。 asyncResultsHandler 就是 new AsyncSetResultsHandler() 。
我们分成两部分来看:
[异步] AidlVehicleStub.prepareAndConvertAsyncRequests()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private <VhalRequestType, VhalRequestsType> void prepareAndConvertAsyncRequests(
List<AsyncGetSetRequest> vehicleStubRequests,
VehicleStubCallbackInterface clientCallback,
AsyncRequestsHandler<VhalRequestType, VhalRequestsType> asyncRequestsHandler) {
asyncRequestsHandler.allocateVhalRequestSize(vehicleStubRequests.size());
synchronized (mLock) {
try {
clientCallback.linkToDeath(() -> {
synchronized (mLock) {
mPendingAsyncRequestPool.removeRequestsForCallback(clientCallback);
}
});
} catch (RemoteException e) {
// Binder已经死亡。
throw new IllegalStateException("Failed to link callback to death recipient, the "
+ "client maybe already died");
}
for (int i = 0; i < vehicleStubRequests.size(); i++) {
AsyncGetSetRequest vehicleStubRequest = vehicleStubRequests.get(i);
long vhalRequestId = mRequestId.getAndIncrement();
AsyncRequestInfo requestInfo = new AsyncRequestInfo(
vhalRequestId, vehicleStubRequest.getServiceRequestId(), clientCallback,
vehicleStubRequest.getTimeoutUptimeMs());
mPendingAsyncRequestPool.addRequest(requestInfo);
asyncRequestsHandler.addVhalRequest(vhalRequestId,
vehicleStubRequest.getHalPropValue());
}
}
}
AsyncRequestInfo 的成员变量 mClientCallback 就是 PropertyHalService 的 VehicleStubCallback 。 而 AsyncRequestInfo 又被添加到 mPendingRequestPool 的成员变量 mPendingRequestPool 中 。
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private static class AsyncRequestInfo implements LongRequestIdWithTimeout {
private final int mServiceRequestId;
private final VehicleStubCallbackInterface mClientCallback;
private final long mTimeoutUptimeMs;
private final long mVhalRequestId;
private AsyncRequestInfo(
long vhalRequestId,
int serviceRequestId,
VehicleStubCallbackInterface clientCallback,
long timeoutUptimeMs) {
mVhalRequestId = vhalRequestId;
mServiceRequestId = serviceRequestId;
mClientCallback = clientCallback;
mTimeoutUptimeMs = timeoutUptimeMs;
}
@Override
public long getRequestId() {
return mVhalRequestId;
}
@Override
public long getTimeoutUptimeMs() {
return mTimeoutUptimeMs;
}
public int getServiceRequestId() {
return mServiceRequestId;
}
public VehicleStubCallbackInterface getClientCallback() {
return mClientCallback;
}
}
[异步] AsyncSetRequestsHandler.sendRequestsToVhal()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
public void sendRequestsToVhal(IVehicle iVehicle, GetSetValuesCallback callbackForVhal)
throws RemoteException, ServiceSpecificException {
SetValueRequests largeParcelableRequest = new SetValueRequests();
largeParcelableRequest.payloads = mVhalRequestItems;
largeParcelableRequest = (SetValueRequests) LargeParcelable.toLargeParcelable(
largeParcelableRequest, () -> {
SetValueRequests newRequests = new SetValueRequests();
newRequests.payloads = new SetValueRequest[0];
return newRequests;
});
iVehicle.setValues(callbackForVhal, largeParcelableRequest);
}
iVehicle 是 VehicleHAL 服务,所以调到对端接口了。 这里的 callbackForVhal 是 GetSetValuesCallback 。 我们先不分析 VehicleHAL 服务 ,先把 car-service 接到回调的流程看完。
[异步] GetSetValuesCallback.onSetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private final class GetSetValuesCallback extends IVehicleCallback.Stub {
...
@Override
public void onSetValues(SetValueResults responses) throws RemoteException {
AidlVehicleStub.this.onSetValues(responses);
}
...
}
[异步] AidlVehicleStub.onSetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private void onSetValues(SetValueResults responses) {
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub#onSetValues");
SetValueResults origResponses = (SetValueResults)
LargeParcelable.reconstructStableAIDLParcelable(responses,
/* keepSharedMemory= */ false);
onGetSetValues(origResponses.payloads, new AsyncSetResultsHandler(),
mPendingSyncSetValueRequestPool);
Trace.traceEnd(TRACE_TAG);
}
[异步] AidlVehicleStub.onGetSetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private <VhalResultType> void onGetSetValues(VhalResultType[] vhalResults,
AsyncResultsHandler asyncResultsHandler,
PendingSyncRequestPool<VhalResultType> pendingSyncRequestPool) {
synchronized (mLock) {
for (VhalResultType result : vhalResults) {
long vhalRequestId = asyncResultsHandler.getVhalRequestId(result);
if (!mPendingAsyncRequestPool.contains(vhalRequestId)) {
// If we cannot find the request Id in the async map, we assume it is for a
// sync request.
completePendingSyncRequestLocked(pendingSyncRequestPool, vhalRequestId, result);
continue;
}
AsyncRequestInfo requestInfo = mPendingAsyncRequestPool.finishRequestIfFound(
vhalRequestId);
if (requestInfo == null) {
Slogf.w(TAG,
"No pending request for ID: %s, possibly already timed out, "
+ "or cancelled, or the client already died", vhalRequestId);
continue;
}
asyncResultsHandler.addVhalResult(requestInfo.getClientCallback(),
requestInfo.getServiceRequestId(), result);
}
}
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub call async result callback");
asyncResultsHandler.callVehicleStubCallback();
Trace.traceEnd(TRACE_TAG);
}
这里跟前提的 同步 例子就不一样了,因为从 mPendingAsyncRequestPool 可以找到 AsyncRequestInfo。 requestInfo.getClientCallback() 就是 PropertyHalService 的 VehicleStubCallback 。 再把那到的 AsyncRequestInfo 添加到 AsyncResultsHandler (其实是 AsyncSetResultsHandler )。 最后调用 AsyncSetResultsHandler.callVehicleStubCallback() 。
[异步] AsyncSetResultsHandler.addVhalResult()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private static final class AsyncSetResultsHandler extends
AsyncResultsHandler<SetValueResult, SetVehicleStubAsyncResult> {
AsyncSetResultsHandler() {
mCallbackToResults = new ArrayMap<VehicleStubCallbackInterface,
List<SetVehicleStubAsyncResult>>();
}
@Override
void addVhalResult(VehicleStubCallbackInterface callback, int serviceRequestId,
SetValueResult result) {
addVehicleStubResult(callback, toVehicleStubResult(serviceRequestId, result));
}
}
private abstract static class AsyncResultsHandler<VhalResultType, VehicleStubResultType> {
protected Map<VehicleStubCallbackInterface, List<VehicleStubResultType>> mCallbackToResults;
protected void addVehicleStubResult(VehicleStubCallbackInterface callback,
VehicleStubResultType vehicleStubResult) {
if (mCallbackToResults.get(callback) == null) {
mCallbackToResults.put(callback, new ArrayList<>());
}
mCallbackToResults.get(callback).add(vehicleStubResult);
}
}
把 callback 和 result 关联起来。
[异步] AsyncSetResultsHandler.callVehicleStubCallback()¶
private static final class AsyncSetResultsHandler extends
AsyncResultsHandler<SetValueResult, SetVehicleStubAsyncResult> {
...
@Override
void callVehicleStubCallback() {
for (Map.Entry<VehicleStubCallbackInterface, List<SetVehicleStubAsyncResult>> entry :
mCallbackToResults.entrySet()) {
entry.getKey().onSetAsyncResults(entry.getValue());
}
}
...
}
根据上面的分析,VehicleStubCallbackInterface 就是 PropertyHalService 的 VehicleStubCallback ,所以这里就回调到了 PropertyHalService.onSetAsyncResults()
[异步] PropertyHalService.onSetAsyncResults()¶
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
@Override
public void onSetAsyncResults(
List<SetVehicleStubAsyncResult> setVehicleStubAsyncResults) {
...
sendSetValueResults(setValueResults);
if (!retryRequests.isEmpty()) {
mHandler.postDelayed(() -> {
retryIfNotExpired(retryRequests);
}, ASYNC_RETRY_SLEEP_IN_MS);
}
}
void sendSetValueResults(List<GetSetValueResult> results) {
if (results.isEmpty()) {
return;
}
try {
mAsyncPropertyResultCallback.onSetValueResults(new GetSetValueResultList(results));
} catch (RemoteException e) {
Slogf.w(TAG, "sendSetValueResults: Client might have died already", e);
}
}
前面分析到:VehicleStubCallback 的成员变量 mAsyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback 。 所以这里就会回调到 CarPropertyManager 的 onSetValueResults()。
[异步] IAsyncPropertyResultCallback.onSetValueResults()¶
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
private final AsyncPropertyResultCallback mAsyncPropertyResultCallback = new AsyncPropertyResultCallback();
private class AsyncPropertyResultCallback extends IAsyncPropertyResultCallback.Stub {
@Override
public IBinder asBinder() {
return this;
}
@Override
public void onGetValueResults(GetSetValueResultList getValueResults) {
...
}
@Override
public void onSetValueResults(GetSetValueResultList setValueResults) {
...
}
@SuppressLint("WrongConstant")
private <RequestType extends AsyncPropertyRequest, CallbackType, ResultType> void onResults(
List<GetSetValueResult> results,
PropertyResultCallback<CallbackType, ResultType> propertyResultCallback) {
...
}
}
至此,我们分析完了 car-service 端 set() 同步、异步设置属性,以及设置后回调的过程。 但我们还未分析 VehicleHAL 端的代码。在 AsyncSetRequestsHandler.sendRequestsToVhal() 函数中,我们调用:
iVehicle 是 VehicleHAL 。根据前面 VehicleHAL 初始化流程我们知道,调用 setValues() 函数会调到 DefaultVehicleHal.cpp 的 setValues() 函数。
DefaultVehicleHal::setValues()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
const SetValueRequests& requests) {
ATRACE_CALL();
if (callback == nullptr) {
return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
}
// 从稳定的大型可序列化对象中反序列化结果
expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
deserializedResults = fromStableLargeParcelable(requests);
if (!deserializedResults.ok()) {
ALOGE("setValues: failed to parse setValues requests");
return std::move(deserializedResults.error());
}
// 获取反序列化结果中的请求列表
const std::vector<SetValueRequest>& setValueRequests =
deserializedResults.value().getObject()->payloads;
// 失败的结果列表
std::vector<SetValueResult> failedResults;
// 发送到硬件的请求列表
std::vector<SetValueRequest> hardwareRequests;
// 检查是否有重复的请求ID
auto maybeRequestIds = checkDuplicateRequests(setValueRequests);
if (!maybeRequestIds.ok()) {
ALOGE("setValues: duplicate request ID");
return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
}
for (auto& request : setValueRequests) {
int64_t requestId = request.requestId;
if (auto result = checkWritePermission(request.value); !result.ok()) {
ALOGW("property does not support writing: %s", getErrorMsg(result).c_str());
// 将失败的结果添加到列表中
failedResults.push_back(SetValueResult{
.requestId = requestId,
.status = getErrorCode(result),
});
continue;
}
if (auto result = checkProperty(request.value); !result.ok()) {
ALOGW("setValues[%" PRId64 "]: property is not valid: %s", requestId,
getErrorMsg(result).c_str());
// 将失败的结果添加到列表中
failedResults.push_back(SetValueResult{
.requestId = requestId,
.status = StatusCode::INVALID_ARG,
});
continue;
}
// 将请求添加到发送到硬件的列表中
hardwareRequests.push_back(request);
}
// 硬件请求的ID集合
std::unordered_set<int64_t> hardwareRequestIds;
for (const auto& request : hardwareRequests) {
// 将硬件请求的ID添加到集合中
hardwareRequestIds.insert(request.requestId);
}
std::shared_ptr<SetValuesClient> client;
{
// 加锁,确保onBinderDied不会并发调用
std::scoped_lock lockGuard(mLock);
if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
// 返回客户端死亡的异常状态
return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
"client died");
}
// 获取或创建客户端
client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
}
if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
ALOGE("setValues[%s], failed to add pending requests, error: %s",
toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
return toScopedAStatus(addRequestResult);
}
if (!failedResults.empty()) {
// 将已知的失败结果发送给客户端
client->sendResults(std::move(failedResults));
}
if (hardwareRequests.empty()) {
return ScopedAStatus::ok();
}
if (StatusCode status =
mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
status != StatusCode::OK) {
// 将已知的失败结果发送给客户端
client->tryFinishRequests(hardwareRequestIds);
ALOGE("setValues[%s], failed to set value to VehicleHardware, status: %d",
toString(hardwareRequestIds).c_str(), toInt(status));
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
toInt(status), "failed to set value to VehicleHardware");
}
return ScopedAStatus::ok();
}
这段代码比较长,我们把关键部分整理出来:
-
callback java端传进来的,其实也就是 IVehicleCallback.aidl
-
mPendingRequestPool mPendingRequestPool 是在 DefaultVehicleHal 构造函数里创建的。 PendingRequestPool 的功能在前面有详细介绍。
-
mSetValuesClients 先记住 mSetValuesClients 这个 map 的 vaule 类型。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
using SetValuesClient =
GetSetValuesClient<aidl::android::hardware::automotive::vehicle::SetValueResult,
aidl::android::hardware::automotive::vehicle::SetValueResults>;
std::unordered_map<const AIBinder*, std::shared_ptr<SetValuesClient>> mSetValuesClients
GUARDED_BY(mLock);
- client
std::shared_ptr<SetValuesClient> client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
-
client->addRequests(hardwareRequestIds) 添加客户端请求。
-
client->sendResults(std::move(failedResults)); 将结果发送给此客户端。
-
client->tryFinishRequests(hardwareRequestIds); 标记请求已完成。
-
mVehicleHardware->setValues()
可以看到,最关键的就是这两步:
- 调用 getOrCreateClient() 获取或创建客户端。
- 调用 FakeVehicleHardware::setValues() 设置属性。
DefaultVehicleHal::getOrCreateClient()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
/**
* @brief 获取或创建客户端对象
*
* @tparam T 客户端对象类型
* @param clients 客户端对象的映射表
* @param callback 回调函数
* @param pendingRequestPool 挂起请求池
* @return std::shared_ptr<T> 客户端对象的共享指针
*/
template <class T>
std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
const AIBinder* clientId = callback->asBinder().get();
if (clients->find(clientId) == clients->end()) {
(*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
}
return (*clients)[clientId];
}
这是一个模板函数,根据 clients 的数据类型可以知道,T 就是 GetSetValuesClient 。 我们找下 GetSetValuesClient 是在哪里定义。
ConnectedClient¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
// 一个表示带有回调接口的绑定器客户端的类。每个回调函数,例如GetValues或SetValues对于一个特定的绑定器客户端是一个独立的ConnectedClient。
// 对于一个ConnectedClient,我们使用一个待处理请求池来管理所有待处理的请求,所以请求ID必须对于一个客户端是唯一的。
// 我们还管理一个客户端的一组回调函数,例如timeoutCallback,它可以传递给硬件。
// 这个类是线程安全的。
class ConnectedClient {
public:
using CallbackType =
std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
ConnectedClient(std::shared_ptr<PendingRequestPool> requestPool, CallbackType callback);
// 获取此客户端的唯一ID。
const void* id();
// 添加客户端请求。这些请求将被注册为待处理请求,直到调用tryFinishRequests为止。
// 如果任何一个请求ID与待处理请求ID之一重复,则返回INVALID_ARG错误;
// 如果待处理请求池已满且无法再添加请求,则返回TRY_AGAIN错误。
VhalResult<void> addRequests(const std::unordered_set<int64_t>& requestIds);
// 标记请求已完成。返回一个已完成的待处理请求ID列表。它必须是请求的请求ID的集合。
std::unordered_set<int64_t> tryFinishRequests(const std::unordered_set<int64_t>& requestIds);
protected:
// 获取在此客户端的请求超时时要调用的回调。
virtual std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() = 0;
const std::shared_ptr<PendingRequestPool> mRequestPool;
const CallbackType mCallback;
};
GetSetValuesClient¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
// 一个表示调用IVehicle.setValues或IVehicle.getValues的客户端的类。
template <class ResultType, class ResultsType>
class GetSetValuesClient final : public ConnectedClient {
public:
GetSetValuesClient(std::shared_ptr<PendingRequestPool> requestPool, CallbackType callback);
// 将结果发送给此客户端。
void sendResults(std::vector<ResultType>&& results);
// 将每个结果分别发送给此客户端。每个结果将通过一个回调调用发送。
void sendResultsSeparately(const std::vector<ResultType>& results);
// 获取在此客户端的请求完成时要调用的回调。
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> getResultCallback();
protected:
// 获取在此客户端的请求超时时要调用的回调。
std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() override;
private:
// 以下成员仅在构造期间初始化。
std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> mTimeoutCallback;
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> mResultCallback;
};
GetSetValuesClient::addRequests()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
VhalResult<void> ConnectedClient::addRequests(const std::unordered_set<int64_t>& requestIds) {
return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback());
}
先来看这个 mRequestPool 到底是什么。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
const std::shared_ptr<PendingRequestPool> mRequestPool;
mRequestPool 是在 ConnectedClient 构造函数里初始化的。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
ConnectedClient::ConnectedClient(std::shared_ptr<PendingRequestPool> requestPool,
std::shared_ptr<IVehicleCallback> callback)
: mRequestPool(requestPool), mCallback(callback) {}
根据我们这个例子,下面这个模板函数调用 ConnectedClient 构造函数。
template <class ResultType, class ResultsType>
GetSetValuesClient<ResultType, ResultsType>::GetSetValuesClient(
std::shared_ptr<PendingRequestPool> requestPool, std::shared_ptr<IVehicleCallback> callback)
: ConnectedClient(requestPool, callback) {
// 创建一个指向PendingRequestPool::TimeoutCallbackFunc类型的智能指针mTimeoutCallback
// 该回调函数用于处理超时请求
mTimeoutCallback = std::make_shared<const PendingRequestPool::TimeoutCallbackFunc>(
[callback](const std::unordered_set<int64_t>& timeoutIds) {
return onTimeout<ResultType, ResultsType>(callback, timeoutIds);
});
// 复制requestPool到requestPoolCopy
auto requestPoolCopy = mRequestPool;
// 获取当前对象的id,并赋值给clientId
const void* clientId = id();
// 创建一个指向std::function<void(std::vector<ResultType>)>类型的智能指针mResultCallback
// 该回调函数用于处理获取或设置值的回调
mResultCallback = std::make_shared<const std::function<void(std::vector<ResultType>)>>(
[clientId, callback, requestPoolCopy](std::vector<ResultType> results) {
return getOrSetValuesCallback<ResultType, ResultsType>(
clientId, callback, std::move(results), requestPoolCopy);
});
}
再返回到 DefaultVehicleHal::getOrCreateClient() 中。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
template <class T>
std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
const AIBinder* clientId = callback->asBinder().get();
if (clients->find(clientId) == clients->end()) {
(*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
}
return (*clients)[clientId];
}
看到了吧:
在返回到 调用 DefaultVehicleHal::getOrCreateClient() 的地方,也就是 DefaultVehicleHal::setValues() ,此时可以知道两件事:
- 这里的 pendingRequestPool 其实就是 DefaultVehicleHal 的成员变量 mPendingRequestPool,其在 DefaultVehicleHal 构造函数中初始化。也就是 PendingRequestPool。
- 这里的 callback 就是java端传进来的,其实也就是 IVehicleCallback.aidl
好了,回到我们的 ConnectedClient::addRequests() 函数里。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
VhalResult<void> ConnectedClient::addRequests(const std::unordered_set<int64_t>& requestIds) {
return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback());
}
所以这里调用的是 PendingRequestPool::addRequests() 函数。
PendingRequestPool::addRequests()¶
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
VhalResult<void> PendingRequestPool::addRequests(
const void* clientId, const std::unordered_set<int64_t>& requestIds,
std::shared_ptr<const TimeoutCallbackFunc> callback) {
// 对互斥锁进行加锁,确保线程安全
std::scoped_lock<std::mutex> lockGuard(mLock);
std::list<PendingRequest>* pendingRequests;
// 初始化待处理请求的数量为0
size_t pendingRequestCount = 0;
// 如果 mPendingRequestsByClient 中存在指定的 clientId
if (mPendingRequestsByClient.find(clientId) != mPendingRequestsByClient.end()) {
pendingRequests = &mPendingRequestsByClient[clientId];
for (const auto& pendingRequest : *pendingRequests) {
// 获取当前PendingRequest的请求ID集合
const auto& pendingRequestIds = pendingRequest.requestIds;
// 遍历传入的请求ID集合
for (int64_t requestId : requestIds) {
// 如果当前PendingRequest的请求ID集合中存在重复的请求ID
if (pendingRequestIds.find(requestId) != pendingRequestIds.end()) {
return StatusError(StatusCode::INVALID_ARG)
<< "duplicate request ID: " << requestId;
}
}
// 累加已有PendingRequest的请求ID数量
pendingRequestCount += pendingRequestIds.size();
}
} else {
// 为该clientId创建一个新的空的PendingRequest列表
pendingRequests = &mPendingRequestsByClient[clientId];
}
// 如果传入的请求ID数量超过了每个客户端允许的最大待处理请求数量
if (requestIds.size() > MAX_PENDING_REQUEST_PER_CLIENT - pendingRequestCount) {
return StatusError(StatusCode::TRY_AGAIN)
<< "too many pending requests";
}
int64_t currentTime = elapsedRealtimeNano();
// 根据当前时间,计算超时时间戳
int64_t timeoutTimestamp = currentTime + mTimeoutInNano;
// 将新的PendingRequest添加到PendingRequest列表中
pendingRequests->push_back({
.requestIds = std::unordered_set<int64_t>(requestIds.begin(), requestIds.end()),
.timeoutTimestamp = timeoutTimestamp,
.callback = callback,
});
return {};
}
看到这里有点迷茫,先不管,再尝试往下看看。
GetSetValuesClient::sendResults()¶
在前面 DefaultVehicleHal::setValues() 中,如果设置属性失败(没有权限、属性ID不合法),则主动调用 client->sendResults(std::move(failedResults)) 把错误信息回调给客户端。
std::vector<SetValueResult> failedResults;
...
if (!failedResults.empty()) {
// 将已知的失败结果发送给客户端
client->sendResults(std::move(failedResults));
}
函数的实现如下:
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
template <class ResultType, class ResultsType>
void GetSetValuesClient<ResultType, ResultsType>::sendResults(std::vector<ResultType>&& results) {
return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, std::move(results));
}
所以这里的 ResultsType 就是 SetValueResult 。
sendGetOrSetValueResults¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
// 将所有的 GetValue/SetValue 结果通过回调函数一次性发送
template <class ResultType, class ResultsType>
void sendGetOrSetValueResults(std::shared_ptr<IVehicleCallback> callback,
std::vector<ResultType>&& results) {
ResultsType parcelableResults;
ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults);
// 检查结果是否成功转换为Parcelable
if (status.isOk()) {
// 调用回调函数,并检查回调是否成功
if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
!callbackStatus.isOk()) {
// 打印错误信息
ALOGE("failed to call GetOrSetValueResults callback, client ID: %p, error: %s, "
"exception: %d, service specific error: %d",
callback->asBinder().get(), callbackStatus.getMessage(),
callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
}
return;
}
int statusCode = status.getServiceSpecificError();
ALOGE("failed to marshal result into large parcelable, error: "
"%s, code: %d",
status.getMessage(), statusCode);
// 分别发送GetOrSetValueResults的结果
sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(callback,
parcelableResults.payloads);
}
因为我们的类型是 SetValueResult ,所以这里的 callCallback 对应的是这个模板显式具体化函数。
template <>
ScopedAStatus callCallback<SetValueResults>(std::shared_ptr<IVehicleCallback> callback,
const SetValueResults& results) {
return callback->onSetValues(results);
}
这里清楚的看到,调用的就是 IVehicleCallback 的 onSetValues() 回调函数。 最终就会通过 IPC 走到 前面提到的 GetSetValuesCallback.onSetValues() 函数里。 但,不要高兴得太早。这里只是错误的情况的回调。我们还是得回到 DefaultVehicleHal::setValues() 里,也就是调用 FakeVehicleHardware::setValues() 设置属性。
FakeVehicleHardware::setValues()¶
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
const std::vector<SetValueRequest>& requests) {
for (auto& request : requests) {
if (FAKE_VEHICLEHARDWARE_DEBUG) {
ALOGD("Set value for property ID: %d", request.value.prop);
}
// 在真实的VHAL实现中,你可以选择在这里将setValue请求发送到车辆总线,
// 或者你可以在setValue中发送请求,该函数在处理程序线程中运行。
// 如果你决定在这里发送setValue请求,你不应该在这里等待响应,
// 处理程序线程应该处理setValue响应。
mPendingSetValueRequests.addRequest(request, callback);
}
return StatusCode::OK;
}
从这里的注释可以看出来了,这里只是给出了一个demo告诉我们怎么写VehicleHardware。所以这里如何回调回去也不再详细分析。 思路就是有一个线程,如果有事件(set、get)请求,就在后台线程处理好事件,并通过 callback 回调到客户端。
get 获取属性¶
CarPropertyManager.setPropertiesAsync()¶
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
@ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0,
minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0)
public void getPropertiesAsync(
@NonNull List<GetPropertyRequest> getPropertyRequests,
long timeoutInMs,
@Nullable CancellationSignal cancellationSignal,
@Nullable Executor callbackExecutor,
@NonNull GetPropertyCallback getPropertyCallback) {
...
try {
if (DBG) {
Log.d(TAG, "calling CarPropertyService.getPropertiesAsync");
}
mService.getPropertiesAsync(new AsyncPropertyServiceRequestList(
getPropertyServiceRequests), mAsyncPropertyResultCallback, timeoutInMs);
...
}
mAsyncPropertyResultCallback 是
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
private final AsyncPropertyResultCallback mAsyncPropertyResultCallback = new AsyncPropertyResultCallback();
private class AsyncPropertyResultCallback extends IAsyncPropertyResultCallback.Stub {
@Override
public IBinder asBinder() {
return this;
}
@Override
public void onGetValueResults(GetSetValueResultList getValueResults) {
...
}
@Override
public void onSetValueResults(GetSetValueResultList setValueResults) {
...
}
@SuppressLint("WrongConstant")
private <RequestType extends AsyncPropertyRequest, CallbackType, ResultType> void onResults(
List<GetSetValueResult> results,
PropertyResultCallback<CallbackType, ResultType> propertyResultCallback) {
...
}
}
CarPropertyService.getPropertiesAsync()¶
packages/services/Car/service/src/com/android/car/CarPropertyService.java
public void getPropertiesAsync(
AsyncPropertyServiceRequestList getPropertyServiceRequestsParcelable,
IAsyncPropertyResultCallback asyncPropertyResultCallback, long timeoutInMs) {
...
mPropertyHalService.getCarPropertyValuesAsync(getPropertyServiceRequests,
asyncPropertyResultCallback, timeoutInMs);
}
[异步] PropertyHalService.getCarPropertyValuesAsync()¶
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
public void getCarPropertyValuesAsync(
List<AsyncPropertyServiceRequest> serviceRequests,
IAsyncPropertyResultCallback asyncPropertyResultCallback,
long timeoutInMs) {
VehicleStubCallback vehicleStubCallback = createVehicleStubCallback(
asyncPropertyResultCallback);
List<AsyncGetSetRequest> vehicleStubRequests = prepareVehicleStubRequests(
GET, serviceRequests, timeoutInMs, vehicleStubCallback,
/* assocSetValueRequestInfo= */ null, /* outRequestInfo= */ null);
sendVehicleStubRequests(GET, vehicleStubRequests, vehicleStubCallback);
}
IAsyncPropertyResultCallback asyncPropertyResultCallback 是 CarPropertyManager 的 成员变量 mAsyncPropertyResultCallback ( AsyncPropertyResultCallback )。
再找下 vehicleStubCallback 是谁。
asyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback 。
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
@GuardedBy("mLock")
private final Map<IBinder, VehicleStubCallback> mResultBinderToVehicleStubCallback = new ArrayMap<>();
VehicleStubCallback createVehicleStubCallback(
IAsyncPropertyResultCallback asyncPropertyResultCallback) {
IBinder asyncPropertyResultBinder = asyncPropertyResultCallback.asBinder();
VehicleStubCallback callback;
synchronized (mLock) {
if (mResultBinderToVehicleStubCallback.get(asyncPropertyResultBinder) == null) {
callback = new VehicleStubCallback(asyncPropertyResultCallback);
try {
callback.linkToDeath(() -> onBinderDied(asyncPropertyResultBinder));
} catch (RemoteException e) {
throw new IllegalStateException("Linking to binder death recipient failed, "
+ "the client might already died", e);
}
mResultBinderToVehicleStubCallback.put(asyncPropertyResultBinder, callback);
} else {
callback = mResultBinderToVehicleStubCallback.get(asyncPropertyResultBinder);
}
}
return callback;
}
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
private class VehicleStubCallback extends VehicleStubCallbackInterface {
private final IAsyncPropertyResultCallback mAsyncPropertyResultCallback;
private final IBinder mClientBinder;
VehicleStubCallback(
IAsyncPropertyResultCallback asyncPropertyResultCallback) {
// mAsyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback
mAsyncPropertyResultCallback = asyncPropertyResultCallback;
mClientBinder = asyncPropertyResultCallback.asBinder();
}
private void sendGetValueResults(List<GetSetValueResult> results) {
if (results.isEmpty()) {
return;
}
try {
mAsyncPropertyResultCallback.onGetValueResults(new GetSetValueResultList(results));
} catch (RemoteException e) {
Slogf.w(TAG, "sendGetValueResults: Client might have died already", e);
}
}
void sendSetValueResults(List<GetSetValueResult> results) {
if (results.isEmpty()) {
return;
}
try {
mAsyncPropertyResultCallback.onSetValueResults(new GetSetValueResultList(results));
} catch (RemoteException e) {
Slogf.w(TAG, "sendSetValueResults: Client might have died already", e);
}
}
...
}
packages/services/Car/service/src/com/android/car/VehicleStub.java
public abstract static class VehicleStubCallbackInterface {
/**
* Method called when {@link getAsync} returns results.
*/
public abstract void onGetAsyncResults(
List<GetVehicleStubAsyncResult> getVehicleStubAsyncResults);
/**
* Method called when {@link setAsync} returns results.
*/
public abstract void onSetAsyncResults(
List<SetVehicleStubAsyncResult> setVehicleStubAsyncResults);
/**
* Register a callback that will be called when the callback binder died.
*/
public abstract void linkToDeath(DeathRecipient recipient) throws RemoteException;
/**
* Method called when async requests timed-out.
*
* If the callback's binder is already dead, this function will not be called.
*/
public abstract void onRequestsTimeout(List<Integer> serviceRequestIds);
}
mResultBinderToVehicleStubCallback 是通过 IBinder 和 VehicleStubCallback 关联起来。所以只有通过 CarPropertyManager 拿到传进来的 AsyncPropertyResultCallback ( asBinder() ),就可以知道在 PropertyHalService 里其对应的 VehicleStubCallback。
这里还有一个比较重要的点:VehicleStubCallback 的成员变量 mAsyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback 。
sendVehicleStubRequests 会根据 requestType 来调用 VehicleHal 接口。
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
private void sendVehicleStubRequests(@AsyncRequestType int requestType,
List<AsyncGetSetRequest> vehicleStubRequests, VehicleStubCallback callback) {
switch (requestType) {
case GET: // fallthrough
case GET_INITIAL_VALUE_FOR_SET:
mVehicleHal.getAsync(vehicleStubRequests, callback);
break;
case SET:
mVehicleHal.setAsync(vehicleStubRequests, callback);
break;
}
}
我们这里例子是 GET 。
VehicleHal.getAsync()¶
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public void getAsync(List<VehicleStub.AsyncGetSetRequest> getVehicleStubAsyncRequests,
VehicleStub.VehicleStubCallbackInterface getVehicleStubAsyncCallback) {
mVehicleStub.getAsync(getVehicleStubAsyncRequests, getVehicleStubAsyncCallback);
}
这里的 mVehicleStub 依然是 AidlVehicleStub 。 getVehicleStubAsyncRequests 就是 PropertyHalService 的 VehicleStubCallback 。
AidlVehicleStub.getAsync()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
@Override
public void getAsync(List<AsyncGetSetRequest> getVehicleStubAsyncRequests,
VehicleStubCallbackInterface getCallback) {
getOrSetAsync(getVehicleStubAsyncRequests, getCallback, new AsyncGetRequestsHandler(),
new AsyncGetResultsHandler(mPropValueBuilder));
}
注意:这里创建的两个 Handler 跟前面分析的 set 流程不一样了。
AidlVehicleStub.getOrSetAsync()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private <VhalRequestType, VhalRequestsType> void getOrSetAsync(
List<AsyncGetSetRequest> vehicleStubAsyncRequests,
VehicleStubCallbackInterface vehicleStubCallback,
AsyncRequestsHandler<VhalRequestType, VhalRequestsType> asyncRequestsHandler,
AsyncResultsHandler asyncResultsHandler) {
prepareAndConvertAsyncRequests(vehicleStubAsyncRequests, vehicleStubCallback,
asyncRequestsHandler);
try {
asyncRequestsHandler.sendRequestsToVhal(mAidlVehicle, mGetSetValuesCallback);
...
}
VehicleStubCallbackInterface vehicleStubCallback 就是 PropertyHalService 的 VehicleStubCallback 。 asyncRequestsHandler 就是 new AsyncGetRequestsHandler() 。 asyncResultsHandler 就是 new AsyncGetResultsHandler() 。
我们分成两部分来看:
AidlVehicleStub.prepareAndConvertAsyncRequests()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private <VhalRequestType, VhalRequestsType> void prepareAndConvertAsyncRequests(
List<AsyncGetSetRequest> vehicleStubRequests,
VehicleStubCallbackInterface clientCallback,
AsyncRequestsHandler<VhalRequestType, VhalRequestsType> asyncRequestsHandler) {
asyncRequestsHandler.allocateVhalRequestSize(vehicleStubRequests.size());
synchronized (mLock) {
try {
clientCallback.linkToDeath(() -> {
synchronized (mLock) {
mPendingAsyncRequestPool.removeRequestsForCallback(clientCallback);
}
});
} catch (RemoteException e) {
// Binder已经死亡。
throw new IllegalStateException("Failed to link callback to death recipient, the "
+ "client maybe already died");
}
for (int i = 0; i < vehicleStubRequests.size(); i++) {
AsyncGetSetRequest vehicleStubRequest = vehicleStubRequests.get(i);
long vhalRequestId = mRequestId.getAndIncrement();
AsyncRequestInfo requestInfo = new AsyncRequestInfo(
vhalRequestId, vehicleStubRequest.getServiceRequestId(), clientCallback,
vehicleStubRequest.getTimeoutUptimeMs());
mPendingAsyncRequestPool.addRequest(requestInfo);
asyncRequestsHandler.addVhalRequest(vhalRequestId,
vehicleStubRequest.getHalPropValue());
}
}
}
AsyncRequestInfo 的成员变量 mClientCallback 就是 PropertyHalService 的 VehicleStubCallback 。 而 AsyncRequestInfo 又被添加到 mPendingRequestPool 的成员变量 mPendingRequestPool 中 。
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private static class AsyncRequestInfo implements LongRequestIdWithTimeout {
private final int mServiceRequestId;
private final VehicleStubCallbackInterface mClientCallback;
private final long mTimeoutUptimeMs;
private final long mVhalRequestId;
private AsyncRequestInfo(
long vhalRequestId,
int serviceRequestId,
VehicleStubCallbackInterface clientCallback,
long timeoutUptimeMs) {
mVhalRequestId = vhalRequestId;
mServiceRequestId = serviceRequestId;
mClientCallback = clientCallback;
mTimeoutUptimeMs = timeoutUptimeMs;
}
@Override
public long getRequestId() {
return mVhalRequestId;
}
@Override
public long getTimeoutUptimeMs() {
return mTimeoutUptimeMs;
}
public int getServiceRequestId() {
return mServiceRequestId;
}
public VehicleStubCallbackInterface getClientCallback() {
return mClientCallback;
}
}
AsyncGetRequestsHandler.sendRequestsToVhal()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
@Override
public void sendRequestsToVhal(IVehicle iVehicle, GetSetValuesCallback callbackForVhal)
throws RemoteException, ServiceSpecificException {
Trace.traceBegin(TRACE_TAG, "Prepare LargeParcelable");
GetValueRequests largeParcelableRequest = new GetValueRequests();
largeParcelableRequest.payloads = mVhalRequestItems;
// TODO(b/269669729): Don't try to use large parcelable if the request size is too
// small.
largeParcelableRequest = (GetValueRequests) LargeParcelable.toLargeParcelable(
largeParcelableRequest, () -> {
GetValueRequests newRequests = new GetValueRequests();
newRequests.payloads = new GetValueRequest[0];
return newRequests;
});
Trace.traceEnd(TRACE_TAG);
Trace.traceBegin(TRACE_TAG, "IVehicle#getValues");
iVehicle.getValues(callbackForVhal, largeParcelableRequest);
Trace.traceEnd(TRACE_TAG);
}
iVehicle 是 VehicleHAL 服务,所以调到对端接口了。 这里的 callbackForVhal 是 GetSetValuesCallback 。 我们先不分析 VehicleHAL 服务 ,先把 car-service 接到回调的流程看完。
GetSetValuesCallback.onGetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private final class GetSetValuesCallback extends IVehicleCallback.Stub {
...
@Override
public void onGetValues(SetValueResults responses) throws RemoteException {
AidlVehicleStub.this.onGetValues(responses);
}
...
}
AidlVehicleStub.onGetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private void onGetValues(GetValueResults responses) {
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub#onGetValues");
GetValueResults origResponses = (GetValueResults)
LargeParcelable.reconstructStableAIDLParcelable(responses,
/* keepSharedMemory= */ false);
onGetSetValues(origResponses.payloads, new AsyncGetResultsHandler(mPropValueBuilder),
mPendingSyncGetValueRequestPool);
Trace.traceEnd(TRACE_TAG);
}
AidlVehicleStub.onGetSetValues()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private <VhalResultType> void onGetSetValues(VhalResultType[] vhalResults,
AsyncResultsHandler asyncResultsHandler,
PendingSyncRequestPool<VhalResultType> pendingSyncRequestPool) {
synchronized (mLock) {
for (VhalResultType result : vhalResults) {
long vhalRequestId = asyncResultsHandler.getVhalRequestId(result);
if (!mPendingAsyncRequestPool.contains(vhalRequestId)) {
// If we cannot find the request Id in the async map, we assume it is for a
// sync request.
completePendingSyncRequestLocked(pendingSyncRequestPool, vhalRequestId, result);
continue;
}
AsyncRequestInfo requestInfo = mPendingAsyncRequestPool.finishRequestIfFound(
vhalRequestId);
if (requestInfo == null) {
Slogf.w(TAG,
"No pending request for ID: %s, possibly already timed out, "
+ "or cancelled, or the client already died", vhalRequestId);
continue;
}
asyncResultsHandler.addVhalResult(requestInfo.getClientCallback(),
requestInfo.getServiceRequestId(), result);
}
}
Trace.traceBegin(TRACE_TAG, "AidlVehicleStub call async result callback");
asyncResultsHandler.callVehicleStubCallback();
Trace.traceEnd(TRACE_TAG);
}
从 mPendingAsyncRequestPool 可以找到 AsyncRequestInfo。requestInfo.getClientCallback() 就是 PropertyHalService 的 VehicleStubCallback 。 再把那到的 AsyncRequestInfo 添加到 AsyncResultsHandler (其实是 AsyncGetResultsHandler )。 最后调用 AsyncGetResultsHandler.callVehicleStubCallback() 。
AsyncGetResultsHandler.addVhalResult()¶
packages/services/Car/service/src/com/android/car/AidlVehicleStub.java
private static final class AsyncGetResultsHandler extends
AsyncResultsHandler<GetValueResult, GetVehicleStubAsyncResult> {
...
AsyncGetResultsHandler(HalPropValueBuilder propValueBuilder) {
...
mCallbackToResults = new ArrayMap<VehicleStubCallbackInterface,
List<GetVehicleStubAsyncResult>>();
}
...
@Override
void addVhalResult(VehicleStubCallbackInterface callback, int serviceRequestId,
GetValueResult result) {
addVehicleStubResult(callback, toVehicleStubResult(serviceRequestId, result));
}
...
}
private abstract static class AsyncResultsHandler<VhalResultType, VehicleStubResultType> {
protected Map<VehicleStubCallbackInterface, List<VehicleStubResultType>> mCallbackToResults;
...
protected void addVehicleStubResult(VehicleStubCallbackInterface callback,
VehicleStubResultType vehicleStubResult) {
if (mCallbackToResults.get(callback) == null) {
mCallbackToResults.put(callback, new ArrayList<>());
}
mCallbackToResults.get(callback).add(vehicleStubResult);
}
}
把 callback 和 result 关联起来。
AsyncGetResultsHandler.callVehicleStubCallback()¶
private static final class AsyncSetResultsHandler extends
AsyncResultsHandler<SetValueResult, SetVehicleStubAsyncResult> {
...
@Override
void callVehicleStubCallback() {
for (Map.Entry<VehicleStubCallbackInterface, List<GetVehicleStubAsyncResult>> entry :
mCallbackToResults.entrySet()) {
entry.getKey().onGetAsyncResults(entry.getValue());
}
}
...
}
根据上面的分析,VehicleStubCallbackInterface 就是 PropertyHalService 的 VehicleStubCallback ,所以这里就回调到了 PropertyHalService.onGetAsyncResults()
PropertyHalService.onGetAsyncResults()¶
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
@Override
public void onGetAsyncResults(
List<GetVehicleStubAsyncResult> getVehicleStubAsyncResults) {
...
sendGetValueResults(getValueResults);
...
if (!retryRequests.isEmpty()) {
mHandler.postDelayed(() -> {
retryIfNotExpired(retryRequests);
}, ASYNC_RETRY_SLEEP_IN_MS);
}
}
private void sendGetValueResults(List<GetSetValueResult> results) {
if (results.isEmpty()) {
return;
}
try {
mAsyncPropertyResultCallback.onGetValueResults(new GetSetValueResultList(results));
} catch (RemoteException e) {
Slogf.w(TAG, "sendGetValueResults: Client might have died already", e);
}
}
前面分析到:VehicleStubCallback 的成员变量 mAsyncPropertyResultCallback 就是 CarPropertyManager 传进来的 AsyncPropertyResultCallback 。 所以这里就会回调到 CarPropertyManager 的 onGetValueResults()。
IAsyncPropertyResultCallback.onGetValueResults()¶
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
private final AsyncPropertyResultCallback mAsyncPropertyResultCallback = new AsyncPropertyResultCallback();
private class AsyncPropertyResultCallback extends IAsyncPropertyResultCallback.Stub {
@Override
public IBinder asBinder() {
return this;
}
@Override
public void onGetValueResults(GetSetValueResultList getValueResults) {
...
}
@Override
public void onSetValueResults(GetSetValueResultList setValueResults) {
...
}
@SuppressLint("WrongConstant")
private <RequestType extends AsyncPropertyRequest, CallbackType, ResultType> void onResults(
List<GetSetValueResult> results,
PropertyResultCallback<CallbackType, ResultType> propertyResultCallback) {
...
}
}
至此,我们分析完了 car-service 端 get() 异步获取属性,及回调的过程。 但我们还未分析 VehicleHAL 端的代码。在 AsyncGetRequestsHandler.sendRequestsToVhal() 函数中,我们调用:
iVehicle 是 VehicleHAL 。根据前面 VehicleHAL 初始化流程我们知道,调用 setValues() 函数会调到 DefaultVehicleHal.cpp 的 getValues() 函数。
DefaultVehicleHal::getValues()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
const GetValueRequests& requests) {
ATRACE_CALL();
// 如果回调函数为空指针,则返回异常状态码
if (callback == nullptr) {
return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
}
expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
deserializedResults = fromStableLargeParcelable(requests);
// 反序列化错误
if (!deserializedResults.ok()) {
ALOGE("getValues: failed to parse getValues requests");
return std::move(deserializedResults.error());
}
const std::vector<GetValueRequest>& getValueRequests =
deserializedResults.value().getObject()->payloads;
// 检查是否存在重复的请求ID
auto maybeRequestIds = checkDuplicateRequests(getValueRequests);
if (!maybeRequestIds.ok()) {
ALOGE("getValues: duplicate request ID");
return toScopedAStatus(maybeRequestIds, StatusCode::INVALID_ARG);
}
// 存储已知失败的结果
std::vector<GetValueResult> failedResults;
// 存储将要发送给硬件的请求
std::vector<GetValueRequest> hardwareRequests;
for (const auto& request : getValueRequests) {
if (auto result = checkReadPermission(request.prop); !result.ok()) {
ALOGW("property does not support reading: %s", getErrorMsg(result).c_str());
// 将失败的结果添加到failedResults列表中
failedResults.push_back(GetValueResult{
.requestId = request.requestId,
.status = getErrorCode(result),
.prop = {},
});
} else {
// 将请求添加到hardwareRequests列表中
hardwareRequests.push_back(request);
}
}
std::unordered_set<int64_t> hardwareRequestIds;
for (const auto& request : hardwareRequests) {
hardwareRequestIds.insert(request.requestId);
}
std::shared_ptr<GetValuesClient> client;
{
std::scoped_lock lockGuard(mLock);
if (!monitorBinderLifeCycleLocked(callback->asBinder().get())) {
return ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
"client died");
}
// 获取或创建GetValuesClient对象
client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
}
if (auto addRequestResult = client->addRequests(hardwareRequestIds); !addRequestResult.ok()) {
ALOGE("getValues[%s]: failed to add pending requests, error: %s",
toString(hardwareRequestIds).c_str(), getErrorMsg(addRequestResult).c_str());
return toScopedAStatus(addRequestResult);
}
if (!failedResults.empty()) {
// 将已知失败的结果发送给客户端
client->sendResults(std::move(failedResults));
}
if (hardwareRequests.empty()) {
return ScopedAStatus::ok();
}
if (StatusCode status =
mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests);
status != StatusCode::OK) {
// 如果硬件返回错误,则尝试完成该请求的所有待处理请求
client->tryFinishRequests(hardwareRequestIds);
ALOGE("getValues[%s]: failed to get value from VehicleHardware, status: %d",
toString(hardwareRequestIds).c_str(), toInt(status));
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
toInt(status), "failed to get value from VehicleHardware");
}
return ScopedAStatus::ok();
}
这段代码比较长,我们把关键部分整理出来:
-
callback java端传进来的,其实也就是 IVehicleCallback.aidl
-
mPendingRequestPool mPendingRequestPool 是在 DefaultVehicleHal 构造函数里创建的。 PendingRequestPool 的功能在前面有详细介绍。
-
mGetValuesClients 先记住 mGetValuesClients 这个 map 的 vaule 类型。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
using GetValuesClient =
GetSetValuesClient<aidl::android::hardware::automotive::vehicle::GetValueResult,
aidl::android::hardware::automotive::vehicle::GetValueResults>;
std::unordered_map<const AIBinder*, std::shared_ptr<GetValuesClient>> mGetValuesClients
GUARDED_BY(mLock);
- client
std::shared_ptr<GetValuesClient> client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
-
client->addRequests(hardwareRequestIds) 添加客户端请求。
-
client->sendResults(std::move(failedResults)); 将结果发送给此客户端。
-
client->tryFinishRequests(hardwareRequestIds); 标记请求已完成。
-
mVehicleHardware->getValues()
可以看到,最关键的就是这两步:
- 调用 getOrCreateClient() 获取或创建客户端。
- 调用 FakeVehicleHardware::getValues() 设置属性。
DefaultVehicleHal::getOrCreateClient()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
/**
* @brief 获取或创建客户端对象
*
* @tparam T 客户端对象类型
* @param clients 客户端对象的映射表
* @param callback 回调函数
* @param pendingRequestPool 挂起请求池
* @return std::shared_ptr<T> 客户端对象的共享指针
*/
template <class T>
std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
const AIBinder* clientId = callback->asBinder().get();
if (clients->find(clientId) == clients->end()) {
(*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
}
return (*clients)[clientId];
}
这是一个模板函数,根据 clients 的数据类型可以知道,T 就是 GetSetValuesClient 。GetValuesClient 我们找下 GetSetValuesClient 是在哪里定义。
ConnectedClient¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
// 一个表示带有回调接口的绑定器客户端的类。每个回调函数,例如GetValues或SetValues对于一个特定的绑定器客户端是一个独立的ConnectedClient。
// 对于一个ConnectedClient,我们使用一个待处理请求池来管理所有待处理的请求,所以请求ID必须对于一个客户端是唯一的。
// 我们还管理一个客户端的一组回调函数,例如timeoutCallback,它可以传递给硬件。
// 这个类是线程安全的。
class ConnectedClient {
public:
using CallbackType =
std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
ConnectedClient(std::shared_ptr<PendingRequestPool> requestPool, CallbackType callback);
// 获取此客户端的唯一ID。
const void* id();
// 添加客户端请求。这些请求将被注册为待处理请求,直到调用tryFinishRequests为止。
// 如果任何一个请求ID与待处理请求ID之一重复,则返回INVALID_ARG错误;
// 如果待处理请求池已满且无法再添加请求,则返回TRY_AGAIN错误。
VhalResult<void> addRequests(const std::unordered_set<int64_t>& requestIds);
// 标记请求已完成。返回一个已完成的待处理请求ID列表。它必须是请求的请求ID的集合。
std::unordered_set<int64_t> tryFinishRequests(const std::unordered_set<int64_t>& requestIds);
protected:
// 获取在此客户端的请求超时时要调用的回调。
virtual std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() = 0;
const std::shared_ptr<PendingRequestPool> mRequestPool;
const CallbackType mCallback;
};
GetSetValuesClient¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
// 一个表示调用IVehicle.setValues或IVehicle.getValues的客户端的类。
template <class ResultType, class ResultsType>
class GetSetValuesClient final : public ConnectedClient {
public:
GetSetValuesClient(std::shared_ptr<PendingRequestPool> requestPool, CallbackType callback);
// 将结果发送给此客户端。
void sendResults(std::vector<ResultType>&& results);
// 将每个结果分别发送给此客户端。每个结果将通过一个回调调用发送。
void sendResultsSeparately(const std::vector<ResultType>& results);
// 获取在此客户端的请求完成时要调用的回调。
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> getResultCallback();
protected:
// 获取在此客户端的请求超时时要调用的回调。
std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> getTimeoutCallback() override;
private:
// 以下成员仅在构造期间初始化。
std::shared_ptr<const PendingRequestPool::TimeoutCallbackFunc> mTimeoutCallback;
std::shared_ptr<const std::function<void(std::vector<ResultType>)>> mResultCallback;
};
GetSetValuesClient::addRequests()¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
VhalResult<void> ConnectedClient::addRequests(const std::unordered_set<int64_t>& requestIds) {
return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback());
}
先来看这个 mRequestPool 到底是什么。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
const std::shared_ptr<PendingRequestPool> mRequestPool;
mRequestPool 是在 ConnectedClient 构造函数里初始化的。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
ConnectedClient::ConnectedClient(std::shared_ptr<PendingRequestPool> requestPool,
std::shared_ptr<IVehicleCallback> callback)
: mRequestPool(requestPool), mCallback(callback) {}
根据我们这个例子,下面这个模板函数调用 ConnectedClient 构造函数。
template <class ResultType, class ResultsType>
GetSetValuesClient<ResultType, ResultsType>::GetSetValuesClient(
std::shared_ptr<PendingRequestPool> requestPool, std::shared_ptr<IVehicleCallback> callback)
: ConnectedClient(requestPool, callback) {
// 创建一个指向PendingRequestPool::TimeoutCallbackFunc类型的智能指针mTimeoutCallback
// 该回调函数用于处理超时请求
mTimeoutCallback = std::make_shared<const PendingRequestPool::TimeoutCallbackFunc>(
[callback](const std::unordered_set<int64_t>& timeoutIds) {
return onTimeout<ResultType, ResultsType>(callback, timeoutIds);
});
// 复制requestPool到requestPoolCopy
auto requestPoolCopy = mRequestPool;
// 获取当前对象的id,并赋值给clientId
const void* clientId = id();
// 创建一个指向std::function<void(std::vector<ResultType>)>类型的智能指针mResultCallback
// 该回调函数用于处理获取或设置值的回调
mResultCallback = std::make_shared<const std::function<void(std::vector<ResultType>)>>(
[clientId, callback, requestPoolCopy](std::vector<ResultType> results) {
return getOrSetValuesCallback<ResultType, ResultsType>(
clientId, callback, std::move(results), requestPoolCopy);
});
}
再返回到 DefaultVehicleHal::getOrCreateClient() 中。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
template <class T>
std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool) {
const AIBinder* clientId = callback->asBinder().get();
if (clients->find(clientId) == clients->end()) {
(*clients)[clientId] = std::make_shared<T>(pendingRequestPool, callback);
}
return (*clients)[clientId];
}
看到了吧:
在返回到 调用 DefaultVehicleHal::getOrCreateClient() 的地方,也就是 DefaultVehicleHal::getValues() ,此时可以知道两件事:
- 这里的 pendingRequestPool 其实就是 DefaultVehicleHal 的成员变量 mPendingRequestPool,其在 DefaultVehicleHal 构造函数中初始化。也就是 PendingRequestPool。
- 这里的 callback 就是java端传进来的,其实也就是 IVehicleCallback.aidl
好了,回到我们的 ConnectedClient::addRequests() 函数里。
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
VhalResult<void> ConnectedClient::addRequests(const std::unordered_set<int64_t>& requestIds) {
return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback());
}
所以这里调用的是 PendingRequestPool::addRequests() 函数。
PendingRequestPool::addRequests()¶
hardware/interfaces/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
VhalResult<void> PendingRequestPool::addRequests(
const void* clientId, const std::unordered_set<int64_t>& requestIds,
std::shared_ptr<const TimeoutCallbackFunc> callback) {
// 对互斥锁进行加锁,确保线程安全
std::scoped_lock<std::mutex> lockGuard(mLock);
std::list<PendingRequest>* pendingRequests;
// 初始化待处理请求的数量为0
size_t pendingRequestCount = 0;
// 如果 mPendingRequestsByClient 中存在指定的 clientId
if (mPendingRequestsByClient.find(clientId) != mPendingRequestsByClient.end()) {
pendingRequests = &mPendingRequestsByClient[clientId];
for (const auto& pendingRequest : *pendingRequests) {
// 获取当前PendingRequest的请求ID集合
const auto& pendingRequestIds = pendingRequest.requestIds;
// 遍历传入的请求ID集合
for (int64_t requestId : requestIds) {
// 如果当前PendingRequest的请求ID集合中存在重复的请求ID
if (pendingRequestIds.find(requestId) != pendingRequestIds.end()) {
return StatusError(StatusCode::INVALID_ARG)
<< "duplicate request ID: " << requestId;
}
}
// 累加已有PendingRequest的请求ID数量
pendingRequestCount += pendingRequestIds.size();
}
} else {
// 为该clientId创建一个新的空的PendingRequest列表
pendingRequests = &mPendingRequestsByClient[clientId];
}
// 如果传入的请求ID数量超过了每个客户端允许的最大待处理请求数量
if (requestIds.size() > MAX_PENDING_REQUEST_PER_CLIENT - pendingRequestCount) {
return StatusError(StatusCode::TRY_AGAIN)
<< "too many pending requests";
}
int64_t currentTime = elapsedRealtimeNano();
// 根据当前时间,计算超时时间戳
int64_t timeoutTimestamp = currentTime + mTimeoutInNano;
// 将新的PendingRequest添加到PendingRequest列表中
pendingRequests->push_back({
.requestIds = std::unordered_set<int64_t>(requestIds.begin(), requestIds.end()),
.timeoutTimestamp = timeoutTimestamp,
.callback = callback,
});
return {};
}
看到这里有点迷茫,先不管,再尝试往下看看。
GetSetValuesClient::sendResults()¶
在前面 DefaultVehicleHal::setValues() 中,如果设置属性失败(没有权限、属性ID不合法),则主动调用 client->sendResults(std::move(failedResults)) 把错误信息回调给客户端。
std::vector<GetValueResult> failedResults;
...
if (!failedResults.empty()) {
// 将已知的失败结果发送给客户端
client->sendResults(std::move(failedResults));
}
函数的实现如下:
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
template <class ResultType, class ResultsType>
void GetSetValuesClient<ResultType, ResultsType>::sendResults(std::vector<ResultType>&& results) {
return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, std::move(results));
}
所以这里的 ResultsType 就是 GetValueResult 。
sendGetOrSetValueResults¶
hardware/interfaces/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
// 将所有的 GetValue/SetValue 结果通过回调函数一次性发送
template <class ResultType, class ResultsType>
void sendGetOrSetValueResults(std::shared_ptr<IVehicleCallback> callback,
std::vector<ResultType>&& results) {
ResultsType parcelableResults;
ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults);
// 检查结果是否成功转换为Parcelable
if (status.isOk()) {
// 调用回调函数,并检查回调是否成功
if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
!callbackStatus.isOk()) {
// 打印错误信息
ALOGE("failed to call GetOrSetValueResults callback, client ID: %p, error: %s, "
"exception: %d, service specific error: %d",
callback->asBinder().get(), callbackStatus.getMessage(),
callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
}
return;
}
int statusCode = status.getServiceSpecificError();
ALOGE("failed to marshal result into large parcelable, error: "
"%s, code: %d",
status.getMessage(), statusCode);
// 分别发送GetOrSetValueResults的结果
sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(callback,
parcelableResults.payloads);
}
因为我们的类型是 GetValueResult ,所以这里的 callCallback 对应的是这个模板显式具体化函数。
template <>
ScopedAStatus callCallback<GetValueResults>(std::shared_ptr<IVehicleCallback> callback,
const GetValueResults& results) {
return callback->onGetValues(results);
}
这里清楚的看到,调用的就是 IVehicleCallback 的 onGetValues() 回调函数。 最终就会通过 IPC 走到 前面提到的 GetSetValuesCallback.onGetValues() 函数里。 但,不要高兴得太早。这里只是错误的情况的回调。我们还是得回到 DefaultVehicleHal::getValues() 里,也就是调用 FakeVehicleHardware::getValues() 设置属性。
FakeVehicleHardware::getValues()¶
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
StatusCode FakeVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback,
const std::vector<GetValueRequest>& requests) const {
for (auto& request : requests) {
if (FAKE_VEHICLEHARDWARE_DEBUG) {
ALOGD("getValues(%d)", request.prop.prop);
}
// 在真实的VHAL实现中,你可以选择在binder线程中将getValue请求发送到车辆总线,
// 或者你可以在getValue中发送请求,getValue在处理程序线程中运行。
// 如果你决定在这里发送getValue请求,你不应该在这里等待响应,处理程序线程应该处理getValue响应。
mPendingGetValueRequests.addRequest(request, callback);
}
return StatusCode::OK;
}
从这里的注释可以看出来了,这里只是给出了一个demo告诉我们怎么写VehicleHardware。所以这里如何回调回去也不再详细分析。 思路就是有一个线程,如果有事件(set、get)请求,就在后台线程处理好事件,并通过 callback 回调到客户端。
附录¶
文中提到的一个接口文件会在编译的时候自动生成,主要目录是在:
out/soong/.intermediates/hardware/interfaces/automotive/vehicle/aidl/
android.hardware.automotive.vehicle-V2-ndk-source
android.hardware.automotive.vehicle-V2-java-source
out/soong/.intermediates/hardware/interfaces/automotive/vehicle/aidl_property
android.hardware.automotive.vehicle.property-V2-ndk-source
android.hardware.automotive.vehicle.property-V2-java-source