IOS app電量測試方法調研
方法一——硬體檢測
通過硬體 PowerMonitor 可以精準地獲得應用的電量消耗。
步驟如下:
- 拆開iOS裝置的外殼,找到電池後面的電源針腳。
- 連線電源監控器的裝置針腳
- 執行應用
- 測量電量消耗
下圖展示了與iPhone的電池針腳連線的電源監控器工具。
enter image description here- 可以精準地獲得應用的電量消耗。
- 裝置價格 $771.00 USD
- 需要拆解手機
方法二——instruments
步驟
1.iOS 設定選項 ->開發者選項->logging ->start recording
enter image description here2.進行需要測試電量的場景操作後進入開發者選項點選stop recording
3.將iOS裝置和Mac連線
4.開啟Instrument,選擇Energy Diagnostics
5.選擇 File > Import Logged Data from Device
enter image description here6.儲存的資料以時間軸輸出到Instrument面板
缺點
1)進行電量測量時,必須斷開iOS device和PC的連線,因此不能通過ui自動化測試的方式執行app操作;2)電量取樣速率為1s/次,電量使用level為0-20,1/20:表示執行該app,電池生命會有20個小時;20/20:表示執行該app,電池電量僅有1小時的生命
測試精確度為5%;
3)電量測試資料只能通過Energy Diagnostics Instruments檢視,不能匯出為cvs檔案,無法計算整體耗電量、平均耗電量,只能手動計算平均值
方法三——api介面呼叫的方式
最初我們用到的是UIDevice類batteryLevel介面。這個介面只能獲取到剩餘電量百分比,目前世面上能見到的所有iOS系統版本都可用,如上文所提到的,他和系統介面上展示的值幾乎沒有區別,唯一不同的是,他是以mAh為單位計的,以這個值計算的剩餘電量百分比,就是系統上顯示的那個值。這樣看來,這個介面也沒有什麼多大的意義。還得繼續嘗試。
接著我們使用到的是IOKit中的IOPMPowerSource介面,私有介面,呼叫方式如下:
在iOS 10及以上的系統上,能獲取到的資訊如下:
看看關鍵資訊:
第三行CurrentCapacity是當前的剩餘電量;
第六行FullyCharged是否滿電量;
第八行IsCharging是否正在充電;
第九行MaxCapacity最大電池容量;
第十行Voltage當前電壓。
資訊是多了一些,有當前電壓值,有剩餘電量。這個有什麼用呢?我們先科普一點點小知識。
首先,某一裝置的電壓,基本是在一定範圍之內變動的,相對穩定的一個值。就像iPhone 6P的電壓,基本是在4V上下。當電池剩餘電量越少時,電壓值會變得越小,但波動不大。電壓過小時,可能會引起手機直接關機,這也是為什麼有時還有20%電量,但手機卻開不了機了。新的電池,電壓波動會小一些,越是老化,電壓波動可能越大。所以電壓這個值能用來判斷當前電池的健康度。
然後是剩餘電量2548,他的單位是mAh。手機電池常用類似1000mAh這樣的標識,這不是具體的電量,光看這個值,能解理到的含義是,以1000mA的電流來放電,能放1小時。或者說,以200mA的穩定電流放電,能放5小時。但明顯這樣意義並不大。因為我們還不知道電池在工作時,會以多少mA的電流工作,所以也就不知道能用多久,我們想知道的是,電池到底還有多少電,這個才是一個具體的值。上面提過,電壓是相對固定的,我們可以算出具體剩餘多少電,以1000mAh,粗略計電壓穩定為4V,根據公式計算得出W=U*I*t=4v*1000mAh=4000mWh。這個就是當前電池剩餘的電量。當計算剩餘電量的百分比的時候,用哪個值去算都一樣了。
以上是IOPMPowerSource介面在iOS10及以上系統上獲取的資訊。但事實上,在iOS 9及以前的系統上,能獲取到更多更詳細的資訊,大部分是一些硬體的固定資訊,對我們測試沒有幫助。但也有一些其他有用的資訊,比如說當前的溫度,電流,都是很有用的資訊,如下圖:
溫度能用來直接判斷當前的發熱情況,電流能直接判斷當前的電池發電功率,都可以有效判斷當前電池的使用狀態。
但是這個介面拿到的資料,仍然是不夠具體,全是整機的電池情況,沒有具體到某一個應用或是其他維度的電量統計。所以,還得繼續摸索。
這一次我們應用到的是BatteryUsageUI.bundle中PLBatteryUsageUIQuery,也是個私有介面。這裡賣個關子,實現就不帖了,有心的同學可以根據我的關鍵字找到具體的東西。這個介面就厲害了,具體得說,他能拿到每一個APP的CPU\GPU\顯示\網路\儲存等前後臺所有詳細資訊,一個巨大的表。
當我們探索到這一步時,激動不已,以為光明就在眼前了。可是事實卻是,這個介面早在iOS9的第一個版本,就完全被封了,只能在iOS 8上的機子上拿到資料。而且經過多次確認後,我們發現,這個資料是每個小時才會更新一次,並不是實時的。
但儘管如此,還是大大得增強了我們繼續探索的信心,我們第一次獲取到了每一個App的電量消耗情況,而且我們很確信,蘋果iOS的電量排行榜,就是根據這些資料計算出來的。因為,我們在這之前,已經發現在越獄環境下有個工具,叫DetailedBatteryUsage,這個外掛只做了一件事情,就是把系統設定裡,電池的顯示方式設定成了“2”,而預設的顯示方式是“0”。設定為“2”以後,就可以在電池設定裡看到很詳細的資訊,如下圖:
跟我們用介面拿到的資料是一致的,所以我們確認電量排行榜資料來至於這個介面,而且,系統一直在呼叫這個介面在統計電量相關的資訊,只是對使用者而言不可見,而且介面也不可見。在越獄環境下能拿到這些資料,對我們定位問題已經有很大的幫助了,但是一方面這些資料是系統顯示出來的,我們處理很不方便,效率也低,另一方面,這些資料只能在越獄的機器上拿到,而目前主流的系統都還是不能越獄的。我們不得不再進一步。
方法四——iOS Diagnostics
什麼是iOS Diagnostics
iOS diagnostics 是iOS系統本身自帶的一套診斷系統,在這個診斷系統中也記錄了電量相關資訊,這些資訊以Sqlite的形式儲存在本地,並定期傳給蘋果伺服器,以供蘋果相關人員分析。由此可以通過讀取iOS系統記錄的資料來進行電量測試,這個資料由iOS系統提供,並且記錄了每個App的耗電量,故可以得到比較準確的耗電量資訊。
蘋果官網提供的電量診斷如圖:
如何獲取diagnostics的電量資料庫
1. iOS10以上裝置
通過查閱蘋果官方的BugReport網站,發現有一項是:Battery Life。通過查閱官方文件發現,這個方式可以自己獲取iOS 診斷的電量資料庫詳細資訊,並通過itunes同步到本地,由此可以拿到相關的電量資料。
蘋果的官方說明:
步驟如下:
A. 使用開發者賬號下載Profile
B. 靜置約半個小時,通過iTunes同步到電腦上
C. 從電腦獲取電量資料庫檔案
對應目錄如下:
macos:~/Library/Logs/CrashReporter/MobileDevice/[Your_Device_Name]/
Windows:C:\Users\[Your_User_Name]\AppData\Roaming\Apple Computer\Logs\CrashReporter\MobileDevice\ [Your_Device_Name]\
D. 電量資料庫以”Powerlog_”開頭,以“.PLSQL” or “.PLSQL.gz”結尾
2. iOS9及以下裝置
提供一個思路:
可以通過 mitmproxy(抓包工具) + diags://123456攔截介面的形式獲得,介面:
如下圖:
電量資料庫的解讀與分析
拿到電量資料庫之後,我們要做的就是通過資料庫中存的電量資訊來幫助我們分析實際App的耗電量。可以下載SqlLiteStudio.dmg來開啟.plsql資料庫檔案。下載地址:http://sqlitestudio.pl/index.rvt?act=download
下面是和電量相關的幾個表:
PLAccountingOperator_EventNone_Nodes | 記錄了所有應用的noteID |
PLAccountingOperator_Aggregate_RootNodeEnergy | 記錄了每個noteID的電量消耗 |
PLAppTimeService_Aggregate_AppRunTime | 記錄了App的執行狀態,一小時記錄一次 |
PLBatteryAgent_EventBackward_Battery | 記錄了整機的電量變化,20秒記錄一次(電壓、電流、溫度等等) |
PLBatteryAgent_EventBackward_BatteryUI | 記錄了整機剩餘電量百分比,20秒記錄一次。(手機螢幕上顯示的剩餘電量正是基於這個資料) |
PLIOReportAgent_EventBackward_EnergyModel | 記錄了IO相關的電量消耗(SoC、DRAM、IPS等等) |
PLSpringBoardAgent_Aggregate_SBNotifications_Aggregat | 記錄了推送通知的時間和數量 |
PLLocationAgent_EventForward_ClientStatus | 定位的相關資訊 |
一方面我們可以獲取整機的電量資料變化情況
附:sql如下
(SELECT datetime(timestamp, 'unixepoch', 'localtime') AS time, Level AS 電量百分比 FROM PLBatteryAgent_EventBackward_BatteryUI;)
通過電量百分比資料可以獲得整機在測試期間的電量變化趨勢圖。
同時,我們也可以精確獲取到App在某個測試時間段的電量消耗。通過記錄下操作場景的時間段,再讀取資料庫的資料,就可以精確獲取該場景在該機器上的電量消耗情況。
通過PLAppTimeService_Aggregate_AppRunTime 表獲取到App的執行情況:
根據App的執行情況從PLAccountingOperator_Aggregate_RootNodeEnergy這個表獲取到App電量消耗情況:
這裡就能很清楚的知道所測試的App在某個時間段詳細的耗電資訊,如2018-03-05上午10點測試某個app時的耗電:
螢幕耗電:47284----56.97%
RestOfSOC耗電:9699----11.68%
CPU耗電:17472----21.05%
WIFI耗電:1995----2.4%
DRAM(記憶體)耗電:2649----3.19%
GPU耗電:3907----4.7%
RootNodeID和裝置名的對應關係是定義在資料表PLAccountingOperator_EventNone_Nodes裡面的。通過如下sql可以關聯查詢出不同裝置的具體耗電量。
附:sql如下
(SELECT datetime(a.timestamp, 'unixepoch', 'localtime') AS time, a.Energy, b.Name AS Device FROM PLAccountingOperator_Aggregate_RootNodeEnergy a,
PLAccountingOperator_EventNone_Nodes b WHERE a.RootNodeID = b.ID AND NodeID = (SELECT ID FROM PLAccountingOperator_EventNone_Nodes WHERE name = "**.**.**");
結合表PLBatteryAgent_EventBackward_Battery可以獲得此段時間該裝置詳細的耗電情況:
附:sql如下
(SELECT datetime(timestamp, 'unixepoch', 'localtime') AS time,Level AS 電量百分比,Voltage AS 電壓,FullAvailableCapacity AS 最大容量,CurrentCapacity AS 當前容量,CycleCount AS 電池迴圈次數,Temperature AS 電池溫度,*FROM PLBatteryAgent_EventBackward_Battery;)
由公式計算出該段時間的耗電量約:W=U*I*t (注意,公式中 I*t即為sql中查詢出來的電容量)
結合前面的耗電百分比得出該段時間App耗電:
螢幕耗電:56.97%*W=493mWh
CPU耗電:21.05%*W=224mWh
Rest of SoC耗電:11.68%*W=107mWh
WIFI耗電:2.4%*W=26mWh
記憶體耗電:3.19%*W=35mWh
GPU耗電:4.7%*W=57mWh
平均電流約:273mA
平均溫度:32.2℃
通過ui自動化做電量測試的探索
我們知道鋰電池充電分成三個階段:預充,恆流,恆壓。恆壓階段就是所謂的涓流充電。電量一般在80%左右往上,即進入恆壓模式,此時充電速度會開始變慢,直到將電池充滿。
也就是說在電池電量低於80%時的恆流階段,電量增加(充電速度)是勻速的。因此可以考慮將電池電量低於80%時,做UI自動化測試,然後將採集的電量資料除去充電補償電量就可以得到測試階段app的實際耗電量了。單位時間的充電補償電量可以以同一測試手機連線同一電腦同一usb介面充電時電池容量從20%充電到70%的平均速度進行計算。
總結
iOS Diagnostics電量測試步驟:
1.裝上對應的system debug證書;
2.選定測試場景以及時長;
3.記錄開始時的剩餘電量,執行測試,記錄下哪個時間段對應的是哪個場景;
3.執行測試完成後,精置半小時,取下系統的電量資料庫,對該次測試的各個場景的耗電量做一個全面的評價。
注意事項:
1.給手機充放電,讓手機剩餘電量在我們預設的值——比如90%——每個場景測試開始時,保證手機都是這一電量;
2.手機系統設定,一般要關注螢幕亮度、藍芽、定位、通知訊息、音量、其它後臺應用等等,為排除對被測應用的影響,通常是全部關閉或調到最小即可。