使用方法及启动流程
发布时间:2025-06-24 20:44:54 作者:北方职教升学中心 阅读量:604
Android 车载应用开发指南系列文章
Android 车载应用开发指南(1)- 车载操作系统全解析
Android 车载应用开发指南(2)- 应用开发入门
Android 车载应用开发指南(3)- SystemUI 详解
Android 车载应用开发指南(4)- CarService 详解
Android 车载应用开发指南(5)- CAN Bus 协议详解
Android 车载应用开发指南(6)- 汽车混动技术简介
一 概述
CarService是车载 Android 操作系统 Android Automotive OS(下文简介 AAOS)的核心服务之一,所有车载相关的应用都需要通过 CarService来查询、
第一步:判断平台是否支持车载功能
APP 层在调用 Car API 之前首先会调用 PMS 中的 hasSystemFeature()
方法判断设备是否支持车载功能
if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)){.....}
源码路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@GuardedBy("mAvailableFeatures")finalArrayMap<String,FeatureInfo>mAvailableFeatures; @OverridepublicbooleanhasSystemFeature(Stringname,intversion){// allow instant applicationssynchronized(mAvailableFeatures){finalFeatureInfofeat =mAvailableFeatures.get(name);if(feat ==null){returnfalse;}else{returnfeat.version >=version;}}}
mAvailableFeatures
里面的内容是通过读取/system/etc/permissions
下面的 xml 文件(对应 SDK 的位置—frameworks/native/data/etc 下的 XML 文件中的 feature 字段)
源码路径:frameworks/native/data/etc/car_core_hardware.xml
<permissions><!-- Feature to specify if the device is a car --><featurename="android.hardware.type.automotive"/>..... </permission>
源码路径:frameworks/native/data/etc/android.hardware.type.automotive.xml
<!-- These features determine that the device running android is a car. --><permissions><featurename="android.hardware.type.automotive"/></permissions>
第二步:创建 Car 对象,获取 Manager
Car 作为汽车平台最高等级的 API(
packages/services/Car/car-lib/src/android/car/Car.java
),为外界提供汽车所有服务和数据的访问
- 通过
createCar()
方法新建 Car 实例 - 成功连接时可以通过
getCarManager
方法获取相关的 Manager 实例。源码路径: frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
publicSystemServicestartService(StringclassName){finalClass<SystemService>serviceClass =loadClassFromLoader(className,this.getClass().getClassLoader());returnstartService(serviceClass);} publicvoidstartService(@NonNullfinalSystemServiceservice){// Register it.mServices.add(service);longtime =SystemClock.elapsedRealtime();try{service.onStart();}catch(RuntimeExceptionex){thrownewRuntimeException("Failed to start service "+service.getClass().getName()+": onStart threw an exception",ex);}warnIfTooLong(SystemClock.elapsedRealtime()-time,service,"onStart");}
3.2 绑定 CarService 服务
源码路径: frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java
privatestaticfinalStringCAR_SERVICE_INTERFACE="android.car.ICar"; @OverridepublicvoidonStart(){EventLog.writeEvent(EventLogTags.CAR_HELPER_START); IntentFilterfilter =newIntentFilter(Intent.ACTION_REBOOT);filter.addAction(Intent.ACTION_SHUTDOWN);mContext.registerReceiverForAllUsers(mShutdownEventReceiver,filter,null,null);mCarWatchdogDaemonHelper.addOnConnectionChangeListener(mConnectionListener);mCarWatchdogDaemonHelper.connect();Intentintent =newIntent();intent.setPackage("com.android.car");// 绑定包名,设置广播仅对该包有效intent.setAction(CAR_SERVICE_INTERFACE);// 绑定 action,表明想要启动能够响应设置的这个 action 的活动,并在清单文件 AndroidManifest.xml 中设置 action 属性// 绑定后回调if(!mContext.bindServiceAsUser(intent,mCarServiceConnection,Context.BIND_AUTO_CREATE,mHandler,UserHandle.SYSTEM)){Slogf.wtf(TAG,"cannot start car service");}loadNativeLibrary();}
源码路径:packages/services/Car/service/AndroidManifest.xml
sharedUserId 是系统级别的,类似 SystemUI,它编译出来同样是一个 APK 文件
设备文件路径:
/system/priv-app/CarService/CarService.apk
<manifestxmlns:android="http://schemas.android.com/apk/res/android"xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"package="com.android.car"coreApp="true"android:sharedUserId="android.uid.system">...... <applicationandroid:label="@string/app_title"android:directBootAware="true"android:allowBackup="false"android:persistent="true"> <serviceandroid:name=".CarService"android:singleUser="true"android:exported="true"><intent-filter><actionandroid:name="android.car.ICar"/></intent-filter></service>...... </application>
3.3 CarService 初始化
CarService
进入启动时序后,会在onCreate()
方法中进行一系列自身的初始化操作,步骤如下:1)通过 HIDL 接口获取到 HAL 层的 IHwBinder 对象
IVehicle
,与 AIDL 的用法类似,必须持有 IHwBinder 对象我们才可以与 Vehicle HAL 层进行通信。- 首先 CarService是一个系统级别的服务 APK,类似 SystemUI,其在开机时由 SystemServer 通过 CarServiceHelperService 启动。如果 service 允许绑定,
onBind()
会返回客户端与服务互相联系的通信句柄
- 首先 CarService是一个系统级别的服务 APK,类似 SystemUI,其在开机时由 SystemServer 通过 CarServiceHelperService 启动。如果 service 允许绑定,
源码路径:/packages/services/Car/service/src/com/android/car/CarService.java
@OverridepublicIBinderonBind(Intentintent){returnmICarImpl;}
所以此处的 mICarImpl会作为 IBinder 返回给CarServiceHelperService.java - bindServiceAsUser
方法中的参数 mCarServiceConnection(回调)
3.4 回调 ServiceConnection
ICarImpl 初始化完毕,会作为 IBinder 返回给
CarServiceHelperService.java - bindServiceAsUser
方法中绑定此服务的 mCarServiceConnection(回调)
mCarServiceConnection初始化如下:
- 其中返回的 ICarImpl被保存在了 CarServiceHelperService的 mCarService
- mCarService.transact跨进程通信,调用 ICar.aidl中定义的第一个方法 setCarServiceHelper
源码路径:/frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java
privatestaticfinalStringCAR_SERVICE_INTERFACE="android.car.ICar";privateIBindermCarService;privatefinalICarServiceHelperImplmHelper =newICarServiceHelperImpl(); privatefinalServiceConnectionmCarServiceConnection =newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamecomponentName,IBinderiBinder){if(DBG){Slogf.d(TAG,"onServiceConnected: %s",iBinder);}handleCarServiceConnection(iBinder);} @OverridepublicvoidonServiceDisconnected(ComponentNamecomponentName){handleCarServiceCrash();}};@VisibleForTestingvoidhandleCarServiceConnection(IBinderiBinder){synchronized(mLock){if(mCarServiceBinder ==iBinder){return;// already connected.}Slogf.i(TAG,"car service binder changed, was %s new: %s",mCarServiceBinder,iBinder);//1. 返回的 ICarImpl 被保存在了 CarServiceHelperService 的 mCarServiceBindermCarServiceBinder =iBinder;Slogf.i(TAG,"**CarService connected**");} sendSetSystemServerConnectionsCall();...} privatevoidsendSetSystemServerConnectionsCall(){Parceldata =Parcel.obtain();data.writeInterfaceToken(CAR_SERVICE_INTERFACE);data.writeStrongBinder(mHelper.asBinder());//将 ICarServiceHelperImpl 类型的对象作为数据跨进程传递data.writeStrongBinder(mCarServiceConnectedCallback.asBinder());IBinderbinder;synchronized(mLock){binder =mCarServiceBinder;}intcode =IBinder.FIRST_CALL_TRANSACTION;try{//2. 跨进程传输//对端是 mCarService 即 ICarImpl,调用 binder 的 transact 进行跨进程通信//其 code 代表需要调用的对端方法,data 为携带的传输数据//FIRST_CALL_TRANSACTION = 0x00000001,即调用对端 ICar.aidl 中定义的第一个方法 setCarServiceHelperif(VERBOSE)Slogf.v(TAG,"calling one-way binder transaction with code %d",code);// oneway void setSystemServerConnections(in IBinder helper, in IBinder receiver) = 0;binder.transact(code,data,null,Binder.FLAG_ONEWAY);if(VERBOSE)Slogf.v(TAG,"finished one-way binder transaction with code %d",code);}...}
跨进程 setSystemServerConnections
@OverridepublicvoidsetSystemServerConnections(IBinderhelper,IBinderreceiver){Bundlebundle;try{EventLog.writeEvent(EventLogTags.CAR_SERVICE_SET_CAR_SERVICE_HELPER,Binder.getCallingPid());assertCallingFromSystemProcess();//将 ICarServiceHelper 的代理端保存在 ICarImpl 内部 mICarServiceHelperICarServiceHelpercarServiceHelper =ICarServiceHelper.Stub.asInterface(helper);synchronized(mLock){mICarServiceHelper =carServiceHelper;}//同时也传给了 SystemInterface//此时他们有能力跨进程访问 CarServiceHelperServicemSystemInterface.setCarServiceHelper(carServiceHelper);mCarOccupantZoneService.setCarServiceHelper(carServiceHelper);mCarUserService.setCarServiceHelper(carServiceHelper);...}
3.5 小结
CarService
的启动时序如下所示:
四 总结
本文讲解了CarService
的总体结构、位于 /hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0
2.2 CarService 组成
CarService 源码位置:/packages/services/Car
其目录结构如下所示:
.├── Android.mk ├── apicheck.mk ├── apicheck_msg_current.txt ├── apicheck_msg_last.txt ├── car-cluster-logging-renderer //LoggingClusterRenderingService 继承 InstrumentClusterRenderingService├── car-default-input-service //按键消息处理├── car-lib //提供给汽车 App 特有的接口,许多定制的模块都在这里实现,包括 Sensor,HVAC,Cabin,ActiveParkingAssiance,Diagnostic,Vendor 等├── car-maps-placeholder //地图软件相关├── car_product //系统编译相关├── car-support-lib //android.support.car├── car-systemtest-lib //系统测试相关├── car-usb-handler //开机自启,用于管理车机 USB├── CleanSpec.mk ├── evs ├── obd2-lib ├── PREUPLOAD.cfg ├── procfs-inspector ├── service //com.android.car 是一个后台运行的组件,可以长时间运行并且不需要和用户去交互的,这里即使应用被销毁,它也可以正常工作├── tests ├── tools //是一系列的工具,要提到的是里面的 emulator,测试需要用到的。使用方法及启动流程。控制整车的状态,不仅仅是车辆控制,实际上 CarService几乎就是整个车载 Framework 最核心的组件。WMS、PMS) 与手机并无区别,采用的是同一套源代码,所以我们可以将 AAOS 理解为 Android OS + Automotive Services + Automotive APPs。Android 原生 CarService 包含了许多功能服务: Car ** Service(C/S 模式中的服务端)它们与 HAL 层的 VehicleHAL 通信,进而通过车载总线(例如 CAN 总线)与车身进行通讯,同时它们还通过 Car API:Car ** Manger(C/S 模式中的客户端)为应用层的 Car App 提供接口,从而让 App 能够实现对车身的控制与状态的显示。
五 参考
Android carservice 架构及启动流程
【Android R】车载 Android 核心服务 - CarService 解析
CarService
中实现的功能非常庞大,可以说相比传统手机端的 Android 系统,AAOS 中独特且最重要的部分都在 Framework 的CarService
中。位于 /packages/services/Car
Android 通信模式通常基于 C/S 模式,即有客户端和服务端,每个服务有对应的代理对象(比如 ActivityManager 相对服务 AMS,就是客户端)。
车载 HAL 与 AAOS 架构:
- Car App:包括 OEM 和第三方开发的 App
- Car API:内有包含 CarSensorManager 在内的 API。
CarService 启动流程主要分为以下四个步骤:
- SystemServer启动 CarServiceHelperService服务
- 在调用
startService()
后,CarServiceHelperService的onStart()
方法通过 bindService 的方式启动 CarService(一个系统级别的 APK,位于 system/priv-app) - 启动 CarService后首先调用
onCreate()
,创建 ICarImpl对象并初始化,在此时创建了一系列 Car 相关的核心服务,并遍历init
初始化 - 然后调用 onBind 将该 ICarImpl对象返回给 CarServiceHelperService,CarServiceHelperService在内部的一个 Binder 对象 ICarServiceHelperImpl传递给 CarService,建立双向跨进程
3.1 启动 CarServiceHelperService 服务
SystemServer
会在startOtherServices()
方法中让SystemServiceManager
先通过反射的形式创建出StartCarServiceHelperService
对象。二 CarService 架构
2.1 简介
AAOS 并没有大刀阔斧的改变 Android 原有的整体架构,几乎所有的核心服务 (AMS、
Car***Manager:
packages/services/Car/car-lib/src/android/car/
Car***Service:
packages/services/Car/service/src/com/android/car/
以下列举 CarService 中核心服务:
Service 端 功能 Client 端 AppFocusService 管理同类应用焦点的服务 CarAppFocusManager CarAudioService 汽车音频服务 CarAudioManager CarPackageManagerService 汽车包管理服务 CarPackageManager CarDiagnosticService 汽车诊断服务 CarDiagnosticManager CarPowerManagerService 汽车电源管理服务 CarPowerManager IInstrumentClusterManagerServcie 仪表服务 IInstrumentClusterManager CarProjecitonService 投屏服务 CarProjecitonManager VmsSubscriberService 车辆地图服务 VmsSubscriberManager CarBluetoothService 汽车蓝牙服务 CarBluetoothManager CarStorageMonitoringService 汽车存储监控服务 CarStorageMonitoringManager CarDrivingStateService 汽车驾驶状态服务 CarDrivingStateManager CarUXRestrictionsService 汽车用户体验限制服务 CarUXRestrictionsManager CarConfigurationService 汽车配置服务 CarConfigurationManager CarTrustedDeviceService 授信设备管理 CarTrustAgentEnrollmentManager CarMediaService 媒体管理服务 CarMediaManager CarBugreportManagerService 错误报告服务 CarBugreportManager 2.3 使用 CarService
说明:本文源码分析基于版本:android-12.0.0_r3
前文提到,CarService需要通过 Car API为应用层提供接口,所以应用开发者只需要知道如何使用 Car API。
源码路径:frameworks/base/services/java/com/android/server/SystemServer.java
privatevoidstartOtherServices(@NonNullTimingsTraceAndSlogt){...// 仅在 automotive 中启动if(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)){t.traceBegin("StartCarServiceHelperService");finalSystemServicecshs =mSystemServiceManager .startService(CAR_SERVICE_HELPER_SERVICE_CLASS);if(cshs instanceofDumpable){mDumper.addDumpable((Dumpable)cshs);}if(cshs instanceofDevicePolicySafetyChecker){dpms.setDevicePolicySafetyChecker((DevicePolicySafetyChecker)cshs);}t.traceEnd();}...}
然后在
SystemServiceManager
中调用StartCarServiceHelperService
的onStart()
方法。 - CarServiceHelperService通过绑定服务的方式启动 CarService,启动之后创建了一个 Binder 对象 ICarImpl,并通过 onBind 返回给 system_server进程。
3)将
ICar.aidl
的实现类添加到 ServiceManager 中。AAOS 定义了标准的硬件抽象层 HAL(Hardware Abstraction Layer)来规范各个子系统与 Framework 的调用接口,并且通过 CarService以及相关的 Car API 对上层应用提供标准编程接口。
源码路径:packages/services/Car/service/src/com/android/car/CarService.java
@OverridepublicvoidonCreate(){LimitedTimingsTraceLoginitTiming =newLimitedTimingsTraceLog(CAR_SERVICE_INIT_TIMING_TAG,Trace.TRACE_TAG_SYSTEM_SERVER,CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);initTiming.traceBegin("CarService.onCreate"); initTiming.traceBegin("getVehicle");// 获取 hal 层的 Vehicle servicemVehicle =getVehicle();initTiming.traceEnd();...//创建 ICarImpl 实例mICarImpl =newICarImpl(this,mVehicle,SystemInterface.Builder.defaultSystemInterface(this).build(),mVehicleInterfaceName);//然后调用 ICarImpl 的 init 初始化方法mICarImpl.init(); linkToDeath(mVehicle,mVehicleDeathRecipient);//将该 service 注册到 ServiceManagerServiceManager.addService("car_service",mICarImpl);//设置 boot.car_service_created 属性SystemProperties.set("boot.car_service_created","1"); super.onCreate(); initTiming.traceEnd();// "CarService.onCreate"} @NullableprivatestaticIVehiclegetVehicle(){finalStringinstanceName =SystemProperties.get("ro.vehicle.hal","default"); try{//该 service 启动文件 hardware/interfaces/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rcreturnandroid.hardware.automotive.vehicle.V2_0.IVehicle.getService(instanceName);}catch(RemoteExceptione){Slog.e(CarLog.TAG_SERVICE,"Failed to get IVehicle/"+instanceName +" service",e);}catch(NoSuchElementExceptione){Slog.e(CarLog.TAG_SERVICE,"IVehicle/"+instanceName +" service not registered yet");}returnnull;}
接着再看
ICarImpl
的实现,如下所示:1)创建各个核心服务对象
2)把服务对象缓存到 CarLocalServices中,这里主要是为了方便 Service之间的相互访问
源码路径:/packages/services/Car/service/src/com/android/car/ICarImpl.java
@VisibleForTestingICarImpl(ContextserviceContext,IVehiclevehicle,SystemInterfacesystemInterface,StringvehicleInterfaceName,@NullableCarUserServicecarUserService,@NullableCarWatchdogServicecarWatchdogService,@NullableICarPowerPolicySystemNotificationpowerPolicyDaemon){...mContext =serviceContext;mSystemInterface =systemInterface;CarLocalServices.addService(SystemInterface.class,mSystemInterface);//创建 VehicleHal 对象mHal =constructWithTrace(t,VehicleHal.class,()->newVehicleHal(serviceContext,vehicle));...// 创建核心服务对象,并缓存到 CarLocalServicesmCarPropertyService =constructWithTrace(t,CarPropertyService.class,()->newCarPropertyService(serviceContext,mHal.getPropertyHal()));mCarDrivingStateService =constructWithTrace(t,CarDrivingStateService.class,()->newCarDrivingStateService(serviceContext,mCarPropertyService));mCarUXRestrictionsService =constructWithTrace(t,CarUxRestrictionsManagerService.class,()->newCarUxRestrictionsManagerService(serviceContext,mCarDrivingStateService,mCarPropertyService));... // 将创建的服务对象依次添加到一个 list 中保存起来List<CarServiceBase>allServices =newArrayList<>();allServices.add(mFeatureController);allServices.add(mCarUXRestrictionsService);// mCarUserService depends on itallServices.add(mCarUserService);allServices.add(mSystemActivityMonitoringService);allServices.add(mCarPowerManagementService);allServices.add(mCarPropertyService);allServices.add(mCarDrivingStateService);allServices.add(mCarOccupantZoneService);addServiceIfNonNull(allServices,mOccupantAwarenessService);allServices.add(mCarPackageManagerService);allServices.add(mCarInputService);allServices.add(mGarageModeService);...} @MainThreadvoidinit(){LimitedTimingsTraceLogt =newLimitedTimingsTraceLog(CAR_SERVICE_INIT_TIMING_TAG,Trace.TRACE_TAG_SYSTEM_SERVER,CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS); t.traceBegin("ICarImpl.init"); t.traceBegin("VHAL.init");mHal.init();t.traceEnd(); t.traceBegin("CarService.initAllServices");//启动的所有服务遍历调用 init 初始化(各个都继承了 CarServiceBase)for(CarServiceBaseservice :mAllServices){t.traceBegin(service.getClass().getSimpleName());service.init();t.traceEnd();}t.traceEnd();// "CarService.initAllServices" t.traceEnd();// "ICarImpl.init"}
然后将上面 onCreate() 创建的 mICarImpl 对象返回:
onBind()
回调方法会继续传递通过bindService()
传递来的 intent 对象(即上面的bindServiceAsUser
方法)onUnbind()
会处理传递给unbindService()
的 intent 对象。传统的手机系统加上相关的汽车服务,构成了现在的 AAOS,而其中 CarService就是提供汽车相关功能的最主要的模块。
对于 CarService也是采用了 C/S 模式,Car App并不会直接通过 CarService 的实例调用相关功能,而是通过对应的 Car API完成对服务的调用。比如 Hvac 通过 getCarManager 方法获取了一个 CarHvacManager,当获取到 manager 后就可以进行相关操作
// 创建 Car 实例CarcarApiClient =Car.createCar(context);// 获取 CarHvacManagerCarHvacManagermanager =(CarHvacManager)mCarApiClient.getCarManager(Car.HVAC_SERVICE);
// 调用 disconnect() 断开连接carApiClient.disconnect();
三 CarService 实现原理
想要弄清楚
CarService
实现方式,首先需要搞明白CarService
的启动流程。4)设定 SystemProperty,将
CarService
设定为创建完成状态,只有包含CarService
在内的所有的核心 Service 都完成初始化,才能结束开机动画并发送开机广播。位于/packages/services/Car/car-lib
- CarService:系统中与车相关的服务。
CarServiceHelperService
是CarService
的 SystemService 端的配套服务。 - ICarImpl返回给 CarServiceHelperService之后,CarServiceHelperService也将其内部的一个 Binder 对象(ICarServiceHelperImpl)传递到了 CarService进程,自此 CarService和 system_server两个进程建立了双向 Binder 通信。
- ICarImpl构造方法中创建了一系列和汽车相关的核心服务,并依次启动这些服务即调用各自 init 方法。这里的 CarService就是服务端,Car API就是客户端。
2)创建 ICarImpl 对象,并调用
init
方法,它就是ICar.aidl
接口的实现类,我们需要通过它才能拿到其他的 Service 的 IBinder 对象。