前言
上一篇文档总结 Android Automotive 框架的 APP 和 API 部分内容,本篇文档将会继续根据 Android Automotive 框架结构,总结 Framework 层 CarService 服务的内容。
本文档对 Android Automotive Framework 层服务将会按照如下顺序展开描述:
CarService 介绍
CarService 服务分类
CarService 代码路径编译路径
CarService 启动流程
CarService 提供服务流转示例,以 Property 为例
上一篇:AndroidAutomotive模块介绍(二)应用及接口介绍
下一篇:AndroidAutomotive模块介绍(四)VehicleHal介绍
正文
1、CarService 介绍
系统框架层提供了多个模块,来对 Android Automotive 进行支持,Google 以 CarService (com.android.car) 服务对外提供支持。CarService 并不是指一个服务,而是一系列服务的统称,在 CarService 中会创建许多子服务以支持车载系统功能。
2、CarService 服务分类
CarService 作为服务的入口,具体的业务逻辑会分布在内部的子服务中。
2.1 CarService 所有服务介绍
下面是 CarService 子服务的介绍:
- CarUserService
汽车多用户服务。在启动时管理用户,包括:
创建用作驱动程序的用户;
创建用作乘客的用户;
首次运行时创建辅助管理员用户;
切换驾驶员;
- SystemActivityMonitoringService
监控AMS新Activity或Service启动的服务。
- CarPowerManagementService
汽车电源管理服务。控制电源状态并与系统的其他部分交互以确保其自身状态。
- CarUserNoticeService
向用户显示初始通知UI的服务。它仅在启用设置时启动它,并根据用户的请求通知UI自行关闭。
- CarPropertyService
处理车辆属性的管理器。此类实现 ICarProperty 的 binder 接口。有助于更容易地创建处理车辆属性的多个 Manager。
- CarDrivingStateService
推断车辆当前驾驶状态的服务。它通过侦听 CarPropertyService 的相关属性来计算驾驶状态。
- CarUxRestrictionsManagerService
用户体验限制的服务。根据监听到的车辆当前驾驶状态,限制 HMI 显示。
- CarPackageManagerService
汽车包管理服务。
- PerUserCarServiceHelper
提供作为当前用户绑定/取消绑定到 PerUserCarService 的方法,为 UserSwitch 广播设置侦听器,并调用已注册回调的客户端。
- CarInputService
CarInputService 通过车辆HAL监控和处理输入事件。
- CarProjectionService
汽车投屏服务。
- GarageModeService
车库模式。车库模式启用车内空闲时间。
- AppFocusService
应用程序焦点服务确保一次只有一个应用程序类型的实例处于活动状态。
- CarAudioService
负责与汽车音响系统交互的服务。
- CarNightService
用于处理用于将车辆设置为夜间模式的事件。
- InstrumentClusterService
负责与汽车仪表盘交互的服务。
- SystemStateControllerService
系统状态控制服务。原生系统中是一个空服务,并没有实现。
- VmsBrokerService
VMS 客户端实现,使用 HAL 特定消息编码将 VmsPublisher / VmsSubscriber API 调用代理到车辆 HAL。
- VmsClientManager
用于管理车载消息服务(VMS)的客户端。VMS 是一种用于车辆间通信的消息传递系统,允许车辆之间共享信息和通知。
- VmsSubscriberService
用于订阅车辆消息服务(VMS)。VMS 是一种用于车辆间通信的消息传递系统,允许车辆之间共享信息和通知。VmsSubscriberService 允许车载应用程序注册并接收其他车辆发送的 VMS 消息。
- VmsPublisherService
用于发布车辆消息服务(VMS)。
- CarDiagnosticService
汽车诊断服务。工程模式会用到此服务。
- CarStorageMonitoringService
提供存储监视数据(如 I/O 统计数据)的服务。为了接收此类数据,用户需要实现 IIoStatsListener 并根据此服务注册自己。
- CarConfigurationService
该服务将查看系统上的默认 JSON 配置文件并解析其结果。该服务将查找映射到 R.raw.car_config 的 JSON 文件。如果此值不存在或格式不正确,则此服务不会失败;相反,它返回各种配置的默认值。
- CarLocationService
此服务在车辆停放时存储 LocationManager 中最后一个已知位置,并在车辆通电时恢复该位置。
- CarTrustedDeviceService
汽车服务中启用受信任设备功能的部分。可信设备是一项功能,其中远程设备注册为可信设备,可以授权 Android 用户而不是用户输入密码或 PIN。
- CarMediaService
CarMediaService 管理汽车应用程序的当前活动媒体源。这与 MediaSessionManager 的活动会话不同,因为同一时间内车内只能有一个活动源。
在车内,活动的媒体源不一定有活动的 MediaSession,例如,如果只是在浏览它。但是,该源仍然被视为活动源,并且应该是任何媒体相关 UI(媒体中心、主屏幕等)中显示的源。
- CarBugreportManagerService
Bug report服务。
2.2 CarService 常用服务介绍
下面对 CarService 中常用的服务进行简要描述。
2.2.1 CarPowerManagementService
电源管理在 AndroidAutomotive 上是一个比较重要的功能,相对于手机来说,由于车辆的使用场景的特殊以及复杂性,同时需要和车辆其他 ECU(Electronic Control Unit)电子控制单元的配置,增加了车载系统中电源管理的难度。
和手机不同, 手机可以频繁充电, 哪怕长时间不用,手机电量耗尽, 使用时再充上电就 ok 了, 不会有什么问题. 可是车机不同, 行驶过程中车机需要始终保持工作, 用户是不能随意重启车机的, 否则可能会影响驾驶安全; 而在停车熄火后,车机就要尽量降低其功耗, 否则如果将电瓶中电耗尽, 那可不是插上充电线这么简单了,需要车辆救援搭电才能启动。
2.2.1.1 接口
与其他的 CarService 中的服务不同, 除了提供了 java 类的接口 CarPowerManager 以外, CarPowerManagementService 还有对应的 C++ 类的接口, 类名同样也叫 CarPowerManager。这两个的源码位置分别位于:
packages/services/Car/car-lib/src/android/car/hardware/power/CarPowerManager.java
packages/services/Car/car-lib/native/CarPowerManager/CarPowerManager.cpp
增加 C++ 类的接口主要是为了向一些使用 C++ 编写的服务提供 CarPowerManager 相关的功能. 帮助其管理电源的状态. 在接口的定义和功能上面, 无论是 java 还是 C++ 的 CarPowerManager 都是一样的, 他们都对应于同一个CarPowerManagerService。
上层 APP 可以通过 Car-lib 中的接口通过 CarPowerManager 访问 CarPowerManagementService,底层 Native 服务可以通过 CarPowerManager C++ 类访问 CarPowerManagementService。如下图所示:
2.2.1.2 CarPowerManager 使用
CarPowerManager 提供了电源状态变化通知, 调节电源状态的功能。
CarPowerManager 对于电源状态的监听是通过注册回调实现的,CarPowerManager 中定义两个 interface 类 CarPowerStateListener 和 CarPowerStateListenerWithCompletion。通过定义的 onStateChanged() 监听来自 CarPowerManagementService 服务端电源状态的变化,当然这个数据来源于底层或者其他 ECU 状态。监听类注册到 CarPowerManagementService 服务端,由服务端管理回调。
- setListener(CarPowerStateListener listener) 注册 CarPowerStateListener 监听;
- setListenerWithCompletion(CarPowerStateListenerWithCompletion listener) 注册 CarPowerStateListenerWithCompletion 监听;
不同的地方是 setListenerWithCompletion 传递的 CarPowerStateListenerWithCompletion 接口的回调中包含
CompletableFuture 对象, 用于通知 CarPowerManagementService 该注册监听的应用已经完成了相关流程的处理。
下面列出 CarPowerManagementService 所支持的跨进程调用的接口:
方法 | 说明 |
---|---|
void registerListener(in ICarPowerStateListener listener) | 注册 ICarPowerStateListener 监听类 |
void unregisterListener(in ICarPowerStateListener listener) | 取消 ICarPowerStateListener 监听类 |
void requestShutdownOnNextSuspend() | 请求电源管理器在下一个机会关闭而不是暂停。 |
void finished(in ICarPowerStateListener listener) | 结束 ICarPowerStateListener 监听 |
void scheduleNextWakeupTime(int seconds) | 在 CarPowerManagementSystem 中安排下一次唤醒时间 |
void registerListenerWithCompletion(in ICarPowerStateListener listener) | 注册 ICarPowerStateListener 监听类 |
2.2.1.3 CarPowerManagementService 处理流程
总体来说,电源状态的变化由车辆主控单元由下往上推送至 CarPowerManagementService。
举例来说,由于用户的熄火状态(具体的信号触发条件不同),车辆的电源状态开始变化,车辆主控单元将信号发送给车载娱乐系统 (In-Vehicle Infotainment , IVI) 单元。进而再由 VehicleHAL 硬件抽象层上报给 CarPowerManagementService,最后进入到Android系统的关机流程。
简要流程如下所示:
VehicleHAL 接收到电源变化的信号后,通过PowerHalService在分发给 CarPowerManagementService,电源事件在 VehicleHAL 定义了相关的属性 ID, 通过属性 ID 进行分发。
PowerHalService 对象是在 VehicleHAL (此处并非指车辆硬件抽象层, 而是 CarService 中的VehicleHal 类)的构造函数中创建的,最后再由 CarPowerManagementService 根据不同状态进行处理,并通知相关使用了 CarPowerManager 监听状态变化的应用。
2.2.2 CarInputService
CarInputService 是 AndroidAutomotive 中的服务,负责处理与车辆输入设备相关的操作,例如处理车辆上的按钮、方向盘控制、触摸屏输入等。该服务允许开发人员管理和相应来自车辆输入设备的事件,并与车辆上运行的应用程序进行交互。
原生定义的 ICarInputListener.aidl 文件中只定义了一个函数
oneway interface ICarInputListener {
void onKeyEvent(in KeyEvent keyEvent, int targetDisplay) = 1;
}
onKeyEvent() 用于监听 Event 事件,监听输入设备的输入事件。
对于 CarInputService,这里在功能流转上简单介绍,CarInputService 实现了 InputHalService.InputListener 接口,在初始化过程中,将自身注册到 InputHalService 中,InputHalService 监听来自底层 VehicleDisplay、VehicleHwKeyInputAction 相关的触摸信号,通过 InputListener 接口将 Event 事件返回给 CarInputService,从而实现 Event 的转发。
2.2.3 CarAudioService
Android Automotive OS (AAOS) 是在核心 Android 音频堆栈的基础之上打造而成,以支持用作车辆信息娱乐系统的用例。AAOS 负责实现信息娱乐声音(即媒体、导航和通讯声音),但不直接负责具有严格可用性和计时要求的铃声和警告。虽然 AAOS 提供了信号和机制来帮助车辆管理音频,但最终还是由车辆来决定应为驾驶员和乘客播放什么声音,从而确保对保障安全至关重要的声音和监管声音能被确切听到,而不会中断。
当 Android 管理车辆的媒体体验时,应通过应用来代表外部媒体来源(例如电台调谐器),这类应用可以处理该来源的音频焦点和媒体键事件。
汽车音频系统可以处理以下声音和声音流:
Android 管理来自 Android 应用的声音,同时控制这些应用,并根据其声音类型将声音路由到 HAL 中的输出设备:
- 逻辑声音流:在核心音频命名法中称为“声源”,使用音频属性进行标记。
- 物理声音流:在核心音频命名法中称为“设备”,在混音后没有上下文信息。
为了确保可靠性,外部声音(来自独立声源,例如安全带警告铃声)在 Android 外部(HAL 下方,甚至是在单独的硬件中)进行管理。系统实现者必须提供一个混音器,用于接受来自 Android 的一个或多个声音输入流,然后以合适的方式将这些声音流与车辆所需的外部声源组合起来。
HAL 实现和外部混音器负责确保对保障安全至关重要的外部声音能够被用户听到,而且负责在 Android 提供的声音流中进行混音,并将混音结果路由到合适的音响设备。
CarAudio 类图如下所示:
CarAudio 流程图如下所示:
2.2.3.1 接口
下面对 CarAudioService 所提供的接口进行介绍:
方法 | 说明 |
---|---|
boolean isDynamicRoutingEnabled() | 是否启用动态路由。 |
void setGroupVolume(int zoneId, int groupId, int index, int flags) | 为主分区中的卷组设置卷索引。 |
int getGroupMaxVolume(int zoneId, int groupId) | 返回主区域中卷组的最大卷索引。 |
int getGroupMinVolume(int zoneId, int groupId) | 返回主区域中卷组的最小卷索引。 |
int getGroupVolume(int zoneId, int groupId) | 返回主区域中卷组的当前卷索引。 |
void setFadeTowardFront(float value) | 调整车辆座舱前后的相对音量。 |
void setBalanceTowardRight(float value) | 调节车辆舱室左右两侧的相对音量。 |
String[] getExternalSources() | 查询系统配置,以便报告可用的非麦克风音频输入设备。 |
CarAudioPatchHandle createAudioPatch(in String sourceAddress, int usage, int gainInMillibels) | 给定一个由 getExternalSources() 标识的输入端口,请求它的音频信号在 HAL 下面路由到与给定用法相关的输出端口。例如,调谐器的输出可能直接路由到与 AudioAttributes 关联的输出总线。在调谐器播放时使用 USAGE_MEDIA。 |
void releaseAudioPatch(in CarAudioPatchHandle patch) | 删除输入端口和提供句柄标识的输出端口之间的关联。 |
int getVolumeGroupCount(int zoneId) | 获取主区域中可用卷组的计数。 |
int getVolumeGroupIdForUsage(int zoneId, int usage) | 获取主区域中给定 AudioAttributes 使用情况的卷组 id。 |
int[] getUsagesForVolumeGroupId(int zoneId, int groupId) | 获取主区域中卷组的 AudioAttributes 用法数组。 |
int[] getAudioZoneIds() | 获取当前可用的音频区域。 |
int getZoneIdForUid(int uid) | 获取当前映射到 uId 的音频区域 id,如果不存在映射,则默认为 PRIMARY_AUDIO_ZONE。 |
boolean setZoneIdForUid(int zoneId, int uid) | 将音频区 id 映射为 uid。 |
boolean clearZoneIdForUid(int uid) | 清除 uid 的当前 zone 映射。 |
int getZoneIdForDisplayPortId(byte displayPortId) | 获取传入的显示端口 id 的区域 id。 |
void registerVolumeCallback(in IBinder binder) | 注册 ICarVolumeCallback 回调。 |
void unregisterVolumeCallback(in IBinder binder) | 取消注册 ICarVolumeCallback 回调。 |
2.2.4 CarPropertyService
CarPropertyService 用于管理与车辆硬件功能相关联的属性,如空调, 车舱功能, 车辆传感器等。
在 packages/services/Car/service/src/com/android/car/ICarImpl.java 的 getCarService() 方法中:
public IBinder getCarService(String serviceName) {
switch (serviceName) {
...
case Car.CABIN_SERVICE:
case Car.HVAC_SERVICE:
case Car.INFO_SERVICE:
case Car.DIAG_SERVICE:
case Car.PROPERTY_SERVICE:
case Car.SENSOR_SERVICE:
case Car.VENDOR_EXTENSION_SERVICE:
return mCarPropertyService;
...
}
}
可以看到 CarPropertyService 同时对应着 CarCabinManager,CarHvacManager,CarInfoManager,CarPropertyManager,CarSensorManager 和 CarVendorExtensionManager这六个对象, 可以说是一个服务分担多个角色. 所以在 Android10 之后, 谷歌直接推荐使用 CarPropertyManager。
- CarCabinManager:CarCabinManager 提供的是座舱内相关功能的 API,包括座椅、安全带、车窗等。属性列表如下:
属性 | 类型 | 功能 |
---|---|---|
ID_DOOR_POS | int | 车门 |
ID_DOOR_MOVE | int | |
ID_DOOR_LOCK | bool | |
ID_MIRROR_Z_POS | int | 后视镜 |
ID_MIRROR_Z_MOVE | int | |
ID_MIRROR_Y_POS | int | |
ID_MIRROR_Y_MOVE | int | |
ID_MIRROR_LOCK | bool | |
ID_MIRROR_FOLD | bool | |
ID_SEAT_MEMORY_SELECT | int | 座椅记忆 |
ID_SEAT_MEMORY_SET | int | |
ID_SEAT_BELT_BUCKLED | bool | 安全带 |
ID_SEAT_BELT_HEIGHT_POS | int | |
ID_SEAT_BELT_HEIGHT_MOVE | int | |
ID_SEAT_FORE_AFT_POS | int | 座椅前后位置 |
ID_SEAT_FORE_AFT_MOVE | int | |
ID_SEAT_BACKREST_ANGLE_1_POS | int | 座椅靠背 |
ID_SEAT_BACKREST_ANGLE_1_MOVE | int | |
ID_SEAT_BACKREST_ANGLE_2_POS | int | |
ID_SEAT_BACKREST_ANGLE_2_MOVE | int | |
ID_SEAT_HEIGHT_POS | int | 座椅高度 |
ID_SEAT_HEIGHT_MOVE | int | |
ID_SEAT_DEPTH_POS | int | 座椅深度 |
ID_SEAT_DEPTH_MOVE | int |
属性 | 类型 | 功能 |
---|---|---|
ID_SEAT_TILT_POS | int | 座椅倾角 |
ID_SEAT_TILT_MOVE | int | |
ID_SEAT_LUMBAR_FORE_AFT_POS | int | 腰托 |
ID_SEAT_LUMBAR_FORE_AFT_MOVE | int | |
ID_SEAT_LUMBAR_SIDE_SUPPORT_POS | int | |
ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE | int | |
ID_SEAT_HEADREST_HEIGHT_POS | int | 头枕 |
ID_SEAT_HEADREST_HEIGHT_MOVE | int | |
ID_SEAT_HEADREST_ANGLE_POS | int | |
ID_SEAT_HEADREST_ANGLE_MOVE | int | |
ID_SEAT_HEADREST_FORE_AFT_POS | int | |
ID_SEAT_HEADREST_FORE_AFT_MOVE | int | |
ID_WINDOW_POS | int | 车窗 |
ID_WINDOW_MOVE | int | |
ID_WINDOW_LOCK | bool |
- CarHvacManager:Hvac 全称供暖通风与空气调节(Heating Ventilation and Air Conditioning),它是空调系统相关功能的服务,AAOS 定义了标准的 CarHvacManager API 来提供相关的功能,通过该服务可以实现对空调系统的监听和控制。注意 CarHvacManager 所涉及的属性都是需要有系统级别的权限,所以第三方应用目前是无法直接使用CarHvacManager的。属性列表如下:
属性 | 类型 | 功能 |
---|---|---|
ID_MIRROR_DEFROSTER_ON | bool | 后视镜除霜 |
ID_STEERING_WHEEL_HEAT | int | 方向盘加热 |
ID_OUTSIDE_AIR_TEMP | float | 车外温度 |
ID_TEMPERATURE_DISPLAY_UNITS | int | 温标(华氏度和摄氏度) |
ID_ZONED_TEMP_SETPOINT | float | 温度 |
ID_ZONED_TEMP_ACTUAL | float | 实际温度 |
ID_ZONED_HVAC_POWER_ON | bool | 空调系统开关 |
ID_ZONED_FAN_SPEED_SETPOINT | int | 风速 |
ID_ZONED_FAN_SPEED_RPM | int | 风扇转速 |
ID_ZONED_FAN_DIRECTION_AVAILABLE | vector | 可用风向 |
ID_ZONED_FAN_DIRECTION | int | 风向 |
ID_ZONED_SEAT_TEMP | int | 座椅温度 |
ID_ZONED_AC_ON | bool | AC开关 |
ID_ZONED_AUTOMATIC_MODE_ON | bool | 自动空调 |
ID_ZONED_AIR_RECIRCULATION_ON | bool | 空调循环 |
ID_ZONED_MAX_AC_ON | bool | 强力空调 |
ID_ZONED_DUAL_ZONE_ON | bool | 多区域空调 |
ID_ZONED_MAX_DEFROST_ON | bool | 强力除霜 |
ID_ZONED_HVAC_AUTO_RECIRC_ON | bool | 自动空气循环 |
ID_WINDOW_DEFROSTER_ON | bool | 车窗除霜 |
-
CarInfoManager:车辆信息服务。例如获取车辆的型号、能源型号、电池容量等信息。
-
CarPropertyManager:车辆属性 API。管理车辆属性。
-
CarSensorManager :CarSensorManager 主要对应的就是和车辆传感器相关的一些功能,相比手机,车辆的传感器种类要更丰富多彩,特别是随着汽车越来越智能化,自动驾驶等功能的加入,传感器的数量还会不断增加。车辆的智能控制功能都和传感器的数据有着密切的关系,如自动空调、自动控制灯光、驾驶座位自动调整等。在 CarSensorManager 中包含了汽车特有的传感器类型,如车速、发动机转速等,如下表中介绍:
属性 | 类型 | 权限 | 系统权限 |
---|---|---|---|
SENSOR_TYPE_CAR_SPEED | 车速 | CAR_SPEED | 否 |
SENSOR_TYPE_RPM | 转速 | CAR_ENGINE_DETAILED | 是 |
SENSOR_TYPE_ODOMETER | 里程数 | CAR_MILEAGE | 是 |
SENSOR_TYPE_FUEL_LEVEL | 油量 | CAR_ENERGY | 否 |
SENSOR_TYPE_PARKING_BRAKE | 驻车制动 | CAR_POWERTRAIN | 否 |
SENSOR_TYPE_GEAR | 档位 | CAR_POWERTRAIN | 否 |
SENSOR_TYPE_NIGHT | 白天黑夜 | CAR_EXTERIOR_ENVIRONMENT | 否 |
SENSOR_TYPE_ENV_OUTSIDE_TEMPERATURE | 车外环境温度 | CAR_EXTERIOR_ENVIRONMENT | 否 |
SENSOR_TYPE_IGNITION_STATE | 点火状态 | CAR_POWERTRAIN | 否 |
SENSOR_TYPE_WHEEL_TICK_DISTANCE | 轮距 | CAR_SPEED | 否 |
SENSOR_TYPE_ABS_ACTIVE | ABS状态 | CAR_DYNAMICS_STATE | 是 |
SENSOR_TYPE_TRACTION_CONTROL_ACTIVE | 牵引力控制 | CAR_DYNAMICS_STATE | 是 |
SENSOR_TYPE_FUEL_DOOR_OPEN | 加油口状态 | CAR_ENERGY_PORTS | 否 |
SENSOR_TYPE_EV_BATTERY_LEVEL | 电量值 | CAR_ENERGY | 否 |
SENSOR_TYPE_EV_CHARGE_PORT_OPEN | 充电口状态 | CAR_ENERGY_PORTS | 否 |
SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED | 充电连接状态 | CAR_ENERGY_PORTS | 否 |
SENSOR_TYPE_EV_BATTERY_CHARGE_RATE | 充电速率 | CAR_ENERGY | 否 |
SENSOR_TYPE_ENGINE_OIL_LEVEL | 机油量 | CAR_ENGINE_DETAILED | 是 |
- CarVendorExtensionManager:制造商扩展服务。市场上的汽车品牌种类繁多,每款车型的功能又不相同。汽车制造商们也在不断推陈出新,推出一些属于品牌特有的功能来吸引消费者的目光。要想将说有的功能都定义为标准的属性肯定非常困难。对此 AAOS的做法是,,除了定义目前市场上绝大多数车型都适用的属性外,同样允许制造商根据自己所拥有的其他功能进行扩展,这就是本节 CarVendorExtensionManager 的主要作用。它让制造商可以扩展 VehicleHAL 中已经定义的属性,加入额外的功能。
3、CarService
3.1 CarService 路径及编译
CarService 的代码路径为:/android/packages/services/Car/service。
CarService 是以系统 APK 的方式提供系统服务的,编译结果会在系统的 /system/priv-app/CarService 路径下。
3.2 启动流程
3.2.1 时序图
下面是 CarService 启动流程时序图
3.2.2 代码流程
3.2.2.1 SystemServer.startOtherServices()
Android 中的 SystemServer 会启动一系列系统服务,CarService 服务是在 startOtherServices() 阶段中启动的。通过启动 CarServiceHelperService 类来拉起 CarService 服务。
private static final String CAR_SERVICE_HELPER_SERVICE_CLASS =
"com.android.internal.car.CarServiceHelperService";
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
traceBeginAndSlog("StartCarServiceHelperService");
mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);
traceEnd();
}
3.2.2.2 SystemServiceManager.startService()
SystemServiceManager 在 Android 中管理系统服务的启动,对于 SystemService,系统服务会继承 SystemService 类,在 SystemServiceManager 中会通过反射创建服务类,然后调用其 onStart() 函数。
public SystemService startService(String className) {
final Class<SystemService> serviceClass;
...
serviceClass = (Class<SystemService>)Class.forName(className);
...
return startService(serviceClass);
}
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {
...
final String name = serviceClass.getName();
// Create the service.
}
final T service;
...
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
...
startService(service);
return service;
}
...
}
public void startService(@NonNull final SystemService service) {
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
...
service.onStart();
...
}
3.2.2.3 CarServiceHelperService
CarServiceHelperService 是 CarService 的启动类,代码路径在:/android/frameworks/opt/car/services/src/com/android/internal/car。
private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";
public void onStart() {
Intent intent = new Intent();
intent.setPackage("com.android.car");
intent.setAction(CAR_SERVICE_INTERFACE);
if (!getContext().bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,
UserHandle.SYSTEM)) {
Slog.wtf(TAG, "cannot start car service");
}
System.loadLibrary("car-framework-service-jni");
}
在 CarServiceHelperService.onStart() 函数中,通过 Intent 的方式开启 CarService 应用,这里
CAR_SERVICE_INTERFACE = “android.car.ICar” 对应 CarService 中 AndroidManifest.xml 中的定义:
<service android:name=".CarService"
android:singleUser="true">
<intent-filter>
<action android:name="android.car.ICar" />
</intent-filter>
</service>
<service android:name=".PerUserCarService" android:exported="false" />
调用 bindServiceAsUser() 函数启动服务。
3.2.2.4 CarService
下面进入 CarService 流程,CarService 入口类为 CarService.java,路径:/android/packages/services/Car/service/src/com/android/car/CarService.java。启动 CarService,会进入到 onCreate() 函数。
public void onCreate() {
Log.i(CarLog.TAG_SERVICE, "Service onCreate");
// 获取 CarService Hal 层,VehicleHal 服务端对象
mVehicle = getVehicle();
if (mVehicle == null) {
throw new IllegalStateException("Vehicle HAL service is not available.");
}
try {
mVehicleInterfaceName = mVehicle.interfaceDescriptor();
} catch (RemoteException e) {
throw new IllegalStateException("Unable to get Vehicle HAL interface descriptor", e);
}
Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
// 创建 ICarImpl 对象
mICarImpl = new ICarImpl(this,
mVehicle,
SystemInterface.Builder.defaultSystemInterface(this).build(),
mCanBusErrorNotifier,
mVehicleInterfaceName);
// 初始化 ICarImpl 对象
mICarImpl.init();
linkToDeath(mVehicle, mVehicleDeathRecipient);
// 添加 car_service 服务端对象为 ICarImpl
ServiceManager.addService("car_service", mICarImpl);
SystemProperties.set("boot.car_service_created", "1");
super.onCreate();
}
// 这里是通过 Binder 获得 hal 层的服务代理对象
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;
}
// 返回 mICarImpl 对象
public IBinder onBind(Intent intent) {
return mICarImpl;
}
3.2.2.5 ICarImpl
CarService 的实现实际是通过 ICarImpl 提供服务的,这里我们来看下 ICarImpl 的初始化。
public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
mContext = serviceContext;
mSystemInterface = systemInterface;
// 创建 VehicleHal,此对象用于与 Hal 层交互
mHal = new VehicleHal(vehicle);
mVehicleInterfaceName = vehicleInterfaceName;
mUserManagerHelper = new CarUserManagerHelper(serviceContext);
final Resources res = mContext.getResources();
final int maxRunningUsers = res.getInteger(
com.android.internal.R.integer.config_multiuserMaxRunningUsers);
// 创建 CarService 子服务
mCarUserService = new CarUserService(serviceContext, mUserManagerHelper,
ActivityManager.getService(), maxRunningUsers);
mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext);
mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(),
systemInterface, mUserManagerHelper);
mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarPropertyService);
mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext,
mCarDrivingStateService, mCarPropertyService);
mCarPackageManagerService = new CarPackageManagerService(serviceContext,
mCarUXRestrictionsService,
mSystemActivityMonitoringService,
mUserManagerHelper);
mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
mCarBluetoothService = new CarBluetoothService(serviceContext, mPerUserCarServiceHelper);
mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
mCarProjectionService = new CarProjectionService(
serviceContext, null /* handler */, mCarInputService, mCarBluetoothService);
mGarageModeService = new GarageModeService(mContext);
mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);
mCarAudioService = new CarAudioService(serviceContext);
mCarNightService = new CarNightService(serviceContext, mCarPropertyService);
mInstrumentClusterService = new InstrumentClusterService(serviceContext,
mAppFocusService, mCarInputService);
mSystemStateControllerService = new SystemStateControllerService(
serviceContext, mCarAudioService, this);
mVmsBrokerService = new VmsBrokerService(mContext.getPackageManager());
mVmsClientManager = new VmsClientManager(
serviceContext, mCarUserService, mUserManagerHelper, mHal.getVmsHal());
mVmsSubscriberService = new VmsSubscriberService(
serviceContext, mVmsBrokerService, mHal.getVmsHal());
mVmsPublisherService = new VmsPublisherService(
serviceContext, mVmsBrokerService, mVmsClientManager);
mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,
systemInterface);
mCarConfigurationService =
new CarConfigurationService(serviceContext, new JsonReaderImpl());
mCarLocationService = new CarLocationService(mContext, mUserManagerHelper);
mCarTrustedDeviceService = new CarTrustedDeviceService(serviceContext);
mCarMediaService = new CarMediaService(serviceContext);
mCarBugreportManagerService = new CarBugreportManagerService(serviceContext);
// 将 CarPowerManagementService、CarUserService、CarTrustedDeviceService、SystemInterface、CarDrivingStateService、PerUserCarServiceHelper 服务添加到 CarLocalServices 集合中,便于获取
CarLocalServices.addService(CarPowerManagementService.class, mCarPowerManagementService);
CarLocalServices.addService(CarUserService.class, mCarUserService);
CarLocalServices.addService(CarTrustedDeviceService.class, mCarTrustedDeviceService);
CarLocalServices.addService(SystemInterface.class, mSystemInterface);
CarLocalServices.addService(CarDrivingStateService.class, mCarDrivingStateService);
CarLocalServices.addService(PerUserCarServiceHelper.class, mPerUserCarServiceHelper);
// 将创建的 CarService 服务添加到 allServices 集合中保存
// Be careful with order. Service depending on other service should be inited later.
List<CarServiceBase> allServices = new ArrayList<>();
allServices.add(mCarUserService);
allServices.add(mSystemActivityMonitoringService);
allServices.add(mCarPowerManagementService);
allServices.add(mCarPropertyService);
allServices.add(mCarDrivingStateService);
allServices.add(mCarUXRestrictionsService);
allServices.add(mCarPackageManagerService);
allServices.add(mCarInputService);
allServices.add(mGarageModeService);
allServices.add(mAppFocusService);
allServices.add(mCarAudioService);
allServices.add(mCarNightService);
allServices.add(mInstrumentClusterService);
allServices.add(mSystemStateControllerService);
allServices.add(mPerUserCarServiceHelper);
allServices.add(mCarBluetoothService);
allServices.add(mCarProjectionService);
allServices.add(mCarDiagnosticService);
allServices.add(mCarStorageMonitoringService);
allServices.add(mCarConfigurationService);
allServices.add(mVmsClientManager);
allServices.add(mVmsSubscriberService);
allServices.add(mVmsPublisherService);
allServices.add(mCarTrustedDeviceService);
allServices.add(mCarMediaService);
allServices.add(mCarLocationService);
allServices.add(mCarBugreportManagerService);
mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}
@MainThread
void init() {
mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL);
traceBegin("VehicleHal.init");
// 初始化 VehicleHal 对象,建立与 Hal 层的连接
mHal.init();
traceEnd();
traceBegin("CarService.initAllServices");
// 遍历 mAllServices 集合中所有的 CarService 子服务,调用 init() 初始化
for (CarServiceBase service : mAllServices) {
service.init();
}
traceEnd();
mSystemInterface.reconfigureSecondaryDisplays();
}
ICarImpl 的初始化函数中初始化了 Android Automotive 各个子服务,创建了各子服务对象。通过 VehicleHal 对象建立了各子服务与 Hal 层的连接。
将 CarPowerManagementService、CarUserService、CarTrustedDeviceService、SystemInterface、CarDrivingStateService、PerUserCarServiceHelper 服务添加到 CarLocalServices 集合中,便于获取。
将 Android Automotive 所有子服务保存在 List allServices 集合中。
ICarImpl 的 init() 函数中调用了 VehicleHal.init() 函数初始化 VehicleHal,并遍历 allServices 集合,调用所有子服务的 init() 函数以完成初始化。
3.2.2.6 VehicleHal
VehicleHal 是车辆 HAL 的抽象。这个类处理本地 HAL 接口,并对接收到的数据进行基本解析(类型检查)。然后将每个事件发送到相应的 HalServiceBase 实现。HalServiceBase 负责为 CarManager API 转换数据到相应的服务类中。
VehicleHal 的初始化中参数包含 IVehicle,IVehicle 是在 CarService.java 的 onCreate() 函数中通过 getVehicle() 得到的 Hal 层服务端代理对象。
public VehicleHal(Context context, IVehicle vehicle) {
// 创建 VehicleHal 的 Handler 线程
mHandlerThread = new HandlerThread("VEHICLE-HAL");
mHandlerThread.start();
// passing this should be safe as long as it is just kept and not used in constructor
// 初始化 PowerHalService Power Hal 对象
mPowerHal = new PowerHalService(this);
// 初始化 PropertyHalService Property Hal 对象
mPropertyHal = new PropertyHalService(this);
// 初始化 InputHalService Input Hal 对象
mInputHal = new InputHalService(this);
// 初始化 VmsHalService Vms Hal 对象
mVmsHal = new VmsHalService(context, this);
// 初始化 DiagnosticHalService Diagnostic Hal 对象
mDiagnosticHal = new DiagnosticHalService(this);
// 将 Hal 服务对象添加到 ArrayList<HalServiceBase> mAllServices 中保存
mAllServices.addAll(Arrays.asList(mPowerHal,
mInputHal,
mPropertyHal,
mDiagnosticHal,
mVmsHal));
// 创建 HalClient 对象
mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/);
}
public void init() {
Set<VehiclePropConfig> properties;
try {
properties = new HashSet<>(mHalClient.getAllPropConfigs());
} catch (RemoteException e) {
throw new RuntimeException("Unable to retrieve vehicle property configuration", e);
}
synchronized (this) {
// Create map of all properties
for (VehiclePropConfig p : properties) {
mAllProperties.put(p.prop, p);
}
}
// 遍历 mAllServices 集合,调用 Hal 服务的 init() 初始化函数
for (HalServiceBase service: mAllServices) {
Collection<VehiclePropConfig> taken = service.takeSupportedProperties(properties);
if (taken == null) {
continue;
}
if (DBG) {
Log.i(CarLog.TAG_HAL, "HalService " + service + " take properties " + taken.size());
}
synchronized (this) {
for (VehiclePropConfig p: taken) {
mPropertyHandlers.append(p.prop, service);
}
}
properties.removeAll(taken);
service.init();
}
}
4、CarPropertyService 示例
下面是 CarPropertyService 的调用流程时序图,从应用调用 CarPropertyManager 接口到 CarPropertyService 处理,调用到 Hal 层的逻辑。
下面的时序图中包括 setProperty() 方法、registerCallback() 方法和信号回调的流程:
5、总结
本篇文章分析了 Android Automotive 框架中 Framework 层服务的功能逻辑,从 CarService 服务介绍,启动流程以及服务功能流程等。
上一篇:AndroidAutomotive模块介绍(二)应用及接口介绍
下一篇:AndroidAutomotive模块介绍(四)VehicleHal介绍