Android 從兩個層面統計電量的消耗,分別爲 軟件排行榜 及 硬件排行榜。它們各有本身的耗電榜單,軟件排行榜爲機器中每一個 App 的耗電榜單,硬件排行榜則爲各個硬件的耗電榜單。這兩個排行榜的統計是互爲獨立,互不干擾的。html
具體的說,耗電信息在 設置 -> 電量
中可以很是直觀的看到。注意,Android 全部功耗統計都是經過代碼估算,沒有集成電路參與彙報。準確度取決於廠商 ROM 所提供的 power_profile.xml
文件。因爲不一樣廠商 power_profile.xml
準確度及源碼有差別,所以不一樣手機、不一樣版本的數據可能有較大差別。java
power_profile.xml
直接影響統計的準確度,而且此文件沒法經過應用修改。再次強調,Android 耗電估算沒有硬件的參與,全靠代碼估算。python
power_profile.xml
文件位於源碼下的 /framework/base/core/res/res/xml/power_profile.xml
,部份內容展現以下:git
<item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA --> <item name="gps.on">0.1</item> <!-- ~50mA --> <!-- Current consumed by the radio at different signal strengths, when paging --> <array name="radio.on"> <!-- Strength 0 to BINS-1 --> <value>0.2</value> <!-- ~2mA --> <value>0.1</value> <!-- ~1mA --> </array> </array> <!-- Different CPU speeds as reported in /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state --> <array name="cpu.speeds"> <value>400000</value> <!-- 400 MHz CPU speed --> </array> <!-- Current when CPU is idle --> <item name="cpu.idle">0.1</item> <!-- Current at each CPU speed, as per 'cpu.speeds' --> <array name="cpu.active"> <value>0.1</value> <!-- ~100mA --> </array> <array name="wifi.batchedscan"> <!-- mA --> <value>.0002</value> <!-- 1-8/hr --> <value>.002</value> <!-- 9-64/hr --> <value>.02</value> <!-- 65-512/hr --> <value>.2</value> <!-- 513-4,096/hr --> <value>2</value> <!-- 4097-/hr --> </array>
這就是在硬件層面統計時,直接參與運算的參數。不管是軟件耗電統計仍是硬件耗電統計,都經過 BatteryStatsHelper
來進行彙總。BatteryStatsHelper
位於 /framework/base/core/java/com/andorid/internal/os/BatteryStatsHelper.java
下。github
在 BatteryStatsHelper.java
中,有這麼一個方法:算法
private void processAppUsage(SparseArray<UserHandle> asUsers) { final boolean forAllUsers = (asUsers.get(UserHandle.USER_ALL) != null); mStatsPeriod = mTypeBatteryRealtime; BatterySipper osSipper = null; final SparseArray<? extends Uid> uidStats = mStats.getUidStats(); final int NU = uidStats.size(); for (int iu = 0; iu < NU; iu++) { final Uid u = uidStats.valueAt(iu); final BatterySipper app = new BatterySipper(BatterySipper.DrainType.APP, u, 0); mCpuPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); mWakelockPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); mMobileRadioPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); mWifiPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); mBluetoothPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); mSensorPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); mCameraPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); mFlashlightPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType); final double totalPower = app.sumPower(); if (DEBUG && totalPower != 0) { Log.d(TAG, String.format("UID %d: total power=%s", u.getUid(), makemAh(totalPower))); } } ... // code }
processAppUsage()
方法中,一個應用的總功耗在這裏體現出來了:docker
cpushell
Wakelock(保持喚醒鎖)服務器
無線電(2G/3G/4G)網絡
WIFI
藍牙
傳感器
相機
閃光燈
這些數據,將決定着你的應用在耗電排行榜中的位置,以及是否給予用戶警告高耗電。這些警告對於應用來講多是致命的,用戶可能所以而卸載應用。
應用總功耗是上述八個統計值的和。這八個統計器同繼承自 PowerCalculator.java
具體來講,這八個耗電計算器的算法分別以下:
耗電統計概述就如上所述。總的來講並不複雜,經過聚合八種不一樣方式的消耗,來得出總的耗電量,並給予用戶展現。
bugreport
文件可視化。在第一代的 Battery Historian 中,google 使用了 python 做爲數據解析工具。拿到
bugreport
文件後,經過終端執行 python 來生成可視化的 html 文件。這種方法使用起來較爲麻煩,並且沒法部署到服務器。所以在第二代 Battery Historian,google 選擇了使用 docker 容器。如今徹底不推薦使用第一代 Battery Historian,已經許久沒有維護了,並且功能過於簡陋。
須要注意的是 battery-historian 在使用時候不能在充電,同時確保設備運行的 Android 版本是 5.0 及以上。
經過上面的描述,對 battery-historian 的功能有個大概的瞭解,下面進入到實戰。
battery-historian 雖然功能強大,可是也是須要先提供數據的,其數據的獲取須要咱們手動操做。下面介紹如何獲取 bugreports。
adb kill-server
adb devices || adb start-server
3. Android也不記錄特定於應用程序的用戶空間wakelock轉換的時間戳。若是您但願Historian在時間線上顯示關於每一個單獨喚醒鎖的詳細信息,則應在開始實驗以前使用如下命令啓用完整喚醒鎖報告:
adb shell dumpsys batterystats --enable full-wake-history
4. 採集報告前將battery統計狀態重置,重置命令結束後斷開usb,測試結束後用獲取報告命令導出統計文件包
adb shell dumpsys batterystats --reset
adb bugreport bugreport.zip adb bugreport > $HOME/Documents/bugreport.zip // 指定到對應目錄下,具體分機型,可能會有些不同
6.0 或更低版本:
adb bugreport > bugreport.txt
獲取到數據後,接下去就是對數據進行分析了。
使用 battery-historian 是須要搭建環境的,因爲搭建環境比較複雜, 能夠借用別人搭好的線上環境:https://bathist.ef.lc/,點擊打開後,上傳數據,就會獲得詳細的結果。
如圖所示Battery Historian圖表的一個例子:
其中標號的意義是:
標號1:從下拉列表中添加其餘指標;
標號2:將鼠標懸停在信息圖標上能夠查看有關每一個指標的詳細信息,包括圖表中使用的不一樣顏色表明意義的介紹;
標號3:將鼠標懸停在某個條目上能夠查看該指標的更多詳細信息,以及時間線上特定點的耗電量信息;
這是整個手機狀態圖,包括手機電量,CPU 使用時長,wifi 信號的強度,手機溫度變化等等,都在上面詳細的用圖表展現出來了。
Battery Historian除了可以提供宏觀的系統層面的信息,還可以提供針對指定App的可視化數據和表格信息,這表格主要信息包括:
Device estimated power use等基本信息
Networks Information:app網絡信息
Wakelocks:喚醒鎖信息,通常和業務強相關
Services:服務信息,查看App開啓的services信息
Process info:進程信息
Battery Historian圖表下爲數據分析,包括三個Tab,以下圖所示,能夠查看App更多信息:
其中,標號所表明的意義是:
標號1:System Stats 分組包含系統級別的數據,好比屏幕亮度等。這一欄顯示了系統發生的整體狀況,能夠用來測試是否存在外部影響事件;
標號2:App Stats分組包含針對指定APP的詳細信息;
標號3:能夠根據不一樣的分類標準對APP進行排序;
標號4:在下拉列表中選擇指定的APP後可在App Stats中查看具體信息,App Stats所展現的都是所選定App產生的數據,不會受到外部因素的影響;
下面看看具體某個手機的數據,好比百度APP應用的數據,在右邊選擇對應的 APP,左邊就會展現當前 APP 的電量,網絡等狀況。
前面是經過 Battery History 對 bugreport 的文件進行了分析,那若是咱們想本身分析呢?所以,在這裏有必要了解下 bugreport 的文件內容。
能夠經過關鍵字下面的關鍵字來尋找相關信息。
DUMP OF SERVICE
經過該關鍵字能夠查到 wifi, 網絡, activities 等等的信息。