使用方法及启动流程

发布时间: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),为外界提供汽车所有服务和数据的访问

  1. 通过createCar()方法新建 Car 实例
  2. 成功连接时可以通过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()会返回客户端与服务互相联系的通信句柄

源码路径:/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初始化如下:

  1. 其中返回的 ICarImpl被保存在了 CarServiceHelperServicemCarService
  2. 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
  • Vehicle HAL:汽车的硬件抽象层描述。ICarImpl 返回给 CarServiceHelperService之后,CarServiceHelperService也将其内部的一个 Binder 对象(ICarServiceHelperImpl)传递到了 CarService进程,自此 CarServicesystem_server两个进程建立了双向 Binder 通信。python 写的,通过 adb 可以连接 vehicleHal 的工具,用于模拟测试├── TrustAgent└── vehicle-hal-support-lib

    Android 通信模式通常基于 C/S 模式,即有客户端和服务端,每个服务有对应的代理对象(比如 ActivityManager 相对服务 AMS,就是客户端)。

    在这里插入图片描述

    车载 HAL 与 AAOS 架构:

    • Car App:包括 OEM 和第三方开发的 App
    • Car API:内有包含 CarSensorManager 在内的 API。

      CarService 启动流程主要分为以下四个步骤:

      1. SystemServer启动 CarServiceHelperService服务
      2. 在调用 startService()后,CarServiceHelperServiceonStart()方法通过 bindService 的方式启动 CarService(一个系统级别的 APK,位于 system/priv-app)
      3. 启动 CarService后首先调用 onCreate(),创建 ICarImpl对象并初始化,在此时创建了一系列 Car 相关的核心服务,并遍历 init初始化
      4. 然后调用 onBind 将该 ICarImpl对象返回给 CarServiceHelperServiceCarServiceHelperService在内部的一个 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中调用StartCarServiceHelperServiceonStart()方法。

    • 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 对象返回:

      1. onBind()回调方法会继续传递通过 bindService()传递来的 intent 对象(即上面的bindServiceAsUser方法)
      2. 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:系统中与车相关的服务。

      CarServiceHelperServiceCarService的 SystemService 端的配套服务。

    • ICarImpl返回给 CarServiceHelperService之后,CarServiceHelperService也将其内部的一个 Binder 对象(ICarServiceHelperImpl)传递到了 CarService进程,自此 CarServicesystem_server两个进程建立了双向 Binder 通信。
    • ICarImpl构造方法中创建了一系列和汽车相关的核心服务,并依次启动这些服务即调用各自 init 方法。这里的 CarService就是服务端,Car API就是客户端。

      2)创建 ICarImpl 对象,并调用init方法,它就是ICar.aidl接口的实现类,我们需要通过它才能拿到其他的 Service 的 IBinder 对象。