AndroidAutomotive模块介绍(三)CarService服务

news2024/11/27 19:41:11

前言

上一篇文档总结 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 服务端对象为 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介绍

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4. Django 探究FBV视图

4. 探究FBV视图 视图(Views)是Django的MTV架构模式的V部分, 主要负责处理用户请求和生成相应的响应内容, 然后在页面或其他类型文档中显示. 也可以理解为视图是MVC架构里面的C部分(控制器), 主要处理功能和业务上的逻辑. 我们习惯使用视图函数处理HTTP请求, 即在视图里定义def…

一、flask入门和视图

run启动参数 模板渲染 后端给前端页面传参 前端页面设置css from flask import Flask, render_template,jsonify# 创建flask对象 app Flask(__name__)# 视图函数 路由route app.route("/") def hello_world():# 响应&#xff0c;返回给前端的数据return "h…

将数学表达式对分子分母先因式分解再约分化简simplify()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将数学表达式 对分子分母 先因式分解 再约分化简 simplify() [太阳]选择题 请问以下输出结果正确的是&#xff1a; from sympy import simplify from sympy.abc import x, y A (x**2 2*x 1)…

第07-2章 TCP/IP模型

7.7 TCP/IP模型详解 7.7.1 简介 应用层的PDU>APDU&#xff08;Application PDU&#xff09; 表示层的PDU>PPDU&#xff08;Presentation PDU&#xff09; 会话层的PDU>SPDU&#xff08;Session PDU&#xff09; 7.7.2 TCP/IP协议体系 &#xff08;1&#xff09;TCP…

【尝试】域名验证:配置github二级目录下的txt文件

【尝试】域名验证&#xff1a;配置github二级目录下的txt文件 写在最前面一、初始化本地仓库二、设置远程仓库1. 远程仓库 URL 没有设置或设置错误添加远程仓库修改远程仓库 2. 访问权限问题3. 仓库不存在步骤 1: 在你的仓库中添加文件步骤 2: 确认GitHub Pages设置步骤 3: 访问…

原型模式:复制对象的智能解决方案

在软件开发过程中&#xff0c;对象的创建可能是一个昂贵的操作&#xff0c;特别是当对象的初始化包括从数据库加载数据、进行IO操作或进行复杂计算时。原型模式是一种创建型设计模式&#xff0c;它通过复制现有的实例来创建新的对象实例&#xff0c;从而避免了类初始化时的高成…

高校实习管理系统的设计与实现(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统高校实习管理系统信息管理难度大&#xff0c;容错率低&am…

llama-factory SFT系列教程 (三),chatglm3-6B 命名实体识别实战

背景 llama-factory SFT系列教程 (一)&#xff0c;大模型 API 部署与使用llama-factory SFT系列教程 (二)&#xff0c;大模型在自定义数据集 lora 训练与部署本文为llama-factory SFT系列教程 第三篇 简介 利用 llama-factory 框架&#xff0c;基于 chatglm3-6B 模型 做命名…

Linux内核之自旋锁:自旋锁初始化之spin_lock_init用法实例(四十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

23、链表-反转链表

思路: 第一种方式还是集合方式&#xff0c;用数组装一下&#xff0c;然后从未到头遍历组装就行 第二种方式&#xff1a; 首先构建一个prenull开始遍历 获取nexthead.nexthead.nextpre,将head节点的next指针指向pre&#xff0c;前驱节点pre来到head位置 prehead&#xff1b;…

MySQL索引、B+树相关知识汇总

MySQL索引、B树相关知识汇总 一、有一个查询需求&#xff0c;MySQL中有两个表&#xff0c;一个表1000W数据&#xff0c;另一个表只有几千数据&#xff0c;要做一个关联查询&#xff0c;如何优化&#xff1f;1、为关联字段建立索引二、小表驱动大表 二、b树和b树的区别1、更高的…

一起学习python——基础篇(17)

今天我说一下python中有关文件的操作。 1、检测一个目录里面有无这个文件夹、有无txt文件&#xff0c;代码如下&#xff1a; import os #文件的路径 testPath"D:/pythonFile" testPath2"D:/pythonFile/test.txt" #使用exists()方法检查是否存在文件…

【刷题】图论——最小生成树:Prim、Kruskal【模板】

假设有n个点m条边。 Prim适用于邻接矩阵存的稠密图&#xff0c;时间复杂度是 O ( n 2 ) O(n^2) O(n2)&#xff0c;可用堆优化成 O ( n l o g n ) O(nlogn) O(nlogn)。 Kruskal适用于稀疏图&#xff0c;n个点m条边&#xff0c;时间复杂度是 m l o g ( m ) mlog(m) mlog(m)。 Pr…

要申请开通融资融券账户,有那些条件?

1、什么是融资融券交易? 融资融券交易&#xff0c;又称信用交易&#xff0c;是指投资者向具有融资融券业务资格的证券公司提供担 保物&#xff0c;借入资金买入交易所上市证券&#xff08;融资交易&#xff09;或借入交易所上市证券并卖出&#xff08;融券交易&#xff09; 的…

古月·ROS2入门21讲——学习笔记

第一讲&#xff1a;ROS/ROS2是什么 1. ROS的诞生 对于越来越复杂的智能机器人系统&#xff0c;已经不是一个人或者一个团队可以独立完成的&#xff0c;如何高效开发机器人&#xff0c;是技术层面上非常重要的一个问题&#xff0c;针对这个问题&#xff0c;一群斯坦福大学的有…

根据后端获取到的文档流,下载打开显示“无法打开文件”

原代码&#xff1a; download(item) {this.axios.get(api.download/item.name).then(res > {// console.log(res)let bob new Blob([res.data],{type: application/vnd.ms-excel})const link document.createElement(a);let url window.URL.createObjectURL(bob);link.d…

【JAVA基础篇教学】第四篇:Java条件语句

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第四篇&#xff1a; Java条件语句。 在Java中&#xff0c;条件语句用于根据不同的条件执行不同的代码块。Java提供了if、else if和else等关键字来实现条件判断。 一、if语句 if语句用于执行一个代码块&#xff0c;如果给…

牛客周赛 Round 39(A,B,C,D,E,F,G)

比赛链接 官方题解&#xff08;视频&#xff09; B题是个贪心。CD用同余最短路&#xff0c;预处理的完全背包&#xff0c;多重背包都能做&#xff0c;比较典型。E是个诈骗&#xff0c;暴力就完事了。F是个线段树。G是个分类大讨论&#xff0c;出题人钦定的本年度最佳最粪 题目…

Unity之PUN实现多人联机射击游戏的优化(Section 3)

目录 &#x1f4a3;一、准备工作 &#x1f4a3;二、生成弹头脚本的编写 &#x1f4a3;三、实现发射和伤害同步 手雷都加了在给狗剩加个火箭筒不过分吧。效果看GIF动图&#xff0c;分别是单机和联机的效果。 添加火箭筒依旧是在原有的基础上更改&#xff0c;我查看火箭筒模型…

性能测试-数据库优化二(SQL的优化、数据库拆表、分表分区,读写分离、redis)

数据库优化 explain select 重点&#xff1a; type类型&#xff0c;rows行数&#xff0c;extra SQL的优化 在写on语句时&#xff0c;将数据量小的表放左边&#xff0c;大表写右边where后面的条件尽可能用索引字段&#xff0c;复合索引时&#xff0c;最好按复合索引顺序写wh…