AndroidAutomotive模块介绍(三)CarService服务

前言

上一篇文档总结 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_POSint车门
ID_DOOR_MOVEint
ID_DOOR_LOCKbool
ID_MIRROR_Z_POSint后视镜
ID_MIRROR_Z_MOVEint
ID_MIRROR_Y_POSint
ID_MIRROR_Y_MOVEint
ID_MIRROR_LOCKbool
ID_MIRROR_FOLDbool
ID_SEAT_MEMORY_SELECTint座椅记忆
ID_SEAT_MEMORY_SETint
ID_SEAT_BELT_BUCKLEDbool安全带
ID_SEAT_BELT_HEIGHT_POSint
ID_SEAT_BELT_HEIGHT_MOVEint
ID_SEAT_FORE_AFT_POSint座椅前后位置
ID_SEAT_FORE_AFT_MOVEint
ID_SEAT_BACKREST_ANGLE_1_POSint座椅靠背
ID_SEAT_BACKREST_ANGLE_1_MOVEint
ID_SEAT_BACKREST_ANGLE_2_POSint
ID_SEAT_BACKREST_ANGLE_2_MOVEint
ID_SEAT_HEIGHT_POSint座椅高度
ID_SEAT_HEIGHT_MOVEint
ID_SEAT_DEPTH_POSint座椅深度
ID_SEAT_DEPTH_MOVEint
属性类型功能
ID_SEAT_TILT_POSint座椅倾角
ID_SEAT_TILT_MOVEint
ID_SEAT_LUMBAR_FORE_AFT_POSint腰托
ID_SEAT_LUMBAR_FORE_AFT_MOVEint
ID_SEAT_LUMBAR_SIDE_SUPPORT_POSint
ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVEint
ID_SEAT_HEADREST_HEIGHT_POSint头枕
ID_SEAT_HEADREST_HEIGHT_MOVEint
ID_SEAT_HEADREST_ANGLE_POSint
ID_SEAT_HEADREST_ANGLE_MOVEint
ID_SEAT_HEADREST_FORE_AFT_POSint
ID_SEAT_HEADREST_FORE_AFT_MOVEint
ID_WINDOW_POSint车窗
ID_WINDOW_MOVEint
ID_WINDOW_LOCKbool
  • CarHvacManager:Hvac 全称供暖通风与空气调节(Heating Ventilation and Air Conditioning),它是空调系统相关功能的服务,AAOS 定义了标准的 CarHvacManager API 来提供相关的功能,通过该服务可以实现对空调系统的监听和控制。注意 CarHvacManager 所涉及的属性都是需要有系统级别的权限,所以第三方应用目前是无法直接使用CarHvacManager的。属性列表如下:
属性类型功能
ID_MIRROR_DEFROSTER_ONbool后视镜除霜
ID_STEERING_WHEEL_HEATint方向盘加热
ID_OUTSIDE_AIR_TEMPfloat车外温度
ID_TEMPERATURE_DISPLAY_UNITSint温标(华氏度和摄氏度)
ID_ZONED_TEMP_SETPOINTfloat温度
ID_ZONED_TEMP_ACTUALfloat实际温度
ID_ZONED_HVAC_POWER_ONbool空调系统开关
ID_ZONED_FAN_SPEED_SETPOINTint风速
ID_ZONED_FAN_SPEED_RPMint风扇转速
ID_ZONED_FAN_DIRECTION_AVAILABLEvector可用风向
ID_ZONED_FAN_DIRECTIONint风向
ID_ZONED_SEAT_TEMPint座椅温度
ID_ZONED_AC_ONboolAC开关
ID_ZONED_AUTOMATIC_MODE_ONbool自动空调
ID_ZONED_AIR_RECIRCULATION_ONbool空调循环
ID_ZONED_MAX_AC_ONbool强力空调
ID_ZONED_DUAL_ZONE_ONbool多区域空调
ID_ZONED_MAX_DEFROST_ONbool强力除霜
ID_ZONED_HVAC_AUTO_RECIRC_ONbool自动空气循环
ID_WINDOW_DEFROSTER_ONbool车窗除霜
  • 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_ACTIVEABS状态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 服务端对象为 ICarImplServiceManager.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 propertiesfor (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介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/306907.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式强化学习

标题 易混淆概念联邦学习与强化学习1&#xff09;联邦学习应用于强化学习2&#xff09;强化学习应用于联邦学习 时空图卷积网络&#xff08;ST-GCN&#xff09;基本概念结合训练 易混淆概念 DistributionalRL是分布RL&#xff0c;不是分布式RL。分布RL是把Q值从一个期望构建成…

MySQL——创建和插入

一、插入数据 INSERT 使用建议; 在任何情况下建议列出列名&#xff0c;在 VALUES 中插入值时&#xff0c;注意值和列的意义对应关系 values 指定的值顺序非常重要&#xff0c;决定了值是否被保存到正确的列中 在指定了列名的情况下&#xff0c;你可以仅对需要插入的列给到…

【链表】1移除链表元素

这里写自定义目录标题 一、题目二、先考虑头结点&#xff0c;再考虑非头结点三、虚拟头结点解决 一、题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 二、先考虑头结点&#xff0c;…

Okhttp全链路监控

目标&#xff1a; 1&#xff09;.监控网络请求的各个阶段 2&#xff09;获取每一个阶段的耗时和性能&#xff0c;用于性能分析。包括dns解析&#xff0c;socket连接时间&#xff0c;tls连接时间&#xff0c;请求发送时间&#xff0c;服务器接口处理时间&#xff0c;应答传输时…

机器学习-09-图像处理02-PIL+numpy+OpenCV实践

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中图像处理技术。 参考 【人工智能】PythonOpenCV图像处理&#xff08;一篇全&#xff09; 一文讲解方向梯度直方图&#xff08;hog&#xff09; 【杂谈】计算机视觉在人脸图像领域的十几个大的应用方向&…

线性代数

标量、向量、张量 标量占据的是零维空间向量占据的是一维数据&#xff0c;例如语音信号矩阵占据的是二维数组&#xff0c;例如灰度图像张量占据的是三维乃至更高维的数组&#xff0c;例如RGB图像和视频 内积(点乘)概述 内积(inner product) 计算的则是两个向量之间的关系 两…

gpt系列概述——从gpt1到chatgpt

GPT建模实战&#xff1a;GPT建模与预测实战-CSDN博客 OpenAI的GPT&#xff08;Generative Pre-trained Transformer&#xff09;系列模型是自然语言处理领域的重要里程碑。从2018年至2020年&#xff0c;该公司相继推出了GPT-1、GPT-2和GPT-3&#xff0c;这些模型在文本生…

kali工具----枚举工具

一、枚举工具 枚举是一类程序&#xff0c;它允许用户从一个网络中收集某一类的所有相关信息。本节将介绍DNS枚举和SNMP枚举技术。DNS枚举可以收集本地所有DNS服务和相关条目。DNS枚举可以帮助用户收集目标组织的关键信息&#xff0c;如用户名、计算机名和IP地址等&#xff0c;…

前端js基础知识(八股文大全)

一、js的数据类型 值类型(基本类型)&#xff1a;数字(Number)、字符串&#xff08;String&#xff09;、布尔(Boolean)、对空&#xff08;Null&#xff09;、未定义&#xff08;Undefined&#xff09;、Symbol,大数值类型(BigInt) 引用数据类型&#xff1a;对象(Object)、数组…

智能售货机:引领便捷生活

智能售货机&#xff1a;引领便捷生活 在这个科技迅速进步的时代&#xff0c;便捷已成为生活的必需。智能售货机作为技术与便利完美结合的产物&#xff0c;正逐渐改变我们的购物方式&#xff0c;为都市生活增添新的活力。 智能售货机的主要优势是它的极致便利性。不论是在地铁…

javaweb day29

事务 写法 事务的四大特性

AndroidAutomotive模块介绍(四)VehicleHal介绍

前言 前面的文章中&#xff0c;描述了 Android Automotive 的框架中应用、Framework 层服务等知识&#xff0c;本篇文章将会继续按照 Android Automotive 框架介绍 Vehicle Hal 层服务的内容。 上一篇&#xff1a;AndroidAutomotive模块介绍&#xff08;三&#xff09;CarSer…

如何选择适用于Mac的文件恢复软件?适用于 Mac 的最佳数据恢复软件清单

有人会说&#xff0c;我们的数字生活正变得几乎和我们的物理生活一样重要。我们在线工作&#xff0c;将记忆保存在数码照片库中&#xff0c;在信使中交流&#xff0c;并保留各种文档的数字扫描。 每个人都知道备份是必不可少的。建议每天至少同步一个数字备份&#xff08;例如…

物联网实战--驱动篇之(八)磁编码器(AS5600)

目录 一、AS5600磁编码简介 二、AS5600使用 一、AS5600磁编码简介 AS5600是一款性价比极高的磁编码传感器&#xff0c;一般用于电机转动位置的记录&#xff0c;一般采用IIC通讯&#xff0c;也可以用模拟信号获取转动角度&#xff0c;具体资料在这里。AS5600-ASOM_&#xff08…

Argus DBM 一款开源的数据库监控工具,无需部署Agent

开箱即用 无需部署Agent&#xff0c;开箱即用。我们使用JDBC直连您的数据库&#xff0c;输入IP端口账户密码即可。 全平台支持 Argus目前支持对Mysql, PostgreSQL, Oracle等数据库类型的监控&#xff0c;我们也会尽快适配其它数据库&#xff0c;致力于监控所有数据库。我们提…

c++命令行解析开源库cxxopts上手教程

文章目录 cxxopts快速入门1. cmake环境配置2. 定义解析的规则3. 使用例子 cxxopts 简介 cxxopts是一个轻量级的C命令行解析库&#xff0c;它提供了易于使用的API来定义和解析命令行选项。它支持多种类型的选项&#xff0c;并且允许用户自定义选项的处理逻辑。 项目地址&#x…

【网安播报】GitHub上的恶意Visual Studio 项目推送 Keyzetsu 恶意软件

1、GitHub 上的恶意 Visual Studio 项目推送 Keyzetsu 恶意软件 威胁行为者正在滥用 GitHub 自动化功能和恶意 Visual Studio 项目来推送“Keyzetsu”恶意软件的新变种并窃取加密货币付款。攻击者创建了GitHub 存储库&#xff0c;并使用各种方法来人为地提高其在平台上的受欢迎…

Android广播之监听应用程序安装与卸载

&#x1f604;作者简介&#xff1a;小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c; 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想当开发的测试&#xff0c;不是一个好测…

小程序地理位置权限申请+uniapp调用uni.getLocation

文章目录 一、小程序地理位置权限申请二、uniapp调用uni.getLocation 一、小程序地理位置权限申请 需要确保小程序类目已经填写 点击左侧导航栏找到最后的“设置”——“基本设置”——“前往填写” 在开发管理——接口设置——地理位置中可以看到&#xff1a; 即可点击想要申…

LeetCode-Java:303、304区域检索(前缀和)

文章目录 题目303、区域和检索&#xff08;数组不可变&#xff09;304、二维区域和检索&#xff08;矩阵不可变&#xff09; 解①303&#xff0c;一维前缀和②304&#xff0c;二维前缀和 算法前缀和一维前缀和二维前缀和 题目 303、区域和检索&#xff08;数组不可变&#xff…