BatteryService服务分析
版权声明:本文为博主原创文章,未经博主允许不得转载。
BatteryService是在systemServer启动核心服务的时候启动的。
同样我们按照PMS启动的流程来分析BatteryService的启动流程。
1.BatteryService的构造方法
BatteryService的构造方法比较简单,只是从资源中获取一些预定的值
- 电量统计服务
- mBatteryStats = BatteryStatsService.getService();
- //电池危急电量
- 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);
2.BatteryService onStart方法
onStart方法中 将BatteryService服务注册到ServiceManager,注册了底层电量变换的回调方法,最终调用BatteryService的update方法更新电池信息
- public void onStart() {
- IBinder b = ServiceManager.getService("batteryproperties");
- final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
- IBatteryPropertiesRegistrar.Stub.asInterface(b);
- try {
- //注册底层电量变化的监听,调用update更新电池信息
- batteryPropertiesRegistrar.registerListener(new BatteryListener());
- ……
- //注册BatteryService服务
- publishBinderService("battery", new BinderService());
- publishLocalService(BatteryManagerInternal.class, new LocalService());
- }
3.onBootPhase方法
当ActivityManager启动完成的时候,回调onBootPhase方法
onBootPhase方法很简单,就是注册了一个关于ContentObserver
来监测设置中关于低电量警告的电量值是否改变
如果该电量值发生变化,回调updateBatteryWarningLevelLocked()方法。
- private void updateBatteryWarningLevelLocked() {
- final ContentResolver resolver = mContext.getContentResolver();
- //获取默认的警告电量值
- int defWarnLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
- //获取自己设置的警告电量值
- 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()方法来做真正的更新。我们知道当监听的底层电池电量发生变化的时候,回调update()方法,最终也会调用该方法来更新,那就来分析下该方法的具体实现。
processValuesLocked方法分析
首先我们先看该方法的第一部分:
- 计算当前是否是危险电量
- mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
- if (mBatteryProps.chargerAcOnline) {
- //充电状态
- 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;
- }
processValuesLocked第一部分主要工作
1. 判断当前是否是危险电量状态
2. 根据底层提供的电池数据,判断当前手机的充电状态
继续着看该方法的实现
- try {
- //调用该方法通知电量统计服务batteryStats,来跟踪目前电池的状态
- //稍后再分析
- mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
- mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
- mBatteryProps.batteryVoltage);
- } catch (RemoteException e) {
- }
- //没有电的时候关机
- shutdownIfNoPowerLocked();
- //当前电池温度过高关机
- shutdownIfOverTempLocked();
这部分首先调用BatteryStats.setBatteryState()方法来通知电量统计服务跟踪统计电池状态信息
然后当电量低于危险电量的时候关机
当电池温度大于定义的电池温度后关机
- //计算未充电时间时长
- dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
- }
- if (!mBatteryLevelLow) {
- if (mPlugType == BATTERY_PLUGGED_NONE
- && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {
- //当前未充电,且当前电量<提醒电量,设置低电量为true,表示进入低电量
- mBatteryLevelLow = true;
- }
- } else {
- if (mPlugType != BATTERY_PLUGGED_NONE) {
- //低电量的时候,当前变成的充电状态,退出低电量提醒
- mBatteryLevelLow = false;
- } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
- //当前电量 > 关闭低电量提醒电量,退出低电量提醒
- mBatteryLevelLow = false;
- } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
- //强制退出
- mBatteryLevelLow = false;
- }
- }
- //发送电池电量变化的广播
- sendIntentLocked();
- //根据不同的情况发送连接电源,电源断开,进入低电量,退出低电量等广播
- if (mPlugType != 0 && mLastPlugType == 0) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- Intent statusIntent = new I ntent(Intent.ACTION_POWER_CONNECTED);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
- }
- });
- }
- ^
- //更新LED等显示
- mLed.updateLightsLocked();
- //将新的电池信息更新到变量中
- mLastBatteryStatus = mBatteryProps.batteryStatus;
- mLastBatteryHealth = mBatteryProps.batteryHealth;
- ……
- mLastInvalidCharger = mInvalidCharger;
- }
每当电池信息发生变化都会调用processValueLocked方法来更新电池信息。该方法的包括的基本内容在代码注释中已经标注过了,下面我们来看下其中更新LED等的逻辑mLed.updateLightsLocked
- public void updateLightsLocked() {
- final int level = mBatteryProps.batteryLevel;
- final int status = mBatteryProps.batteryStatus;
- //电量低于BatteryWarning的电量
- if (level < mLowBatteryWarningLevel) {
- //已经连接上充电
- if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
- //指示灯显示红色
- mBatteryLight.setColor(mBatteryLowARGB);
- } else {
- //没有连接充电线,红灯闪烁
- mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
- mBatteryLedOn, mBatteryLedOff);
- }
- } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
- || status == BatteryManager.BATTERY_STATUS_FULL) {
- //当前正在充电或者当前电量已经充满
- if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
- //当电池已经充满或者快要充满的时候指示灯显示绿色
- mBatteryLight.setColor(mBatteryFullARGB);
- } else {
- //当正在充电或者电量超过一半的时候,指示灯显示橘黄色
- mBatteryLight.setColor(mBatteryMediumARGB);
- }
- } else {
- //其他正常情况指示灯关闭
- mBatteryLight.turnOff();
- }
- }
更新LED等方法主要根据电池电量和充电状态来决定LED指示灯的颜色和显示方式。低于警告电量的时候LED指示灯显示红色,当电池充满电的时候指示灯显示绿色
现在我们分析下BatteryStats.setBatteryState()方法。
setBatteryState()方法最终调用到BatteryStatsImpl类的setBatteryStateLocked()方法中
下面我们来看下关键代码。
- public void setBatteryStateLocked(int status, int health, int plugType, int level,
- int temp, int volt) {
- //判断当前是否是电池供电
- final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
- ……
- int oldStatus = mHistoryCur.batteryStatus;
- if (onBattery) {
- //如果是电池供电,则记录下当前的未充电的电量
- mDischargeCurrentLevel = level;
- if (!mRecordingHistory) {
- mRecordingHistory = true;
- //将当前的电池状态添加到历史记录
- startRecordingHistory(elapsedRealtime, uptime, true);
- }
- }
- ……
- if (onBattery != mOnBattery) {
- //充电状态发生了变化
- mHistoryCur.batteryLevel = (byte)level;
- ……
- mHistoryCur.batteryVoltage = (char)volt;
- //调用setOnBatteryLocked()处理充电状态发生变化的逻辑
- setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
- } else {
- //充电状态没有发生变化
- boolean changed = false;
- //统计电量的各种状态等是否发生变化
- if (mHistoryCur.batteryLevel != level) {
- mHistoryCur.batteryLevel = (byte)level;
- changed = true;
- ……
- ……
- }
- if (changed) {
- //如果电量信息发生变化就讲当前的状态添加到历史记录
- addHistoryRecordLocked(elapsedRealtime, uptime);
- }
- }
- }
该方法中首先判断当前是否是未充电状态,如果是未充电状态,就记录下当前的电池电量mDischargeCurrentLevel = level,然后判断充电状态是否发生了变化,如果没有发生变化,则判断当前电量的各种属性,如电池电量,电池信息是否发生变化,如果电量属性发生了变化,就将当前的电量添加到历史记录中。
如果充电状态发生了变化,则调用setOnBatteryLocked()方法处理相关的逻辑
- void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
- final int oldStatus, final int level) {
- ……
- if (onBattery) {
- //如果拔去充电器的时候电量是满的
- //或者,当前电量大于90
- //或者是从一个很低的电量充电到很高的电量,未充电时小于20,冲完成是大于80
- //或者电量历史记录的数据太大
- //重置电量统计的相关信息,清除当前的电量统计
- boolean reset = false;
- if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
- || level >= 90
- || (mDischargeCurrentLevel < 20 && level >= 80)
- || (getHighDischargeAmountSinceCharge() >= 200
- && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {
- //重置电量统计的相关信息,清除当前的电量统计
- resetAllStatsLocked();
- }
- ……
- //由充电变为不充电,记录下变成不充电状态时的电量
- mDischargeCurrentLevel = mDischargeUnplugLevel = level;
- ……
- //更新TimeBase,和电量统计计时器有关
- updateTimeBasesLocked(true, !screenOn, uptime, realtime);
- } else {
- ……
- //记录变成充电状态时的电量
- mDischargeCurrentLevel = mDischargePlugLevel = level;
- //当前电量低于断开电源时的电量,表示电量消耗了
- if (level < mDischargeUnplugLevel) {
- //记录下电池用电时的电量消耗
- mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
- mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
- }
- //更新TimeBase,和电量统计计时器有关
- updateTimeBasesLocked(false, !screenOn, uptime, realtime);
- ……
- }
- }
setOnBatteryLocked方法中代码看似很多,其实主要内容就是根据充电状态变化后,根据当前的充电状态来做相应的处理
由充电变为未充电,根据逻辑判断是否需要重置电量统计信息。比如当充电电量大于90的时候,拔掉充电器,设置中电池电量相关的统计信息会重置清空
由为充电变为充电,记录了使用电池期间消耗的电量
下面我们使用流程图来总结下BatteryService服务processValueLocked方法的处理流程。