4. Power HAL 接口详解:power_hidl.h、IPower.hal、关键函数

Power HAL(硬件抽象层)是 Android 系统中连接上层 PowerManagerService 与底层 Kernel/Driver 的关键桥梁。在功耗调试场景下,理解 Power HAL 的接口定义、参数传递路径以及核心函数的调用时机,是定位异常功耗行为(如屏幕关闭后 CPU 未降频、无线充电锁频等)的基础。

本章将深入剖析 Power HAL 的三个核心层面:HIDL 接口定义文件(IPower.hal)、C++ 头文件(power_hidl.h)以及关键函数(setInteractive、setFeature)的实现逻辑与参数配置方法。

4.1 Power HAL 架构分层与数据流

Power HAL 位于 Android 框架的 HIDL(HAL Interface Definition Language) 层,其调用链路如下:

调用链路: PowerManagerService → PowerManager → PowerHIDLService → Power HAL (vendor) → Kernel Governor/Driver

下图展示了 Power HAL 在 Android 系统架构中的位置及其与 CTS 测试的关系:

Power HAL 架构分层与 CTS 测试覆盖 PowerManagerService PowerManager (API) PowerHIDLService IPower.hal (HIDL 接口定义) setInteractive(bool on) | setFeature(Feature feature, bool state) | ... power_hidl.h / power.cpp (Vendor 实现) setInteractive() → 设置 CPU 频率/调度策略 | setFeature() → 控制特定硬件特性 Kernel Governor / cpufreq / cpuset / devfreq CTS 覆盖
调试要点: 在功耗异常场景下,应首先确认 Power HAL 的 setInteractive() 是否被正确调用。若屏幕关闭后该函数未被调用或参数错误,则 CPU 可能仍处于高性能状态,导致异常功耗。

4.2 IPower.hal 接口定义详解

IPower.hal 是 Power HAL 的 HIDL 接口定义文件,位于 hardware/interfaces/power/ 目录下。它定义了所有上层可调用的 Power HAL 方法。以下是核心接口的详细说明:

接口方法 参数 返回值 功能描述 CTS 测试覆盖
setInteractive(bool on) on: true 表示交互状态(屏幕亮),false 表示非交互状态(屏幕灭) Status 通知 HAL 设备交互状态变化,用于调整 CPU/GPU 频率、调度策略 PowerManagerTest#testSetInteractive
setFeature(Feature feature, bool state) feature: 特性枚举;state: 启用/禁用 Status 控制特定硬件特性(如双频 Wi-Fi、无线充电加速等) PowerManagerTest#testSetFeature
setPowerProfile(PowerProfile profile) profile: 功耗模式枚举(如 BALANCED、LOW_POWER、HIGH_PERFORMANCE) Status 设置系统功耗模式,影响所有组件的功耗策略 PowerManagerTest#testSetPowerProfile
getSupportedFeatures() 无 vec<Feature> 返回当前 HAL 实现支持的特性列表 PowerManagerTest#testGetSupportedFeatures

以下是一个典型的 IPower.hal 接口定义片段:

// hardware/interfaces/power/1.0/IPower.hal
package android.hardware.power@1.0;

interface IPower {
    /**
     * 设置设备交互状态。
     * @param on true 表示设备处于交互状态(屏幕亮),false 表示非交互状态(屏幕灭)。
     * @return Status 表示操作结果。
     */
    setInteractive(bool on) generates (Status status);

    /**
     * 设置特定硬件特性。
     * @param feature 要控制的特性。
     * @param state true 表示启用,false 表示禁用。
     * @return Status 表示操作结果。
     */
    setFeature(Feature feature, bool state) generates (Status status);

    // 其他接口...
};
常见问题: 部分厂商在实现 setInteractive(false) 时,未正确降低 CPU 最低频率或未切换到省电调度器,导致 CTS 测试 testSetInteractive 失败。调试时应检查 /sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq 在调用后的变化。

4.3 power_hidl.h 头文件与 Vendor 实现

power_hidl.h 是 Power HAL 的 C++ 头文件,定义了 HAL 实现类 Power 的接口。Vendor 厂商需要继承该类并实现所有纯虚函数。该头文件通常位于 hardware/interfaces/power/1.0/default/ 目录下。

以下是 power_hidl.h 的核心结构:

// hardware/interfaces/power/1.0/default/power_hidl.h
#include <android/hardware/power/1.0/IPower.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

namespace android {
namespace hardware {
namespace power {
namespace V1_0 {
namespace implementation {

using ::android::hardware::power::V1_0::IPower;
using ::android::hardware::power::V1_0::Feature;
using ::android::hardware::power::V1_0::Status;
using ::android::hardware::Return;

struct Power : public IPower {
    // 实现 setInteractive
    Return<Status> setInteractive(bool on) override;

    // 实现 setFeature
    Return<Status> setFeature(Feature feature, bool state) override;

    // 其他接口实现...
};

}  // namespace implementation
}  // namespace V1_0
}  // namespace power
}  // namespace hardware
}  // namespace android

Vendor 厂商在 power.cpp 中实现这些函数时,通常会通过 sysfs 节点或 ioctl 与 Kernel 交互。以下是一个典型的 setInteractive 实现示例:

// vendor/xxx/power/power.cpp
Return<Status> Power::setInteractive(bool on) {
    if (on) {
        // 屏幕亮:恢复高性能
        write_to_sysfs("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "1512000");
        write_to_sysfs("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "performance");
    } else {
        // 屏幕灭:进入省电模式
        write_to_sysfs("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "300000");
        write_to_sysfs("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "powersave");
    }
    return Status::SUCCESS;
}

4.4 关键函数详解:setInteractive

setInteractive(bool on) 是 Power HAL 中最核心的函数之一,直接影响设备的功耗表现。其调用时机与系统状态密切相关:

  • 屏幕点亮(on=true): 当用户按下电源键、收到通知唤醒或通过 ADB 唤醒时,PowerManagerService 调用 setInteractive(true),HAL 应提升 CPU/GPU 频率、切换到交互式调度器,确保界面流畅。
  • 屏幕熄灭(on=false): 当屏幕超时关闭或用户按下电源键锁屏时,调用 setInteractive(false),HAL 应降低频率、切换到省电调度器,减少功耗。

下表展示了不同场景下 setInteractive 的典型参数配置:

场景 setInteractive 参数 CPU 最低频率 调度器策略 预期功耗变化
亮屏交互 true 1.5 GHz schedutil / performance 高功耗(正常)
亮屏空闲 true 300 MHz schedutil 中等功耗
灭屏待机 false 300 MHz powersave 低功耗(期望)
灭屏音乐播放 false 300 MHz powersave 低功耗(需保留音频 DMA)
调试技巧: 使用以下命令实时监控 setInteractive 的调用情况:
adb logcat -b events | grep -i "power_interactive"
输出示例:I power_interactive: state=0 // 0 表示灭屏,1 表示亮屏

4.5 关键函数详解:setFeature

setFeature(Feature feature, bool state) 用于控制特定的硬件特性,这些特性通常与功耗密切相关。Feature 枚举定义在 types.hal 中,不同 Android 版本支持的 Feature 有所不同。

以下是 Android 10/11 中常见的 Feature 枚举:

Feature 枚举值 数值 功能描述 功耗影响 CTS 测试用例
POWER_FEATURE_DOUBLE_TAP_TO_WAKE 1 双击唤醒屏幕 增加触控 IC 待机功耗 testDoubleTapToWake
POWER_FEATURE_SUSTAINED_PERFORMANCE 2 持续性能模式(用于游戏/VR) 限制峰值功耗,防止过热降频 testSustainedPerformance
POWER_FEATURE_VR_MODE 3 VR 模式(高帧率、低延迟) 显著增加功耗 testVrMode
POWER_FEATURE_WIRELESS_CHARGER 4 无线充电加速 增加充电功耗,但缩短充电时间 testWirelessCharger

以下是一个 setFeature 的典型实现示例,展示了如何控制无线充电加速特性:

// vendor/xxx/power/power.cpp
Return<Status> Power::setFeature(Feature feature, bool state) {
    switch (feature) {
        case Feature::POWER_FEATURE_WIRELESS_CHARGER:
            // 通过 sysfs 控制无线充电 IC 的输入电流限制
            if (state) {
                // 启用加速:设置输入电流为 10W
                write_to_sysfs("/sys/class/power_supply/wireless/current_max", "2000000");
            } else {
                // 禁用加速:恢复默认 5W
                write_to_sysfs("/sys/class/power_supply/wireless/current_max", "1000000");
            }
            break;
        case Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
            // 控制触控 IC 的双击唤醒功能
            write_to_sysfs("/sys/devices/virtual/touch/touch_dev/double_tap", state ? "1" : "0");
            break;
        default:
            return Status::UNSUPPORTED;
    }
    return Status::SUCCESS;
}
避坑指南: 部分厂商在实现 setFeature 时,未正确处理 getSupportedFeatures() 的返回值。如果 HAL 返回的 Feature 列表与实际实现不一致,CTS 测试 testSetFeature 将失败。调试时应确保 getSupportedFeatures() 返回的 Feature 集合与 setFeature 中实际处理的 Feature 完全匹配。

4.6 CTS 用例定位与调试方法

与 Power HAL 相关的 CTS 测试用例主要集中在 android.os.cts.PowerManagerTest 中。以下是针对 setInteractive 和 setFeature 的用例定位方法:

  1. 查找测试用例:
    # 在 CTS 源码中查找 PowerManagerTest
    find cts/tests/tests/os/ -name "PowerManagerTest.java"
    # 查看测试方法列表
    grep -n "testSetInteractive\|testSetFeature\|testDoubleTapToWake" cts/tests/tests/os/src/android/os/cts/PowerManagerTest.java
  2. 运行单个测试用例:
    # 运行 testSetInteractive
    adb shell am instrument -w -r -e class android.os.cts.PowerManagerTest#testSetInteractive android.os.cts/.PowerManagerTestRunner
  3. 分析测试日志:
    # 抓取 Power HAL 相关日志
    adb logcat -b all | grep -E "PowerHAL|power_hal|setInteractive|setFeature"

下表总结了常见 CTS 失败场景与对应的 HAL 调试方向:

CTS 测试用例 失败现象 HAL 调试方向
testSetInteractive 灭屏后 CPU 频率未降低 检查 setInteractive(false) 中 scaling_min_freq 是否写入成功
testSetFeature 设置 Feature 后状态未改变 检查 setFeature 中 sysfs 路径是否正确,权限是否足够
testDoubleTapToWake 双击唤醒功能无效 检查 POWER_FEATURE_DOUBLE_TAP_TO_WAKE 的 sysfs 节点是否可写
testSustainedPerformance 持续性能模式下功耗过高 检查 setFeature 中是否限制了 CPU/GPU 的最高频率
调试建议: 在 CTS 测试失败时,优先使用 adb shell dumpsys power 查看 PowerManagerService 的状态,确认 mInteractive 和 mWakefulness 的值是否符合预期。然后通过 adb shell cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq 验证 CPU 频率是否已按预期调整。

4.7 本章小结

本章详细介绍了 Power HAL 的核心接口 IPower.hal、power_hidl.h 以及关键函数 setInteractive 和 setFeature。理解这些接口的定义、参数含义和实现方式,是进行功耗调试和 CTS 用例定位的基础。在实际调试中,应重点关注:

  • 调用链路: 确认上层是否正确调用了 HAL 接口。
  • 参数传递: 检查 HAL 实现中 sysfs 节点的读写是否正确。
  • CTS 覆盖: 确保 HAL 实现与 CTS 测试用例的预期行为一致。