前言

上一篇文档总结 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。如下图所示:

android auto没法用_应用程序

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系统的关机流程。

简要流程如下所示:

android auto没法用_应用程序_02

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 auto没法用_android auto没法用_03

Android 管理来自 Android 应用的声音,同时控制这些应用,并根据其声音类型将声音路由到 HAL 中的输出设备:

  • 逻辑声音流:在核心音频命名法中称为“声源”,使用音频属性进行标记。
  • 物理声音流:在核心音频命名法中称为“设备”,在混音后没有上下文信息。

为了确保可靠性,外部声音(来自独立声源,例如安全带警告铃声)在 Android 外部(HAL 下方,甚至是在单独的硬件中)进行管理。系统实现者必须提供一个混音器,用于接受来自 Android 的一个或多个声音输入流,然后以合适的方式将这些声音流与车辆所需的外部声源组合起来。

HAL 实现和外部混音器负责确保对保障安全至关重要的外部声音能够被用户听到,而且负责在 Android 提供的声音流中进行混音,并将混音结果路由到合适的音响设备。

CarAudio 类图如下所示:

android auto没法用_Android_04

CarAudio 流程图如下所示:

android auto没法用_应用程序_05

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 启动流程时序图

android auto没法用_Android_06

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() 方法和信号回调的流程:

android auto没法用_java_07

5、总结

本篇文章分析了 Android Automotive 框架中 Framework 层服务的功能逻辑,从 CarService 服务介绍,启动流程以及服务功能流程等。