kernel层:qpnp-smbcharger.c qpnp-fg.c dwc3-msm.c power_supply_core.c power_supply_sysfs.c
文件路径:kernel\drivers\power\
system/core/healthd层:healthd.cpp BatteryMonitor.cpp、BatteryPropertiesRegistrar.cpp
文件路径:system\core\healthd
framework层:
\frameworks\native\services\batteryservice\IBatteryPropertiesRegistrar.cpp
\frameworks\base\services\core\java\com\android\server\batteryservice.java
\frameworks\base\core\java\android\os\batterymanager.java
2.1、Power_supply子系统:
Power_supply子系统在power_supply_core.c中创建:
power_supply_class = class_create(THIS_MODULE, "power_supply");
Power_supply子系统节点:
power_supply子系统支持kobject结构,在power_supply_sysfs.c文件中,支持show、store属性:
.show = power_supply_show_property, \
.store = power_supply_store_property, \
当用户空间执行cat capacity读取电量的时候,会调用 power_supply_show_property,在函数中会调用get_property,通过指针会调用到qpnp-smbcharger.c文件中的smbchg_battery_get_property
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = get_prop_batt_capacity(chip);
break;
从而读取寄存器的值获取到电量,当然也能在这个文件下通过POWER_SUPPLY_ATTR自己创建节点。
电池电量capacity显示:
2.2、充电部分主要包含USB驱动部分、charger部分、FG部分,
他们之间是如何协调工作的?
==》对于USB、charger和FG,三个驱动在power_supply子系统下对应的节点分别为usb、battery、bms。 USB驱动通过dwc3_msm_pm_power_supplied_to关联到battery和bms,FG通过fg_supplicants关联到battery、bcl、fg_adc,charger部分则充当suppied_from,被动接收某些电池属性的变化(某些battery本身属性自己会检测上报)。
例:
在USB驱动dwc3-msm.c 文件中,当充电器插入的时候,会通过power_supply_set_online设置usb online的状态,然后通过power_supply_changed函数上报,同时通知到charger部分。
2.3、power_supply_changed如何实现上报?
==》在power_supply_core.c文件中,电池属性上报通过power_supply_changed(struct power_supply *psy),此时会:
psy->changed = true; ==》设置属性变化标志位
pm_stay_awake(psy->dev); ==》阻止系统休眠
schedule_work(&psy->changed_work); ==》启动psy->changed_work 工作队列
在power_supply_changed_work工作队列中:
psy->changed = false; ==》清除标志位
__power_supply_changed_work ==》调用sypplied_to和sypplied_from
power_supply_update_leds ==》更新led灯状态
kobject_uevent ==》上报uevent事件
2.3.1、__power_supply_changed_work
==》__power_supply_changed_work中会调用supplied_to和supplied_from,从而将USB、charger、FG关联起来,battery下没有注册supplied_to,则被动接收电池属性变化(目前没有看到有注册supplied_from),同时也会调用到supplied_from这边的external_power_changed指针。例如在charger的smbchg_external_power_changed中则会做一些设置充电电流等操作。
例:
之前在smbchg_external_power_changed函数中添加了一个sleep(1000),导致手机开机过后出现死机现象,分析原因为external_power_changed函数处于自旋锁中,自旋锁的含义是一直占着进程资源不释放不让系统休眠,而sleep函数是让出当前CPU让系统进入休眠,从而导致冲突。
2.3.2、kobject_uevent上报uenevt事件
==》kobject_uevent函数会通过netlink_broadcast_filtered以netlink(一种socket通信)的方式上报,netlink能够实现内核空间与用户空间通信。
最后在if (likely(!psy->changed))
pm_relax(psy->dev); ==》上报完成过后释放锁,让系统休眠
2.4、kernel部分小结:
kernel部分首先将USB、FG、charger几个部分通过sypplied_to关联起来,检测到任何一个部分电池属性有变化时,会调用power_supply_changed函数上报,同时更新信息到相关联模块,最终通过netlink上报uevent事件,在上报的整个过程中,系统保持唤醒状态。
3、system/core/healthd层
3.1、healthd收到uevent事件后如何处理?
==》在healthd.cpp文件中,healthd_mainloop函数中有while(1)一直等待EPOLL事件的发生,监听uevent事件。
此函数会回调到uevent_event函数中,它会读取socket中的字符串,然后判断事件来源是否是由kernel的power_supply子系统发出的。
代码if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) ,如果是,那就调用healthd_battery_update()更新电源状态,
healthd_battery_update函数中的gBatteryMonitor->update()为接口,真正实现在BatteryMonitor.cpp文件的update函数,此时会遍历power_supply子系统节点下所有电池属性(底层电池属性有变化时,会通过set_property写到节点里面去),在update最后会调用healthd_mode_ops->battery_update(&props);
此时又会调回到healthd.cpp中的healthd_mode_android_battery_update,
BatteryMonitor.cpp文件主要是对电池属性的汇总以及遍历电池属性。
3.1.1 在healthd_mode_android_battery_update函数中 notifyListeners通知正在监听的对象。
if (gBatteryPropertiesRegistrar != NULL)
gBatteryPropertiesRegistrar->notifyListeners(*props);
3.2 在BatteryPropertiesRegistrar.cpp文件中的 notifyListeners会触发batteryPropertiesChanged。
3.3 healthd部分小结:
healthd部分小结:在healthd中会一直循环监听kernel上报的uevent事件,当监听到有power_supply子系统上报的uevent事件时会遍历其目录下所有节点,之后又会通过 notifyListeners上报给正在监听battery属性变化的对象。
4、framework层
4.1、当healthd上报监听过后,framework如何实现监听?
==》在BatteryPropertiesRegistrar.cpp文件中,除了能够接收healthd上报的notifyListeners之外,还会registerListener,上层根据自己的需要去实现监听接口即可监听电池属性的变化,对于batteryPropertiesChanged,真正的监听在batteryservice.java中实现,变化的属性通过Binder机制通信IBatteryPropertiesListener .cpp作为客户端,batteryservice作为服务端。
4.2、没有JNI,batteryservice.java如何访问BatteryPropertiesRegistrar.cpp?
==》实际上IBatteryPropertiesListener 、IBatteryPropertiesRegistrar 在framework层都有对应的aidl 文件。编译的时候通过aidl会自动生成 IBatteryPropertiesListener.java 与 IBatteryPropertiesRegistrar.java 文件。
aidl文件目录:
\frameworks\base\core\java\android\os\IBatteryPropertiesListener.aidl
4.3、当batteryservice.java监听到相应属性变化时,如果是电池过温或者电量过低等情况,则会弹出相应的提示框。
4.4、同时在batterymanager.java中也会实现registerlistener监听电池属性的变化,用于上层充电图标的显示。
public BatteryManager() {
mBatteryStats = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(
ServiceManager.getService("batteryproperties"));
}
4.5 、framework层小结:
framework层会根据自己的需要实现监听接口,一旦监听到healthd有上报电池属性变化,batteryservice.java则会根据具体情况弹出提示框,而batterymanager.java则会显示相应的充电图标、电量等。