前言
对比开辟车载Android和手机Android应用,最大的区别应该就是很多车载应用必要思量汽车团体的运行状态,例如,控制车载空调或车速到达肯定的阈值时,出于安全的思量多媒体应用要主动保持静音;汽车处于行驶状态下,OTA应用要保持静默等等。APP怎样从Framework层获取车辆状态的数据,而Framework层又是从那里获取到数据,它们的运行机制是怎样的,就是本篇要表明的题目了。
本文是车载Android焦点折务系列文章的第二篇,系列目次如下:
1.【Android R】车载 Android 焦点折务 - CarService 解析
2.【Android R】车载 Android 焦点折务 - CarPropertyService 解析
这个系列文章的告急目标在于整理原生车载Android体系中,一些焦点Service的运行原理与源码实现,以是会有大段的源码解读,内容会比力枯燥。如果阅读本文时还没有车载或车载相干的履历并不丰富,发起先阅读从应用工程师的角度再谈车载 Android 体系,相识车载Android体系的根本结构。
本系列涉及的应用层API以及Framework层的实现方式,基于原生车载Android R体系,由于现实项目中各个主机厂商会对CarService做种种修改,本系列内容仅供车载开辟者参考。
CarPropertyService 简介
通过上一篇的介绍,我们相识了狭义上的CarService着实只是一系列Binder对象的容器,本身并没有多少特殊功能,有过车载履历的同砚大概会有疑问,因为这大概和你正在履历的项目有收支,这是因为部门量产型的车载项目为了包管关键服务的稳固性,CarService中不少功能都被独立出去了,导致CarService现实上只能提供了查询、设置车辆属性的功能,而这部门功能就是本篇的主角 - CarPropertyService实现的。
从实现上来说CarPropertyService的架构如下:
我们从下往上依次来介绍:
用于罗致MCU数据的HAL层步伐。VehicleHAL与MCU之间是怎样举行通讯的,每个车载项目技能选型不同,实现上也千差万别,无法具体介绍。我个人履历过得的某个车载项目是使用DBUS。
HIDL在Client端的HwBinder对象,实现最根本的HIDL通讯功能。
用于与HAL层的Vehicle HAL步伐的通讯接口。它必要对罗致到的数据举行根本解析(范例检查),然后将每个事故发送到相应的HalServiceBase实现类里。
由于Framework层的VehicleHal与HAL层的VehicleHAL存在重名,反面为了区分会用VehicleHal(FWK) 体现Framework层的VehicleHal,用VehicleHAL(HAL) 体现HAL层的VehicleHAL。
负责进一步处理来自VehicleHal(FWK)数据的接口。是HalServiceBase的实现类。
是ICarProperty.aidl的实现类。是应用层与HAL层的通讯中继。
CarPropertyService在Client端的署理。车载体系中的应用必要通过CarPropertyManager来获取或设置车辆的属性。
先来看 CarPropertyManager 提供的API。
车辆属性 API
在Android R中CarInfoManager、CarCabinManager、CarHvacManager、CarSensorManager、CarVendorExtensionManager均已颠末时,在我个人现实履历的车载项目中,负责开辟CarService的同事,也会选择将以上Manager移除使用CarPropertyManager更换。
固然将汽车的Property属性分散到独立的Manager中可以让Car API的易用性、可读性更强,但是随着汽车属性的不绝增长,API的维护也会变得愈加复杂,而CarPropertyManager从实现上就让维护工作变得简单,Google大概也是基于以上的思量选择不再维护独立的Manager。
以是本文不再介绍CarInfoManager、CarCabinManager、CarHvacManager、CarSensorManager、CarVendorExtensionManager的实现,有必要的同砚请参考源码中是怎样实现的。
CarPropertyManager API 介绍
CarPropertyManager 中界说的常量
范例常量名intCAR_SET_PROPERTY_ERROR_CODE_ACCESS_DENIED 体现设置操纵失败的状态,汽车拒绝访问。intCAR_SET_PROPERTY_ERROR_CODE_INVALID_ARG 体现设置操纵失败的状态,参数无效。intCAR_SET_PROPERTY_ERROR_CODE_PROPERTY_NOT_AVAILABLE 体现设置操纵失败的状态,属性不可用。intCAR_SET_PROPERTY_ERROR_CODE_TRY_AGAIN 体现设置操纵失败的状态,重新实验。intCAR_SET_PROPERTY_ERROR_CODE_UNKNOWN 体现设置操纵失败的状态,未知错误。floatSENSOR_RATE_FAST 以10Hz的速率读取传感器。floatSENSOR_RATE_FASTEST 以100Hz的速率读取传感器。floatSENSOR_RATE_NORMAL 以1Hz的速率读取传感器。floatSENSOR_RATE_ONCHANGE 读取ON_CHANGE传感器floatSENSOR_RATE_UI 以5Hz的速率读取传感器。CarPropertyManager 中界说的方法。
返回值范例方法名intgetAreaId(int propId, int area) 返回包罗车辆属性选定区域的areaId。booleangetBooleanProperty(int prop, int area) 返回bool范例的车辆属性,此方法大概必要几秒钟才气完成,因此必要从非主线程调用它。CarPropertyConfig<?>getCarPropertyConfig(int propId) 按属性Id获取CarPropertyConfig。floatgetFloatProperty(int prop, int area) 返回float范例的车辆属性,此方法大概必要几秒钟才气完成,因此必要从非主线程调用它。int[]getIntArrayProperty(int prop, int area) 返回int数组范例的车辆属性,此方法大概必要几秒钟才气完成,因此必要从非主线程调用它。intgetIntProperty(int prop, int area) 返回int范例的车辆属性,此方法大概必要几秒钟才气完成,因此必要从非主线程调用它。<E> CarPropertyValue<E>getProperty(Class<E> clazz, int propId, int areaId) 返回CarPropertyValue范例的车辆属性,此方法大概必要几秒钟才气完成,因此必要从非主线程调用它。<E> CarPropertyValue<E>getProperty(int propId, int areaId)List<CarPropertyConfig>getPropertyList(ArraySet<Integer> propertyIds)List<CarPropertyConfig>getPropertyList()booleanisPropertyAvailable(int propId, int area) 根据汽车的当前状态,检查给定属性是否可用或禁用。booleanregisterCallback(CarPropertyManager.CarPropertyEventCallback callback, int propertyId, float rate) 注册CarPropertyEventCallback以获取车辆属性更新。voidsetBooleanProperty(int prop, int areaId, boolean val) 修改属性。voidsetFloatProperty(int prop, int areaId, float val) 设置float范例的车辆属性,此方法大概必要几秒钟才气完成,因此必要从非主线程调用它。voidsetIntProperty(int prop, int areaId, int val) 设置int范例的车辆属性,此方法大概必要几秒钟才气完成,因此必要从非主线程调用它。<E> voidsetProperty(Class<E> clazz, int propId, int areaId, E val) 按areaId设置车辆属性的值。voidunregisterCallback(CarPropertyManager.CarPropertyEventCallback callback) 制止监听车辆属性的更新回调voidunregisterCallback(CarPropertyManager.CarPropertyEventCallback callback, int propertyId) 制止监听车辆属性的更新回调setXXXProperty/getXXXProperty默认只实现了对float、int、boolean、intArray范例的拓展,如必要使用更多的范例,可以使用setProperty/getProperty(Class<T> class)传入必要拓展的范例即可。
CarPropertyManager 的实现原理并不复杂,可以直接参考源码:/packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java。
CarPropertyConfig API 介绍
CarPropertyConfig体现有关汽车属性的一样寻常信息,例如汽车区域的数据范例和最小/最大范围(如果实用)。也是现实开辟中非常常用的类。
CarPropertyConfig 中界说的常量。
范例常量名intVEHICLE_PROPERTY_ACCESS_NONE 属性访问权限未知intVEHICLE_PROPERTY_ACCESS_READ 该属性是可读的intVEHICLE_PROPERTY_ACCESS_READ_WRITE 该属性是可读、可写的intVEHICLE_PROPERTY_ACCESS_WRITE 该属性是可写的intVEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS 这种属性值会以肯定的频率不绝上报intVEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE 该属性的值会在发生变革时上报intVEHICLE_PROPERTY_CHANGE_MODE_STATIC 该属性的值始终不会改变CarPropertyConfig 中界说的方法
返回值范例方法名intgetAccess() 返回汽车属性的访问范例。具体范例就是上面界说的前4个常量int[]getAreaIds() 返回汽车的区域id数组intgetAreaType() 返回汽车属性的区域范例。intgetChangeMode() 返回汽车属性的更改模式。具体模式就是上面界说的后3个常量List<Integer>getConfigArray() 返回额外的设置属性floatgetMaxSampleRate() 返回最大频率。仅支持一连上报的属性floatgetMinSampleRate() 返回最小频率。仅支持一连上报的属性TgetMaxValue(int areaId)TgetMaxValue()TgetMinValue()TgetMinValue(int areaId)intgetPropertyId() 返回属性IDClass<T>getPropertyType() 返回车辆属性的范例booleanisGlobalProperty() 返回 是否是全局属性CarPropertyManager 使用示例
使用CarPropertyManager可以分为以下几个步调:
1)使用Car毗连到 CarService ,并获取到 CarPropertyManager 。
Car car = Car.createCar(this, workThreadHandler, 2000, new Car.CarServiceLifecycleListener() { @Override public void onLifecycleChanged(@NonNull Car car, boolean ready) { // ready 在Service断开毗连时会变为falseif (ready) { CarPropertyManager propertyMgr = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE); } else { // CarService 发生非常或毗连被断开了,必要client端处理。} }});2)给全部的property属性注册监听事故
// 空调的property id list,必要看hal层是怎样界说的 private final ArraySet<Integer> mHvacPropertyIds = new ArraySet<>(Arrays.asList(new Integer [] { ... }));CarPropertyManager propertyMgr = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);List<CarPropertyConfig> propertyList = propertyMgr.getPropertyList(mHvacPropertyIds);for (CarPropertyConfig config : propertyList) { // 给每个单独的propertyId注册监听回调。propertyMgr.registerCallback(callback,config.getPropertyId(), SENSOR_RATE_ONCHANGE);}3)获取单个Property的值
public boolean getBooleanProperty(@PropertyId int propertyId, int area) { return propertyMgr.getBooleanProperty(propertyId, area);}固然使用getBooleanProperty、getIntProperty、getFloatProperty、getIntArrayProperty代码上更简便一些,但是更发起使用getProperty()。getProperty()的返回值是CarPropertyValue,这其中包罗了Property的状态信息,可以让使用方覆盖更多的非常场景。
当属性不可用时,getXXXProperty()会返回默认的值,造成使用方读取数据禁绝确。
public CarPropertyValue<Boolean> getBooleanProperty(int propertyId, int area) { return propertyMgr.getProperty(Boolean.class, propertyId, area);}CarPropertyValue<Boolean> value = getBooleanProperty(CarHvacManager.ID_ZONED_AC_ON, 0);if (value == null && value.getStatus() != CarPropertyValue.STATUS_AVAILABLE) { // ac 不可用} else if (value.getValue()) { // ac 开} else { // ac 关}4)设定单个Property的值
public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val) { if (mHvacPropertyIds.contains(propertyId)) { propertyMgr.setBooleanProperty(propertyId, area, val); }}设定的值终极会通过aidl接口,将数据传输到CarPropertyService中,接下来我们继承看数据在CarPropertyService中是怎样通报的。
CarPropertyService 实现原理
CarPropertyService 初始化流程
CarPropertyService是在CarService中完成创建的,CarService的初始化流程在之前的文章【Android R】车载 Android 焦点折务 - CarService 解析中已经有过介绍,不再赘述。CarPropertyService的初始流程分为以下4步:
1)起首,在ICarImpl中创建VehicleHal(FWK);
@VisibleForTestingICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface, CanBusErrorNotifier errorNotifier, String vehicleInterfaceName, @Nullable CarUserService carUserService, @Nullable CarWatchdogService carWatchdogService) { ... mHal = new VehicleHal(serviceContext, vehicle); // 在任何其他服务组件之前执行此操纵,以允许举行功能检查。纵然没有初始化,它也应该工作。 // 为此,vhal-get会被重试,因为它大概太早了。VehiclePropValue disabledOptionalFeatureValue = mHal.getIfAvailableOrFailForEarlyStage( VehicleProperty.DISABLED_OPTIONAL_FEATURES, INITIAL_VHAL_GET_RETRY); String[] disabledFeaturesFromVhal = null; if (disabledOptionalFeatureValue != null) { String disabledFeatures = disabledOptionalFeatureValue.value.stringValue; if (disabledFeatures != null && !disabledFeatures.isEmpty()) { disabledFeaturesFromVhal = disabledFeatures.split(","); } } if (disabledFeaturesFromVhal == null) { disabledFeaturesFromVhal = new String[0]; } ...}2)在 VehicleHal(FWK) 创建过程中,同时创建出 PropertyHalService 和 HalClient;
public VehicleHal(Context context, IVehicle vehicle) { ... mPropertyHal = new PropertyHalService(this); ...mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/ );}3)然后,在ICarImpl中创建 CarPropertyService;
ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface, CanBusErrorNotifier errorNotifier, String vehicleInterfaceName, @Nullable CarUserService carUserService, @Nullable CarWatchdogService carWatchdogService) { ... mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal()); ...}4)末了,在 ICarImpl 中调用 VehicleHal.init() 、 CarPropertyService.init() 完成初始化。
@MainThreadvoid init() { mHal.init(); for (CarServiceBase service : mAllServices) { service.init(); }}接下来,我们依次把这些模块是怎样实现数据上报的流程梳理一下,先来看处于Framework最底层的 HalClient。
HalClient
车辆HAL客户端。直接与车辆HAL的HIDL接口IVehicle交互。包罗一些可检索属性的逻辑,将车辆通知重定向到给定的looper线程中。
HalClient(IVehicle vehicle, Looper looper, IVehicleCallback callback, int waitCapMs, int sleepMs) { mVehicle = vehicle; Handler handler = new CallbackHandler(looper, callback); mInternalCallback = new VehicleCallback(handler); mWaitCapMs = waitCapMs; mSleepMs = sleepMs;}VehicleCallback 是HIDL接口IVehicleCallback.Stub的实现类,负责监听HAL层上报的数据,然后将其发送到CallbackHandler中举行处理。
private static final class VehicleCallback extends IVehicleCallback.Stub { private final Handler mHandler; VehicleCallback(Handler handler) { mHandler = handler; } @Override public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) { mHandler.sendMessage(Message.obtain( mHandler, CallbackHandler.MSG_ON_PROPERTY_EVENT, propValues)); } @Override public void onPropertySet(VehiclePropValue propValue) { mHandler.sendMessage(Message.obtain( mHandler, CallbackHandler.MSG_ON_PROPERTY_SET, propValue)); } @Override public void onPropertySetError(int errorCode, int propId, int areaId) { mHandler.sendMessage(Message.obtain( mHandler, CallbackHandler.MSG_ON_SET_ERROR, new PropertySetError(errorCode, propId, areaId))); } }CallbackHandler是一个自界说的Handler,会将VehicleHal(HAL)上报的数据分类通过callback回调给VehicleHal(FWK)。
private static final class CallbackHandler extends Handler { private static final int MSG_ON_PROPERTY_SET = 1; private static final int MSG_ON_PROPERTY_EVENT = 2; private static final int MSG_ON_SET_ERROR = 3; ... @Override public void handleMessage(Message msg) { IVehicleCallback callback = mCallback.get(); ... try { switch (msg.what) { case MSG_ON_PROPERTY_EVENT: callback.onPropertyEvent((ArrayList<VehiclePropValue>) msg.obj); break; case MSG_ON_PROPERTY_SET: callback.onPropertySet((VehiclePropValue) msg.obj); break; case MSG_ON_SET_ERROR: PropertySetError obj = (PropertySetError) msg.obj; callback.onPropertySetError(obj.errorCode, obj.propId, obj.areaId); break; default: Log.e(TAG, "Unexpected message: " + msg.what); } } catch (RemoteException e) { Log.e(TAG, "Message failed: " + msg.what); } }}思索一个题目,为什么HAL上报的数据信息要先颠末Handler再处理呢?
这既有线程切换的思量,尚有就是VehicleHAL(HAL)上报的数据有时会非常频仍,将数据放到Looper的MessageQueue中可以便于我们按照上报的序次,有序地处理数据。
VehicleHal
用于与HAL层的Vehicle HAL步伐的通讯接口。将HalClient回调过来的数据,举行开端的处理。我们以onPropertyEvent为例,看一下VehicleHAl(FWK)是怎么处理HalClient回调过来的数据的。
VehicleHAl(FWK)的处理方式分为两步
1)第一步,根据上报数据找到对应的HalServiceBase(HalServiceBase是PropertyHalService的父类),将VehiclePropValue添加到PropertyHalService的list中。
@Overridepublic void onPropertyEvent(ArrayList<VehiclePropValue> propValues) { synchronized (mLock) { for (VehiclePropValue v : propValues) { HalServiceBase service = mPropertyHandlers.get(v.prop); if(service == null) { Log.e(CarLog.TAG_HAL, "HalService not found for prop: 0x" + toHexString(v.prop)); continue; } service.getDispatchList().add(v); mServicesToDispatch.add(service); ... } } ...}2)第二步,主动触发PropertyHalService.onHalEvents()将VehiclePropValue发送到PropertyHalService中,紧接着清算掉缓存数据。
@Overridepublic void onPropertyEvent(ArrayList<VehiclePropValue> propValues) { ... for (HalServiceBase s : mServicesToDispatch) { s.onHalEvents(s.getDispatchList()); s.getDispatchList().clear(); } mServicesToDispatch.clear();}PropertyHalService
在PropertyHalService.onHalEvents中处理罗致到的value list。将数据转换为CarPropertyValue后,通过PropertyHalListener将处理好的数据回调给CarPropertyService,而终极会由CarPropertyService将数据回调会应用层的接口。
@Overridepublic void onHalEvents(List<VehiclePropValue> values) { PropertyHalListener listener; ... if (listener != null) { for (VehiclePropValue v : values) { if (v == null) { continue; } ... int mgrPropId = halToManagerPropId(v.prop); CarPropertyValue<?> propVal; if (isMixedTypeProperty(v.prop)) { // parse mixed type property value.VehiclePropConfig propConfig; synchronized (mLock) { propConfig = mHalPropIdToVehiclePropConfig.get(v.prop); } boolean containBooleanType = propConfig.configArray.get(1) == 1; propVal = toMixedCarPropertyValue(v, mgrPropId, containBooleanType); } else { propVal = toCarPropertyValue(v, mgrPropId); } // 封装到 CarPropertyEventCarPropertyEvent event = new CarPropertyEvent( CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, propVal); mEventsToDispatch.add(event); } listener.onPropertyChange(mEventsToDispatch); mEventsToDispatch.clear(); }}留意两个方法,toMixedCarPropertyValue() 和 toCarPropertyValue() 如果数据范例是Integer、Float、Long、Float[]、Long[]、Integer[]、byte[]、String则由 toCarPropertyValue()负责数据转换。除此以外的范例由toMixedCarPropertyValue()负责数据转换。它们都是将VehiclePropValue转换为CarPropertyValue。
设定/获取 Property
设定和与获取Property的流程并不复杂,这里就不再粘贴源码了逐个解说了,贴上一份设定的时序图。
权限控制
上面在分析CarPropertyService监听属性变革的具体实现时,我们提到了使用Car API的接口必要注册对应的权限,那么这些权限是怎样管理的呢?
在PropertyHalService的构造方法中,创建了一个PropertyHalServiceIds的对象,而这个对象就是用来存储每个属性所必要的权限的。
PropertyHalServiceIds源码位置:/packages/services/Car/service/src/com/android/car/hal/PropertyHalServiceIds.java
public PropertyHalService(VehicleHal vehicleHal) { mPropIds = new PropertyHalServiceIds(); mSubscribedHalPropIds = new HashSet<Integer>(); mVehicleHal = vehicleHal;}在PropertyHalServiceIds的构造方法中,将每个属性对应必要的权限举行了逐一关联,生存在一个SparseArray中。
那么接下来我们以getProperty()方法为例,看一下是怎样限定无权限应用的调用的。
@Overridepublic CarPropertyValue getProperty(int prop, int zone) { ... ICarImpl.assertPermission(mContext, mHal.getReadPermission(prop)); return mHal.getProperty(prop, zone);}@Nullablepublic String getReadPermission(int mgrPropId) { int halPropId = managerToHalPropId(mgrPropId); return mPropIds.getReadPermission(halPropId);}@Nullablepublic String getReadPermission(int propId) { Pair<String, String> p = mProps.get(propId); if (p != null) { // 属性ID存在。返回 权限。if (p.first == null) { Log.e(TAG, "propId is not available for reading : 0x" + toHexString(propId)); } return p.first; } else if (isVendorProperty(propId)) { // 如果属性是供应商属性,而且没有特定权限。return Car.PERMISSION_VENDOR_EXTENSION; } else { return null; }}getReadPermission的调用链很好懂,告急就是将传入的id与PropertyHalServiceIds中关联好的权限比对,并取出对应的权限字符串。
assertPermission方法会判定调用方是否拥有相应的权限,或本次调用是否是自身发起的,如果不是,则会抛出SecurityException。
#########ICarImpl.java###############public static void assertPermission(Context context, String permission) { if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("requires " + permission); }}setProperty()方法的权限检查与getProperty()方法类似,不外getProperty()方法是检查ReadPermission,setProperty()方法是检查WritePermission。
车辆属性的读取以及操纵必要慎重授权给应用,以是权限控制在车载Android体系中就显得尤为告急。
VehicleHAL
VehicleHAL 是由Android Automotive OS界说的硬件抽象层(hardware abstract layer)。它界说了 OEM 可以实现的属性以及与Framework Service交互的接口。用户对车辆APP产生的一系列操纵终极都会来到VehicleHAL,并由于VehicleHAL转发出Android体系。
源码地点:/hardware/interfaces/automotive/vehicle/2.0/
源码结构
VehicleHAL告急由IPC接口和交互逻辑两部门组成,如下所示
界说VehicleHAL对外袒露的方法。
界说属性变革时的回调接口
界说在IVehicle.hal与IVehicleCallback.hal中使用的数据结构和属性值。
上述三个hal文件的结构与AIDL的通讯结构非常相似,不外这种通讯方式叫做HIDL(读作:嗨豆)。
有关HIDL的进一步内容,请参考官方文档:https://source.android.google.cn/docs/core/architecture/hidl
是Android Automotive OS对于VechicleHAL的参考实现。但是其中并没有实现与车辆总线举行数据交互如许的业务逻辑,这块的内容必要主机制造商自行实现。
VehicleHAL 接口
VHAL 支持以下接口:
- getAllPropConfigs() generates (vec<VehiclePropConfig> propConfigs);
列出 VehicleHAL 所支持的全部属性的设置。CarService 仅使用支持的属性。
- getPropConfigs(vec<int32_t> props) generates (StatusCode status, vec<VehiclePropConfig> propConfigs);
返回所选属性的设置。
- get(VehiclePropValue requestedPropValue) generates (StatusCode status, VehiclePropValue propValue);
获取车辆属性值。
- set(VehiclePropValue propValue) generates (StatusCode status);
向属性写入一个值。写入的结果是按属性举行界说的。
- subscribe(IVehicleCallback callback, vec<SubscribeOptions> options) generates (StatusCode status);
开始监督属性值的变革。
- unsubscribe(IVehicleCallback callback, int32_t propId) generates (StatusCode status);
取消订阅属性事故。
VHAL 支持以下回调接口:
- oneway onPropertyEvent(vec<VehiclePropValue>propValues);
通知车辆属性值的变革。应只针对已订阅属性执行。
- oneway onPropertySet(VehiclePropValue propValue);
如果客户端使用SubscribeFlags.EVENTS_FROM_ANDROID标志订阅了属性,而且调用了IVehicle.set()方法,则会调用此方法。
- oneway onPropertySetError(StatusCode errorCode,int32_t propId,int32_tareaId);
返回全局 VHAL 级错误或每个属性的错误。全局错误会导致 HAL 重新启动,这大概会导致包罗应用在内的其他组件重新启动。
编译VehicleHAL
HIDL接口界说好之后,与AIDL接口一样必要编译更jar提供给Framework的开辟,以下步调是编译原生的VehicleHAL,现实项目中的VehicleHAL一样寻常会放置vendor内里,但是编译方式一样。
cd hardware/interfaces/automotive/vehicle/2.0mma编译好的jar包位于
/out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0/android.hardware.automotive.vehicle-V2.0-java/android_common/javac
如下图所示:
由于博主并没有现实从事过HAL层的开辟,有关VehicleHAL就只介绍到这里,现实工作中一样寻常会有单独负责HAL层的同事编写这里的代码。
更多内容请参考官方的文档:https://source.android.google.cn/docs/devices/automotive/vhal
总结
本篇介绍了CarPropertyService的实现原理,但是仅通过阅读这篇文章着实并不能完全把握整个CarPropertyService,这是任何技能性文章都做不到的通病,现实项目依然必要我们仔细阅读源码,分析方法的寄义,本篇文章的现实目标是让你弄清晰关键节点的实现方式和运行原理。
我个人也负责过CarPropertyService的开辟工作,当时由于对CarPropertyService的运行机制并不相识,选择整个重写CarPropertyService,现在想想着实走了不少弯路。
好了,感谢你的阅读,希望能资助到你。 |