AAOS 电源管理深度解析:休眠/唤醒/功耗优化
AAOS 电源管理深度解析:休眠/唤醒/功耗优化
一、引言
车载操作系统(AAOS)的电源管理与手机有着本质区别。手机只需要考虑单用户手持场景,而 AAOS 要同时面对:熄火断电、驻车娱乐、倒车影像、远程控车、OTA 升级等多复杂场景。一旦休眠时序出错,可能导致黑屏死机、蓝牙断连甚至无法点火。
本文基于 Android 14(android-14-dev 分支),从 AOSP 源码出发,深入分析 AAOS 电源管理的三大核心模块:
- CarPowerManagementService —— 电源状态机(
packages/services/Car/service/src/com/android/car/power/) - CarPowerPolicyDaemon —— 电源策略引擎(
frameworks/hardware/interfaces/automotive/powerpolicy/) - CarPowerManager —— 应用层 API(
car-lib/src/android/car/hardware/power/)
我们会追踪关键代码路径,并结合 diagram 帮助你建立起完整的电源管理知识体系。
二、整体架构
下图展示了 AAOS 电源管理系统的分层架构:
核心组件职责
| 组件 | 语言 | 位置 | 职责 |
|---|---|---|---|
CarPowerManager |
Java | car-lib/.../power/ |
应用层 API,提供状态变更回调 |
CarPowerManagementService |
Java | service/.../car/power/ |
电源状态机引擎,驱动状态流转 |
PowerComponentHandler |
Java | service/.../car/power/ |
电源组件(Audio/Display/WiFi/Bluetooth 等)状态跟踪 |
ScreenOffHandler |
Java | service/.../car/power/ |
息屏判定与 Display 电源下电时序 |
PolicyReader |
Java | service/.../car/power/ |
解析 power_policy.xml 策略配置 |
carPowerPolicyDaemon |
C++ | cpp/powerpolicy/ |
Native 策略守护进程,单一事实来源 |
ICarPowerPolicyServer.aidl |
AIDL | frameworks/hardware/interfaces/.../powerpolicy/ |
策略 daemon 的 AIDL 接口 |
三、电源状态机(CarPowerManagementService)
3.1 核心状态定义
CarPowerManagementService 的包路径为 com.android.car.power,通过内部类 CpmsState 定义电源状态:
// packages/services/Car/service/src/com/android/car/power/CarPowerManagementService.java
package com.android.car.power;
public class CarPowerManagementService extends ICarPower.Stub implements
CarServiceBase, PowerHalService.PowerEventListener {
// CpmsState 内部类,同时持有 AP 状态和 listener 状态
private static class CpmsState {
// AP 电源状态
static final int WAIT_FOR_VHAL = 0;
static final int ON = 1;
static final int SHUTDOWN_PREPARE = 2;
static final int WAIT_FOR_FINISH = 3;
static final int SUSPEND = 4;
static final int GARAGE_MODE_SHUTDOWN_PREPARE = 5;
static final int SHUTDOWN_POSTPONE = 6;
static final int SIMULATE_ERROR_STATE = 7;
static final int SHUTDOWN_IMMEDIATELY = 8;
public final int mState;
public final int mCarPowerStateListenerState;
CpmsState(int state, int listenerState) {
mState = state;
mCarPowerStateListenerState = listenerState;
}
}
}
3.2 状态流转图
3.3 PowerHandler 驱动的状态变换
与传统的 switch-case 状态机不同,AAOS 采用 Handler + 消息队列 的异步驱动模式。PowerHandler 是 CarPowerManagementService 的内部 Handler,负责串行处理所有电源状态变更:
// 初始化
public void init() {
synchronized (mLock) {
mHandlerThread = new HandlerThread(CarLog.TAG_POWER);
mHandlerThread.start();
mHandler = new PowerHandler(mHandlerThread.getLooper());
}
mHal.setListener(this);
if (mHal.isPowerStateSupported()) {
// 初始状态:等待 VHAL 注册
// CpmsState(内部状态, listener状态)
onApPowerStateChange(new CpmsState(CpmsState.WAIT_FOR_VHAL,
CarPowerManager.STATE_WAIT_FOR_VHAL));
} else {
onApPowerStateChange(new CpmsState(CpmsState.ON,
CarPowerManager.STATE_ON));
}
mSystemInterface.startDisplayStateMonitoring(this);
}
当 VHAL 通知电源事件时,onApPowerStateChange 被调用:
@Override
public void onApPowerStateChange(PowerState state) {
PowerHandler handler;
synchronized (CarPowerManagementService.this) {
mPendingPowerStates.addFirst(new CpmsState(state));
handler = mHandler;
}
handler.handlePowerStateChange();
}
核心处理逻辑在 doHandlePowerStateChange() 中:
private void doHandlePowerStateChange() {
CpmsState state;
synchronized (CarPowerManagementService.this) {
state = mPendingPowerStates.peekFirst();
mPendingPowerStates.clear();
if (state == null) return;
if (!needPowerStateChangeLocked(state)) return;
releaseTimerLocked();
}
Log.i(TAG, "setCurrentState " + state.toString());
mCurrentState = state;
switch (state.mState) {
case CpmsState.WAIT_FOR_VHAL:
handleWaitForVhal(state);
break;
case CpmsState.ON:
handleOn(state);
break;
case CpmsState.SHUTDOWN_PREPARE:
handleShutdownPrepare(state);
break;
// ... 其他状态
}
}
3.4 Suspend 主流程源码追踪
当 VMCU 检测到驾驶员熄火,通过 VHAL 触发 sleep 流程:
应用层通过 CarPowerManager 注册监听器。Android 14 在 car-lib/src/android/car/hardware/power/CarPowerManager.java 中定义了带 STATE_ 前缀的电源状态常量,应用收到的是 public API 层的状态值,而非 CPMS 内部的 CpmsState:
// car-lib/src/android/car/hardware/power/CarPowerManager.java
package android.car.hardware.power;
public class CarPowerManager extends CarManagerBase {
// 电源状态常量(与 native 层 CarPowerManager.h 保持一致)
@SystemApi
public static final int STATE_INVALID = 0;
public static final int STATE_WAIT_FOR_VHAL = 1;
public static final int STATE_SUSPEND_ENTER = 2;
public static final int STATE_SUSPEND_EXIT = 3;
public static final int STATE_SHUTDOWN_ENTER = 5;
public static final int STATE_ON = 6;
public static final int STATE_SHUTDOWN_PREPARE = 7;
public static final int STATE_SHUTDOWN_CANCELLED = 8;
public static final int STATE_HIBERNATION_ENTER = 9;
public static final int STATE_HIBERNATION_EXIT = 10;
public static final int STATE_PRE_SHUTDOWN_PREPARE = 11;
public static final int STATE_POST_SUSPEND_ENTER = 12;
public static final int STATE_POST_SHUTDOWN_ENTER = 13;
public static final int STATE_POST_HIBERNATION_ENTER = 14;
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "STATE_", value = {
STATE_INVALID, STATE_WAIT_FOR_VHAL,
STATE_SUSPEND_ENTER, STATE_SUSPEND_EXIT,
STATE_SHUTDOWN_ENTER, STATE_ON,
STATE_SHUTDOWN_PREPARE, STATE_SHUTDOWN_CANCELLED,
STATE_HIBERNATION_ENTER, STATE_HIBERNATION_EXIT,
STATE_PRE_SHUTDOWN_PREPARE,
STATE_POST_SUSPEND_ENTER,
STATE_POST_SHUTDOWN_ENTER,
STATE_POST_HIBERNATION_ENTER,
})
public @interface CarPowerState {}
// 基础监听器(同步返回)
@SystemApi
public interface CarPowerStateListener {
void onStateChanged(@CarPowerState int state);
}
// 带异步完成回调的监听器(需调用 future.complete())
@SystemApi
public interface CarPowerStateListenerWithCompletion {
void onStateChanged(@CarPowerState int state,
@NonNull CompletablePowerStateChangeFuture future);
}
@RequiresPermission(Car.PERMISSION_CAR_POWER)
public void requestShutdownOnNextSuspend() {
try {
mService.requestShutdownOnNextSuspend();
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
}
}
}
注意:STATE_SHUTDOWN_PREPARE(值 7)对应 CPMS 内部的 SHUTDOWN_PREPARE;STATE_SUSPEND_ENTER(值 2)是通知应用准备 suspend 的 public API 状态。两者数值不同,CPMS 在 CpmsState 构造时同时记录 mState(CPMS 内部状态)和 mListenerState(通知给 listener 的状态),通过 PowerHandler 在通知时完成翻译。
四、电源策略引擎(Power Policy)
4.1 PowerComponent 体系
PowerComponent.aidl 定义了所有可独立控制的电源组件,位于 frameworks/hardware/interfaces/automotive/powerpolicy/aidl/:
// frameworks/hardware/interfaces/automotive/powerpolicy/aidl/
// android/frameworks/automotive/powerpolicy/PowerComponent.aidl
package android.frameworks.automotive.powerpolicy;
@Backing(type="byte")
enum PowerComponent {
INVALID,
AUDIO,
MEDIA,
DISPLAY,
BLUETOOTH,
WIFI,
CELLULAR,
ETHERNET,
PROJECTION,
NFC,
INPUT,
VISUAL_INTERACTION,
VOICE_INTERACTION,
TRUSTED_DEVICE_DETECTION,
LOCATION,
MICROPHONE,
CPU,
}
4.2 PowerPolicy 定义与 XML 配置
OEM 在 /vendor/etc/automotive/power_policy.xml 中定义电源策略:
<!-- /vendor/etc/automotive/power_policy.xml -->
<power_policy_group>
<!-- 预占策略:高优先级,覆盖当前策略 -->
<power_policy id="emergency_call" pre_emptive="true">
<component type="AUDIO" state="ON"/>
<component type="DISPLAY" state="ON"/>
<component type="VOICE_INTERACTION" state="ON"/>
</power_policy>
<!-- 普通休眠策略 -->
<power_policy id="sleep">
<component type="AUDIO" state="OFF"/>
<component type="DISPLAY" state="OFF"/>
<component type="MEDIA" state="OFF"/>
</power_policy>
<!-- Garage Mode 策略 -->
<power_policy id="garage_mode">
<component type="AUDIO" state="OFF"/>
<component type="DISPLAY" state="OFF"/>
<component type="MEDIA" state="OFF"/>
</power_policy>
</power_policy_group>
PolicyReader.java 的具体解析逻辑:
// packages/services/Car/service/src/com/android/car/power/PolicyReader.java
package com.android.car.power;
class PolicyReader {
private final Map<String, PowerPolicy> mPolicies = new ArrayMap<>();
public void parsePowerPolicies(@NonNull XmlResourceParser parser) {
// 解析 <power_policy id="..." pre_emptive="true|false">
// 内部的 <component type="..." state="..."/>
// 构建策略映射表,供 PowerComponentHandler 使用
}
}
4.3 ICarPowerPolicyServer 接口
Native 策略 daemon 通过 ICarPowerPolicyServer.aidl 暴露服务,路径在 frameworks/hardware/interfaces/:
// frameworks/hardware/interfaces/automotive/powerpolicy/aidl/
// android/frameworks/automotive/powerpolicy/ICarPowerPolicyServer.aidl
package android.frameworks.automotive.powerpolicy;
@VintfStability
interface ICarPowerPolicyServer {
CarPowerPolicy getCurrentPowerPolicy();
boolean getPowerComponentState(in PowerComponent componentId);
void registerPowerPolicyChangeCallback(
in ICarPowerPolicyChangeCallback callback,
in CarPowerPolicyFilter filter);
void unregisterPowerPolicyChangeCallback(
in ICarPowerPolicyChangeCallback callback);
void applyPowerPolicy(in @utf8InCpp String policyId);
void setPowerPolicyGroup(in @utf8InCpp String policyGroupId);
}
CarPowerPolicy 的 Java 层封装:
// car-lib/src/android/car/hardware/power/CarPowerPolicy.java
public final class CarPowerPolicy implements Parcelable {
public String getPolicyId() { /* 返回策略 ID */ }
public int[] getEnabledComponents() { /* 返回开启的组件列表 */ }
public int[] getDisabledComponents() { /* 返回关闭的组件列表 */ }
public boolean isComponentEnabled(int component) { /* 检查组件状态 */ }
}
五、PowerComponentHandler + ScreenOffHandler
5.1 PowerComponentHandler:组件状态跟踪与 Mediator 模式
PowerComponentHandler 在 Android 14 中采用 Mediator 模式 管理各电源组件的开关状态。它持有 SparseBooleanArray mComponentStates 记录每个组件的使能状态,并为特定组件注册 PowerComponentMediator 来处理用户可控制组件的策略冲突:
// packages/services/Car/service/src/com/android/car/power/PowerComponentHandler.java
package com.android.car.power;
import android.car.hardware.power.CarPowerPolicy;
import android.car.hardware.power.CarPowerPolicyFilter;
import android.car.hardware.power.PowerComponent;
import static android.car.hardware.power.PowerComponentUtil.*;
class PowerComponentHandler {
// 组件当前状态(true=使能,false=关闭)
private final SparseBooleanArray mComponentStates = new SparseBooleanArray();
// 被电源策略关闭的组件(key=component, value=true)
private final SparseBooleanArray mComponentsOffByPolicy = new SparseBooleanArray();
// Mediator 映射表 — 处理用户可控制组件的策略仲裁
private final SparseArray<PowerComponentMediator> mPowerComponentMediators =
new SparseArray<>();
// 上一次策略变更中被修改的组件列表
private final ArrayList<Integer> mLastModifiedComponents = new ArrayList<>();
PowerComponentHandler(Context context, SystemInterface systemInterface) { /* ... */ }
/** 根据 CarPowerPolicy 一次性更新多个组件状态 */
void applyPowerPolicy(CarPowerPolicy policy) {
synchronized (mLock) {
mLastModifiedComponents.clear();
int[] enabled = policy.getEnabledComponents();
int[] disabled = policy.getDisabledComponents();
for (int component : enabled) {
if (!mComponentStates.get(component, false)) {
setComponentEnabledLocked(component, true);
mLastModifiedComponents.add(component);
}
}
for (int component : disabled) {
if (mComponentStates.get(component, false)) {
setComponentEnabledLocked(component, false);
mLastModifiedComponents.add(component);
}
}
}
}
/** 修改单个组件状态(Mediator 会介入用户可控组件) */
@GuardedBy("mLock")
private boolean setComponentEnabledLocked(int component, boolean enabled) {
int componentIndex = mComponentStates.indexOfKey(component);
boolean oldState = mComponentStates.get(component, false);
if (oldState == enabled && componentIndex >= 0) return false;
mComponentStates.put(component, enabled);
PowerComponentMediator mediator = mPowerComponentMediators.get(component);
if (mediator == null) return true;
if (mediator.isUserControllable()) {
if (!enabled && mediator.isUserEnabled()) {
mediator.disableByPolicy(); // 策略覆盖用户设置
} else if (enabled && mediator.isDisabledByPolicy()) {
mediator.restoreUserSetting(); // 恢复用户偏好
}
}
return true;
}
boolean isComponentEnabled(int component) {
return mComponentStates.get(component, false);
}
}
PowerComponentMediator 负责仲裁"策略要求关 vs 用户想开"的冲突,保障紧急电话等高优先级场景不被用户设置阻断。
5.2 ScreenOffHandler:多 Display 息屏管理
Android 14 的车机支持多屏(仪表盘、中控、后排娱乐),ScreenOffHandler 按 DisplayPowerMode 管理每个 Display 的电源模式。四种模式定义在内部注解 @DisplayPowerMode:
| 模式 | 常量 | 行为 |
|---|---|---|
| NONE | DISPLAY_POWER_MODE_NONE |
未初始化 |
| OFF | DISPLAY_POWER_MODE_OFF |
息屏,超时后关闭 |
| ON | DISPLAY_POWER_MODE_ON |
亮屏,用户注销后超时息屏 |
| ALWAYS_ON | DISPLAY_POWER_MODE_ALWAYS_ON |
常亮,用户可手动关闭 |
使用 DisplayPowerInfo 内部类为每块屏幕维护独立状态:
// packages/services/Car/service/src/com/android/car/power/ScreenOffHandler.java
package com.android.car.power;
class ScreenOffHandler {
@VisibleForTesting
static final int DISPLAY_POWER_MODE_NONE = -1;
@VisibleForTesting
static final int DISPLAY_POWER_MODE_OFF = 0;
@VisibleForTesting
static final int DISPLAY_POWER_MODE_ON = 1;
@VisibleForTesting
static final int DISPLAY_POWER_MODE_ALWAYS_ON = 2;
@IntDef(prefix = "DISPLAY_POWER_MODE_", value = {
DISPLAY_POWER_MODE_NONE,
DISPLAY_POWER_MODE_OFF,
DISPLAY_POWER_MODE_ON,
DISPLAY_POWER_MODE_ALWAYS_ON,
})
private @interface DisplayPowerMode {}
// 每块 Display 的状态跟踪
private static final class DisplayPowerInfo {
private final int mDisplayId;
private int mUserId;
private @DisplayPowerMode int mMode;
private boolean mIsDriverDisplay;
private long mLastUserActivityTime;
// ...
}
private final Context mContext;
private final SystemInterface mSystemInterface;
private final Handler mHandler;
private final SparseArray<DisplayPowerInfo> mDisplayPowerInfos = new SparseArray<>();
private final DisplayManager mDisplayManager;
ScreenOffHandler(Context context, SystemInterface systemInterface, Looper looper) {
mContext = context;
mSystemInterface = systemInterface;
mHandler = new Handler(looper);
mDisplayManager = context.getSystemService(DisplayManager.class);
// 为每个 Display 创建 DisplayPowerInfo
DisplayHelper.forEachDisplay(mDisplayManager, (displayId) -> {
mDisplayPowerInfos.put(displayId,
new DisplayPowerInfo(displayId));
});
}
/** 设置指定 Display 的电源模式 */
void setDisplayMode(int displayId, @DisplayPowerMode int mode) {
DisplayPowerInfo info = mDisplayPowerInfos.get(displayId);
if (info == null) return;
info.setMode(mode);
scheduleDisplayStateUpdate(displayId);
}
/** 用户交互时刷新息屏定时器 */
void onUserActivity(int displayId) {
DisplayPowerInfo info = mDisplayPowerInfos.get(displayId);
if (info == null) return;
info.setLastUserActivityTime(SystemClock.elapsedRealtime());
scheduleDisplayStateUpdate(displayId);
}
private void scheduleDisplayStateUpdate(int displayId) {
mHandler.removeMessages(MSG_UPDATE_DISPLAY_STATE, displayId);
mHandler.sendMessageDelayed(
mHandler.obtainMessage(MSG_UPDATE_DISPLAY_STATE, displayId, 0),
getScreenOffDelayMs(displayId));
}
}
六、休眠模式详解
6.1 Suspend-to-RAM(S3 / STR)
CPMS 通过 SystemInterface 执行最终的 suspend 调用。SystemInterface 定义了三个 suspend 结果常量,用于处理 suspend 成功、需要重试、或者中止的情况:
// com.android.car.systeminterface.SystemInterface
import static com.android.car.systeminterface.SystemInterface.SUSPEND_RESULT_ABORT;
import static com.android.car.systeminterface.SystemInterface.SUSPEND_RESULT_RETRY;
import static com.android.car.systeminterface.SystemInterface.SUSPEND_RESULT_SUCCESS;
// 在 CPMS 中处理 suspend 结果:
// mSystemInterface 负责与 BSP/kernel 交互
// 如果 suspend 失败(SUSPEND_RESULT_RETRY),CPMS 会以指数退避重试
// 初始间隔 INITIAL_SUSPEND_RETRY_INTERVAL_MS = 10ms
// 最大间隔 MAX_RETRY_INTERVAL_MS = 100ms
底层通过写入 /sys/power/state 实现。从 source.android.com 官方文档确认:
# 挂起到 RAM
echo mem > /sys/power/state
# 挂起到磁盘(hibernate)
echo disk > /sys/power/state
CPMS 在 Suspend-to-RAM 前会先等待组件就绪,并启动 MIN_SUSPEND_WAIT_DURATION_MS ~ MAX_SUSPEND_WAIT_DURATION_MS(最大 3 分钟)的超时定时器。如果所有组件确认就绪,CPMS 通知 VMCU AP 已休眠,VMCU 切断 SoC 主电源。
6.2 唤醒源管理
| 唤醒源 | 优先级 | 典型场景 |
|---|---|---|
| CAN Bus 消息 | 高 | 开门、点火、远程控车 |
| GPIO 中断 | 高 | 物理按键 |
| USB 插入 | 中 | CarPlay / Android Auto |
| RTC 定时 | 中 | OTA 定时唤醒 |
| 网络 WoWLAN | 低 | 远程查询车辆状态 |
七、常见问题与调优 Checklist
7.1 应用层注意事项
- 正确注册监听器:使用
CarPowerStateListener,不要依赖ACTION_SCREEN_OFF - 异步完成回调:
onStateChanged带有CompletablePowerStateChangeFuture,应用完成准备后必须调用future.complete() - 及时释放资源:避免在
SHUTDOWN_PREPARE后长时间持有 wake lock
7.2 OEM 配置建议
- power_policy.xml:预占策略仅用于紧急电话等高优先级场景
- Garage Mode 电耗:OTA 下载限制带宽,监控 12V 蓄电池电压
- ScreenOff 延迟:建议 5000ms+,避免频繁上下电
7.3 调试命令
# 查看当前电源状态
adb shell dumpsys car_service --service CarPowerManagementService
# 查看电源策略
adb shell dumpsys car_service --service CarPowerPolicyDaemon
# 查看 PowerComponent 状态
adb shell dumpsys car_service --service PowerComponentHandler
八、总结
AAOS 的电源管理是多层次协同的系统工程:
| 层次 | 组件 | 职责 |
|---|---|---|
| Java Framework | CarPowerManagementService |
状态机引擎,通过 PowerHandler + 消息队列驱动 |
| Java Framework | PowerComponentHandler / ScreenOffHandler |
细粒度组件电源管理 |
| AIDL 接口 | ICarPowerPolicyServer.aidl / PowerComponent.aidl |
电源策略契约定义 |
| Native Daemon | carPowerPolicyDaemon |
解析 XML 策略,单一事实来源 |
| HAL | PowerHalService / Vehicle HAL |
与 VMCU 通信,收发电源事件 |
| Kernel | Linux PM | suspend/resume 硬件操作 |
设计亮点在于 Handler 驱动的异步状态机——通过 PendingPowerStates + PowerHandler 串行处理,保证状态变更原子性且避免阻塞。Power Policy 机制让 OEM 可以灵活配置各组件的电源行为,无需修改框架代码。
本文基于 Android 14(android-14-dev)AOSP 源码撰写,建议读者结合源码阅读以获得更完整的理解。
版权声明:本文参考代码来自 AOSP
android-14-dev分支。文中观点仅代表个人理解,如有错误欢迎指正。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)