袁宜霞
(廣東省外語藝術(shù)職業(yè)學(xué)院,廣東廣州 510000)
隨著5G 網(wǎng)絡(luò)的普及帶來了移動互聯(lián)網(wǎng)的巨大發(fā)展,移動終端的App 應(yīng)用越來越多,使用場景越來越豐富,使用頻率也越來越高,使得移動終端電量消耗過快的問題日益突出。移動終端的電池電量是非常有限的,保持持久的續(xù)航能力尤為重要。App研發(fā)團(tuán)隊(duì)必須慎重檢查電量的使用,以免導(dǎo)致用戶手機(jī)耗電發(fā)熱,帶來不良體驗(yàn)。
移動終端電池不耐用有兩方面原因:一方面是手機(jī)硬件和操作系統(tǒng)的問題,另一方面是移動應(yīng)用App的問題,例如:隨意自啟動,頻繁在后臺多次喚醒,搶占桌面、通知欄和懸浮窗等。本文著重于關(guān)注Android 移動應(yīng)用App 對電量帶來的影響,總結(jié)導(dǎo)致電量消耗過快的常見原因,介紹Android 電量相關(guān)測試與優(yōu)化技術(shù),并以案例的方式,針對典型問題提出相應(yīng)優(yōu)化措施,進(jìn)一步有效地提升App電量方面的用戶體驗(yàn)。
圖1是一個典型的智能手機(jī)硬件架構(gòu)圖[1]。
圖1 智能手機(jī)的硬件架構(gòu)[1]
當(dāng)智能手機(jī)待機(jī)時,主板可以直接關(guān)閉應(yīng)用處理器、無線網(wǎng)卡和顯示器等外設(shè)的供電電源,而基帶處理器、蜂窩話音和射頻設(shè)備等需持續(xù)供電,保證繼續(xù)等待來電、搜索網(wǎng)絡(luò)等功能[1]。
GPS、SD 卡、相機(jī)、傳感器、音頻、藍(lán)牙組件的耗電較少,而CPU、屏幕和射頻通信(蜂窩話音、蜂窩數(shù)據(jù)和Wi-Fi)的耗電量較大,需要特別關(guān)注[2]。
關(guān)于CPU,本文將從計算類型和頻率方面進(jìn)行分析。
1)計算類型
縮短應(yīng)用程序代碼產(chǎn)生指令運(yùn)行的時間,從而減少應(yīng)用程序?qū)PU時間片的占用總時間,進(jìn)而降低單位時間內(nèi)目標(biāo)應(yīng)用程序在整臺手機(jī)耗電的百分比。例如:在對算法性能要求高的應(yīng)用程序中建議減少大整數(shù)除法的操作。
2)頻率
CPU 在不同頻率工作時,需要的電壓是不同的,提高電壓將直接提高CPU的耗電。電量=電流*時間,CPU工作的同時也會帶著顯示器等其他耗電組件一起運(yùn)作,隨著時長的增加,單位運(yùn)算量所耗費(fèi)的電量也跟著增加。因此,App 運(yùn)行時提高CPU利用率,減少sleep的使用將能減少耗電量。
手機(jī)顯示屏主要是LCD和OLED 兩個大類:LCD是背光源發(fā)光,在背光燈泡亮度一定的情況下,顯示不同顏色時耗電是一樣的;OLED 是主動發(fā)光,顯示不同顏色時,每個LED單元的功耗不同,所以整體功耗不同。全白顏色時OLED 耗電是LCD的3 倍,全黑顏色時LCD 耗電是OLED 的10 倍,30%白色時OLED和LCD耗電一樣[3]。
對于LCD屏幕,需要重點(diǎn)關(guān)注屏幕亮度(0-255)的取值,值越大耗電量越大。一樣的圖片,最亮亮度下LCD屏幕的耗電量是最暗亮度下的2~3倍[3],所以選擇適當(dāng)?shù)牧炼葘⒛芙o應(yīng)用程序帶來更優(yōu)的省電效果;對于OLED 屏幕,不但要關(guān)注屏幕亮度,還要關(guān)注每個像素的RGB值,例如:Super AMOLED 最高亮度時全黑比全白節(jié)省電量60%[3],所以應(yīng)用程序UI界面應(yīng)多采用深色調(diào)。
1)蜂窩數(shù)據(jù)
蜂窩數(shù)據(jù)組件在以下三種狀態(tài)中切換:①高功率狀態(tài):在這個狀態(tài)下蜂窩數(shù)據(jù)需申請使用專享信道與基站進(jìn)行通訊。當(dāng)數(shù)據(jù)傳輸活動停止超過一個固定時間閾值時,狀態(tài)遷移至低功率狀態(tài);②低功率狀態(tài):在這個狀態(tài)下蜂窩組件釋放了專享信道資源,使用共享公用信道與基站進(jìn)行信令通訊。這個狀態(tài)下耗電比高功率狀態(tài)低20%以上。當(dāng)傳輸空閑時間超過特定閾值時,狀態(tài)遷移至空閑狀態(tài);③空閑狀態(tài):這個狀態(tài)下蜂窩組件只接收尋呼信息。這個狀態(tài)的功耗為高功率狀態(tài)的六十分之一。
經(jīng)測試,傳輸3 秒的數(shù)據(jù),蜂窩數(shù)據(jù)組件需要約16 秒時間才能回到耗電量最低的空閑狀態(tài)。因此,在蜂窩數(shù)據(jù)下,采用將大量碎片數(shù)據(jù)一起打包后,等待較大的時間間隔再進(jìn)行依次整體傳輸?shù)牟呗?,將會更省電?/p>
2)Wi-Fi
Wi-Fi 耗電需要關(guān)注2個因素:每秒發(fā)送和接收的包數(shù)(包率)和網(wǎng)速(通道率)。Wi-Fi組件在活動狀態(tài)下有四種模式:低功率、高功率、低傳輸、高傳輸。當(dāng)Wi-Fi組件從低或高功率狀態(tài)開始傳輸數(shù)據(jù)時,短暫地進(jìn)入相應(yīng)的低或高傳輸狀態(tài),發(fā)送完畢就回到之前相應(yīng)的狀態(tài)。當(dāng)進(jìn)行高速傳輸時,Wi-Fi 組件在高傳輸狀態(tài)維持的時間非常短。
綜上,用Wi-Fi 傳輸數(shù)據(jù)時,在不超過最大傳輸單元的情況下,增大每個包的大小并降低發(fā)包的頻率能夠節(jié)省電量。
為了適應(yīng)嵌入式設(shè)備省電的需要,Linux 操作系統(tǒng)實(shí)現(xiàn)了一套休眠和喚醒的機(jī)制,Android 沿用了這套機(jī)制并有新的改進(jìn)。Early suspend:一種新的系統(tǒng)狀態(tài)。顯示器被關(guān)閉,重力感應(yīng)器、觸摸屏進(jìn)入掛起狀態(tài),但是其他設(shè)備繼續(xù)工作,系統(tǒng)依然進(jìn)行任務(wù)處理,比如掃描SD卡文件。Late resume:一種新的系統(tǒng)操作。喚醒進(jìn)入Early suspend狀態(tài)的設(shè)備。
當(dāng)系統(tǒng)進(jìn)入休眠時,CPU 掛起,所有用戶態(tài)應(yīng)用程序和內(nèi)核態(tài)的進(jìn)程全部被凍結(jié),按照各個設(shè)備注冊的順序調(diào)用外圍設(shè)備的suspend 回調(diào)函數(shù),執(zhí)行每個外圍設(shè)備的suspend,使核心設(shè)備和CPU進(jìn)行休眠,直到系統(tǒng)被某種原因喚醒才會解除。此時系統(tǒng)只有系統(tǒng)時鐘RTC(Real-Time Clock)在進(jìn)行工作。
為了喚醒CPU,終端軟件需要設(shè)置鬧鐘alarm。底層系統(tǒng)提供了兩種類型的時鐘,軟時鐘Timer 與硬時鐘RTC。Android系統(tǒng)提供AlarmManager 這個API,其對應(yīng)AlarmManagerServie服務(wù)程序,該服務(wù)程序在系統(tǒng)啟動時被啟動并初始化鬧鈴設(shè)備,一共有四種Alarm 類型:RTC_WAKEUP、RTC、ELAPSED_REALTIME_WAKEUP、ELAPSED_REALTIME[4]。
在特定使用場景下(例如:資源下載),應(yīng)用程序需要喚醒系統(tǒng)并且讓系統(tǒng)在一段時間內(nèi)保持喚醒。因此,Android 系統(tǒng)提供了一種鎖機(jī)制,只要進(jìn)程持有wake lock,系統(tǒng)就無法進(jìn)入休眠狀態(tài),這將會帶來較大的耗電量。所以,關(guān)注應(yīng)用程序中alarm和wake lock的使用是否合理對于節(jié)省電量十分重要。
目前,各種應(yīng)用程序耗電量評估系統(tǒng)主要都是通過CPU利用率來估算每個應(yīng)用程序所消耗的電量,部分系統(tǒng)也會根據(jù)其他硬件設(shè)備(屏幕、蜂窩數(shù)據(jù)、Wi-Fi等)使用時長來修正應(yīng)用程序的耗電量。
移動終端App 電量測試是為了找出被測試的應(yīng)用程序中不合理消耗電量的場景,從而進(jìn)行代碼優(yōu)化,達(dá)到省電的目的。省電優(yōu)化需要盡可能減少對各類資源占用的時間,例如:CPU、網(wǎng)絡(luò)、屏幕、GPS、相機(jī)、SD 卡等。而不合理耗電的場景往往并不是在應(yīng)用程序前臺操作的過程中,而是在后臺使用場景。
典型的后臺使用場景:當(dāng)用戶按返回鍵或者HOME 鍵時,終端應(yīng)用程序退出UI 界面,UI 主線程會停止運(yùn)行。如果應(yīng)用程序進(jìn)程中不含service,等待3秒后,該進(jìn)程會進(jìn)入“緩存進(jìn)程”列表,點(diǎn)選“顯示緩存進(jìn)程”或者執(zhí)行PS 命令才能看見這個進(jìn)程?!熬彺孢M(jìn)程”與正在運(yùn)行的進(jìn)程相比,僅僅是UI主線程是否運(yùn)行的區(qū)別,創(chuàng)建出來的子線程仍然可以繼續(xù)執(zhí)行,從而為后臺執(zhí)行邏輯代碼進(jìn)行不合理耗電帶來了可能性。以下是需要重點(diǎn)關(guān)注的會在后臺執(zhí)行的耗電API 和對象:java.lang.Thread.new()、ThreadPool.addTask()、run()、Handler.sendMessageDelayed()、java.util.Timer、Thread.sleep、AlarmManager。
手機(jī)滅屏后進(jìn)入的休眠狀態(tài)是移動終端大部分時間所處的狀態(tài)。timer 和sleep 底層都是通過線程信號量來控制調(diào)度的,用的是軟時鐘的計數(shù)器,只統(tǒng)計CPU 運(yùn)行過的相對時間間隔,所以在手機(jī)休眠后,java.util.Timer 和Thread.sleep 會停止。但是,alarm在系統(tǒng)休眠后使用的是RTC的硬時鐘鬧鐘,即可以通過RTC 芯片引腳信號喚醒系統(tǒng)執(zhí)行邏輯,所以,即使手機(jī)休眠了,AlarmManager 還是會持續(xù)工作。綜上,如果AlarmManager使用不當(dāng)將會帶來終端的極大耗電。
本文將分別通過CPU、屏幕顯示和網(wǎng)絡(luò)三個方面的案例,對典型問題提出電量測試方法和相應(yīng)優(yōu)化措施,從而有效地提升App的電量方面的用戶體驗(yàn)。
如下為CPU 相關(guān)概念,CPU 頻率:執(zhí)行相同周期個數(shù)時,CPU主頻越快,那么耗時就越短;CPU時間片:每隔N個高電頻脈沖,時鐘計數(shù)器加1,把自然時間分成固定的小塊,每一塊為一個時間片,手機(jī)一般是10ms,單位是jiffies。于是,機(jī)器時間都轉(zhuǎn)化為用時間片的個數(shù)來衡量;CPU 利用率:指CPU 執(zhí)行非系統(tǒng)空閑進(jìn)程的時間除以CPU總的執(zhí)行時間。
通過CPU 利用率來估算應(yīng)用程序占移動終端系統(tǒng)耗電的百分比是可行的,但操作應(yīng)用程序時,CPU 利用率是一段比值波動的曲線,表示進(jìn)程占用CPU 的百分比,不能定量地評估CPU 的具體消耗,精準(zhǔn)度不高。電量=電流*時間,CPU 利用率高手機(jī)電流就高,但是不一定電量大,還需要看占用CPU 運(yùn)行的時間長短。為了精準(zhǔn)量化應(yīng)用程序?qū)PU的消耗,測試人員需要固定CPU 頻率后獲取執(zhí)行操作進(jìn)程所占用的CPU 時間片總數(shù)。具體操作為:
首先,修改/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq的設(shè)置來固定CPU頻率;然后,電量測試開始前和結(jié)束后,通過如下命令獲得被測試的應(yīng)用程序的進(jìn)程在用戶態(tài)和系統(tǒng)態(tài)消耗的CPU時間片總數(shù):cat/proc/1/stat。此命令會顯示進(jìn)程處于用戶態(tài)的時間utime 和進(jìn)程處于內(nèi)核態(tài)的時間stime,單位是jiffies。最后,電量測試開始前和結(jié)束后得到的utime+stime總數(shù)相減的差值就是被測試應(yīng)用程序所消耗的CPU時間片。
1)典型案例——CPU頻繁輪詢耗電的問題分析:①應(yīng)用程序的線程頻繁監(jiān)聽桌面事件:無論移動終端是否關(guān)閉屏幕以及應(yīng)用程序是否正在被使用,線程一直在輪詢檢測棧頂task(耗時0.2秒),每秒發(fā)出2次廣播,5個監(jiān)聽者輪流去判斷棧頂task 是否為桌面(耗時1 秒);②應(yīng)用程序的線程頻繁檢測前臺服務(wù)是否活著:每5秒進(jìn)行1次檢查。
2)典型案例——CPU頻繁輪詢耗電的解決辦法:①移動終端開啟屏幕且不再使用應(yīng)用程序,應(yīng)用程序的線程0.5s輪詢一次,棧頂發(fā)生變化再對外廣播;②移動終端開啟屏幕且正在使用應(yīng)用程序,應(yīng)用程序的線程30s輪詢一次,棧頂發(fā)生變化再對外廣播;③移動終端滅屏的時候停止應(yīng)用程序的輪詢線程。
測試結(jié)論:在用戶退出應(yīng)用程序以及移動終端滅屏的時候,停止頻繁的輪詢能大大減少電量的消耗。
Android系統(tǒng)的動畫性能不高,在進(jìn)行Android應(yīng)用程序開發(fā)時,遵循以下措施將能減少不必要的電量消耗:減少動畫的長時間展示;合理控制動畫繪制幀率,測試數(shù)據(jù)表明:動畫繪制幀率為每秒40 幀時CPU 占比50%,繪制幀率為每秒10 幀時CPU占比10%,兩者的耗電量相差1倍;僅在顯示動畫的時候才執(zhí)行渲染邏輯,當(dāng)移動終端滅屏或動畫消失的時候立刻停止渲染邏輯避免不必要的電量消耗;提高動畫繪制效率,減少繪制次數(shù)和單次耗時;合理選擇動畫的亮度,因?yàn)樽盍亮炼认翷CD屏幕的耗電量是最暗亮度下的2~3 倍;合理使用暗配色動畫,因?yàn)镺LED屏幕為全黑顏色比全白顏色要節(jié)電60%。
1)典型案例——播放動畫顯示耗電的問題分析:①應(yīng)用程序使用了呼吸動畫效果,CPU 占用高達(dá)50%;②應(yīng)用程序動畫的繪制幀率高達(dá)每秒40 幀;③應(yīng)用程序只有一套較為耗電的白色系背景。
2)典型案例——播放動畫顯示耗電的解決辦法:①應(yīng)用程序不使用呼吸動畫效果,采用其他樣式的動畫;②調(diào)整應(yīng)用程序動畫的繪制頻率為每秒10 幀的時候,足以滿足用戶的視覺效果需求;③為應(yīng)用程序增加一套暗色系背景,讓用戶可以自由選擇背景,也能進(jìn)一步降低應(yīng)用程序的電量消耗。
通過如上的幾種優(yōu)化方法,應(yīng)用程序的電量消耗大幅減少。
對于Android 終端要獲取服務(wù)器上不定時更新的信息,例如:微信用戶需要及時獲得其他用戶發(fā)來的信息,通常有兩種方法:第一種是客戶端使用PULL(拉)的方式,隔一段時間就去服務(wù)器上獲取信息,看看是否有新的信息;第二種就是服務(wù)器使用PUSH(推送)的方式,當(dāng)服務(wù)器端有新信息了,服務(wù)器主動把最新的信息Push 到客戶端上。相對于PUSH 方式,頻繁的PULL 方式會帶來客戶端的網(wǎng)絡(luò)流量和電量的過度消耗。所以,絕大部分應(yīng)用程序都是采用PUSH機(jī)制。國內(nèi)Android App需要實(shí)現(xiàn)一套PUSH 服務(wù),一般會使用小于5 分鐘的周期發(fā)送心跳數(shù)據(jù)包與后臺云服務(wù)保持通訊鏈路[5]。這種方案意味著Android手機(jī)每天將從待機(jī)省電狀態(tài)被喚醒近300次,手機(jī)每天有15%~20%的電量被消耗在發(fā)送過度頻繁的心跳上,所以,在待機(jī)PUSH機(jī)制方面的電量優(yōu)化考慮是很有必要的。
1)典型案例——待機(jī)PUSH 機(jī)制耗電的問題分析:①應(yīng)用程序與后臺維持長連接等待接收push 消息;②應(yīng)用程序使用sleep 方式每隔5分鐘發(fā)送1個心跳包到后臺云服務(wù);③應(yīng)用程序開啟另一個線程每5分鐘用alarm保持2分鐘wake lock。
2)典型案例——待機(jī)PUSH 機(jī)制耗電的解決辦法:①應(yīng)用程序與后臺維持長連接等待接收push消息;②應(yīng)用程序每隔5分鐘用alarm和wake lock給后臺云服務(wù)發(fā)送心跳包后立即釋放wake lock。
PUSH 機(jī)制優(yōu)化前的耗電量明顯高于優(yōu)化后,主要原因在于優(yōu)化前的方案持有喚醒鎖的時間過長。綜上,結(jié)合項(xiàng)目實(shí)際情況,應(yīng)用程序采用合理的PUSH機(jī)制能節(jié)省大量電能消耗。
在全民積極擁抱移動互聯(lián)網(wǎng)的時代,越來越多的用戶關(guān)注應(yīng)用程序?qū)﹄娏康南?。研發(fā)團(tuán)隊(duì)不斷累積優(yōu)秀開發(fā)技術(shù)的同時,測試人員也可以從移動終端的硬件和軟件系統(tǒng)架構(gòu)分析出耗電本質(zhì),進(jìn)行可靠的電量測試,并總結(jié)出電量優(yōu)化措施,協(xié)助研發(fā)團(tuán)隊(duì)打造精品應(yīng)用程序。