SystemServer在启动BatteryService时,一次会调用它的构造函数,onStart,onBootPhase方法;解析来我们分析一下这些方法:
1.Constructor方法:
public BatteryService(Context context) {
super(context);
mContext = context;
mHandler = new Handler(true /*async*/);
//电源呼吸灯
mLed = new Led(context, getLocalService(LightsManager.class));
//BatteryStatsService服务,用于统计服务
mBatteryStats = BatteryStatsService.getService();
//AMS本地服务
mActivityManagerInternal =
LocalServices.getService(ActivityManagerInternal.class);
//电量警告值,该值为5
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
//低电量警告值,该值为15
mLowBatteryWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
//关闭低电量警告的值,为20
mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel +
mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
//高温关机的温度值,该值为68C
mShutdownBatteryTemperature = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shutdownBatteryTemperature);
//设置UEvents监听,监听kernel层上传的无效charge信息
// watch for invalid charger messages if the invalid_charger switch exists
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");
}
}
UEvent机制:UEvent机制时kernel通知用户空间的一种机制,很多地方都用到了UEvent机制,入USB插拔/充电等,其本质是内核发送一个字符串(可通过Socket), 应用层接收解释该字符串,获取相应的信息,如果信息有变化,onUEvent方法触发,做出改变;
使用UEvent机制时,需要一个UEventObserver对象,并重写onUEvent(UEvent e)方法,然后调用startObserving方法进行监听,当一个uevent匹配startObserving方法中指定的字符串时触发onUEvent方法;
2.onStart方法:
public void onStart() {
//获取注册时名为“batteryproperties”的服务
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
mBinderService = new BinderService();
//发布Binder服务
publishBinderService("battery", mBinderService);
//发布本地服务
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
首先获取一个"batteryproperties"的Binder,也即BatteryPropertiesRegistrar,这个服务由healthd层进行注册,底层间隔1分钟,会通过这个服务将电量状态信息更新给BatteryService;
然后,实例化内部类BinderService,该类继承自Binder,然后将这个Binder通过PublishBinderService方法发布到系统服务中;
publishLocalService方法中将BatterySevice的内部类LocalService注册到本地服务;LocalService中提供了一些获取电池相关的方法,且仅限于SystemServer进程内使用;
onBootPhase方法:
public void onBootPhase(int phase) {
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) {
updateBatteryWarningLevelLocked();
}
}
};
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, obs, UserHandle.USER_ALL);
updateBatteryWarningLevelLocked();
}
}
}
这个方法中设置了ContentObserver观察者,当Settings.Global中低电量触发值改变时,就会触发onChange方法,根据上面分析;
接下来分析updateBatteryWarningLevelLocked方法:
private void updateBatteryWarningLevelLocked() {
final ContentResolver resolver = mContext.getContentResolver();
//获取配置文件中存储的低电量触发默认值,15
int defWarnLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
//获取Settings.Global中存储的低电量触发值
mLowBatteryWarningLevel = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
if (mLowBatteryWarningLevel == 0) {
mLowBatteryWarningLevel = defWarnLevel;
}
if (mLowBatteryWarningLevel < mCriticalBatteryLevel) {
mLowBatteryWarningLevel = mCriticalBatteryLevel;
}
mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
//更新电池状态信息的核心方法
processValuesLocked(true);
}
调用更新电池状态信息的核心方法processValuesLocked():
这个是BatteryService最核心的方法,当healthd从kernel层获取电池信息后,会上报给BatteryService,BatteryService中通过这个方法进行处理从而完成更新;
再BatteryService中,有三个地方调用了processValuesLocked方法
1.启动BatteryService时,在onBootPhase方法中的updateBatteryWainingLock方法中;
2.在healthd层向BatteryService更新电池状态信息的update方法中,这里每分钟调用一次;
3.通过adb shell命令dump时在processValuesFromShellLocked方法中;
由于该方法体量较大,我们将分段分析:
1.获取充电类型:
mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
//获取充电类型
if (mBatteryProps.chargerAcOnline) {
//AC充电
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
} else if (mBatteryProps.chargerUsbOnline) {
//USB充电
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
} else if (mBatteryProps.chargerWirelessOnline) {
//无线充电
mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
} else {
//没有充电
mPlugType = BATTERY_PLUGGED_NONE;
}
2.更新统计电池状态信息:
try {
//将电池信息交给BatteryStatsService进行统计
mBatteryStats.setBatteryState(mBatteryProps.batteryStatus,
mBatteryProps.batteryHealth,
mPlugType, mBatteryProps.batteryLevel,
mBatteryProps.batteryTemperature,
mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter,
mBatteryProps.batteryFullCharge);
} catch (RemoteException e) {
// Should never happen.
}
这里将BatteryProperties中更新的电池信息更新到BatteryStatesService中进行统计;
BatteryProperties是由healthd中传入,实现了Parcelable接口,里面存储了healthd从节点文件中读取的电池信息;
3.进行低电量时和高温时的关机:
//低电量关机
shutdownIfNoPowerLocked();
//高温关机
shutdownIfOverTempLocked();
在电量为0并且没有充电时,会自动关机,当温度高于68时,也会进行自动关机;
4.充电类型改变时获取放电时长和放电量:
if (mPlugType != mLastPlugType) {
//上次没充电,说明设备由放电进入充电状态
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
/**
* mDischargeStartTime默认为0,在充电进入放电时赋值为当前时间,放电进入
*充电时又赋值为0
* mDischargeStartLevel为开始放电时的电量
* mDischargeStartTime != 0说明有一次充电->放电
* mDischargeStartLevel!=mBatteryProps.batteryLevel说明电池电量有改变
*/
if (mDischargeStartTime != 0 && mDischargeStartLevel !=
mBatteryProps.batteryLevel) {
//放电时间段 = 当前时间 - 开始放电时间
dischargeDuration = SystemClock.elapsedRealtime() -
mDischargeStartTime;
//重新赋值为0
mDischargeStartTime = 0;
}
} else if (mPlugType == BATTERY_PLUGGED_NONE) {//放电->充电
// charging -> discharging or we just powered up
//重新赋值为当前时间
mDischargeStartTime = SystemClock.elapsedRealtime();
//重新赋值为当前电量
mDischargeStartLevel = mBatteryProps.batteryLevel;
}
}
5.更新低电量临界值:
if (!mBatteryLevelLow) {
// Should we now switch in to low battery mode?
//没充电且当前电量小于等于15%
if (mPlugType == BATTERY_PLUGGED_NONE
&& mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {
mBatteryLevelLow = true;
}
} else {
//充电时mBatteryLevelLow置为false,退出低电量模式
if (mPlugType != BATTERY_PLUGGED_NONE) {
mBatteryLevelLow = false;
//电量到达20%,退出低电量模式
} else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
mBatteryLevelLow = false;
//force为true时进行强制更新
} else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
mBatteryLevelLow = false;
}
}
mBatteryLevelLow是一个用于判断当前电量是否小于低电量警告值得boolean值,和低电量模式有关,在PMS中设置低电量模式时,都会通过LocalService获取到这个值;
6.发送充电/放电模式和到达低电量/退出低电量广播:
/**
*放电->充电,发送Intent.ACTION_POWER_CONNECTED广播,mSequence每次都会+1,
*用于记录广播次序,和JobScheduler有关
*
*充电->放电,发送Intent.ACTION_POWER_DISCONNECTED广播
*/
if (mPlugType != 0 && mLastPlugType == 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_
ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
else if (mPlugType == 0 && mLastPlugType != 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_
BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
/**
* 发送电池电量过低广播Intent.ACTION_BATTERY_LOW,该广播在两种情况下发送:
* 1.设备由充电进入放电(拔掉充电器)后,电量小于15%
* 2.设备在放电过程中,电量小于15%
*
* 当电量达到20%时,发送电池状态正常广播Intent.ACTION_BATTERY_OKAY
*/
if (shouldSendBatteryLowLocked()) {
mSentLowBatteryBroadcast = true;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
statusIntent.setFlags(Intent.
FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
} else if (mSentLowBatteryBroadcast &&
mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
mSentLowBatteryBroadcast = false;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
statusIntent.setFlags(Intent.
FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
7.调用sendIntentLocked方法发送粘性广播:该广播持续性的发送电池电量的变化
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_SEQUENCE, mSequence);
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);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT,
mBatteryProps.maxChargingCurrent);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE,
mBatteryProps.maxChargingVoltage);
intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER,
mBatteryProps.batteryChargeCounter);
mHandler.post(new Runnable() {
@Override
public void run() {
ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
}
});
}
8.更新LED灯状态:
mLed.updateLightsLocked();
public void updateLightsLocked() {
final int level = mBatteryProps.batteryLevel;
final int status = mBatteryProps.batteryStatus;
//电量<15%
if (level < mLowBatteryWarningLevel) {
//电池状态处于充电状态
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
// Solid red when battery is charging
mBatteryLight.setColor(mBatteryLowARGB);
} else {
// Flash red when battery is low and not charging
mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
mBatteryLedOn, mBatteryLedOff);
}
//电池状态处于充电状态||满电量状态
} else if (status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL) {
//处于满电亮状态,或者电量大于90%
if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
// Solid green when full or charging and nearly full
mBatteryLight.setColor(mBatteryFullARGB);
} else {//电量小于90且充电
// Solid orange when charging and halfway full
mBatteryLight.setColor(mBatteryMediumARGB);
}
} else {//不处于充电状态
// No lights if not charging and not low
mBatteryLight.turnOff();
}
}
9.更新电池信息:
mLastBatteryStatus = mBatteryProps.batteryStatus;
mLastBatteryHealth = mBatteryProps.batteryHealth;
mLastBatteryPresent = mBatteryProps.batteryPresent;
mLastBatteryLevel = mBatteryProps.batteryLevel;
mLastPlugType = mPlugType;
mLastBatteryVoltage = mBatteryProps.batteryVoltage;
mLastBatteryTemperature = mBatteryProps.batteryTemperature;
mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
mLastMaxChargingVoltage = mBatteryProps.maxChargingVoltage;
mLastChargeCounter = mBatteryProps.batteryChargeCounter;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
至此,BatteryService得启动流程和和核心方法就分析完比了,现在剩余内部类BatteryListener了;
BatteryService.BatteryListener:
在分析batteryService得启动过程时,对onStart方法中得IBatteryPropertiesRegistrar和BatteryListener没有深入得分析说明,现在主要研究它们之间的关系和作用;
回到onStart方法中:
public void onStart() {
//获取名为“batteryproperties”的服务
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
......
}
首先,在系统服务中获取batteryproperties注册的服务,获取到的对象为Binder,那么这个名为batteryProperties的系统服务,它是在何处注册的呢?
在C++的代码中,找到了batteryProperties注册位置:
\system\core\healthd\BatteryPropertiesRegistrar.cpp
void BatteryPropertiesRegistrar::publish(
const sp<BatteryPropertiesRegistrar>& service) {
defaultServiceManager()->addService(String16("batteryproperties"), service);
}
之后对IBatteryPropertiesRegistrar注册一个监听事件,当监听内容改变时回调对应的方法,监听器如下:
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
@Override public void batteryPropertiesChanged(BatteryProperties props) {
final long identity = Binder.clearCallingIdentity();
try {
BatteryService.this.update(props);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
可以看到,BatteryListener继承于IBatteryPropertiesListener.Stub,因此也是一个Binder对象,当监听内容发生变化时,回调方法batteryPropertiesChanged方法中调用update方法:
private void update(BatteryProperties props) {
synchronized (mLock) {
if (!mUpdatesStopped) {
mBatteryProps = props;
// Process the new values.
processValuesLocked(false);
} else {
mLastBatteryProps.set(props);
}
}
}
在这个方法中,通过监听器传入到BatteryProperties初始化成员变量mBatteryProps;BatteryProperties中带有电池状态信息,通过该方法最终调用processValuesLocked方法,从而完成电池状态信息的更新;
参考文档:
电池服务管理-详解