4. CarService 核心机制

CarService 是 Android Automotive 中承载车辆相关系统能力的核心服务集合,它并不是一个单独的服务,而是由 CarServiceHelperService、CarService、CarPropertyService、CarPackageManagerService、CarUserService 等一组系统服务共同构成的体系。理解它的启动顺序、属性访问路径、权限校验方式以及多用户隔离机制,是进行车载系统服务定制与问题定位的基础。

一、启动流程:从 SystemServer 到 CarService 就绪

CarService 的启动分为两个阶段。第一阶段发生在 SystemServer 启动早期,CarServiceHelperService 作为系统服务被加入,它负责在系统就绪前建立与 CarService 进程的绑定关系。第二阶段由 init 根据 car_service.rc 拉起独立的 com.android.car 进程,在该进程内创建 ICarImpl,并依次初始化各子服务。

关键点在于:CarService 运行在独立进程中,SystemServer 通过 Binder 与其通信。因此启动时序上必须保证 CarService 先完成注册,SystemServer 中的车辆相关调用才不会阻塞或空指针。典型日志如下:

adb logcat | grep -E "CarServiceHelper|ICarImpl|CarPropertyService"
CarServiceHelperService: Starting CarService
ICarImpl: init: CarPropertyService
ICarImpl: init: CarUserService
CarServiceHelperService: CarService connected

如果出现 CarServiceHelperService: Timeout waiting for CarService,通常意味着 CarService 进程崩溃或初始化被阻塞,应优先检查 car_service 进程的 native crash 与 HAL 连接状态。

二、Car 属性服务:车辆信号的统一入口

CarPropertyService 是应用访问车辆信号的唯一正规通道。它把底层 VehicleHal 的 VehicleProperty 抽象为带区域(AreaId)、状态(Status)、时间戳(Timestamp)的属性值,并通过 CarPropertyManager 暴露给应用。

属性访问遵循“配置—订阅—回调”的模式。开发者需要先在 configs 中声明属性权限,再通过 getProperty 或 registerCallback 使用。属性 ID 由 VehiclePropertyIds 定义,例如车速、档位、空调温度等。

CarPropertyManager mgr = car.getCarManager(CarPropertyManager.class);
CarPropertyConfig<Float> cfg = mgr.getCarPropertyConfig(VehiclePropertyIds.PERF_VEHICLE_SPEED);
mgr.registerCallback(callback, VehiclePropertyIds.PERF_VEHICLE_SPEED,
        CarPropertyManager.SENSOR_RATE_ONCHANGE);

属性服务内部维护 PropertyHalService 与 VehicleHal 的订阅关系,只有被订阅的属性才会持续上报,未订阅属性读取时可能返回 STATUS_UNAVAILABLE。这是排查“读不到值”问题的第一检查点。

三、Car 权限模型:基于签名与角色的双重约束

CarService 的权限模型在 Android 标准权限之上增加了车辆专属约束。核心包括三类:

  • 签名权限:如 android.car.permission.CAR_POWERTRAIN,仅授予平台签名或特权应用。
  • 危险权限:如 CAR_SPEED,需要运行时动态申请。
  • 角色与驾驶状态约束:通过 CarUxRestrictions 限制驾驶中可用的 UI 与属性访问。

权限校验发生在 CarPropertyService 的 assertPermission 与 CarPackageManagerService 的 isActivityAllowed 中。若应用未声明对应权限,调用会抛出 SecurityException,日志中可见 Permission denied for property。

常见误区:把 CAR_POWERTRAIN 当作普通危险权限申请。它属于签名级权限,第三方应用无法通过运行时弹窗获得,必须由系统集成商在 privapp-permissions 中预置。

四、Car 用户管理与多用户支持

车载多用户与手机多用户的最大差异在于:车辆存在“驾驶员”与“乘客”的物理区分,且用户切换常与座椅、账号、驾驶位绑定。CarUserService 在 UserManager 之上增加了 CarUserManager,支持 USER_TYPE_DRIVER、USER_TYPE_PASSENGER 等类型,并允许为不同用户分配不同的显示区域(Display)与音频区域。

多用户下的关键机制包括:

  1. 用户创建时通过 CarUserService.createUser 指定用户类型与标志位。
  2. 用户切换时,CarService 会重新绑定该用户下的 CarPropertyService 订阅与 CarPackageManagerService 策略。
  3. 每个用户拥有独立的 CarPropertyManager 回调注册表,避免跨用户信号泄漏。

下表总结了 CarService 四大机制的核心职责与常见排障入口:

机制核心类关键职责排障入口
启动流程CarServiceHelperService / ICarImpl进程拉起与服务注册logcat 中 CarServiceHelper 超时
属性服务CarPropertyService车辆信号读写与订阅getCarPropertyConfig 返回 null
权限模型CarPropertyService / CarPackageManagerService签名、危险、驾驶状态校验SecurityException 与权限日志
多用户CarUserService用户类型、显示与音频隔离dumpsys car_service 用户段

五、案例与复盘:一次属性读取失败的分析

某项目反馈“空调温度读取始终为 0”。排查路径如下:首先确认 CarPropertyManager.getCarPropertyConfig 是否返回配置,结果返回 null,说明该属性未在 configs 中声明;补充 config.xml 后重启 CarService,配置出现但读取仍失败;进一步查看日志发现 Permission denied,原因是应用未申请 CONTROL_CAR_CLIMATE;补权限后读取成功。整个过程体现了“配置—权限—订阅”三层依赖,任何一层缺失都会表现为“读不到值”。

调试建议:使用 adb shell dumpsys car_service --services CarPropertyService 查看当前属性配置与订阅状态,比逐条打印日志更高效。
CarService 核心机制与数据流 SystemServer CarServiceHelperService CarService 进程 ICarImpl 初始化 VehicleHal VehicleProperty 信号 CarPropertyService 属性配置 / 订阅 / 回调 权限模型 签名 / 危险 / 驾驶状态 CarUserService 多用户 / 显示 / 音频隔离 应用层 CarPropertyManager / CarUserManager 配置与权限声明 config.xml / privapp-permissions 多用户运行态 Driver / Passenger 独立回调 关键排障路径 1. 配置缺失 → getCarPropertyConfig 返回 null 2. 权限缺失 → SecurityException / Permission denied 3. 未订阅 → 属性值不更新,STATUS_UNAVAILABLE

综合来看,CarService 的四大机制并非孤立:启动流程决定服务是否可用,属性服务决定信号能否读写,权限模型决定调用是否被允许,多用户机制决定不同座位与账号下的隔离边界。掌握这四者的依赖关系,才能在车载系统开发中快速定位“服务未起、属性无值、权限被拒、用户串扰”四类高频问题。