前言
BatteryStats模块主要用于设备在电池供电是系统对各个模块电量使用的统计,Android提供的Battery Historain工具就是对此模块统计的数据进行解析和展示。
一 BatteryStats模块类图
模块主要类图如下:见根目录的模块类图
-
BatteryStats:抽象类,本模块的核心类,主要定义多个内部类,内部类主要包括Uid、Timer等;
-
BatteryStatsImpl:核心实现类,负责电池数据的统计计算,其实现亮BatteryStats中所有的抽象内部类,这些类用于不同统计实现;
-
Uid:针对每个进程的uid设置,用于统计不同uid下进程的耗电数据,如wakelock、sensor、Proc等数据;
-
BatteryStatsService:系统中battersystats服务,提供binder接口,但电池数据计算工作是在BatteryStatsImpl中;
-
BatteryStatsHelper:负责计算软件和硬件等各个模块的耗电数据,提供给设置、手机管家等模块展示;
-
BatterySipper:表示每一个耗电模块的数据统计。
二 BatteryStats启动过程
BatteryStats服务是在AMS中启动,其启动时序图如下: ActivityManagerService->BatteryStatsService:new BatteryStatsService->BatteryStatsImpl:new & setPowerProfileLocked ActivityManagerService->BatteryStatsService:initPowerManagement
2.1 初始化BatteryStatsService
ActivityManagerService->BatteryStatsService:new
在AMS的构造函数中初始化BatteryStatsService对象,读取统计文件中已经保存的信息,同时开启异步信息记录,设置回调,在AMS的onStart中发布服务。 BatteryStatsService构造函数主要初始化Handler、耗电统计和计算类BatteryStatsImpl,设置耗电参考指标参数等。
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
...
// TODO: Move creation of battery stats service outside of activity manager service.
mBatteryStatsService = new BatteryStatsService(systemContext, systemDir,
BackgroundThread.get().getHandler());
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.scheduleWriteToDisk();
mOnBattery = DEBUG_POWER ? true
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
...
}
BatteryStatsService(Context context, File systemDir, Handler handler) {
...
HandlerThread = new HandlerThread("batterystats-handler");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mStats = new BatteryStatsImpl(systemDir, handler, this,
this, mUserManagerUserInfoProvider);
mWorker = new BatteryExternalStatsWorker(context, mStats);
mStats.setExternalStatsSyncLocked(mWorker);
mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
com.android.internal.R.integer.config_radioScanningTimeout) * 1000L);
mStats.setPowerProfileLocked(new PowerProfile(context));
mStats.startTrackingSystemServerCpuTime();
...
}
2.2 BatteryStatsImpl初始化:
-
创建存储文件、校准文件和每日文件;
-
创建handler信息,注此looper为AMS提供;
-
初始化各类型timer和counter,每一种类型的对应一类事件。
工具类主要有三类,
-
StopwatchTimer负责计时统计
-
LongSamplingCounter负责计数、
-
ControllerActivityCounterImpl包含多个负责计数的类对象,比如数据收发包统计
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
public BatteryStatsImpl(Clocks clocks) {
...
if (systemDir == null) {
mStatsFile = null;
mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
} else {
mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
mBatteryStatsHistory = new BatteryStatsHistory(this, systemDir, mHistoryBuffer);
}
mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
...
mHandler = new MyHandler(handler.getLooper());
...
initTimersAndCounters();
...
initTimes(uptimeUs, realtimeUs);
...
}
2.2.1 初始化全局Timer
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
void initTimes(long uptimeUs, long realtimeUs) {
mStartClockTimeMs = mClocks.currentTimeMillis();
mOnBatteryTimeBase.init(uptimeUs, realtimeUs);
mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs);
mRealtimeUs = 0;
mUptimeUs = 0;
mRealtimeStartUs = realtimeUs;
mUptimeStartUs = uptimeUs;
}
2.2.2 初始化Uid进程Timer
--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) {
mBsi = bsi;
mUid = uid;
/* Observer list of TimeBase object in Uid is short */
mOnBatteryBackgroundTimeBase = new TimeBase(false);
mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
/* Observer list of TimeBase object in Uid is short */
mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false);
mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000);
mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnB