##转载###
版权声明:本文为CSDN博主「sanzhong104204」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq759981398/article/details/73155782
【注意】本文在原作者的基础上做了一些补充
本文进行第一层分解,将整个电池电量上报的过程分解到Android的不同层次。
先上一幅图,对电量上报的流程有个整体的概念,后续对该图的各个部分进行讲解。
如图中所述,整个电量上报过程分为4个层次:
1. Kernel 层
本层属于电池的驱动部分,负责与硬件进行交互,当电池电量信息发生变化时,生成相应的uevent,上报给用户层。
主要相关代码路径:
/linux-4.5/drivers/ower/power_supply_core.c
/linux-4.5/drivers/power/power_supply_sysfs.c
2. Healthd守护进程
本层在Android中属于Native层,healthd中运行一个系统服务batteryproperties,负责监听Kernel中上报的uevent,对电池电量进行实时监控。监听的路径主要是:
/sys/class/power_supply/battery/uevent
当监听路径有数据发生变化时,healtd调用bool BatteryMonitor::update来更新电池信息,代码实现如下
bool BatteryMonitor::update(void) {
.......
//更新电池信息
if (mBatteryPropertiesRegistrar != NULL)
mBatteryPropertiesRegistrar->notifyListeners(props);//更新电池信息
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
}
BatteryPropertiesRegistrar::notifyListener的实现如下:
void BatteryPropertiesRegistrar::notifyListeners(struct BatteryProperties props) {
Mutex::Autolock _l(mRegistrationLock);
for (size_t i = 0; i < mListeners.size(); i++) {
//调用java层BatteryListener的batteryPropertiesChanged方法
mListeners[i]->batteryPropertiesChanged(props);
}
}
主要相关代码路径:
./system/core/healthd/healthd.cpp
./system/core/healthd/BatteryMonitor.cpp
./system/core/healthd/BatteryPropertiesRegistrar.cpp
./system/core/healthd/BatteryMonitor.cpp
3. BatteryService系统服务
本层提供了C++/Java两套接口来访问batteryproperties系统服务。
本层的系统服务battery使用Java代码写成,运行在fwk的中SystemServer进程。
该系统服务的主要作用是:监听batteryproperties服务中的电池信息变化消息,并将该消息以系统广播的形式转发至Android系统中各处。
主要相关代码路径:
/frameworks/native/services/batteryservice/IBatteryPropertiesRegistrar.cpp
/frameworks/native/services/batteryservice/IBatteryPropertiesListener.cpp
/frameworks/native/services/batteryservice/BatteryProperties.cpp
/frameworks/base/core/java/android/os/IBatteryPropertiesRegistrar.aidl
/frameworks/base/core/java/android/os/IBatteryPropertiesListener.aidl
/frameworks/base/core/java/android/os/BatteryProperties.java
/frameworks/base/services/core/java/com/android/server/BatteryService.java
如上的 mListeners[i]->batteryPropertiesChanged是如何注册到BatteryPropertiesRegistrar中的呢?注册监听电池变化代码如下:
\frameworks\base\services\core\java\com\android\server\BatteryService.java
//获取监听对象BatteryListener
mBatteryPropertiesListener = new BatteryListener();
IBinder b = ServiceManager.getService("batterypropreg");
mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
//注册监听对像mBatteryPropertiesListener
mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
} catch (RemoteException e) {
// Should never happen.
}
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
public void batteryPropertiesChanged(BatteryProperties props) {
//当电池变化的时候,监听回调update方法进而实现更新电池状态。
BatteryService.this.update(props);
}
}
mBatteryPropertiesRegistrar.registerListener电池回调监听注册代码实现如下。
./system/core/healthd/BatteryPropertiesRegistrar.cpp
void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) {
{
Mutex::Autolock _l(mRegistrationLock);
// check whether this is a duplicate
for (size_t i = 0; i < mListeners.size(); i++) {
if (mListeners[i]->asBinder() == listener->asBinder()) {
return;
}
}
//将BatteryService中的mBatteryPropertiesListener注册到mListeners中。
//等电池变化的时候,healthd会调用 mListeners[i]->batteryPropertiesChanged(props);
//mListeners[i]便是此处进行赋值注册的
mListeners.add(listener);
listener->asBinder()->linkToDeath(this);
}
mBatteryMonitor->update();
}
发送广播:
当BatteryService.this.update被调用的时候,会发送ACTION_BATTERY_CHANGED广播来通知SystemUI以及感兴趣的应用。代码流程如下
代码路径:
./frameworks/base/services/java/com/android/server/BatteryService.java
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
public void batteryPropertiesChanged(BatteryProperties props) {
//(1)更新电池信息
BatteryService.this.update(props);
}
}
(1)update的实现
代码路径:
./frameworks/base/services/java/com/android/server/BatteryService.java
private void update(BatteryProperties props) {
synchronized (mLock) {
if (!mUpdatesStopped) {
mBatteryProps = props;
// Process the new values.
processValuesLocked();
}
}
}
(2)processValuesLocked的主要实现
代码路径:
./frameworks/base/services/java/com/android/server/BatteryService.java
private void processValuesLocked() {
......
//发送广播
sendIntentLocked();
......
}
(3)sendIntentLocked的实现,可见主要是发送ACTION_BATTERY_CHANGED广播,并附带电池信息。
代码路径:
./frameworks/base/services/java/com/android/server/BatteryService.java
private void sendIntentLocked() {
// 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);
int icon = getIconLocked(mBatteryProps.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage);
intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature);
intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology);
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
if (DEBUG) {
Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
", health:" + mBatteryProps.batteryHealth + ", present:" + mBatteryProps.batteryPresent +
", voltage: " + mBatteryProps.batteryVoltage +
", temperature: " + mBatteryProps.batteryTemperature +
", technology: " + mBatteryProps.batteryTechnology +
", AC powered:" + mBatteryProps.chargerAcOnline + ", USB powered:" + mBatteryProps.chargerUsbOnline +
", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
", icon:" + icon + ", invalid charger:" + mInvalidCharger);
}
mHandler.post(new Runnable() {
@Override
public void run() {
ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
}
});
}
4. SystemUI 应用
该部分属于电量上报的最后的环节。其主要工作是:监听系统广播Intent.ACTION_BATTERY_CHANGED,并对UI作出相应更新。
主要相关代码路径:
./frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
代码逻辑:
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//接收电池变化的广播
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
......
if (!plugged
&& (bucket < oldBucket || oldPlugged)
&& mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& bucket < 0) {
//根据电量的情况判读是否显示电量过低等
showLowBatteryWarning();
// only play SFX when the dialog comes up or the bucket changes
if (bucket != oldBucket || oldPlugged) {
playLowBatterySound();
}
} else if (plugged || (bucket > oldBucket && bucket > 0)) {
dismissLowBatteryWarning();
} else if (mBatteryLevelTextView != null) {
//根据电量的情况判读是否显示电量过低等
showLowBatteryWarning();
}
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mScreenOffTime = SystemClock.elapsedRealtime();
} else if (Intent.ACTION_SCREEN_ON.equals(action)) {
mScreenOffTime = -1;
} else {
Slog.w(TAG, "unknown intent: " + intent);
}
}
};