1.简述
车机系统:Android Automotive OS,这是Android操作系统为汽车量身定制的版本;基于Android的强大平台和功能集进行开发,利用了现有的安全模型、兼容性程序、开发人员工具和基础架构。它保持了Android的高度可定制性和可移植性,同时完全免费和开源。这个系统为汽车特定要求、功能和技术提供了支持,通过在原先的Android系统架构上增加与车相关的模块来实现,这些模块包括Car App(包括OEM和第三方开发的App)、Car API(提供给汽车App特有的接口)、Car Service(系统中与车相关的服务)等。
常说的car模式,就是Car api, Car service,Vehicle HAL;源码位置:
- Car API:packages\services\Car\car-lib
- Car Service:packages\services\Car\service
- Vehicle HAL:hardware\interfaces\automotive\vehicle\2.0
备注:本文章内容以android 10 原生代码为基准
下面是Android车机中简易模块图,本文章主要介绍Car API ---Car Service --- Vehicle HAL数据的通讯部分(一般说MCU通讯)
2 Car API
系统自动编译sdk,编译时引用即可,系统运行时,已经加载了这些类库;每个APP 进程fork时自动拥有了这个执行类库
2.1 Car类
Car sdk入口,主要功能
- Car服务端连接,提供自动重试机制、连接状态获取与监听、断开连接默认处理机制
- 获取相关管理类,这个类以CarManagerBase为基类,可感知连接状态,与服务端实现Binder相关联
- 映射缓存管理类,并根据断连状态进行处理
2.1.1 使用
Car使用一般需要3个流程:
- 创建Car对象
- 进行连接(连接服务定义如右图)
- 连接成功后,获取管理类
Android 10 中,已经不建议调用connect方法进行连接,而是在构造对象实例时自动连接
主要使用方法
//创建实例,并进行监听:
public static Car createCar(Context,Handler, long,CarServiceLifecycleListener)
//服务连接,10已经不推荐使用此方法了
public void connect() throws IllegalStateException
//断开服务
public void disconnect()
//是否连接
public boolean isConnected()
//是否正在连接
public boolean isConnecting()
//获取管理类
public Object getCarManager(String serviceName)
连接服务信息如下:
2.1.2 类图
使用基类CarManagerBase对所有的管理类进行了统一规格处理
- Car服务断开连接通知
- MCU数据事件处理Handler
- 异常处理
2.1.3 断开连接
public void onServiceDisconnected(ComponentName name) {
synchronized (mLock) {
if (mConnectionState == STATE_DISCONNECTED) {
// can happen when client calls disconnect before onServiceDisconnected call.
return;
}
handleCarDisconnectLocked();
}
if (mStatusChangeCallback != null) {
mStatusChangeCallback.onLifecycleChanged(Car.this, false);
} else if (mServiceConnectionListenerClient != null) {
mServiceConnectionListenerClient.onServiceDisconnected(name);
} else {
// This client does not handle car service restart, so should be terminated.
finishClient();
}
}
- 数据复位
- 缓存清理
- 服务封装的管理类销毁
- 回调,如无回调则默认处理
默认处理规则:若Context上下文为Activity,finish Activity,否则杀死进程
2.2 CarPropertyManager类
Android车机系统中用于设置和获取车辆各个属性状态的重要类。作为CarPropertyService在客户端的代理,通过其提供的API,开发者可以实现对车辆属性的读写操作。这些属性包括但不限于车窗升降、空调控制、油量、续航等。在实际开发中,当开发者想要控制这些车辆功能时,就需要与其进行交互。
2.2.1 使用
//实例获取
(CarPropertyManager) mCar. getCarManager(Car.PROPERTY_SERVICE)
//属性获取
public boolean getXXXProperty(int prop, int area), XXX有Boolean,Float, Int, IntArray
// 属性设置
public <E> void setProperty(@NonNull Class<E> clazz, int propId, int areaId, @NonNull E val)
public void setXXXProperty(int prop, int areaId,XXX val), XXX有Boolean,Float,Int
//属性监听操作:
public boolean registerCallback(CarPropertyEventCallback callback, int propertyId,float rate)
//属性解除监听
public void unregisterCallback(@NonNull CarPropertyEventCallback callback)
public void unregisterCallback(@NonNull CarPropertyEventCallback callback, int propertyId)
// 属性是否可用
public boolean isPropertyAvailable(int propId, int area)
// 属性读写权限
public String getWritePermission(int propId)
public String getReadPermission(int propId)
// 属性配置信息
public List<CarPropertyConfig> getPropertyList(@NonNull ArraySet<Integer> propertyIds)
public List<CarPropertyConfig> getPropertyList()
2.2.2 类图
2.3 VmsSubscriberManager类
作为与车辆管理系统交互的一个重要组件,负责处理订阅相关的请求和事件。它可能通过特定的API与VehicleHAL(硬件抽象层)或其他系统服务进行通信,以实现车辆状态信息的获取和控制。用户也可以自定义发布客户端实现进程间的事件交互。
2.3.1 使用
//实例获取
(VmsSubscriberManager) mCar. getCarManager(Car.VMS_SUBSCRIBER_SERVICE)
//最新信息
public byte[] getPublisherInfo(int publisherId)
// 可订阅消息
public VmsAvailableLayers getAvailableLayers()
// 设置消息订阅回调以及执行线程
public void setVmsSubscriberClientCallback(Executor,VmsSubscriberClientCallback)
//清除订阅信息
public void clearVmsSubscriberClientCallback()
// 订阅所有消息
public void startMonitoring()
// 停止订阅所有消息
public void stopMonitoring()
//订阅特定消息
public void subscribe(@NonNull VmsLayer layer)
public void subscribe(@NonNull VmsLayer layer, int publisherId)
//解除订阅特定消息
public void unsubscribe(@NonNull VmsLayer layer)
public void unsubscribe(@NonNull VmsLayer layer, int publisherId)
2.3.2 类图
2.3.3 VmsPublisherClientService
发布客户端Service基类,需要实现下面两个方法
- onVmsPublisherServiceReady:发布准备完成,可以调用publish方法进行发布消息
- onVmsSubscriptionChange:消息订阅状态变化通知
主要使用方法
//设置提供哪些可被订阅消息
public final void setLayersOffering(@NonNull VmsLayersOffering offering)
//发布消息
public final void publish(@NonNull VmsLayer layer, int publisherId, byte[] payload)
//获取当前订阅状态
public final VmsSubscriptionState getSubscriptions()
3 Car Service
3.1 CarService类
Service类,以bind方式提供ICar实现;并对接Vehicle HAL,获取Ivehicle实现,来完成具体硬件信号交互;
IVehicle binder获取
private static IVehicle getVehicle() {
try {
return android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
} catch (RemoteException e) {
Log.e(CarLog.TAG_SERVICE, "Failed to get IVehicle service", e);
} catch (NoSuchElementException e) {
Log.e(CarLog.TAG_SERVICE, "IVehicle service not registered yet");
}
return null;
}
IVehicle服务死亡代理处理
- 若配置允许,则杀死Car Service
- 不杀死,则进行一定时间内重新连接获取
- 获取失败则崩溃重启,重连成功,则ICarImpl重置Ivehicle对象
@Override
public void serviceDied(long cookie) {
if (RESTART_CAR_SERVICE_WHEN_VHAL_CRASH) {
Log.wtf(CarLog.TAG_SERVICE, "***Vehicle HAL died. Car service will restart***");
Process.killProcess(Process.myPid());
return;
}
Log.wtf(CarLog.TAG_SERVICE, "***Vehicle HAL died.***");
try {
mVehicle.unlinkToDeath(this);
} catch (RemoteException e) {
Log.e(CarLog.TAG_SERVICE, "Failed to unlinkToDeath", e); // Log and continue.
}
mVehicle = null;
mVhalCrashTracker.crashDetected();
Log.i(CarLog.TAG_SERVICE, "Trying to reconnect to Vehicle HAL: " +
mVehicleInterfaceName);
mVehicle = getVehicleWithTimeout(WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS);
if (mVehicle == null) {
throw new IllegalStateException("Failed to reconnect to Vehicle HAL");
}
linkToDeath(mVehicle, this);
Log.i(CarLog.TAG_SERVICE, "Notifying car service Vehicle HAL reconnected...");
mICarImpl.vehicleHalReconnected(mVehicle);
}
3.2 ICarImpl
ICar实现,跨进程调用入口,与Car对接,并获取Vehicle HAL层服务句柄;
生命周期依据Service生命周期而定
- init方法,对应Service onCreate
- Release方法,对应Service onDestory
- vehicleHalReconnected方法: Vehicle HAL服务重连成功通知
- getCarService方法:提供特定功能binder实现
3.3 VehicleHal
实现了Vehicale HAL回调,其内部对不同的硬件信号按照功能等进行了分类,并进行信号订阅管理与分发
- 普通属性: PropertyHalService桥接类
- 电源属性:PowerHalService桥接类
- 输入事件属性:InputHalService桥接类
- 订阅发布:VmsHalService桥接类
- 诊断事件属性:DiagnosticHalService桥接类
HalClient类才是对Vehicle HAL层封装的直接实现类,并增加了属性获取设置的重试机制
3.4 CarPropertyService
CarPropertyService是与Vehicle HAL、Car API交互的经典实现;着重对接的是Car API,PropertyHalService类实现了Vehicle HAL的桥接(包括处理属性管控)
与Car API桥接处理
- 属性设置、获取
- 属性监听、分发
- 跨进程死亡检测
与Vehical HAL桥接处理
- 属性设置、获取
- 属性监听
PropertyHalServiceIds类: 管理着处理属性以及属性读写权限
3.5 VMS发布-订阅
发布订阅框架
- 发布服务端,在Car Service中, 见2.3.1
- 订阅服务端,在Car Service中,见2.3.3
- 发布客服端,仅仅与硬件信号相关的在Car service中
- 订阅客户端,仅仅与硬件信号相关的在Car service中
实现主要依赖下面几个类
- VmsClientManager:订阅客户端死亡检测、根据配置进行发布客户端收集与死亡检测
- VmsBrokerService:订阅发布信息变化通知与缓存
- VmsSubscriberService: 订阅服务端,框架订阅入口
- VmsPublisherService: 发布服务端,对接发布客户端
- VmsHalService:硬件信号消息的订阅发布客户端封装,(信号属性唯一,为VehicleProperty.VEHICLE_MAP_SERVICE)
自动客户端收集配置,在XML,分下图中两个属性
4 Vehicle HAL
IVehicle服务是Android Automotive在硬件抽象层的一个核心native服务,用于处理和车辆相关的功能,并为系统提供获取车身信息以及设置相关状态的接口。IVehicle服务作为Android Automotive的核心组件,位于硬件抽象层,是连接车辆硬件和系统框架的重要桥梁。它提供了一系列接口,使得上层应用能够方便地获取车辆状态信息,并能够对车辆进行一定的控制操作。
采用HIDL定义,主要定义如右图:
实现类图:
- VehicleService: 进程启动入口
- VehicleHalManager:IVehicle服务实现
- VehiclePropertyStore:配置管理、数据缓存
- SubscriptionManager:订阅信息存储;
- VehicleEmulator:交换数据读取写入调度与数据桥接;
- EmulatedVehicleHal:数据事件调度管理;
- CommConn: 交换数据读写的基类
报文属性配置信息以及默认值,在DefaultConfig.h中
// 每个属性的信息结构
struct ConfigDeclaration {
VehiclePropConfig config;
/* This value will be used as an initial value for the property. If this field is specified for
* property that supports multiple areas then it will be used for all areas unless particular
* area is overridden in initialAreaValue field. */
VehiclePropValue::RawValue initialValue;
/* Use initialAreaValues if it is necessary to specify different values per each area. */
std::map<int32_t, VehiclePropValue::RawValue> initialAreaValues;
};
// 此属性为定义的变量
const ConfigDeclaration kVehicleProperties[] {
}
5 总结
这里讲解了MCU报文整个通讯流程;在常见Car模式使用中,也是基本只使用这一部分的;作为Car模式中MCU数据开发维护,主要有以下工作
- Vehicle层,实现CommConn类,完成IPC连接以及读写解析
- 报文ID配置,Vehicle层,Car service层
- 报文ID值类型定义,以及是否为APP和Vehicle进行桥接转换
如果在此文章中您有所收获,请给作者一个鼓励,点个赞,谢谢支持
技术变化都很快,但基础技术、理论知识永远都是那些;作者希望在余后的生活中,对常用技术点进行基础知识分享;如果你觉得文章写的不错,请给予关注和点赞;如果文章存在错误,也请多多指教!