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)与音频区域。
多用户下的关键机制包括:
- 用户创建时通过
CarUserService.createUser指定用户类型与标志位。 - 用户切换时,CarService 会重新绑定该用户下的
CarPropertyService订阅与CarPackageManagerService策略。 - 每个用户拥有独立的
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 的四大机制并非孤立:启动流程决定服务是否可用,属性服务决定信号能否读写,权限模型决定调用是否被允许,多用户机制决定不同座位与账号下的隔离边界。掌握这四者的依赖关系,才能在车载系统开发中快速定位“服务未起、属性无值、权限被拒、用户串扰”四类高频问题。