AAOS系列之(五) ---CarPowerService 电源管理模块分析
一文讲透AAOS架构,点到为止不藏私
📌 这篇帖子给大家分析下 CarPowerService 电源管理模块的内容
电源管理(Power Management)是 Android Automotive OS(AAOS)中的一个基础核心服务,主要负责管理与车辆电源状态相关的各类功能。它涵盖了车辆启动与熄火流程、屏幕休眠与唤醒、功放静音控制、超时熄火策略等关键逻辑。
该服务通常基于 CarPowerManagementService 实现,并与底层的车控 MCU 或 VCU 通信,确保系统行为与整车状态保持一致。例如,当车辆熄火或进入 ACC OFF 状态时,系统会触发一系列流程,如关闭屏幕、保存状态、延时关机等,从而保障用户体验与车载设备的安全运行。
关键类文件如下:
类名 | 描述 |
---|---|
android11.0\packages\services\Car\car-lib\src\android\car\hardware\power\CarPowerManager.java | APP调用的管理类 |
android11.0\packages\services\Car\car-lib\src\android\car\hardware\power\ICarPower.aidl | 跨进程定义 |
android11.0\packages\services\Car\service\src\com\android\car\CarPowerManagementService.java | 服务端实现 |
android11.0\packages\services\Car\service\src\com\android\car\hal\PowerHalService.java | HAL层控制类 |
CarPowerManager的UML图如下:
ICarPower.aidl的内容如下:
/** Copyright (C) 2018 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.car.hardware.power;import android.car.hardware.power.ICarPowerStateListener;/** @hide */
interface ICarPower {void registerListener(in ICarPowerStateListener listener) = 0;void unregisterListener(in ICarPowerStateListener listener) = 1;void requestShutdownOnNextSuspend() = 2;void finished(in ICarPowerStateListener listener) = 3;void scheduleNextWakeupTime(int seconds) = 4;void registerListenerWithCompletion(in ICarPowerStateListener listener) = 5;int getPowerState() = 6;void suspend() =7;void suspendOnTime(int seconds) =8;void shutdown() = 9;void shutdownOnTime(int seconds) = 10;void wakeup() = 11;void wakeupOnTime(int seconds) = 12;void cancelWakeup() = 13;void cancelSuspend() = 14;void cancelShutdown() = 15;
}
在这个aidl文件中, 在方法的后面都写了数字,也有些aidl文件中没有写这个数字,是什么区别呢?
1.带编号的形式
void registerListener(in ICarPowerStateListener listener) = 0;
这是 旧版 AIDL(Java AIDL)在生成 Binder stub 时的一种写法,早期版本的 AIDL 编译器生成 .java 文件时,方法在 onTransact() 中对应一个 transaction code,这个编号必须唯一且稳定,以支持多端通信时兼容性(尤其是系统服务)。
这些编号就是对应到:
static final int TRANSACTION_registerListener = 0;
编号的顺序直接影响底层 Binder 的 onTransact() 处理逻辑。
特点:
明确指定了每个方法的 transaction code更稳定,尤其是 AIDL 作为系统接口时常用于系统 AIDL,如 android.car.* 等
2.不带编号的形式
void registerListener(in ICarPowerStateListener listener);
这是 新版 AIDL 编译器(支持 Kotlin、Parcelable、NDK AIDL)引入的简化写法。不手动指定编号,让 AIDL 工具自动分配编号。
使用条件:
仅适用于新版本的 AIDL 编译器编译器会在后台自动分配稳定的 transaction 编号推荐用于应用级接口或 AIDL interface 比较稳定的场景
3. AIDL的实现端CarPowerManagementService.java
CarPowerManagementService 是 Android Automotive(AAOS)中负责车辆电源管理的核心服务。它实现了 ICarPower.aidl 接口,作为车载系统电源状态的控制中心,负责协调系统在不同电源状态下的行为,确保系统与车载硬件、电源状态、以及外部模块(如 MCU、车机控制器)之间保持一致。
主要的方法描述如下:
方法 | 描述 |
---|---|
registerListener() | 注册监听器接收电源状态回调 |
requestShutdownOnNextSuspend() | 在下一次挂起时执行关机 |
scheduleNextWakeupTime(int seconds) | 设置系统定时唤醒时间 |
suspend() / shutdown() / wakeup() | 控制系统进入挂起、关机、唤醒状态 |
getPowerState() | 查询当前电源状态 |
cancelSuspend() / cancelShutdown() / cancelWakeup() | 撤销对应的电源调度操作 |
4.PowerHalService实现了service和HAL层之间的交互:
在 Android Automotive(AAOS)架构中,PowerHalService 作为 系统服务层(如 CarPowerManagementService)与 HAL 层(Vehicle HAL)之间的中介,负责电源状态的通信与事件传递。其主要职责是:
1. 监听来自 HAL 的电源事件2. 将系统电源意图(如关机/挂起)发送给 HAL3. 提供统一的接口供上层服务调用和订阅电源状态
5. 场景分析:
当车辆的ACC信号通过CAN信号发送给车机,首先在MCU的CAN控制器接收到ACC模块发出的信号,MCU控制器经过串口发送给MPU,在Vehicle服务中把CAN信号解析成车辆的属性, 通过HalClient的回调对象, 把事件发送给Java端.
private static final class VehicleCallback extends IVehicleCallback.Stub {private final Handler mHandler;VehicleCallback(Handler handler) {mHandler = handler;}@Override// 从Vehicle的HIDL层接收属性变化事件.public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) {mHandler.sendMessage(Message.obtain(mHandler, CallbackHandler.MSG_ON_PROPERTY_EVENT, propValues));}
通过内部的Handler转发,来跟一下"MSG_ON_PROPERTY_EVENT"这个MSG 在哪里处理?
public void handleMessage(Message msg) {IVehicleCallback callback = mCallback.get();if (callback == null) {Log.i(TAG, "handleMessage null callback");return;}try {switch (msg.what) {case MSG_ON_PROPERTY_EVENT:// 调用callback的onPropertyEvent,这个callback是什么呢?callback.onPropertyEvent((ArrayList<VehiclePropValue>) msg.obj);break;case MSG_ON_PROPERTY_SET:callback.onPropertySet((VehiclePropValue) msg.obj);break;case MSG_ON_SET_ERROR:PropertySetError obj = (PropertySetError) msg.obj;callback.onPropertySetError(obj.errorCode, obj.propId, obj.areaId);break;default:
通过跟踪代码来看, callback的类型定义如下:
private static final class CallbackHandler extends Handler {CallbackHandler(Looper looper, IVehicleCallback callback) {super(looper);mCallback = new WeakReference<IVehicleCallback>(callback);}public void handleMessage(Message msg) {IVehicleCallback callback = mCallback.get();
public class VehicleHal extends IVehicleCallback.Stub {@Overridepublic void onPropertyEvent(ArrayList<VehiclePropValue> propValues) {synchronized (mLock) {for (VehiclePropValue v : propValues) {for (HalServiceBase service : serviceList) {service.getDispatchList().add(v);mServicesToDispatch.add(service);}}for (HalServiceBase s : mServicesToDispatch) {// 遍历所有的HalServiceBase, 其中就包含了PowerHalServices.onHalEvents(s.getDispatchList());s.getDispatchList().clear();}
}
调用PowerHalService的onHalEvents:
@Overridepublic void onHalEvents(List<VehiclePropValue> values) {...dispatchEvents(values, listener);}
private void dispatchEvents(List<VehiclePropValue> values, PowerEventListener listener) {
for (VehiclePropValue v : values) {switch (v.prop) {case AP_POWER_STATE_REPORT:// Ignore this property event. It was generated inside of CarService.break;case AP_POWER_STATE_REQ:int state = v.value.int32Values.get(VehicleApPowerStateReqIndex.STATE);int param = v.value.int32Values.get(VehicleApPowerStateReqIndex.ADDITIONAL);Log.i(CarLog.TAG_POWER, "Received AP_POWER_STATE_REQ="+ powerStateReqName(state) + " param=" + param);listener.onApPowerStateChange(new PowerState(state, param));break;case SYSTEM_ACC_STATUS:int accStatus = v.value.int32Values.get(0);Log.i(CarLog.TAG_POWER, "accStatus " + accStatus);// 当车机的ACC状态发生变化, 回调给listener,这个listener的类型是啥呢?listener.onAccStateChange(accStatus);break;}
调用 PowerEventListener的onAccStateChange
@android11.0\packages\services\Car\service\src\com\android\car\CarPowerManagementService.java
@Overridepublic void onAccStateChange(int state) {Slog.i(CarLog.TAG_POWER, "onAccStateChange state= " + state);if (state == 0) {// 调用hal层的睡眠mHal.sleepStart();} else {// 调用hal层的退出睡眠.mHal.sleepExit();}
到此为止,就实现了车机的ACC状态变化传递给AAOS 中CarService的全流程. 在HalClient中,获取了各个HIDL服务的客户端, 把具体的控制指令通过HIDL的调用, 发送给各个底层的模块去控制设备节点.