简介
BatteryService
电池服务负责监控设备的充电状态和电量,这些值发生改变时,服务将会发起广播通知电池的状态信息
电池上报流程图

1.Kernel层
本层属于电池的驱动部分,负责与硬件进行交互,当电池电量信息发生变化时,生成相应的uevent,上报给用户层。
主要相关代码路径:
\linux-4.5\drivers\power\power_supply_core.c
\linux-4.5\drivers\power\power_supply_sysfs.c
2. Healthd守护进程
本层在Android中属于Native
层,healthd
中运行一个系统服务batteryproperties
,负责监听Kernel中上报的uevent
,对电池电量进行实时监控。
主要相关代码路径:
\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
4. SystemUI 应用
该部分属于电量上报的最后的环节。其主要工作是:监听系统广播Intent.ACTION_BATTERY_CHANGED,并对UI作出相应更新。
主要相关代码路径:
\frameworks\base\packages\SystemUI\src\com\android\systemui\power\PowerUI.java
一、初始化
跟其他系统服务一样, BatteryService
也是继承于SystemService
并通过SystemServer
启动。
1.启动位置
frameworks/base/services/java/com/android/server/SystemServer.java
public final class SystemServer {
private void startCoreServices() {
......
mSystemServiceManager.startService(BatteryService.class);
......
}
}
2.构造函数
public BatteryService(Context context) {
super(context);
mContext = context;
mHandler = new Handler(true /*async*/);
//Step:1
mLed = new Led(context, getLocalService(LightsManager.class));
//电池属性改变的时候,会将全部信息写到mBatteryStats中,app端从mBatteryStats中获取当前电池的电量以及状态
mBatteryStats = BatteryStatsService.getService();
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
//Step:2
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mLowBatteryWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
mShutdownBatteryTemperature = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shutdownBatteryTemperature);
// watch for invalid charger messages if the invalid_charger switch exists
//Step:3
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
UEventObserver invalidChargerObserver = new UEventObserver() {
@Override
public void onUEvent(UEvent event) {
final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
synchronized (mLock) {
if (mInvalidCharger != invalidCharger) {
mInvalidCharger = invalidCharger;
}
}
}
};
invalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
}
- 1.控制充电呼吸灯颜色;
- 2.获取res中常用的battery配置信息,比如电池危急电量、电池低电量模式警告电量、关闭低电量模式警告电量、电池关机温度;
- 监控终端是否连接不匹配的充电器
电量相关常用配置修改路径如下:
frameworks\base\core\res\res\values\config.xml
- 监控终端是否连接不匹配的充电器
3.开始引导
在SystemServiceManager中有一个startBootPhase(final int phase )函数,这个函数有啥作用呢?
android系统的启动,是分为几个阶段的,startBootPhase(final int phase)中的这个phase,就表示android系统的启动目前处于哪个阶段,SystemServiceManager将这个phase传递给每个系统服务,每个服务可以根据不同的阶段去做不同的事情;
@Override
public void onStart() {
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
//Step:1
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
//Step:2
mBinderService = new BinderService();
publishBinderService("battery", mBinderService);
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
@Override
public void onBootPhase(int phase) {
//Step:3
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
// check our power situation now that it is safe to display the shutdown dialog.
synchronized (mLock) {
ContentObserver obs = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
//Step:4
updateBatteryWarningLevelLocked();
}
}
};
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, obs, UserHandle.USER_ALL);
updateBatteryWarningLevelLocked();
}
}
}
- 电池属性变更监听事件,调用
update
更新电池信息;
- 电池属性变更监听事件,调用
- 对其他
service
或者app应用提供BinderService
服务,以及对系统进程提供LocalService
本地服务
- 对其他
- 3.当ActivityManager启动完成的时候,回调
onBootPhase
方法,BatterService才可以对外发送Intent - 4.更新一些低电量提示内容,比如 15%低电量;
4.处理电池属性变化事件
private void updateBatteryWarningLevelLocked() {
........
processValuesLocked(true);
}
private void processValuesLocked(boolean force) {
boolean logOutlier = false;
long dischargeDuration = 0;
mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
//Step:1
if (mBatteryProps.chargerAcOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
} else if (mBatteryProps.chargerUsbOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
} else if (mBatteryProps.chargerWirelessOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
} else {
mPlugType = BATTERY_PLUGGED_NONE;
}
.....
//Step:2
try {
mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter,
mBatteryProps.batteryFullCharge);
} catch (RemoteException e) {
// Should never happen.
}
......
//Step:3
shutdownIfNoPowerLocked();
shutdownIfOverTempLocked();
.......
//Step:4
sendIntentLocked();
mLed.updateLightsLocked();
}
- 1.根据底层提供的电池数据,判断当前手机的充电状态:充电状态、USB连接、无线充电状态、未充电状态;
- 2.电池属性改变的时候,会将全部信息写到mBatteryStats中,app端从mBatteryStats中获取当前电池的电量以及状态;
- 3.电量0%,以及高温关机(默认68度);
- 4.发送电池状态的持续性广播,例如电量、电压、充电模式等;并更新LED灯颜色;
低电量关机
如果电池电量严重不足,或没有电,发起关机。
private void shutdownIfNoPowerLocked() {
if (mBatteryProps.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mActivityManagerInternal.isSystemReady()) {
Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
}
});
}
}
高温关机
如果温度过高,则优雅地关闭(默认为> 68.0C),启动关机画面
private void shutdownIfOverTempLocked() {
if (mBatteryProps.batteryTemperature > mShutdownBatteryTemperature) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mActivityManagerInternal.isSystemReady()) {
Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
}
});
}
}
下面我们使用流程图来总结下BatteryService服务processValueLocked方法的处理流程。

二、疑问
电池属性改变的时候,为什么要将全部信息传递到mBatteryStats中?
IBatteryStats的实现类是BatteryStatsImpl,BatteryStatsImpl继承自BatteryStats,BatteryStats可以被app获取到,它的setBatteryState()方法会将电池属性写到历史记录,并且计算了电池的已用时间和可用时间,这样,当我们需要用到电池信息的时候,就可以先获取到当前的BatteryStats,然后再从BatteryStats中获取电池属性;
从上面可以看出,app端既可以从广播得到电池的当前属性,还可以通过BatteryStats得到电池的当前属性;
BatteryService既通过广播的方式将信息发送给观察者,也提供了接口供外界调用。
网友评论