1. 程式人生 > >[Android Framework] 8.1 Battery系列(六) 上次充滿電計算

[Android Framework] 8.1 Battery系列(六) 上次充滿電計算

Settings中獲取”上次充滿電”時間的程式碼如下:

packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryUtils.java

public long calculateLastFullChargeTime(BatteryStatsHelper batteryStatsHelper,
        long currentTimeMs) {
    //當前時間 - BatteryStats.getStartClockTime()
    return currentTimeMs - batteryStatsHelper.getStats().getStartClockTime();

}

從這裡可以看出,其計算公式可以用如下公式來表示:

上次充滿電時間 = 當前系統時間 - BatteryStats.getStartClockTime(), 因此,我們在BatteryStatsImpl中就來看看這個方法返回的是什麼,如下:

@Override public long getStartClockTime() {
    final long currentTime = System.currentTimeMillis();
    //mStartClockTime距離當前時間超過一年,則重新進行設定
    if (ensureStartClockTime(currentTime)) {
        recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
                mClocks.uptimeMillis());
    }
    return
mStartClockTime; }

ensureStartClockTime()方法用來確保mStartClockTime可用,如果距離當前時間超過一年,則重新進行設定,該方法如下:

boolean ensureStartClockTime(final long currentTime) {
    //一年毫秒數
    final long ABOUT_ONE_YEAR = 365*24*60*60*1000L;
    //如果mStartClockTime < (currentTime-ABOUT_ONE_YEAR),說明上次採集電池資訊時間超過1年
    if (currentTime > ABOUT_ONE_YEAR && mStartClockTime < (currentTime-ABOUT_ONE_YEAR)) {

        //重新計算時間,當前時間-開始計時時間
mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000)); return true; } return false; }

從這個方法中可以看出,實際上返回的是mStartClockTime,它是表示BatteryStats開始計時的一個時間值,當系統開機後初始化BatteryStatsService時,該值會被初始化。

綜上可知,Android中並沒有專門對上次充滿電時間進行標記和處理,而是直接使用了BatteryStatsService採集資料開始時間,通過取該值和當前時間的差得到上次充滿電時間。

再來看看mStartClockTime在哪裡被初始化了:

  • 1.在BatteryStatsImpl構造方法中,呼叫initTimes()初始化:
void initTimes(long uptime, long realtime) {
    //初始化為當前時間
    mStartClockTime = System.currentTimeMillis();
}
  • 2.從Parcel中初始化:
mStartClockTime = in.readLong();
  • 3.在resetAllStatsLocked()中呼叫initTimes()
initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000);

當手機充滿電後,如果拔掉充電器,則會以setBatteryStateLocked()->setOnBatteryLocked()->resetAllStatsLocked()->initTimes()的呼叫順序,將mStartClockTime設定為當前系統時間。從而在Settings中提示上次充滿電為0分鐘前。

綜合上面的分析,可以得出如下幾個結論:

  • 1.上次充滿電時間實際是當前系統時間和BatteryStatsImpl中開始計時時間點的差值。
  • 2.當由未滿到充滿後,如果不拔充電線,不會更新這個時間(沒有更新mStartClockTime);
  • 3.當拔掉電池後開機,實際讀取的是開機到現在的時間(無法讀取Parcel中的資料);

如此看來,Google對於Battery這塊的統計還不是特別精確。