一:CarService简介
Google考虑更多是车载的独立性,需要与androidOS分开,有自己的独立性,才好针对车载拓展,还有就是复用性,他自己在一个单独的进程,区别于ams等。AAOS作为车载操作系统, 需要与车辆上其他的子系统互联互通
AAOS定义了,标准的硬件抽象层HAL(Hardware Abstraction Layer)来规范各个子系统与Framework的调用接口,并且通过CarService以及相关的Car API,对上层应用提供标准编程接口
AAOS并没有大刀阔斧的改变Android原有的整体架构, 几乎所有的核心服务(AMS, WMS, PKMS)与手机并无区别,采用的是同一套代源码, 所以我们可以将AAOS 理解为Android OS + Android Automotive Services更为贴切.传统的手机系统加上相关的汽车服务,构成了现在的AAOS, 而其中CarService就是提供汽车相关功能的最主要的模块
车载分层架构
说明
应用层: app发出控制消息
carservice: carservice通过HIDL(类似aidl实现进层通信)将信息给到HAL Service,HAL Service将消息处理后传递给mcu
mcu: 行车总大脑
can总线: 实时消息传递
ecu: 电子控制单元,具体的执行控件
二:CarService的启动流程
看看CarService源码位置
aosp12\packages\services\Car\service
CarService作为Android Automotive的核心服务,他是在SystemServer中启动的。SystemServer会在StartOtherServices()方法中让SystemServiceManager先通过反射的形式,创建出StartCarServiceHelperService这个对象,并调用其onStart方法, 进入到CarServiceHelperService.java文件中
最终在onStart()方法中启动CarService,并加载jni库为CarService提供必要的API
CarService的onCreate()
主要逻辑:
1:持有mVehicle对象我们才可以与Vehicle HAL层进行通信
Car AIP (客户端) ------> CarService ------> ICarImpl ------> VehicleHal ------> obd can .... 硬件
2:创建ICarImpl对象,并调用init方法,需要通过它才能拿到很多的Service,的IBinder客户端
创建各个核心服务对象,将创建的服务对象依次添加到一个list中保存起来,这里主要是为了方便Service之 间的相互访问。
3:很多的Service添加到ServiceManager中,所以Car API中才可能顺利得到 很多的Service 来使用
4:设定SystemProperty,将CarService设定为创建完成状态,只有包含CarService在内的所有的核心Service都完成初始化,才能结束开机动画并发送开机广播
三:如何使用CarService
使用方法:
步骤1: 通过Car.createCar()方法可以创建出Car的对象。
步骤2:Car.createCar()需要传入ServiceConnection,并在service连接成功后,获取想要的Manager 实例(binder的客户端)
步骤3:构建出Car对象后还需要调用connect()才会连接到CarService上。
步骤1说明
通过getPackageManager().hasSystemFeature(String string)判断系统是否支持特定的模块功能
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
Car carApiClient = Car.createCar(context, mCarServiceConnection);
}
步骤2说明
Car.createCar()需要传入ServiceConnection,并在service连接成功后,获取想要的Manager 实例,实现方式如下:
步骤3说明:
carApiClient.connect();
注意:connect()只能调用一次,如果当前已经处于连接状态,再次调用connect()会抛出异常,
client如果没有捕获该异常,则会引起client端程序崩溃(血的教训!)。
Car.java中通过绑定服务CarService成功后onBind方法返回ICarImpl实例,在启动流程中我们知道ICarImpl中已经拥有所有service的binder(stub)
Car.getCarManager()方法,最终调用到stub.asInterface()方法获取到客户端的Binder对象(proxy),缓存到容器方便以后使用。
如下图调用:
这三步是Android9之前的使用方法
Android10后直接使用
Car carClient = Car.createCar(context);
CarHvacManager manager = (CarHvacManager) carClient.getCarManager(Car.HVAC_SERVICE);
四:CarService系列服务介绍
谷歌在CarService中实现了许多与汽车密切相关的服务, 每个汽车服务, 也会有自己对应的客户端。
CarService对象只是获取各个Manager的媒介,它本身并不承担管理传感器.空调等具体的任务,
具体实现需要获取对应的Manager中API和对应服务来实现。
五:汽车服务运用
汽车服务 --- CarPropertyService 介绍
绝大部分与车辆硬件功能相关联的属性,如空调, 车舱功能, 车辆传感器等,都是通过CarPropertyService来读取或者设置的,CarPropertyManager 是CarPropertyService在客户端的代理, 通过CarPropertyManager提供的API,可以设置和获取车辆各个属性的状态;
CarPropertyService同时对应着 CarCabinManager, CarHvacManager,CarInfoManager,CarPropertyManager, CarSensorManager和 CarVendorExtensionManager这六个对象,可以说是一个服务分担多个角色. 所以在Android11时, 谷歌直接推荐使用CarPropertyManager 来对应CarPropertyService
六:编译car api
编译后可以供其他app使用
编译方式1:
1:source build/envsetup.sh
2:lunch sdk_car_x86_64-userdebug
3:make -j16
4:make android.car
编译成功后的jar存放在/out/soong/.intermediates/packages/services/Car/car
lib/android.car/android_common/javac/目录里哦
编译方式2:
make android.car-system-stubs
编译成功后的jar存放在/out/soong/.intermediates/packages/services/Car/car-lib/android.car
system-stubs/android_common/javac/目录里
实际项目中这种模式较为常用
编译方式3:
make android.car-stubs
三合一的方式:derry@ubuntu:~/AOSP12$ make android.car android.car-system-stubs android
car-stubs -j32a
编译成功后的jar存放在/out/soong/.intermediates/packages/services/Car/car-lib/android.car
stubs/android_common/javac/目录里。
编译出的CarLib库仅包含没有被@SystemApi修饰方法,而且方法同样不包含实现细节,是最严格的编
译模式。
此模式下编译出的CarLib甚至已经没有CarDiagnosticManager这个系统API了。
如何引入编译后的库?
参考:Android.bp - OpenGrok cross reference for /packages/apps/Car/Settings/Android.bp
在android.bp文件中加入引用