介绍
power_supply 目录下online节点是用于判断是否插入battery、ac(外部电源) 和USB 的节点,目录在sys/class/power_supply/battery(ac、usb)/online,主要用于在StatusBar 上显示充电的闪电图标。
SystemUI层介绍
流程介绍
在SystemUI 中控制充电图标的位置在BatteryMeterDrawable.java 类中实现的
SystemUI/src/com/sprd/battery/BatteryMeterDrawable.java
@Override
public void draw(Canvas c) {
...
// 这里表示有任何一个适配器(AC/USB)插入(power_supply目录下的online 节点值为1),并且状态是正在充电中(power_supply目录下status 为Charging 状态, status 的值为BATTERY_STATUS_CHARGING)
if (plugged && level != 100
&& (mTracker.status == BatteryManager.BATTERY_STATUS_CHARGING || mCharging)) {
...
}
这个类相当于一个自定义的充电图标控件,在第一次加载或者调用了invalidateSelf() 方法后会调用draw() 方法重新绘制图标。
整个SystemUI 更新充电图标的流程为:
- BatteryServer 发送ACTION_BATTERY_CHANGED 广播向广播接收器提示Battery 发生了变化
- BatteryControllerImpl.java接收到此广播,调用fireBatteryLevelChanged() 方法向注册了BatteryStateChangeCallback 类回调 onBatteryLevelChanged() 方法
- BatteryMeterDrawable.java 调用onBatteryLevelChanged() 方法后更新充电状态,并且调用postInvalidate() 方法重绘图标
代码流程
1. BatteryService 服务发送电池更新的广播
frameworks/base/services/core/java/com/android/server/BatteryService.java
private final class HealthHalCallback extends IHealthInfoCallback.Stub
implements HealthServiceWrapper.Callback {
@Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
BatteryService.this.update(props);
}
...
}
// 由Health::notifyListeners 调用过来的
private void update(android.hardware.health.V2_0.HealthInfo info) {
synchronized (mLock) {
mRealBatteryLevel = info.legacy.batteryLevel;
if (!mUpdatesStopped) {
mHealthInfo = info.legacy;
processValuesLocked(false);
mLock.notifyAll();
} else {
copy(mLastHealthInfo, info.legacy);
}
}
}
private void processValuesLocked(boolean force) {
...
sendBatteryChangedIntentLocked(); // 发送Intent.ACTION_BATTERY_CHANGED 广播
...
}
private void sendBatteryChangedIntentLocked() {
// Pack up the values and broadcast them to everyone
final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
...
mHandler.post(() -> ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL));
}
2. BatteryControllerImpl 调用流程
BatteryControllerImpl类继承了BroadcastReceiver 类,并且监听了ACTION_BATTERY_CHANGED 广播,当收到ACTION_BATTERY_CHANGED广播后调用fireBatteryLevelChanged() 方法调用注册的回调方法
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@Override
public void onReceive(final Context context, Intent intent) {
...
final String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
...
fireBatteryLevelChanged();
...
}
...
}
protected void fireBatteryLevelChanged() {
synchronized (mChangeCallbacks) {
final int N = mChangeCallbacks.size();
for (int i = 0; i < N; i++) {
// 调用所有注册到mChangeCallbacks中的BatteryStateChangeCallback类回调函数
mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
}
}
}
// BatteryMeterDrawable 会通过此方法添加BatteryStateChangeCallback 回调函数
@Override
public void addCallback(BatteryController.BatteryStateChangeCallback cb) {
synchronized (mChangeCallbacks) {
mChangeCallbacks.add(cb);
}
if (!mHasReceivedBattery) return;
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
cb.onPowerSaveChanged(mPowerSave);
}
3. BatteryMeterDrawable 调用介绍
frameworks/base/packages/SystemUI/src/com/sprd/battery/BatteryMeterDrawable.java
public void startListening() {
...
// 这里向BatteryControllerImpl 类注册了回调
mBatteryController.addCallback(this);
...
}
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
Log.d(TAG, "onBatteryLevelChanged level="+level+",pluggedIn="+pluggedIn+",charging="+charging);
mLevel = level;
mPluggedIn = pluggedIn; // 更新充电器插入状态
mCharging = charging;
postInvalidate(); // 重绘当前控件
}
Framework 层介绍
frameworks/base/services/core/java/com/android/server/BatteryService.java
private final class HealthHalCallback extends IHealthInfoCallback.Stub
implements HealthServiceWrapper.Callback {
@Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
BatteryService.this.update(props);
}
// on new service registered
@Override public void onRegistration(IHealth oldService, IHealth newService,
String instance) {
if (newService == null) return;
...
try {
int r = newService.registerCallback(this); // 向IHealth hal 服务注册回调
if (r != Result.SUCCESS) {
Slog.w(TAG, "health: cannot register callback: " + Result.toString(r));
return;
}
newService.update();
...
}
}
@Override
public void onStart() {
// 服务启动的时候会调用registerHealthCallback() 方法注册服务
registerHealthCallback();
mBinderService = new BinderService();
publishBinderService("battery", mBinderService);
mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
publishBinderService("batteryproperties", mBatteryPropertiesRegistrar);
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
// 这里调用mHealthServiceWrapper.init() 方法初始化mHealthServiceWrapper
private void registerHealthCallback() {
mHealthServiceWrapper = new HealthServiceWrapper();
mHealthHalCallback = new HealthHalCallback();
// IHealth is lazily retrieved.
try {
mHealthServiceWrapper.init(mHealthHalCallback,
new HealthServiceWrapper.IServiceManagerSupplier() {},
new HealthServiceWrapper.IHealthSupplier() {});
...
}
static final class HealthServiceWrapper {
void init(Callback callback,
IServiceManagerSupplier managerSupplier,
IHealthSupplier healthSupplier)
throws RemoteException, NoSuchElementException, NullPointerException {
if (callback == null || managerSupplier == null || healthSupplier == null)
throw new NullPointerException();
IServiceManager manager;
mCallback = callback;
mHealthSupplier = healthSupplier;
IHealth newService = null;
for (String name : sAllInstances) {
traceBegin("HealthInitGetService_" + name);
try {
newService = healthSupplier.get(name); // 获取IHealth hal 服务
} catch (NoSuchElementException ex) {
/* ignored, handled below */
} finally {
traceEnd();
}
if (newService != null) {
mInstanceName = name;
mLastService.set(newService);
break;
}
}
...
mCallback.onRegistration(null, newService, mInstanceName); // 调用onRegistration() 回调函数
mHandlerThread.start();
try {
managerSupplier.get().registerForNotifications(
IHealth.kInterfaceName, mInstanceName, mNotification);
...
}
...
}
Hal层介绍
在BatteryService.java 中使用到的IHealthInfoCallback和IHealth 都是Hal 服务,代码路径为:
- hardware/interfaces/health/2.0/IHealth.hal
- hardware/interfaces/health/2.0/IHealthInfoCallback.hal
Hal 服务实现路径为:
- hardware/interfaces/health/2.0/default/Health.cpp
- hardware/interfaces/health/2.0/default/HealthImplDefault.cpp
在BatteryService 中通过newService.registerCallback(this) 方法向IHealth 中注册了回调
接着查看我们Health::registerCallback() 方法
hardware/interfaces/health/2.0/default/Health.cpp
Return<Result> Health::registerCallback(const sp<IHealthInfoCallback>& callback) {
...
{
std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
callbacks_.push_back(callback); // 将callback 放到callbacks_ 中
}
...
return updateAndNotify(callback);
}
Return<Result> Health::updateAndNotify(const sp<IHealthInfoCallback>& callback) {
std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
std::vector<sp<IHealthInfoCallback>> storedCallbacks{std::move(callbacks_)};
callbacks_.clear();
if (callback != nullptr) {
callbacks_.push_back(callback);
}
Return<Result> result = update(); // 接着会调用update() 方法更新电池状态信息
callbacks_ = std::move(storedCallbacks);
return result;
}
Return<Result> Health::update() {
if (!healthd_mode_ops || !healthd_mode_ops->battery_update) {
return Result::UNKNOWN;
}
bool chargerOnline = battery_monitor_->update(); // 调用BatteryMonitor::update() 方法更新电池状态
healthd_battery_update_internal(chargerOnline);
return Result::SUCCESS;
}
在之后会调用到BatteryMonitor::update() 方法中更新状态并上发状态到Framework 中
system/core/healthd/BatteryMonitor.cpp
bool BatteryMonitor::update(void) {
bool logthis;
initBatteryProperties(&props);
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
else
props.batteryPresent = mBatteryDevicePresent;
props.batteryLevel = mBatteryFixedCapacity ?
mBatteryFixedCapacity :
getIntField(mHealthdConfig->batteryCapacityPath);
props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000;
if (!mHealthdConfig->batteryFullChargePath.isEmpty())
props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
props.batteryTemperature = mBatteryFixedTemperature ?
mBatteryFixedTemperature :
getIntField(mHealthdConfig->batteryTemperaturePath);
std::string buf;
if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
props.batteryStatus = getBatteryStatus(buf.c_str());
if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
props.batteryHealth = getBatteryHealth(buf.c_str());
if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
props.batteryTechnology = String8(buf.c_str());
double MaxPower = 0;
for (size_t i = 0; i < mChargerNames.size(); i++) {
String8 path;
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
if (getIntField(path)) {
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
switch(readPowerSupplyType(path)) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
props.chargerAcOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_USB:
props.chargerUsbOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
props.chargerWirelessOnline = true;
break;
default:
KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
mChargerNames[i].string());
}
path.clear();
path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
int ChargingCurrent =
(access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
path.clear();
path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
int ChargingVoltage =
(access(path.string(), R_OK) == 0) ? getIntField(path) :
DEFAULT_VBUS_VOLTAGE;
double power = ((double)ChargingCurrent / MILLION) *
((double)ChargingVoltage / MILLION);
if (MaxPower < power) {
props.maxChargingCurrent = ChargingCurrent;
props.maxChargingVoltage = ChargingVoltage;
MaxPower = power;
}
}
}
...
healthd_mode_ops->battery_update(&props);
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
}
在update() 方法里会读取/sys/class/power_supply 目录下的所有目录和节点,结果保存在props 中,通过healthd_mode_ops->battery_update() 方法上传到FW 层
healthd_mode_ops->battery_update() 方法在HealthServiceCommon.cpp 中做了初始化
hardware/interfaces/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
static struct healthd_mode_ops healthd_mode_service_2_0_ops = {
.init = healthd_mode_service_2_0_init,
.preparetowait = healthd_mode_service_2_0_preparetowait,
.heartbeat = healthd_mode_service_2_0_heartbeat,
.battery_update = healthd_mode_service_2_0_battery_update,
};
void healthd_mode_service_2_0_battery_update(struct android::BatteryProperties* prop) {
HealthInfo info;
convertToHealthInfo(prop, info.legacy);
Health::getImplementation()->notifyListeners(&info);
}
在调用healthd_mode_ops->battery_update() 时,会调用到HealthServiceCommon:: healthd_mode_service_2_0_battery_update() 方法中,该方法会调用Health::getImplementation()->notifyListeners() 方法将prop数据传给Health.cpp 中,由Health调用notifyListeners() 方法调用从BatteryService 注册的回调实现数据上传给BatteryService 中
hardware/interfaces/health/2.0/default/Health.cpp
void Health::notifyListeners(HealthInfo* healthInfo) {
...
std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
for (auto it = callbacks_.begin(); it != callbacks_.end();) {
auto ret = (*it)->healthInfoChanged(*healthInfo); // 这里就会调用BatteryService 里的healthInfoChanged() 方法
if (!ret.isOk() && ret.isDeadObject()) {
it = callbacks_.erase(it);
} else {
++it;
}
}
}
在此方法中会调用BatteryService 的回调方法healthInfoChanged() 将数据传给BatteryService
Kernel 层分析
在Kernel层,如果power_supply目录下的节点更新了,会通过uenent 的方法通知上层节点修改了,接受通知的地方在healthd_common::healthd_mainloop() 中定义的
healthd_common::healthd_mainloop() 方法的初始化流程:
HealthServiceDefault::main() ->HealthServiceCommon::health_service_main() -> healthd_common::healthd_main() -> healthd_common::healthd_mainloop()
hardware/interfaces/health/2.0/default/healthd_common.cpp
static void healthd_mainloop(void) {
int nevents = 0;
while (1) {
struct epoll_event events[eventct];
int timeout = awake_poll_interval;
int mode_timeout;
/* Don't wait for first timer timeout to run periodic chores */
if (!nevents) periodic_chores();
healthd_mode_ops->heartbeat();
mode_timeout = healthd_mode_ops->preparetowait();
if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) timeout = mode_timeout;
nevents = epoll_wait(epollfd, events, eventct, timeout);
if (nevents == -1) {
if (errno == EINTR) continue;
KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
break;
}
for (int n = 0; n < nevents; ++n) {
if (events[n].data.ptr) (*(void (*)(int))events[n].data.ptr)(events[n].events);
}
}
return;
}
healthd_mainloop() 方法会通过一直循环接收uevent 事件,当接受了事件,则调用events[n].data.ptr 方法
hardware/interfaces/health/2.0/default/healthd_common.cpp
static int healthd_init() {
epollfd = epoll_create(EPOLL_CLOEXEC);
if (epollfd == -1) {
KLOG_ERROR(LOG_TAG, "epoll_create1 failed; errno=%d\n", errno);
return -1;
}
healthd_mode_ops->init(&healthd_config);
wakealarm_init();
uevent_init();
return 0;
}
static void uevent_init(void) {
uevent_fd = uevent_open_socket(64 * 1024, true);
if (uevent_fd < 0) {
KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n");
return;
}
fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
if (healthd_register_event(uevent_fd, uevent_event, EVENT_WAKEUP_FD))
KLOG_ERROR(LOG_TAG, "register for uevent events failed\n");
}
int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) {
struct epoll_event ev;
ev.events = EPOLLIN;
if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP;
ev.data.ptr = (void*)handler;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
KLOG_ERROR(LOG_TAG, "epoll_ctl failed; errno=%d\n", errno);
return -1;
}
eventct++;
return 0;
}
从上面可以看到data.ptr 为uevent_event 方法
hardware/interfaces/health/2.0/default/healthd_common.cpp
#define UEVENT_MSG_LEN 2048
static void uevent_event(uint32_t /*epevents*/) {
char msg[UEVENT_MSG_LEN + 2];
char* cp;
int n;
n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
if (n <= 0) return;
if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
return;
msg[n] = '\0';
msg[n + 1] = '\0';
cp = msg;
while (*cp) {
if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
healthd_battery_update(); // 通知Monitor 更新Battery 信息
break;
}
/* advance to after the next \0 */
while (*cp++)
;
}
}
static void healthd_battery_update(void) {
Health::getImplementation()->update(); // 调用Health.cpp 里面的update() 方法
}
bsp/kernel/kernel4.14/drivers/power/supply/charger-manager.c
static int charger_manager_probe(struct platform_device *pdev)
{
...
charger_manager_policy_init(cm);
...
}
static int charger_manager_policy_init(struct charger_manager *cm)
{
...
INIT_DELAYED_WORK(&(cm->policy.usb_changed_work), policy_usb_change_handler_work);
...
cm->policy.usb_notify.notifier_call = policy_usb_change_callback; // 这里会注册usb 通知,当插入USB时,会调用notifier_call() 方法
ret = usb_register_notifier(cm->policy.usb_phy, &cm->policy.usb_notify);
...
}
static int policy_usb_change_callback(struct notifier_block *nb,
unsigned long limit, void *data)
{
struct charger_policy *info =
container_of(nb, struct charger_policy, usb_notify);
info->limit = limit;
vote_debug("policy_usb_change_callback: %d\n", (uint)limit);
schedule_delayed_work(&info->usb_changed_work, msecs_to_jiffies(100)); // 接着触发usb_changed_work() 方法, 即policy_usb_change_handler_work()
return NOTIFY_OK;
}
static void policy_usb_change_handler_work(struct work_struct *work)
{
...
cm_notify_event(info->hook_psy, CM_EVENT_CHG_START_STOP, NULL);
...
}
static void cm_notify_type_handle(struct charger_manager *cm, enum cm_event_types type, char *msg)
{
...
power_supply_changed(cm->charger_psy);
}
power_supply_changed() 方法在power_supply_core.c 定义的
bsp/kernel/kernel4.14/drivers/power/supply/power_supply_core.c
void power_supply_changed(struct power_supply *psy)
{
unsigned long flags;
dev_dbg(&psy->dev, "%s\n", __func__);
spin_lock_irqsave(&psy->changed_lock, flags);
psy->changed = true;
pm_stay_awake(&psy->dev);
spin_unlock_irqrestore(&psy->changed_lock, flags);
schedule_work(&psy->changed_work);
}
EXPORT_SYMBOL_GPL(power_supply_changed);
之后会调用power_supply_changed_work() 方法
static void power_supply_changed_work(struct work_struct *work)
{
unsigned long flags;
struct power_supply *psy = container_of(work, struct power_supply,
changed_work);
dev_dbg(&psy->dev, "%s\n", __func__);
spin_lock_irqsave(&psy->changed_lock, flags);
if (likely(psy->changed)) {
psy->changed = false;
spin_unlock_irqrestore(&psy->changed_lock, flags);
class_for_each_device(power_supply_class, NULL, psy,
__power_supply_changed_work);
power_supply_update_leds(psy);
// 通知注册在power_supply_notifier通知链上的所有的通知回调函数,并将psy传递过去
atomic_notifier_call_chain(&power_supply_notifier,
PSY_EVENT_PROP_CHANGED, psy);
kobject_uevent(&psy->dev.kobj, KOBJ_CHANGE); // 这里会通过uevent 的方式通知用户空间
spin_lock_irqsave(&psy->changed_lock, flags);
}
if (likely(!psy->changed))
pm_relax(&psy->dev);
spin_unlock_irqrestore(&psy->changed_lock, flags);
}
bsp/kernel/kernel4.14/lib/kobject_uevent.c
int kobject_uevent(struct kobject *kobj, enum kobject_action action)
{
return kobject_uevent_env(kobj, action, NULL);
}
EXPORT_SYMBOL_GPL(kobject_uevent);
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp_ext[])
{
...
if (uevent_ops && uevent_ops->uevent) {
retval = uevent_ops->uevent(kset, kobj, env);
if (retval) {
pr_debug("kobject: '%s' (%p): %s: uevent() returned "
"%d\n", kobject_name(kobj), kobj,
__func__, retval);
goto exit;
}
}
...
}
uevent_ops->uevent() 方法将会调用power_supply_sysfs::power_supply_uevent() 方法,定义的位置在power_supply_class_init() 方法中
bsp/kernel/kernel4.14/drivers/power/supply/power_supply_core.c
static int __init power_supply_class_init(void)
{
power_supply_class = class_create(THIS_MODULE, "power_supply");
...
power_supply_class->dev_uevent = power_supply_uevent; // 这个power_supply_uevent方法会去读取power_supply 目录下的所有节点信息
...
}
kobject_uevent_env() 函数的主要功能是根据参数组合一个字符串并发送。一个典型的字符串如下:
ACTION=change DEVPATH=/devices/qpnp-charger-eab16c00/power_supply/battery
SUBSYSTEM=power_supply POWER_SUPPLY_NAME=battery
POWER_SUPPLY_STATUS=Charging POWER_SUPPLY_HEALTH=Good
POWER_SUPPLY_PRESENT=1 POWER_SUPPLY_VOLTAGE_NOW=3751000
POWER_SUPPLY_VOLTAGE_AVG=3751000 POWER_SUPPLY_CAPACITY=14
POWER_SUPPLY_ONLINE=1 POWER_SUPPLY_CHARGE_FULL=2000000
POWER_SUPPLY_CONSTANT_CHARGE_CURRENT=500000
POWER_SUPPLY_INPUT_CURRENT_LIMIT=500000
POWER_SUPPLY_CURRENT_NOW=261000
POWER_SUPPLY_CURRENT_AVG=261000
POWER_SUPPLY_CHARGE_COUNTER=260000
POWER_SUPPLY_CHARGE_CONTROL_LIMIT=1000000
POWER_SUPPLY_CHARGE_FULL_DESIGN=2000000
POWER_SUPPLY_CAPACITY_RAW=13 POWER_SUPPLY_VOLTAGE_OCV=3675357
POWER_SUPPLY_VOLTAGE_MAX=4350000
POWER_SUPPLY_CURRENT_COUNTER_MBTK=261175
POWER_SUPPLY_SET_SHIP_MODE=-1 POWER_SUPPLY_TECHNOLOGY=Li-ion
POWER_SUPPLY_CHARGING_ENABLED=1
POWER_SUPPLY_BATTERY_CHARGING_ENABLED=1
POWER_SUPPLY_TIME_TO_FULL_NOW=12528
POWER_SUPPLY_CURRENT_NOW=261000 POWER_SUPPLY_TEMP=307
在kobject_uevent_env() 方法中,retval = add_uevent_var(env, "%s", envp_ext[i]);//将kernel想要发送的状态信息存储起来。
最终是通过netlink_broadcast_filtered向用户空间发送了uevent信息。
发送了uevent 消息,总会有一个地方接收,那么接收这个uevent 信息的在方法uevent_event里
hardware/interfaces/health/2.0/default/healthd_common.cpp
#define UEVENT_MSG_LEN 2048
static void uevent_event(uint32_t /*epevents*/) {
char msg[UEVENT_MSG_LEN + 2];
char* cp;
int n;
n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
if (n <= 0) return;
if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
return;
msg[n] = '\0';
msg[n + 1] = '\0';
cp = msg;
while (*cp) {
if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
healthd_battery_update();
break;
}
/* advance to after the next \0 */
while (*cp++)
;
}
}
通过uevent_kernel_multicast_recv() 方法获取uevent 通知,在通过与 "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM 进行比较,判断是否是来自power_supply子系统的,如果是,则调用healthd_battery_update() 方法向上层发送Battery 信息。
参考
- Android Healthd电池服务分析
- 基于Android Q电池服务分析
- Battery监听流程
- Linux下的power_supply小析
- linux驱动DEVICE_ATTR使用、热插拔上报uevent及驱动启动一个c语言用语
- 基于power supply信息传递的uevent机制
- power supply是如何上报电池信息的