前言
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