BatteryService服务分析
Posted zhenjie_chang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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方法的处理流程。
以上是关于BatteryService服务分析的主要内容,如果未能解决你的问题,请参考以下文章
Android耗电量一体化监控: Battery Historian + APM