概述
当设备插入充电且电量发生变化一段时间后,在Settings->Battery中和锁屏界面都会有”还需多长时间充满”提示,这里来分析下这个时长是如何获得的。
Settings中调用接口:
packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryInfo.java
Final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
KeyGuard中调用接口:
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
mBatteryInfo = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
以上两种方式中,KeyGuard通过获得BatteryStatsService对象开始调用方法,Settings中则通过BatteryStatsImpl对象调用。但最终都调用的是BatteryStatsImpl中的computeChargeTimeRemaining(long)
方法,先看BatteryStatsService中的computeChargeTimeRemaining()
方法:
frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
public long computeChargeTimeRemaining() {
synchronized (mStats) {
long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime());
return time >= 0 ? (time/1000) : time;
}
}
在这个方法中,获取了当前系统运行时间后,作为参数调用BatterStatsImpl中的方法,得到计算值并返回,因此,这个方法就是核心方法。该方法如下:
@Override
public long computeChargeTimeRemaining(long curTime) {
Slog.d(TAG,"computeChargeTimeRemaining()---start,mOnBattery="+mOnBattery);
//放电情况下直接返回-1
if (mOnBattery) {
// Not yet working.
return -1;
//mChargeStepTracker是充电记录器
//mNumStepDurations表示充电量的步数纸盒,每次开始充电,为0,之后每充一个电,该值加1
if (mChargeStepTracker.mNumStepDurations < 1) {
return -1;
}
//获取充一个电量的时间
long msPerLevel = mChargeStepTracker.computeTimePerLevel();
if (msPerLevel <= 0) {
return -1;
}
//充一个电的时间*距离充满还有多少电得到预估的时间
return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
}
在这个方法中,首先计算充一个电所需的时长,然后通过这个时长x充满所需多少电得到总时长返回。
整个逻辑思路非常简单,但是其中的算法和逻辑相对来说比较难以理解,尤其是mChargeStepTracker
这个对象是做什么的。因此,这里在分析是如何计算充一个电所需时长之前,先缕清楚电池信息是如何流转到BatteryStateImpl中的,这个流程搞清楚之后,之后的逻辑就不那么吃力了。
首先来看看上述方法中的mChargeStepTracker
对象,它是LevelStepTracker
类的一个实例,从名称来看就知道是负责电量等级跟踪的,这里先看下它的三个属性和构造方法:
public static final class LevelStepTracker {
public long mLastStepTime = -1;//上次充了一个电时的时间
public int mNumStepDurations;//充一个电的步数和,如电量由1充到2时该值为1,由2冲到3时该值为2,...
public final long[] mStepDurations;//充一个电所用时长的数组
public LevelStepTracker(int maxLevelSteps) {
mStepDurations = new long[maxLevelSteps];
}
public LevelStepTracker(int numSteps, long[] steps) {
mNumStepDurations = numSteps;
mStepDurations = new long[numSteps];
System.arraycopy(steps, 0, mStepDurations, 0, numSteps);
}
mChargeStepTracker
对象的初始化如下:
//实例化mChargeStepTracker
final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);