Android 车机 Car模式原理


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通讯)

image.png

2 Car API 

系统自动编译sdk,编译时引用即可,系统运行时,已经加载了这些类库;每个APP 进程fork时自动拥有了这个执行类库

2.1 Car类

Car sdk入口,主要功能

  • Car服务端连接,提供自动重试机制、连接状态获取与监听、断开连接默认处理机制

  • 获取相关管理类,这个类以CarManagerBase为基类,可感知连接状态,与服务端实现Binder相关联

  • 映射缓存管理类,并根据断连状态进行处理

2.1.1 使用

Car使用一般需要3个流程:

  1. 创建Car对象

  2. 进行连接(连接服务定义如右图)

  3. 连接成功后,获取管理类

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)

连接服务信息如下:

image.png

2.1.2 类图

image.png

使用基类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 类图

image.png

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 类图

image.png

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实现,来完成具体硬件信号交互;

image.png

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服务死亡代理处理

  1. 若配置允许,则杀死Car Service

  2. 不杀死,则进行一定时间内重新连接获取

  3. 获取失败则崩溃重启,重连成功,则ICarImpl重置Ivehicle对象

@Overridepublic 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实现

image.png

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的桥接(包括处理属性管控)

image.png

与Car API桥接处理

  • 属性设置、获取

  • 属性监听、分发

  • 跨进程死亡检测

与Vehical HAL桥接处理

  • 属性设置、获取

  • 属性监听

PropertyHalServiceIds类: 管理着处理属性以及属性读写权限

3.5 VMS发布-订阅

发布订阅框架

  • 发布服务端,在Car Service中, 见2.3.1

  • 订阅服务端,在Car Service中,见2.3.3

  • 发布客服端,仅仅与硬件信号相关的在Car service中

  • 订阅客户端,仅仅与硬件信号相关的在Car service中

image.png

实现主要依赖下面几个类

  • VmsClientManager:订阅客户端死亡检测、根据配置进行发布客户端收集与死亡检测

  • VmsBrokerService:订阅发布信息变化通知与缓存

  • VmsSubscriberService: 订阅服务端,框架订阅入口

  • VmsPublisherService: 发布服务端,对接发布客户端

  • VmsHalService:硬件信号消息的订阅发布客户端封装,(信号属性唯一,为VehicleProperty.VEHICLE_MAP_SERVICE)

自动客户端收集配置,在XML,分下图中两个属性

image.png

4 Vehicle HAL 

IVehicle服务是Android Automotive在硬件抽象层的一个核心native服务,用于处理和车辆相关的功能,并为系统提供获取车身信息以及设置相关状态的接口‌。IVehicle服务作为Android Automotive的核心组件,位于硬件抽象层,是连接车辆硬件和系统框架的重要桥梁。它提供了一系列接口,使得上层应用能够方便地获取车辆状态信息,并能够对车辆进行一定的控制操作。

采用HIDL定义,主要定义如右图:

image.png

实现类图:

image.png

  • 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进行桥接转换

如果在此文章中您有所收获,请给作者一个鼓励,点个赞,谢谢支持

技术变化都很快,但基础技术、理论知识永远都是那些;作者希望在余后的生活中,对常用技术点进行基础知识分享;如果你觉得文章写的不错,请给予关注和点赞;如果文章存在错误,也请多多指教!

作者:众少成多积小致巨链接:https://juejin.cn/post/7463352165487263798

关注我获取更多知识或者投稿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值