Power Event 事件通知机制模块
1. 模块定位与核心价值
1.1 系统角色
Power Event 是华为电源管理系统中的中央事件总线,提供了一个统一的、跨模块的事件发布-订阅机制。该模块解决了电源子系统内部各模块间的解耦通信问题。
核心问题域:
解决方案:
发布者模块 事件总线 订阅者模块
────────── ──────── ──────────
直充模块 UI模块
├─ 检测到适配器 ─────→ POWER_NE_DC_CHECK_SUCC ───→ 更新充电图标
└─ 充电启动 ─────→ POWER_NE_DC_LVC_CHARGING ───→ 显示快充动画
充电管理 电池健康监控
├─ 充电开始 ─────→ POWER_NE_CHARGING_START ───→ 记录充电次数
└─ 充电停止 ─────→ POWER_NE_CHARGING_STOP ───→ 更新统计数据
库仑计 关机管理
└─ 电量过低 ─────→ POWER_NE_COUL_LOW_VOL ───→ 触发低电关机
1.2 架构设计
┌─────────────────────────────────────────────────────────┐
│ Power Event 模块 (cc_common_module/power_event) │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Blocking Notifier Chains (BNC) - 可阻塞通知链 │ │
│ │ ├─ POWER_BNT_CONNECT (USB/无线连接事件) │ │
│ │ ├─ POWER_BNT_CHARGING (充电状态事件) │ │
│ │ ├─ POWER_BNT_DC (直充事件) │ │
│ │ ├─ POWER_BNT_WLC (无线充电事件) │ │
│ │ ├─ POWER_BNT_OTG (OTG事件) │ │
│ │ └─ ... 共 30+ 通知链类型 │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Atomic Notifier Chains (ANC) - 原子通知链 │ │
│ │ ├─ POWER_ANT_CHARGE_FAULT (充电器故障) │ │
│ │ ├─ POWER_ANT_DC_FAULT (直充故障) │ │
│ │ └─ ... 共 7 个原子通知链 │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ UEvent 上报 - 内核到用户空间事件传递 │ │
│ │ /sys/class/hw_power/power_event/ │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
2. 双通知链机制详解
2.1 Blocking Notifier Chain (BNC) - 可阻塞通知链
使用场景: 允许回调函数执行耗时操作(如 I2C 通信、延迟等待)
内核机制:
static struct blocking_notifier_head g_power_event_bnh[POWER_BNT_END];
void power_event_bnc_init(void)
{
for (i = 0; i < POWER_BNT_END; i++)
BLOCKING_INIT_NOTIFIER_HEAD(&g_power_event_bnh[i]);
}
注册订阅:
struct notifier_block my_nb = {
.notifier_call = my_event_handler,
};
power_event_bnc_register(POWER_BNT_DC, &my_nb);
发布事件:
power_event_bnc_notify(POWER_BNT_DC, POWER_NE_DC_CHECK_SUCC, NULL);
int adapter_mode = 0x16;
power_event_bnc_notify(POWER_BNT_DC, POWER_NE_DC_ADAPTER_MODE, &adapter_mode);
回调函数示例:
static int my_event_handler(struct notifier_block *nb,
unsigned long event, void *data)
{
switch (event) {
case POWER_NE_DC_CHECK_SUCC:
hwlog_info("Direct charge check success\n");
msleep(100);
update_ui_icon();
break;
case POWER_NE_DC_ADAPTER_MODE:
int *mode = (int *)data;
hwlog_info("Adapter mode = 0x%x\n", *mode);
break;
}
return NOTIFY_OK;
}
2.2 Atomic Notifier Chain (ANC) - 原子通知链
使用场景: 中断上下文或需要极快响应的事件(如硬件故障)
限制:
内核机制:
static struct atomic_notifier_head g_power_event_anh[POWER_ANT_END];
void power_event_anc_init(void)
{
for (i = 0; i < POWER_ANT_END; i++)
ATOMIC_INIT_NOTIFIER_HEAD(&g_power_event_anh[i]);
}
典型应用:
void charger_irq_handler(void)
{
power_event_anc_notify(POWER_ANT_CHARGE_FAULT,
POWER_NE_CHG_FAULT_VBAT_OVP,
NULL);
}
static int fault_handler(struct notifier_block *nb,
unsigned long event, void *data)
{
switch (event) {
case POWER_NE_CHG_FAULT_VBAT_OVP:
g_ovp_flag = 1;
schedule_work(&ovp_work);
break;
}
return NOTIFY_OK;
}
3. 事件类型体系
3.1 通知链类型(30种)
| 类型 | 常量名 | 用途 | 典型事件 |
|---|
| 连接类 | POWER_BNT_CONNECT | USB/无线连接事件 | USB_CONNECT, WIRELESS_DISCONNECT |
| 充电类 | POWER_BNT_CHARGING | 充电状态变化 | CHARGING_START, CHARGING_STOP |
| 直充类 | POWER_BNT_DC | 直充模式事件 | DC_CHECK_SUCC, DC_LVC_CHARGING |
| 快充协议 | POWER_BNT_FCP | FCP 快充事件 | FCP_CHARGING_START |
| 无线充电 | POWER_BNT_WLC | 无线充电接收 | WLC_READY, WLC_AUTH_SUCC |
| 无线发射 | POWER_BNT_WLTX | 无线反向充电 | WLTX_PING_RX, WLTX_HANDSHAKE_SUCC |
| OTG | POWER_BNT_OTG | OTG 供电事件 | OTG_INSERT, OTG_OCP_HANDLE |
| 库仑计 | POWER_BNT_COUL | 电量计事件 | COUL_LOW_VOL |
| PD | POWER_BNT_HW_PD | PD 协议事件 | HW_PD_CHARGER, HW_PD_ORIENTATION_CC |
| 电池 | POWER_BNT_BATTERY | 电池状态事件 | BATTERY_LOW_WARNING, BATTERY_MOVE |
| UI容量 | POWER_BNT_BAT_UI_CAPACITY | UI 电量变化 | BAT_UI_CAP_CHAGNED |
| 屏幕 | POWER_BNT_PANEL_EVENT | 屏幕开关事件 | PANEL_BLANK, PANEL_UNBLANK |
3.2 事件定义(200+ 种)
按功能模块分类:
连接事件(8个)
POWER_NE_USB_DISCONNECT
POWER_NE_USB_CONNECT
POWER_NE_WIRELESS_DISCONNECT
POWER_NE_WIRELESS_CONNECT
POWER_NE_WIRELESS_TX_START
POWER_NE_WIRELESS_TX_STOP
POWER_NE_WIRELESS_AUX_TX_START
POWER_NE_WIRELESS_AUX_TX_STOP
充电状态事件(3个)
POWER_NE_CHARGING_START
POWER_NE_CHARGING_STOP
POWER_NE_CHARGING_SUSPEND
直充事件(10个)
POWER_NE_DC_CHECK_START
POWER_NE_DC_CHECK_SUCC
POWER_NE_DC_LVC_CHARGING
POWER_NE_DC_SC_CHARGING
POWER_NE_DC_STOP_CHARGE
POWER_NE_DC_PING_FAIL
POWER_NE_DC_ADAPTER_MODE
POWER_NE_DC_TEMP_ERR
POWER_NE_DC_VOLTAGE_INVALID
故障事件(30+个)
POWER_NE_CHG_FAULT_BOOST_OCP
POWER_NE_CHG_FAULT_VBAT_OVP
POWER_NE_CHG_FAULT_WEAKSOURCE
POWER_NE_DC_FAULT_VBUS_OVP
POWER_NE_DC_FAULT_IBAT_OCP
POWER_NE_DC_FAULT_OTP
POWER_NE_DC_FAULT_CC_SHORT
无线充电事件(40+个)
POWER_NE_WLRX_PWR_ON
POWER_NE_WLRX_READY
POWER_NE_WLRX_OCP
POWER_NE_WLTX_PING_RX
POWER_NE_WLTX_HANDSHAKE_SUCC
POWER_NE_WLTX_CHARGEDONE
POWER_NE_WLTX_HALL_APPROACH
POWER_NE_WLTX_HALL_AWAY_FROM
4. UEvent 用户空间通信
4.1 内核到用户空间事件传递
机制: 通过 kobject_uevent_env 发送 uevent 到用户空间
Sysfs 节点:
/sys/class/hw_power/power_event/
├── trigger # 只写节点,用于手动触发事件
内核发送 UEvent:
void power_event_report_uevent(const struct power_event_notify_data *n_data)
{
char uevent_buf[1024] = { 0 };
char *envp[] = { uevent_buf, NULL };
strcpy(uevent_buf, n_data->event);
kobject_uevent_env(l_dev->sysfs_ne, KOBJ_CHANGE, envp);
}
struct power_event_notify_data n_data = {
.event = "CHARGER_TYPE=FCP",
.event_len = 17,
};
power_event_report_uevent(&n_data);
用户空间接收(Android):
UEventObserver mPowerEventObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
String chargerType = event.get("CHARGER_TYPE");
if ("FCP".equals(chargerType)) {
updateFastChargeIcon();
}
}
};
mPowerEventObserver.startObserving("DEVPATH=/devices/platform/soc/hw_power/power_event");
4.2 手动触发事件(调试)
用法:
echo "DEBUG_EVENT=test" > /sys/class/hw_power/power_event/trigger
5. 典型应用场景
5.1 直充启动流程事件序列
时间轴 模块A(直充) 事件总线 模块B(充电管理)
─────────────────────────────────────────────────────────────────────────────
T0 插入适配器
↓
T1 开始检测 ─────→ POWER_NE_DC_CHECK_START ──→ 记录检测时间戳
↓
T2 PING 成功
↓
T3 检测成功 ─────→ POWER_NE_DC_CHECK_SUCC ──→ 禁用 Buck 充电
↓
T4 LVC 充电 ─────→ POWER_NE_DC_LVC_CHARGING ──→ 更新充电图标
↓ ↓
↓ 上报 UEvent
↓ ↓
↓ 用户空间更新 UI
T5 温度异常 ─────→ POWER_NE_DC_TEMP_ERR ──→ 降低充电电流
↓
T6 停止充电 ─────→ POWER_NE_DC_STOP_CHARGE ──→ 恢复 Buck 充电
5.2 低电关机场景
void coul_low_voltage_check(void)
{
int vbat = get_battery_voltage();
if (vbat < 3400) {
hwlog_info("Low voltage detected: %d mV\n", vbat);
power_event_bnc_notify(POWER_BNT_COUL,
POWER_NE_COUL_LOW_VOL,
&vbat);
}
}
static int battery_event_handler(struct notifier_block *nb,
unsigned long event, void *data)
{
switch (event) {
case POWER_NE_COUL_LOW_VOL:
int *vbat = (int *)data;
hwlog_err("Critical low voltage: %d mV\n", *vbat);
struct power_event_notify_data n_data = {
.event = "LOW_BATTERY_SHUTDOWN=1",
.event_len = 24,
};
power_event_report_uevent(&n_data);
break;
}
return NOTIFY_OK;
}
5.3 屏幕开关省电优化
void panel_blank_notify(bool blank)
{
if (blank) {
power_event_bnc_notify(POWER_BNT_PANEL_EVENT,
POWER_NE_PANEL_BLANK,
NULL);
} else {
power_event_bnc_notify(POWER_BNT_PANEL_EVENT,
POWER_NE_PANEL_UNBLANK,
NULL);
}
}
static int charging_panel_handler(struct notifier_block *nb,
unsigned long event, void *data)
{
switch (event) {
case POWER_NE_PANEL_BLANK:
mod_delayed_work(system_wq, &charge_work,
msecs_to_jiffies(10000));
break;
case POWER_NE_PANEL_UNBLANK:
mod_delayed_work(system_wq, &charge_work,
msecs_to_jiffies(1000));
break;
}
return NOTIFY_OK;
}
6.1 功能定位
文件: power_extra_event.c
作用: 处理特定平台的额外事件,主要用于不同屏幕驱动框架的适配。
支持的屏幕客户端:
enum panel_client_type {
PANEL_CLIENT_FB,
PANEL_CLIENT_DRM_8425,
};
6.2 DTS 配置
power_extra_event {
compatible = "huawei,power_extra_event";
status = "ok";
panel_client = <1>; // 0=FB, 1=DRM_8425
};
6.3 实现原理
static int power_extra_event_probe(struct platform_device *pdev)
{
power_dts_read_u32(np, "panel_client", &di->panel_client, PANEL_CLIENT_FB);
if (di->panel_client == PANEL_CLIENT_DRM_8425) {
power_panel_event_parse_active_panel();
}
power_panel_event_register(di);
}
7. 调试与监控
7.1 日志输出
关键日志标签: power_event
典型日志:
[power_event] receive blocking event type=7 event=103,dc_lvc_charging
[power_event] receive atomic event type=4 event=213,dc_fault_vbus_ovp
[power_event] receive uevent_buf 24,LOW_BATTERY_SHUTDOWN=1
7.2 事件统计脚本
#!/bin/bash
echo "=== Power Event Statistics ==="
dmesg | grep "power_event" | grep "receive blocking" | \
awk '{print $(NF-1)}' | sort | uniq -c | sort -rn
echo ""
echo "=== Top 10 Events ==="
dmesg | grep "power_event" | grep -oP 'event=\d+,\K[^,]+' | \
sort | uniq -c | sort -rn | head -10
7.3 实时监控工具
logcat -s power_event | while read line; do
echo "[$(date '+%H:%M:%S')] $line"
done
dmesg -w | grep "power_event" | grep "dc_"
8. 设计模式与最佳实践
8.1 观察者模式应用
Power Event 是经典观察者模式的内核实现:
角色映射:
Subject(主题):power_event_bnh / power_event_anh 通知链数组
Observer(观察者):notifier_block 结构体
Notify(通知):power_event_bnc_notify / power_event_anc_notify
优势:
松耦合:发布者不需要知道订阅者是谁
动态订阅:运行时可随时注册/注销观察者
一对多:一个事件可通知多个订阅者
8.2 事件设计原则
1. 事件粒度控制
POWER_NE_DC_LVC_CHARGING
POWER_NE_DC_SC_CHARGING
POWER_NE_DC_CHARGING
2. 事件命名规范
格式:POWER_NE_<模块>_<动作/状态>
示例:
POWER_NE_WLC_READY // 无线充电_就绪
POWER_NE_WLTX_PING_RX // 无线发射_检测接收器
POWER_NE_CHG_FAULT_VBAT_OVP // 充电器_故障_电池过压
3. 数据传递规范
int adapter_mode = 0x16;
power_event_bnc_notify(type, event, &adapter_mode);
struct dc_error_info {
int error_code;
int ibat;
int vbat;
};
struct dc_error_info info = {...};
power_event_bnc_notify(type, event, &info);
power_event_bnc_notify(type, event, NULL);
8.3 订阅注册最佳实践
模块初始化时注册:
static struct notifier_block my_nb = {
.notifier_call = my_event_handler,
};
static int __init my_module_init(void)
{
power_event_bnc_register(POWER_BNT_DC, &my_nb);
power_event_bnc_register(POWER_BNT_CHARGING, &my_nb);
return 0;
}
static void __exit my_module_exit(void)
{
power_event_bnc_unregister(POWER_BNT_DC, &my_nb);
power_event_bnc_unregister(POWER_BNT_CHARGING, &my_nb);
}
事件处理函数模板:
static int my_event_handler(struct notifier_block *nb,
unsigned long event, void *data)
{
switch (event) {
case POWER_NE_DC_CHECK_SUCC:
handle_dc_check_succ(data);
break;
case POWER_NE_DC_TEMP_ERR:
handle_temp_error(data);
break;
default:
break;
}
return NOTIFY_OK;
}
9. 技术要点总结
9.1 核心功能
| 功能 | 实现机制 | 应用场景 |
|---|
| 模块间通信 | 通知链(Notifier Chain) | 充电模块通知电池管理模块 |
| 内核到用户空间 | kobject_uevent_env | 更新充电图标、触发系统关机 |
| 阻塞通知 | blocking_notifier_chain | 允许睡眠的事件处理 |
| 原子通知 | atomic_notifier_chain | 中断上下文快速响应 |
| 事件同步 | power_event_sync | 确保用户空间事件同步 |
9.2 事件覆盖范围
连接事件(8种) + 充电事件(3种) + 直充事件(10种) +
无线充电事件(40+种) + 故障事件(30+种) +
PD事件(12种) + OTG事件(7种) + 其他(100+种)
────────────────────────────────────────────────
总计:200+ 种事件类型
9.3 设计优势
解耦性:发布者与订阅者完全解耦
扩展性:新增事件类型无需修改现有代码
灵活性:运行时动态注册/注销订阅
高效性:原子通知链支持中断上下文
可靠性:内核标准 notifier chain 机制保证稳定性
9.4 注意事项
阻塞 vs 原子:根据上下文选择正确的通知链类型
事件命名:遵循命名规范,避免冲突
数据生命周期:注意 data 指针的有效性
返回值:事件处理函数必须返回 NOTIFY_OK
注销清理:模块卸载时必须注销所有订阅