深刻淺出Android App耗電量統計

前言html

    在Android統計App耗電量比較麻煩,直至Android 4.4,它仍沒公開「電量統計」API或文檔……額,是的,僅沒有公開,並非沒有。平時在手機「設置- 電量」看到的數據java

    Image

    就是系統調用內部API的統計結果。android

 

基礎概念web

    1. 手機由衆多「部件」組成,所謂「部件」是指:CPU,WIFI,GPS....因此,Android App消耗總電量爲 App運行過程當中,涉及各部件的消耗電量的總和。
    2. 假設運行App致使CPU運行,時間:t,CPU單位時間消耗電量:w,則App的CPU耗電量爲:W = w*t,而有物理公式 W = U*I*t(U:電壓值,I:電流值),在手機中,通常U恆定不變,因此,能夠單獨經過 Q(電容量,單位: mAh)= I * t 表示電量
 
系統源碼分析

    核心源碼/packages/apps/Settings/src/com/android/settings/fuelgauge/PowerUsageSummary.javaapp

    核心類tcp

        - BatteryStatsImpl:提供App各部件運行時間。函數

        - PowerProfile:提供部件電流數值。源碼分析

    問題ui

        - Android怎樣存儲與讀取App耗電量信息(即:BatteryStatsImpl數據怎麼來的?)google

        - Android怎麼存儲部件電流數值(即:PowerProfile數據怎麼來的?)

        - Android具體耗電量計算方法

 

    1. Android怎樣存儲與讀取App耗電量信息

        (1)先看下PowerUsageSummary.java如何獲取BatteryStatsImpl?

         Image(1)

        Image(2)

        Image(3)

        可見 BatteryStatsImpl 經過 系統服務「batteryinfo」得到。

     

        (2)系統服務「batteryinfo」是什麼玩意呢?(見:BatteryStatsService.java

        Image(4)

        系統服務「batteryinfo」其實就是BatteryStatsService,而BatteryStatsService「惟一的」構造函數提供了一個很重要的信息:filename!

      

        (3)BatteryStatsService在哪裏建立?filename是什麼?(見:ActivityManagerService.java

        Image(5)

        filename文件是:/data/system/batterystats.bin,關於batterystats.bin,以前民間不少文章說它用做電池校訂,但Android工程師Dianne Hackborn在google+上明確:

        Image(6)

        betterystats.bin文件僅僅是一個記錄不一樣app使用電量的一個文件。

 

        (4)再看看 BatteryStatsImpl(String filename) 構造函數(見:BatteryStatsImpl.java

        Image(7)

        這裏只作了些基本的初始化。真正載入betterystats.bin數據是在(ActivityManagerService.java)mBatteryStatsService.getActiveStatistics().readLocked();

        Image(8)

        Image(9)

 

        至此,Android怎樣存儲與讀取App耗電量信息分析結束。

        總結:

        (1)ActivityManagerService 建立並初始化 BatteryStatsService,並傳入耗電量記錄文件batterystats.bin;

        (2)BatteryStatsService 在內部建立 BatteryStatsImpl 實例,並傳入耗電記錄文件batterystats.bin;

        (3)ActivityManagerService 執行 mBatteryStatsService.getActiveStatistics().readLocked();致使 BatteryStatsService 的 BatteryStatsImpl 加載batterystats.bin數據;

        (4)在PowerUsageSummary計算App耗電量時,PowerUsageSummary從BatteryStatsService 中獲取BatteryStatsImpl 實例,從而得到App的相關數據。

 

    2. Android怎麼存儲部件電流數值

        (1)比較簡單,見 PowerProfile.java

        Image(10)

        PowerProfile讀取資源 com.android.internal.R.xml.power_profile,並把數據加載到sPowerMap。

 

        (2)com.android.internal.R.xml.power_profile在哪裏?

        在官方文檔《Power Profiles for Android》明確了power_profile.xml位置:device///frameworks/base/core/res/res/xml/power_profile.xml。

        下面是一個samsung的power_profile.xml

        Image(11)

        字段含義見《Power Profiles for Android》。

 

        (3)每一個OEM廠商有本身獨立的power_profile.xml配置

        官方文檔代表:OEM廠商應該有本身的power_profile.xml,由於部件(如:cpu, wifi…)耗電量應與具體硬件相關,這個只有OEM廠商清楚……

        Image(12)

  

        (4)PowerProfile關鍵API:

        - public double getAveragePower(String type):返回type的電流值(mA),type表示power_profile.xml中的某關鍵字(如:gps.on)。

        - public double getAveragePower(String type, int level) :返回type的電流值(mA),level表示xml中array的第幾個value。

 

        至此,Android怎麼存儲部件電流數值分析結束。

        總結:

        (1)Android部件電流信息存於:power_profile.xml

        (2)每一個OEM廠商有私有power_profile.xml

        (2)PowerProfile讀取power_profile.xml,並提供API訪問部件電流數值。

 

    3. Android具體耗電量計算方法

        App耗電量統計:processAppUsage()  

        硬件耗電量統計:processMiscUsage()

 

        processAppUsage()分析

            【1】processAppUsage耗電量統計的 時間段 是?

            Image(13)

            Image(14)

            關於統計的 時間段,BatteryStats有4個選項:

            Image(15)

            可見,processAppUsage 是 上一次拔掉設備後 ~ 至今 的App耗電量統計。

          

            【2】processAppUsage 的統計對象真的是App?

            Image(16)

            具體的 統計流程 都在for循環裏,額……因此processAppUsage真實統計粒度是Uid。

            Uid與App關係:2個App簽名和sharedUserId相同,則在運行時,他們擁有相同Uid。就是說processAppUsage統計的多是多個App的耗電量數據,對於普通App,出現這種狀況的概率較少,而對於Android系統應用則較爲常見。

 

            【3】耗電量計算公式 - 部分1:計算Uid屬下每一個Process的耗電量數據,並求和。

            Uid_Power1 = (Process1_Power + … + ProcessN_Power);

            Process_Power = (CPUSpeed_Time * POWER_CPU_ACTIVE);

            Image(17)

 

            【4】耗電量計算公式 - 部分2:計算Uid的wake lock耗電量

            這裏,Android只計算了partial wake lock的耗電量。

            Uid_Power2 = PartialWakeLock_Time * POWER_CPU_WAKE

            Image(18)

 

            【5】耗電量計算公式 - 部分3:計算Uid的數據流量(data traffic)耗電量

            Uid_Power3 = ( tcpBytesReceived + tcpBytesSent ) * averageCostPerByte

            Image(19)

            Image(20)

 

            【6】耗電量計算公式 - 部分4:計算Uid WIFI耗電量。

            Uid_Power4 = wifiRunningTimeMs * POWER_WIFI_ON

            Image(21)

 

            【7】耗電量計算公式 - 部分5:計算Uid其餘傳感器耗電量。

            Uid_Power5 = (Sensor1_Power + … + SensorN_Power)

            Sensor_Power = Sensor_Time * Power_Sensor

 

            至此,App耗電量計算方法分析結束。硬件耗電量統計(processMiscUsage())亦相似。

            總結App耗電量計算公式:

                Uid_Power(App耗電量,單位:mAh) = Uid_Power1 + Uid_Power2 + Uid_Power3 + Uid_Power4 + Uid_Power5

                    Uid_Power1 = (Process1_Power + … + ProcessN_Power);

                        - Process_Power = (CPUSpeed_Time * POWER_CPU_ACTIVE);

                    Uid_Power2 = PartialWakeLock_Time * POWER_CPU_WAKE              

                    Uid_Power3 = ( tcpBytesReceived + tcpBytesSent ) * averageCostPerByte

                    Uid_Power4 = wifiRunningTimeMs * POWER_WIFI_ON

                    Uid_Power5 = (Sensor1_Power + … + SensorN_Power)

                        - Sensor_Power = Sensor_Time * Power_Sensor

 
            說這麼多,來一發……不,來一個統計耗電量的App吧,其實,以前已有人把這段Android系統代碼摳出來,作了一個App,能夠到 這裏下載
 
--------------我是一個分割線--------------
 
            有一個好消息是:android5.0後,獲取電量數據不用這麼痛苦了,dumpsys  batterystats數據中。包含: Estimated power use (mAh):,下面就是每一個uid的耗電量,只要把app下全部uid耗電量加起來便可!
相關文章
相關標籤/搜索