Android Automotive Power Policy 全流程技术解析

3 阅读17分钟

Android Automotive Power Policy 全流程技术解析

基于 AOSP(Android15 Automotive LTS3) CarService 源码分析,涵盖从硬件信号到应用层回调的完整链路。


目录

  1. 架构总览
  2. 核心参与者
  3. 系统启动与初始化流程
  4. Power Policy 定义体系
  5. 电源状态机(CPMS State Machine)
  6. Policy 应用全流程
  7. Listener 注册与通知机制
  8. Listener 通知顺序的决定因素
  9. Silent Mode 机制
  10. 典型场景全链路分析
  11. 调试与验证方法
  12. 关键源码文件索引

1. 架构总览

Android Automotive Power Policy 框架采用分层架构,由 Native 守护进程和 Java 系统服务协同管理车辆电源组件的开关状态。

┌─────────────────────────────────────────────────────────────────────┐
│                          VHAL (Vehicle HAL)                         │
│   AP_POWER_STATE_REQ  /  POWER_POLICY_REQ  /  POWER_POLICY_GROUP   │
└──────────┬──────────────────────┬───────────────────────────────────┘
           │                      │
           ▼                      ▼
┌─────────────────────┐  ┌───────────────────────────────────────────┐
│   PowerHalService   │  │  carpowerpolicyd (CPPD) - Native Daemon   │
│  (Java, CarService) │  │                                           │
│                     │  │  ┌─────────────┐  ┌────────────────────┐  │
│  接收 VHAL 电源状态  │  │  │PolicyManager│  │PowerComponentHandler│ │
│  驱动 CPMS 状态机    │  │  └─────────────┘  └────────────────────┘  │
└─────────┬───────────┘  │  ┌────────────────┐                       │
          │              │  │SilentModeHandler│                       │
          ▼              │  └────────────────┘                       │
┌────────────────────┐   └─────┬─────────────────────┬───────────────┘
│        CPMS        │         │                     │
│ CarPowerManagement │◄────────┘                     │
│     Service        │   AIDL (Delegate/             │
│                    │   SystemNotification)          │
│ ┌──────────────┐   │                                │
│ │PolicyReader  │   │                                ▼
│ │(Java policy) │   │                     ┌──────────────────────┐
│ └──────────────┘   │                     │  Native Clients      │
│ ┌──────────────┐   │                     │  (AudioControl HAL,  │
│ │PowerComponent│   │                     │   AHAL, etc.)        │
│ │Handler (Java)│   │                     │  直接连接 CPPD       │
│ └──────────────┘   │                     └──────────────────────┘
└───────┬────────────┘
        │ oneway AIDL (ICarPowerPolicyListener)
        ▼
┌───────────────────────────────────────────────┐
│  Java Listeners (CarService 内部)              │
│  ┌──────────────────┐ ┌────────────────────┐  │
│  │CarAudioPowerList.│ │  CarMediaService   │  │
│  │  (AUDIO filter)  │ │  (MEDIA filter)    │  │
│  └──────────────────┘ └────────────────────┘  │
└───────────────────────────────────────────────┘

关键设计原则

  • CPPD 负责早期(CarService 启动前)电源策略管理和 Native 客户端通知
  • CarService 启动后接管电源策略控制权(notifyCarServiceReady
  • Policy 只定义"哪些组件 ON/OFF",不定义执行顺序
  • Listener 通知是异步的(oneway AIDL),不保证严格时序

2. 核心参与者

2.1 carpowerpolicyd(CPPD)

Native C++ 守护进程,运行在独立进程中。

源码位置packages/services/Car/cpp/powerpolicy/server/src/

职责

  • 系统启动最早阶段的电源策略管理
  • 读取 /vendor/etc/automotive/power_policy.xml 配置
  • 管理 Accumulated Policy(累积策略状态)
  • 通知 Native 客户端(如 Audio HAL)策略变化
  • 监听 VHAL 的 POWER_POLICY_REQPOWER_POLICY_GROUP_REQ 属性
  • 向 VHAL 写入 CURRENT_POWER_POLICY 属性

核心组件

组件说明
CarPowerPolicyServerAIDL 服务端,处理策略请求和通知
PolicyManager解析和管理策略定义(含 vendor XML)
PowerComponentHandler维护组件累积状态(Accumulated Policy)
SilentModeHandler监控 sysfs 中的 Silent Mode 硬件状态

2.2 CarPowerManagementService(CPMS)

Java 系统服务,运行在 CarService 进程内。

源码位置packages/services/Car/service/src/com/android/car/power/CarPowerManagementService.java

职责

  • 实现完整的电源状态机(WAIT_FOR_VHAL → ON → SHUTDOWN_PREPARE → ...)
  • 接收 PowerHalService 传来的 VHAL 电源状态事件
  • 与 CPPD 通过 AIDL 交互(发送策略变更请求、接收回调)
  • 管理 Java 侧 Power Policy Listener(通过 RemoteCallbackList
  • 分发策略变更通知给已注册的 Java Listener

核心字段

// 已注册的策略变更 Listener(基于 RemoteCallbackList<ICarPowerPolicyListener>)
private final PowerManagerCallbackList<ICarPowerPolicyListener> mPowerPolicyListeners;

// 与 CPPD 的 AIDL 连接(Refactored 版)
private ICarPowerPolicyDelegate mRefactoredCarPowerPolicyDaemon;
// Legacy 版
private ICarPowerPolicySystemNotification mCarPowerPolicyDaemon;

// 当前策略 ID
private String mCurrentPowerPolicyId;
// 当前策略组 ID
private String mCurrentPowerPolicyGroupId;
// 当前累积策略
private CarPowerPolicy mCurrentAccumulatedPowerPolicy;
// 策略是否被锁定(系统策略生效时锁定)
private boolean mIsPowerPolicyLocked;

2.3 PowerHalService

Java 服务,VHAL 与 CPMS 之间的桥梁。

源码位置packages/services/Car/service/src/com/android/car/hal/PowerHalService.java

职责

  • 监听 VHAL 的 AP_POWER_STATE_REQ 属性变化
  • VehicleApPowerStateReq(ON / SHUTDOWN_PREPARE / CANCEL_SHUTDOWN / FINISHED)转换为 PowerState 对象
  • 通过 PowerEventListener.onApPowerStateChange() 回调 CPMS
  • 提供 sendXxx() 方法向 VHAL 报告当前电源状态(AP_POWER_STATE_REPORT

2.4 PolicyReader

Java 工具类,负责解析和管理电源策略定义。

源码位置packages/services/Car/service/src/com/android/car/power/PolicyReader.java

内置系统策略

策略 ID类型Enabled 组件Disabled 组件
system_power_policy_all_on普通全部组件
system_power_policy_initial_on普通AUDIO, DISPLAY, CPU其余全部
system_power_policy_no_user_interaction抢占式WIFI, CELLULAR, ETHERNET, TRUSTED_DEVICE_DETECTION, CPUMEDIA, AUDIO, DISPLAY, BLUETOOTH, PROJECTION, NFC, INPUT, VOICE_INTERACTION, VISUAL_INTERACTION, LOCATION, MICROPHONE
system_power_policy_suspend_prep抢占式AUDIO, BLUETOOTH, WIFI, LOCATION, MICROPHONE, CPU

2.5 PowerComponentHandler

Java 和 Native 侧各有一个实现,负责维护组件状态和计算累积策略。

Java 侧(CarService 内)

源码packages/services/Car/service/src/com/android/car/power/PowerComponentHandler.java

// 组件当前状态:component ID -> boolean (on/off)
private final SparseBooleanArray mComponentStates;
// 上次策略变更中被修改的组件
private final SparseBooleanArray mLastModifiedComponents;

applyPowerPolicy() 方法遍历策略的 enabled/disabled 数组,更新 mComponentStates,并记录哪些组件发生了实际变化到 mLastModifiedComponents

Native 侧(CPPD 内)

源码packages/services/Car/cpp/powerpolicy/server/src/PowerComponentHandler.cpp

void PowerComponentHandler::applyPowerPolicy(const CarPowerPolicyPtr& powerPolicy) {
    // 使用 std::unordered_map 合并当前累积状态和新策略
    std::unordered_map<PowerComponent, bool> componentStates;
    // 先载入当前累积状态
    setComponentStates(componentStates, mAccumulatedPolicy->enabledComponents, true);
    setComponentStates(componentStates, mAccumulatedPolicy->disabledComponents, false);
    // 再叠加新策略
    setComponentStates(componentStates, powerPolicy->enabledComponents, true);
    setComponentStates(componentStates, powerPolicy->disabledComponents, false);
    // 从 unordered_map 写回 vector(顺序不确定)
    ...
}

重要:Native 侧使用 std::unordered_map,遍历顺序不确定。因此累积策略中 enabled/disabled vector 的组件排列顺序是不保序的


3. 系统启动与初始化流程

3.1 CPPD 启动(最早阶段)

系统启动
  │
  ▼
carpowerpolicyd main()
  │
  ├─ CarPowerPolicyServer::startService(looper)
  │    │
  │    ├─ 检查 CarService 是否已运行
  │    │    mIsCarServiceInOperation = (AServiceManager_checkService != nullptr)
  │    │
  │    ├─ mPolicyManager.init()
  │    │    ├─ initRegularPowerPolicy()     → 注册 all_on, initial_on
  │    │    ├─ initPreemptivePowerPolicy()  → 注册 no_user_interaction, suspend_prep
  │    │    └─ readPowerPolicyConfiguration() → 解析 /vendor/etc/automotive/power_policy.xml
  │    │
  │    ├─ mComponentHandler.init()
  │    │    └─ 所有标准组件初始化为 disabled
  │    │
  │    ├─ mSilentModeHandler.init()
  │    │    └─ 监控 sysfs: pm_silentmode_hw_state
  │    │
  │    ├─ 注册 AIDL 服务
  │    │    ├─ ICarPowerPolicyServer (供 native client 调用)
  │    │    └─ ICarPowerPolicyDelegate / ICarPowerPolicySystemNotification (供 CarService 调用)
  │    │
  │    └─ connectToVhal()
  │         ├─ 连接 VHAL Service
  │         ├─ applyInitialPowerPolicy()
  │         │    ├─ 查找 policyGroup 中 WaitForVHAL 的默认策略
  │         │    └─ 如无自定义 → 应用 system_power_policy_initial_on
  │         └─ subscribeToVhal()
  │              ├─ 订阅 POWER_POLICY_REQ     → 收到后 applyPowerPolicy()
  │              └─ 订阅 POWER_POLICY_GROUP_REQ → 收到后 setPowerPolicyGroup()
  │
  └─ Looper 事件循环

3.2 CarService 启动

CarService 启动
  │
  ▼
ICarImpl 构造函数
  │
  ├─ 按序构造各 CarSystemService 并加入 allServices 列表
  │    ├─ ...
  │    ├─ CarAudioService          (line 335)
  │    ├─ ...
  │    ├─ CarMediaService          (line 376)
  │    ├─ ...
  │    └─ CarPowerManagementService
  │
  ├─ mAllServicesInInitOrder = allServices.toArray()
  │
  └─ ICarImpl.init()
       │
       ├─ 对每个 service 调用 service.init()
       │    │
       │    ├─ CPMS.init()
       │    │    ├─ 连接 CPPD (connectToPowerPolicyDaemon)
       │    │    ├─ mSilentModeHandler.init()
       │    │    ├─ 初始化到 WAIT_FOR_VHAL 状态
       │    │    └─ 应用默认策略 (initial_on)
       │    │
       │    ├─ CarAudioService.init()
       │    │    └─ 注册 PowerPolicyListener (filter: AUDIO)
       │    │
       │    ├─ CarMediaService.init()
       │    │    └─ 注册 PowerPolicyListener (filter: MEDIA)
       │    │
       │    └─ ... 其他 Service
       │
       └─ 通知 CPPD: notifyCarServiceReady()
            └─ CPPD 停止独立策略管理: mIsCarServiceInOperation = true

3.3 CPMS 与 CPPD 的控制权交接

存在两种交互模式,取决于 car_power_policy_refactoring feature flag:

Legacy 模式(flag = false):

CPMS ──notifyCarServiceReady()──> CPPD (ICarPowerPolicySystemNotification)
CPMS ──notifyPowerPolicyChange(policyId, force)──> CPPD
     (CPMS 主导策略决策,通知 CPPD 执行并通知 native 客户端)

Refactored 模式(flag = true):

CPMS ──notifyCarServiceReady(callback)──> CPPD (ICarPowerPolicyDelegate)
     <──返回 PowerPolicyInitData (当前策略、策略组、已注册策略列表)──
CPMS ──applyPowerPolicyAsync(requestId, policyId, force)──> CPPD
     (CPPD 执行策略变更,通过 callback 通知 CPMS 更新组件和策略状态)
CPPD ──callback.updatePowerComponents(policy)──> CPMS
CPPD ──callback.onPowerPolicyChanged(accumulatedPolicy)──> CPMS

4. Power Policy 定义体系

4.1 策略来源

电源策略有三个来源,优先级依次降低:

  1. 系统内置策略:硬编码在 PolicyReader.javaPolicyManager.cpp
  2. Vendor XML 配置/vendor/etc/automotive/power_policy.xml
  3. 运行时动态注册:通过 notifyPowerPolicyDefinition() AIDL 接口

4.2 Vendor XML 配置格式

<powerPolicy version="1.0" defaultPolicyGroup="basic_policy_group">
  <!-- 自定义组件定义 -->
  <customComponents>
    <customComponent value="1001">CUSTOM_SENSOR</customComponent>
  </customComponents>

  <!-- 策略定义 -->
  <policies>
    <policy id="my_custom_policy">
      <component id="POWER_COMPONENT_AUDIO">on</component>
      <component id="POWER_COMPONENT_MEDIA">off</component>
      <otherComponents behavior="untouched"/>
    </policy>
  </policies>

  <!-- 策略组定义 -->
  <policyGroups>
    <policyGroup id="basic_policy_group">
      <defaultPolicy state="WaitForVHAL" id="my_custom_policy"/>
      <defaultPolicy state="On" id="my_custom_policy"/>
    </policyGroup>
  </policyGroups>

  <!-- 系统策略覆写(仅允许 BLUETOOTH, NFC, TRUSTED_DEVICE_DETECTION) -->
  <systemPolicyOverrides>
    <policy id="system_power_policy_no_user_interaction">
      <component id="POWER_COMPONENT_BLUETOOTH">on</component>
    </policy>
  </systemPolicyOverrides>
</powerPolicy>

4.3 策略组与状态映射

策略组(Policy Group)定义了电源状态到默认策略的映射关系:

policyGroup "basic_policy_group":
    WaitForVHAL → "my_custom_policy"
    On"my_custom_policy"

当电源状态转换时,CPMS 调用 applyDefaultPowerPolicyForState(state, fallbackPolicyId) 查找当前策略组中对应状态的默认策略。如果策略组无配置,则回退到 fallback 策略。

4.4 抢占式策略(Preemptive Power Policy)

抢占式策略具有更高优先级,应用后会锁定策略变更:

// applyPreemptivePowerPolicy()
mIsPowerPolicyLocked = true;
mPendingPowerPolicyId = mCurrentPowerPolicyId;  // 保存当前策略
mCurrentPowerPolicyId = policyId;                // 切换到抢占式策略

当抢占式策略被取消(cancelPreemptivePowerPolicy),之前保存的 pending 策略会被恢复。

系统内置的抢占式策略:

  • system_power_policy_no_user_interaction:关闭用户交互相关组件
  • system_power_policy_suspend_prep:挂起前准备

4.5 Accumulated Policy(累积策略)

累积策略代表系统中所有组件的当前实际状态,每次应用新策略时叠加更新:

初始状态:所有组件 OFF
  │
  ▼ 应用 initial_on → AUDIO=ON, DISPLAY=ON, CPU=ON,其余不变
  │
  ▼ 应用 all_on → 所有组件 ON
  │
  ▼ 应用 no_user_interaction → MEDIA=OFF, AUDIO=OFF, DISPLAY=OFF, ..., CPU=ON, WIFI=ON, ...

Listener 收到的 accumulatedPolicy 参数即此累积状态。


5. 电源状态机(CPMS State Machine)

5.1 状态定义

// CpmsState 内部类
public static final int WAIT_FOR_VHAL = 0;       // 等待 VHAL 就绪
public static final int ON = 1;                   // 正常运行
public static final int SHUTDOWN_PREPARE = 2;     // 关机/休眠准备
public static final int WAIT_FOR_FINISH = 3;      // 等待 VHAL 确认可以进入休眠
public static final int SUSPEND = 4;              // 收到 FINISHED,执行实际挂起
public static final int SIMULATE_SLEEP = 5;       // 模拟深度睡眠(调试用)
public static final int SIMULATE_HIBERNATION = 6; // 模拟休眠(调试用)

5.2 状态转换图

                    系统启动
                       │
                       ▼
              ┌─────────────────┐
              │  WAIT_FOR_VHAL  │◄──────────────── CANCEL_SHUTDOWN
              │  (初始状态)      │                        ▲
              └────────┬────────┘                        │
                       │ VHAL 报告 ON                     │
                       ▼                                  │
              ┌─────────────────┐                        │
              │       ON        │                        │
              │  (正常运行)     │                        │
              └────────┬────────┘                        │
                       │ VHAL 请求 SHUTDOWN_PREPARE       │
                       ▼                                  │
              ┌─────────────────┐                        │
              │SHUTDOWN_PREPARE │────────────────────────┘
              │                 │    (取消关机)
              │ PRE_SHUTDOWN_P. │
              │     ↓           │
              │ SHUTDOWN_PREP.  │
              └────────┬────────┘
                       │ Listener 完成 + Garage Mode 结束
                       ▼
              ┌─────────────────┐
              │ WAIT_FOR_FINISH │
              │ (SUSPEND_ENTER/ │
              │  SHUTDOWN_ENTER/│
              │  HIBERN._ENTER) │
              └────────┬────────┘
                       │ VHAL 报告 FINISHED
                       ▼
              ┌─────────────────┐
              │    SUSPEND      │
              │  (执行挂起)     │
              └────────┬────────┘
                       │ 唤醒
                       ▼
              ┌─────────────────┐
              │  WAIT_FOR_VHAL  │ (STATE_SUSPEND_EXIT / STATE_HIBERNATION_EXIT)
              │  (唤醒后状态)    │
              └────────┬────────┘
                       │ VHAL 报告 ON
                       ▼
              ┌─────────────────┐
              │       ON        │
              └─────────────────┘

5.3 关键状态处理逻辑

WAIT_FOR_VHAL → handleWaitForVhal()
private void handleWaitForVhal(CpmsState state) {
    mSilentModeHandler.querySilentModeHwState();
    if (!mFeatureFlags.carPowerPolicyRefactoring()) {
        // 应用 initial_on 策略(仅启用 AUDIO, DISPLAY, CPU)
        applyDefaultPowerPolicyForState(STATE_WAIT_FOR_VHAL,
                PolicyReader.POWER_POLICY_ID_INITIAL_ON);
        if (!mSilentModeHandler.isSilentMode()) {
            cancelPreemptivePowerPolicy();
        }
    }
    sendPowerManagerEvent(carPowerStateListenerState, INVALID_TIMEOUT);
    // 根据具体子状态向 VHAL 报告
    switch (carPowerStateListenerState) {
        case STATE_WAIT_FOR_VHAL:    mHal.sendWaitForVhal(); break;
        case STATE_SHUTDOWN_CANCELLED: mHal.sendShutdownCancel(); break;
        case STATE_SUSPEND_EXIT:     mHal.sendSleepExit(); break;
        case STATE_HIBERNATION_EXIT: mHal.sendHibernationExit(); break;
    }
}
ON → handleOn()
void handleOn() {
    if (!mFeatureFlags.carPowerPolicyRefactoring()) {
        if (!mSilentModeHandler.isSilentMode()) {
            cancelPreemptivePowerPolicy();  // 取消 no_user_interaction 等抢占策略
        }
        // 应用 all_on 策略(启用所有组件)
        applyDefaultPowerPolicyForState(ON, PolicyReader.POWER_POLICY_ID_ALL_ON);
    }
    sendPowerManagerEvent(CarPowerManager.STATE_ON, INVALID_TIMEOUT);
    mHal.sendOn();
}
SHUTDOWN_PREPARE → handleShutdownPrepare()

分两阶段执行:

阶段1: PRE_SHUTDOWN_PREPARE

private void handlePreShutdownPrepare() {
    sendPowerManagerEvent(STATE_PRE_SHUTDOWN_PREPARE, timeoutMs);
    // 等待 Listener 完成(有超时机制)
    waitForCompletionWithShutdownPostpone(state, timeoutMs, taskAtCompletion, intervalMs);
    // 完成后转入阶段2
    → onApPowerStateChange(SHUTDOWN_PREPARE, STATE_SHUTDOWN_PREPARE);
}

阶段2: SHUTDOWN_PREPARE (core)

private void doShutdownPrepare() {
    makeSureNoUserInteraction();  // 应用 no_user_interaction 策略
    sendPowerManagerEvent(STATE_SHUTDOWN_PREPARE, timeoutMs);
    mHal.sendShutdownPrepare();
    waitForShutdownPrepareListenersToComplete(timeoutMs, intervalMs);
    // 完成后 → finishShutdownPrepare() → WAIT_FOR_FINISH
}

6. Policy 应用全流程

6.1 策略应用入口

策略应用有多个入口:

入口触发方式说明
电源状态转换CPMS 状态机applyDefaultPowerPolicyForState()
抢占式策略makeSureNoUserInteraction()applyPreemptivePowerPolicy()
VHAL 属性POWER_POLICY_REQCPPD 直接处理
Shell 命令adb shell cmd car_service apply-power-policy调用 CPMS 公开方法
Silent ModeSilentModeHandlerCPPD 侧直接应用 no_user_interaction

6.2 Legacy 模式下的完整流程

doShutdownPrepare() 调用 makeSureNoUserInteraction() 为例:

CPMS.makeSureNoUserInteraction()
  │
  ├─ mSilentModeHandler.updateKernelSilentMode(true)
  │    └─ 写入 sysfs: pm_silentmode_kernel_state = 1
  │
  └─ applyPreemptivePowerPolicy("system_power_policy_no_user_interaction")
       │
       ├─ 1. PolicyReader 查找策略定义
       │    mPolicyReader.getPreemptivePowerPolicy(policyId)
       │    → CarPowerPolicy {
       │        enabled:  [WIFI, CELLULAR, ETHERNET, TRUSTED_DEVICE_DETECTION, CPU]
       │        disabled: [MEDIA, AUDIO, DISPLAY, BLUETOOTH, PROJECTION, NFC,
       │                   INPUT, VOICE_INTERACTION, VISUAL_INTERACTION, LOCATION, MICROPHONE]
       │      }
       │
       ├─ 2. 锁定策略变更
       │    mIsPowerPolicyLocked = true
       │    mPendingPowerPolicyId = 之前的策略ID(用于后续恢复)
       │
       ├─ 3. Java 侧 PowerComponentHandler 应用策略
       │    mPowerComponentHandler.applyPowerPolicy(policy)
       │    │
       │    │  遍历 enabledComponents:
       │    │    WIFI → setComponentEnabledLocked(WIFI, true)
       │    │    CELLULAR → setComponentEnabledLocked(CELLULAR, true)
       │    │    ... 记录实际变化到 mLastModifiedComponents
       │    │
       │    │  遍历 disabledComponents:
       │    │    MEDIA → setComponentEnabledLocked(MEDIA, false)
       │    │    AUDIO → setComponentEnabledLocked(AUDIO, false)
       │    │    ... 记录实际变化到 mLastModifiedComponents
       │    │
       │    └─ mCurrentPolicyId = policyId
       │
       ├─ 4. 通知 CPPD(Legacy: notifyPowerPolicyChangeToDaemon)
       │    daemon.notifyPowerPolicyChange(policyId, force=true)
       │    │
       │    └─ CPPD 侧执行:
       │         ├─ applyPowerPolicy(policyId, carServiceExpected=true, force)
       │         │    ├─ PolicyManager 查找策略
       │         │    ├─ canApplyPowerPolicyLocked() → 检查并锁定
       │         │    └─ applyAndNotifyPowerPolicy()
       │         │         ├─ mComponentHandler.applyPowerPolicy(policy)
       │         │         │    └─ unordered_map 合并累积状态
       │         │         │
       │         │         ├─ notifyVhalNewPowerPolicy(policyId)
       │         │         │    └─ 写入 VHAL: CURRENT_POWER_POLICY = policyId
       │         │         │
       │         │         └─ 通知 Native Clients:
       │         │              for (auto client : clients) {
       │         │                  ICarPowerPolicyChangeCallback::fromBinder(client.binder)
       │         │                      ->onPolicyChanged(*accumulatedPolicy);
       │         │              }
       │         └─ (native clientsAudio HAL 收到通知)
       │
       └─ 5. 通知 Java Listeners
            notifyPowerPolicyChangeToListeners(notification, appliedPolicy)
            // 详见第7章

6.3 Refactored 模式下的流程差异

CPMS.applyPowerPolicy(policyId, delayNotification=false, upToDaemon=false, force=true)
  │
  ├─ 向 CPPD 发送异步请求
  │    daemon.applyPowerPolicyAsync(requestId, policyId, force)
  │
  ├─ CPPD 处理:
  │    ├─ PolicyManager 查找策略
  │    ├─ applyAndNotifyPowerPolicy()
  │    │    ├─ mComponentHandler.applyPowerPolicy(policy)
  │    │    ├─ callback.updatePowerComponents(policy)    ← 通知 CPMS 更新 Java 侧组件
  │    │    ├─ notifyVhalNewPowerPolicy(policyId)
  │    │    ├─ 通知 native clients
  │    │    └─ callback.onPowerPolicyChanged(accumulatedPolicy) ← 通知 CPMS 策略已生效
  │    └─ 发送成功结果给请求方
  │
  ├─ CPMS 等待请求完成 (request.await())
  │
  ├─ 更新本地状态
  │    updateCurrentPowerPolicy(accumulatedPolicy)
  │
  └─ 通知 Java Listeners
       notifyPowerPolicyChange(notification)

7. Listener 注册与通知机制

7.1 Listener 注册

Java 侧 Listener 注册
// CPMS.addPowerPolicyListener()
public void addPowerPolicyListener(CarPowerPolicyFilter filter,
        ICarPowerPolicyListener listener) {
    mPowerPolicyListeners.register(listener, filter);  // filter 作为 cookie 存储
}

mPowerPolicyListeners 的类型链:

PowerManagerCallbackList<ICarPowerPolicyListener>
    extends RemoteCallbackList<ICarPowerPolicyListener>
        内部: ArrayMap<IBinder, Callback> mCallbacks

register() 调用 mCallbacks.put(binder, cb)ArrayMap.put() 根据 binder.hashCode() 进行二分查找排序插入

Native 侧 Listener 注册
// CarPowerPolicyServer::registerPowerPolicyChangeCallback()
mPolicyChangeCallbacks.emplace_back(binder, filter, callingPid);
// std::vector<CallbackInfo>,按注册顺序追加

7.2 Listener 通知流程(Java 侧)

private void notifyPowerPolicyChangeToListeners(
        PowerPolicyChangeNotification policyChangeNotification,
        CarPowerPolicy appliedPolicy) {

    // 在专用 broadcast handler 线程上投递任务
    mBroadcastHandler.post(() -> {
        // 1. 创建 broadcast 快照(从 ArrayMap 按 index 复制)
        int idx = mPowerPolicyListeners.beginBroadcast();

        // 2. 倒序遍历(idx-- > 0)
        while (idx-- > 0) {
            ICarPowerPolicyListener listener =
                    mPowerPolicyListeners.getBroadcastItem(idx);
            CarPowerPolicyFilter filter =
                    (CarPowerPolicyFilter) mPowerPolicyListeners.getBroadcastCookie(idx);

            // 3. 组件过滤:只通知关心的组件发生变化的 Listener
            if (!PowerComponentHandler.isComponentChanged(updatedComponents, filter)) {
                continue;  // 跳过不相关的 Listener
            }

            // 4. oneway AIDL 调用(异步,不等待返回)
            listener.onPolicyChanged(appliedPolicy,
                    policyChangeNotification.accumulatedPolicy);
        }

        mPowerPolicyListeners.finishBroadcast();
    });
}

7.3 组件过滤机制(isComponentChanged)

public static boolean isComponentChanged(SparseBooleanArray updatedComponents,
        CarPowerPolicyFilter carPowerPolicyFilter) {
    int[] components = carPowerPolicyFilter.getComponents();
    for (int i = 0; i < components.length; i++) {
        if (updatedComponents.get(components[i], false)) {
            return true;  // 此 Listener 关心的组件在本次策略变更中发生了变化
        }
    }
    return false;  // 无关组件变化,跳过此 Listener
}

这意味着:如果某次策略变更只改变了 AUDIO 状态、没改变 MEDIA 状态,那么 CarMediaService 的 Listener 不会被调用。

7.4 Listener 通知流程(Native 侧)

// CarPowerPolicyServer::applyAndNotifyPowerPolicy()
auto accumulatedPolicy = mComponentHandler.getAccumulatedPolicy();
for (auto client : clients) {
    ICarPowerPolicyChangeCallback::fromBinder(client.binder)
            ->onPolicyChanged(*accumulatedPolicy);
}

Native 侧采用简单的顺序遍历 std::vector<CallbackInfo>,按注册顺序调用。


8. Listener 通知顺序的决定因素

8.1 Java 侧顺序由 ArrayMap 的 hashCode 排序决定

RemoteCallbackList 内部使用 ArrayMap<IBinder, Callback>ArrayMapput() 方法通过二分查找将元素按 hashCode 升序排列在 mHashes[] 数组中:

// ArrayMap.put()
hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();
index = indexOf(key, hash);
// index < 0 时,取反得到插入位置
index = ~index;
// System.arraycopy 腾出位置,保持 mHashes[] 升序
mHashes[index] = hash;

注意ArrayMap 默认构造函数设 mIdentityHashCode = false,因此走 key.hashCode() 分支。 但 Binder 未覆写 hashCode(),最终调用 Object.hashCode(),等价于 System.identityHashCode(key)。两个分支结果一致。

beginBroadcast()valueAt(0), valueAt(1), ..., valueAt(N-1) 顺序复制到快照数组,即 hashCode 从小到大

notifyPowerPolicyChangeToListeners() 使用 while (idx-- > 0) 倒序遍历,即先调用 hashCode 最大的 Listener

8.2 hashCode 的来源

ART 运行时的 identityHashCode 实现(art/runtime/mirror/object.cc):

static uint32_t GenerateIdentityHashCode() {
    // LCG 线性同余生成器
    // seed 初始值 = 987654321 + time(nullptr),每次启动不同
    uint32_t expected_value, new_value;
    do {
        expected_value = hash_code_seed.load(std::memory_order_relaxed);
        new_value = expected_value * 1103515245 + 12345;
    } while (!hash_code_seed.compare_exchange_weak(...));
    return new_value & LockWord::kHashMask;
}

结论:Listener 在 ArrayMap 中的位置由其 IBinder 的 identityHashCode 决定,该值使用 LCG 伪随机算法生成,种子包含 time(nullptr)。因此每次系统启动后,同样两个 Listener 的遍历顺序可能不同

8.3 实际表现

Suspend(关闭)时——由同一策略 no_user_interaction 同时关闭 AUDIO 和 MEDIA:

  • 两个 Listener 在同一 while(idx--) 循环中被调用
  • 哪个先调用,取决于本次启动时两个 IBinder 的 hashCode 大小关系
  • 日志可能表现为 Audio 先、Media 后,或反过来

Resume(恢复)时——涉及两个不同的策略:

  1. system_power_policy_initial_on:只启用 AUDIO, DISPLAY, CPU(不包含 MEDIA)
    • isComponentChanged 检查:只有 AUDIO Listener 匹配 → 只通知 CarAudioPowerListener
  2. system_power_policy_all_on:启用所有组件
    • AUDIO 已从 initial_on 变为 ON,此次 all_on 不再改变 AUDIO → 只有 MEDIA Listener 匹配

结论:Resume 时 Audio 总是先于 Media 恢复,不是因为遍历顺序,而是因为两个策略分两次 broadcast 循环依次应用,Audio 在第一个策略中恢复,Media 在第二个策略中恢复。

8.4 为什么修改 NO_USER_INTERACTION_DISABLED_COMPONENTS 数组顺序无效

该数组仅用于构造策略定义(哪些组件 ON/OFF),不是执行队列。有三个层面保证了它的顺序无意义:

  1. PolicyReader:数组只构建 CarPowerPolicy 对象的 enabled/disabled int 数组
  2. CPPD PowerComponentHandler:使用 std::unordered_map 汇总后写回 vector,顺序被打乱
  3. CPMS notifyPowerPolicyChangeToListeners:遍历顺序由 ArrayMap 中 Listener 的 hashCode 决定,与组件数组无关

9. Silent Mode 机制

9.1 概述

Silent Mode 用于在车辆发动机未启动(如远程唤醒)时静默运行系统,禁用所有用户交互组件。

9.2 硬件状态监控(CPPD 侧)

// SilentModeHandler 监控 sysfs 文件
// /sys/kernel/silent_boot/pm_silentmode_hw_state
// 值: "0" = non-silent, "1" = silent

当硬件状态变化时:

SilentModeHandler 检测到 hw_state 变化
  │
  ├─ isSilent = true:
  │    └─ CarPowerPolicyServer::notifySilentModeChange(true)
  │         └─ applyPowerPolicy("system_power_policy_no_user_interaction", ...)
  │
  └─ isSilent = false:
       └─ CarPowerPolicyServer::notifySilentModeChange(false)
            └─ applyPowerPolicy(pendingPowerPolicyId, ...)  // 恢复之前的策略

9.3 内核状态通知(CPMS 侧)

// CPMS 在 doShutdownPrepare() 和 makeSureNoUserInteraction() 中:
mSilentModeHandler.updateKernelSilentMode(true);
// → 写入 /sys/kernel/silent_boot/pm_silentmode_kernel_state = 1
// 通知内核进入静默模式

9.4 Forced Silent Mode(调试用)

通过 shell 命令手动强制 Silent Mode:

# 进入强制静默模式
adb shell cmd car_service silent-mode forced-silent

# 退出强制静默模式
adb shell cmd car_service silent-mode forced-non-silent

# 恢复自动模式
adb shell cmd car_service silent-mode non-forced-silent-mode

10. 典型场景全链路分析

10.1 场景:正常休眠(Suspend to RAM)

MCU 发送休眠请求
  │
  ▼
VHAL: AP_POWER_STATE_REQ = SHUTDOWN_PREPARE (type=DEEP_SLEEP, canPostpone=true)
  │
  ▼
PowerHalService.onApPowerStateChange(PowerState)
  │
  ▼
CPMS.onApPowerStateChange(SHUTDOWN_PREPARE, STATE_PRE_SHUTDOWN_PREPARE)
  │
  ▼
doHandlePowerStateChange() → case SHUTDOWN_PREPARE
  │
  ├─ handlePreShutdownPrepare()
  │    ├─ sendPowerManagerEvent(STATE_PRE_SHUTDOWN_PREPARE)
  │    │    └─ 通知 CarPowerStateListener(带 completion)
  │    └─ 等待 Listener 完成(可postpone)
  │
  ▼ 所有 Listener 完成
  ├─ handleCoreShutdownPrepare() → doShutdownPrepare()
  │    │
  │    ├─ makeSureNoUserInteraction()
  │    │    ├─ updateKernelSilentMode(true)
  │    │    └─ applyPreemptivePowerPolicy("no_user_interaction")
  │    │         │
  │    │         ├─ Java PowerComponentHandler: 更新组件状态
  │    │         ├─ → CPPD: notifyPowerPolicyChange("no_user_interaction", force=true)
  │    │         │    ├─ CPPD PowerComponentHandler: 合并累积状态
  │    │         │    ├─ → VHAL: CURRENT_POWER_POLICY = "no_user_interaction"
  │    │         │    └─ → Native Clients: onPolicyChanged(accumulated)
  │    │         │         └─ Audio HAL 收到通知,日志: "AUDIO is being disabled"
  │    │         │
  │    │         └─ → Java Listeners (via mBroadcastHandler):
  │    │              ├─ CarAudioPowerListener: setAudioEnabled(false)
  │    │              │   └─ 日志: "setting isAudioEnabled to false"
  │    │              └─ CarMediaService: MEDIA is OFF, pause playback
  │    │                  └─ 日志: "onPolicyChanged(); MEDIA is OFF"
  │    │
  │    ├─ sendPowerManagerEvent(STATE_SHUTDOWN_PREPARE)
  │    ├─ mHal.sendShutdownPrepare()
  │    └─ waitForShutdownPrepareListenersToComplete()  // Garage Mode 运行
  │
  ▼ Garage Mode 完成或超时
  ├─ finishShutdownPrepare()
  │    ├─ applyPreemptivePowerPolicy("suspend_prep")  // 关闭更多组件
  │    └─ → WAIT_FOR_FINISH (STATE_SUSPEND_ENTER)
  │
  ▼ 等待 Listener 完成
  ├─ mHal.sendSleepEntry(wakeupSec)
  │
  ▼ VHAL: AP_POWER_STATE_REQ = FINISHED
  └─ handleFinish() → 系统挂起

10.2 场景:唤醒恢复(Resume from Suspend)

系统唤醒
  │
  ▼
CPMS.onApPowerStateChange(WAIT_FOR_VHAL, STATE_SUSPEND_EXIT)
  │
  ▼
handleWaitForVhal()
  │
  ├─ mSilentModeHandler.querySilentModeHwState()
  │
  ├─ applyDefaultPowerPolicyForState(WAIT_FOR_VHAL, INITIAL_ON)
  │    │
  │    └─ 应用 system_power_policy_initial_on
  │         enabled: [AUDIO, DISPLAY, CPU]   ← 注意:没有 MEDIA!
  │         │
  │         ├─ isComponentChanged 检查:
  │         │    AUDIO 从 OFF→ON: CarAudioPowerListener 匹配 ✓
  │         │    MEDIA 未变化:    CarMediaService 不匹配 ✗
  │         │
  │         └─ 只通知 CarAudioPowerListener: setAudioEnabled(true)
  │              └─ 日志: "setting isAudioEnabled to true"
  │
  ├─ cancelPreemptivePowerPolicy()
  │    └─ mIsPowerPolicyLocked = false, 恢复 pendingPolicyId
  │
  ├─ mHal.sendSleepExit()
  │
  ▼ VHAL: AP_POWER_STATE_REQ = ON
  │
  handleOn()
  │
  ├─ cancelPreemptivePowerPolicy()  // 如果还有
  │
  └─ applyDefaultPowerPolicyForState(ON, ALL_ON)
       │
       └─ 应用 system_power_policy_all_on
            enabled: [所有组件]
            │
            ├─ isComponentChanged 检查:
            │    AUDIO 已经是 ON(从 initial_on): 未变化 → CarAudioPowerListener 不匹配 ✗
            │    MEDIA 从 OFF→ON: CarMediaService 匹配 ✓
            │
            └─ 只通知 CarMediaService: MEDIA is ON
                 └─ 日志: "onPolicyChanged(); MEDIA is ON"

关键发现:Resume 过程中,Audio 总是先于 Media 恢复,不是因为遍历顺序,而是因为 initial_onall_on 是两个独立的策略,分两次 broadcast 应用。initial_on 只包含 AUDIO(不含 MEDIA),所以 AUDIO 必然最先恢复。

10.3 场景:通过 Shell 命令触发策略切换

# 手动应用策略
adb shell cmd car_service apply-power-policy <policyId>

# 模拟休眠/唤醒
adb shell cmd car_service silent-mode forced-silent     # 触发 no_user_interaction
adb shell cmd car_service silent-mode forced-non-silent  # 触发恢复

# 模拟完整的挂起-唤醒周期
adb shell cmd car_service suspend
adb shell cmd car_service resume

11. 调试与验证方法

11.1 关键日志 TAG

TAG来源说明
CarPowerManagementServiceCPMS状态机转换、策略应用
carpowerpolicydCPPDNative 守护进程日志
CAR.AUDIOCarAudioServiceAudio 组件状态变更
CAR.MEDIA (TAG_MEDIA)CarMediaServiceMedia 组件状态变更
AHAL_PowerPolicyClientAudio HALNative Audio 客户端
SilentModeHandlerCPMS / CPPDSilent Mode 状态变更

11.2 推荐日志过滤

# 综合观察策略变更流程
adb logcat | grep -E "power policy|PowerPolicy|CAR.AUDIO|CAR.MEDIA|AHAL_Power|silentmode|carpowerpolicyd"

# 精确定位 CPMS 策略分发
adb logcat -s CarPowerManagementService:I

# 观察 CPPD native 侧
adb logcat -s carpowerpolicyd:D

11.3 Dump 当前状态

# CarService 完整 dump
adb shell dumpsys car_service --services CarPowerManagementService

# 输出包含:
# - mCurrentPowerPolicyId
# - mCurrentPowerPolicyGroupId
# - 已注册 Listener 数量
# - PowerComponentHandler 各组件当前状态
# - SilentModeHandler 状态
# CPPD dump
adb shell dumpsys android.frameworks.automotive.powerpolicy.ICarPowerPolicyServer/default

# 输出包含:
# - Current power policy
# - Registered callbacks (pid, filter)
# - Component states (accumulated)

11.4 区分 Listener 调用顺序

如需精确定位 Java Listener 的调用先后,可以在以下位置添加带时间戳的日志:

// CarAudioPowerListener.java - onPolicyChanged 回调入口
Slogf.i(TAG, "onPolicyChanged: uptimeMs=%d, tid=%d, AUDIO enabled=%b",
    SystemClock.uptimeMillis(), Thread.currentThread().getId(),
    accumulatedPolicy.isComponentEnabled(AUDIO));

// CarMediaService.java - onPolicyChanged 回调入口
Slogf.i(TAG, "onPolicyChanged: uptimeMs=%d, tid=%d, MEDIA enabled=%b",
    SystemClock.uptimeMillis(), Thread.currentThread().getId(),
    accumulatedPolicy.isComponentEnabled(PowerComponent.MEDIA));

注意:由于 notifyPowerPolicyChangeToListeners()mBroadcastHandler 线程中执行,所有 Java Listener 回调在同一线程(同一 tid)上顺序执行(非并行),先后完全由 while(idx--) 的遍历顺序决定。


12. 关键源码文件索引

Java 侧(CarService)

文件路径说明
CarPowerManagementServicepackages/services/Car/service/.../power/CarPowerManagementService.java核心状态机与策略管理
PolicyReaderpackages/services/Car/service/.../power/PolicyReader.java策略定义与解析
PowerComponentHandlerpackages/services/Car/service/.../power/PowerComponentHandler.javaJava 侧组件状态管理
SilentModeHandlerpackages/services/Car/service/.../power/SilentModeHandler.java静默模式处理
PowerHalServicepackages/services/Car/service/.../hal/PowerHalService.javaVHAL 电源事件桥梁
ICarImplpackages/services/Car/service/.../ICarImpl.javaService 创建与初始化顺序
CarAudioPowerListenerpackages/services/Car/service/.../audio/CarAudioPowerListener.javaAudio 策略 Listener
CarAudioServicepackages/services/Car/service/.../audio/CarAudioService.javaAudio 服务
CarMediaServicepackages/services/Car/service/.../CarMediaService.javaMedia 服务与策略 Listener

Native 侧(CPPD)

文件路径说明
CarPowerPolicyServerpackages/services/Car/cpp/powerpolicy/server/src/CarPowerPolicyServer.cpp/.hCPPD 主服务
PolicyManagerpackages/services/Car/cpp/powerpolicy/server/src/PolicyManager.cpp/.h策略解析与管理
PowerComponentHandlerpackages/services/Car/cpp/powerpolicy/server/src/PowerComponentHandler.cpp/.hNative 侧组件状态
SilentModeHandlerpackages/services/Car/cpp/powerpolicy/server/src/SilentModeHandler.cpp/.hsysfs 静默模式监控
PowerPolicyClientBasepackages/services/Car/cpp/powerpolicy/client/include/PowerPolicyClientBase.hNative 客户端基类

Framework 基础设施

文件路径说明
RemoteCallbackListframeworks/base/core/java/android/os/RemoteCallbackList.javaListener 管理基类
ArrayMapframeworks/base/core/java/android/util/ArrayMap.javahashCode 排序的 Map
ICarPowerPolicyListener.aidlpackages/services/Car/car-lib/.../power/ICarPowerPolicyListener.aidloneway 回调接口

ART 运行时

文件路径说明
object.ccart/runtime/mirror/object.ccGenerateIdentityHashCode() - LCG 算法