大家都知道目前的手機(jī)剩辟,平板等電子設(shè)備耗電都比較大,Android系統(tǒng)因?yàn)闅v史和開(kāi)源等原因溅话,一直對(duì)耗電支持的不是很好崇败。特別現(xiàn)在很多apk完全不care耗電盅称,動(dòng)不動(dòng)給你裝上全家桶,還會(huì)相互間互相喚醒進(jìn)程后室,簡(jiǎn)直就是流氓軟件缩膝。從現(xiàn)有的應(yīng)用來(lái)說(shuō),為了他們商業(yè)目的岸霹,有很多是類似要求長(zhǎng)期后臺(tái)運(yùn)行的疾层,或者定時(shí)運(yùn)行的,這些服務(wù)對(duì)耗電影響都非常大松申。
雖然Android每次版本大更新云芦,都對(duì)其進(jìn)行了優(yōu)化,加入了很多特性贸桶。比如在Android 5.0加入了JobScheduler API機(jī)制(批處理)舅逸;在Android 6.0加入App Standby(應(yīng)用待機(jī)),Doze休眠機(jī)制;并且在Android7.0谷歌對(duì)Doze休眠機(jī)制做了進(jìn)一步的優(yōu)化皇筛,只要手動(dòng)在后臺(tái)刪掉應(yīng)用卡片琉历,關(guān)屏后該應(yīng)用就會(huì)被很快深度休眠。
但是應(yīng)用開(kāi)發(fā)工程師由于各種原因沒(méi)有使用新的特性水醋,導(dǎo)致用戶感覺(jué)設(shè)備耗電還是很大旗笔。所以國(guó)內(nèi)很多手機(jī)廠家都有對(duì)android系統(tǒng)的耗電進(jìn)行優(yōu)化,從原理來(lái)說(shuō)拄踪,目前這些廠家也是主要對(duì)兩方面進(jìn)行優(yōu)化:
1.減少定時(shí)休眠喚醒頻率蝇恶,比如合并應(yīng)用申請(qǐng)的定時(shí)喚醒鬧鐘來(lái)喚醒已經(jīng)休眠的設(shè)備。
2.減少wake lock的頻率和時(shí)間惶桐。只要系統(tǒng)中存在任一有效的wake_lock撮弧,系統(tǒng)就不能進(jìn)入深度休眠,但可以進(jìn)行設(shè)備的淺度休眠操作姚糊。wake_lock一般在關(guān)閉lcd贿衍、tp但系統(tǒng)仍然需要正常運(yùn)行的情況下使用,比如聽(tīng)歌救恨、傳輸很大的文件等贸辈。
1.通過(guò)kernel log來(lái)查看喚醒次數(shù)
可通過(guò)如下打印來(lái)確認(rèn)喚醒源:
<4>[ 1321.989235] wakeup gpio0: 00000010
具體意思如下:
gpio0:表示是GPIO0
00000010:表示的是GPIO分組從高到低四個(gè)字節(jié)分別是:DCBA,每個(gè)字節(jié)的0-7bit就表示D7-D0 ?C7-C0 ?B7-B0 ?A7-A0.
從這里可以看出上面喚醒的GPIO是:GPIO0 PA4肠槽,對(duì)應(yīng)的是RTC的中斷腳擎淤。
2.通過(guò)上層dumpsys信息來(lái)查看
2.1dumpsys alarm
通過(guò)dumpsys alarm命令打印可以看到哪個(gè)應(yīng)用喚醒次數(shù)比較多,和總共占用的時(shí)間:
Alarm Stats:
com.google.android.gsf +20ms running, 1 wakeups:// alarm喚醒一次
+20ms 1 wakes 1 alarms: cmp={com.google.android.gsf/com.google.android.gsf.checkin.EventLogService$Receiver}
android +44s431ms running, 2 wakeups:// alarm喚醒兩次
+41s632ms 0 wakes 1 alarms: act=com.android.server.action.NETWORK_STATS_POLL
+5s33ms 2 wakes 2 alarms: act=android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED
+4s219ms 0 wakes 1 alarms: act=com.android.server.NetworkTimeUpdateService.action.POLL
+2s202ms 0 wakes 19 alarms: act=android.intent.action.TIME_TICK
com.android.providers.calendar +40s25ms running, 3 wakeups:
這里的喚醒統(tǒng)計(jì)的是:應(yīng)用申請(qǐng)RTC_WAKEUP 或 ELAPSED_REALTIME_WAKEUP的Alarm秸仙。不管系統(tǒng)是否在休眠揉燃,都會(huì)產(chǎn)生Alarm,所以這里的Alarm次數(shù)與第一章中說(shuō)的kernel中統(tǒng)計(jì)的被RTC中斷喚醒的次數(shù)是匹配不上的筋栋,前都會(huì)大于后者炊汤。
看下Android系統(tǒng)定義的休眠喚醒不同的類型。
/**
* Alarm time in {@link android.os.SystemClock#elapsedRealtime
* SystemClock.elapsedRealtime()} (time since boot, including sleep),
* which will wake up the device when it goes off.
*/
public static final int ELAPSED_REALTIME_WAKEUP = 2;
/**
* Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()}
* (wall clock time in UTC), which will wake up the device when it goes off.
*/
public static final int RTC_WAKEUP = 0;
2.2 dumpsys batterystats
這個(gè)信息可以通過(guò)Project Volta里的工具h(yuǎn)istorian.py將其圖形化顯示弊攘。
先導(dǎo)出bugreport
adb bugreport > bugreport.txt
將其轉(zhuǎn)換成圖形化結(jié)果(目前好像只有百度瀏覽器才能打開(kāi)這個(gè)html)
python historian.py -a bugreport.txt | tee battery.html
簡(jiǎn)單說(shuō)明如下:
1.橫軸是時(shí)間
2. wifi_scan指的是wifi處于掃描
3. wifi_running指的是wifi打開(kāi)狀態(tài)
4. screen指的是屏亮的狀態(tài)
5. plugged指的是插入外設(shè)
6. wake_lock指的是kernel中被鎖住的狀態(tài)
3.系統(tǒng)狀態(tài)分析
可通過(guò)screen與wake_lock來(lái)初步確認(rèn)系統(tǒng)是否被喚醒抢腐,如果screen是關(guān)的,然后又有wake_lock襟交,也表明系統(tǒng)被喚醒并被鎖住一段時(shí)間迈倍。
把上層的喚醒和wifi喚醒都關(guān)了,測(cè)試了39個(gè)小時(shí)消耗30%電量
有以下幾個(gè)問(wèn)題:
1.喚醒次數(shù)的確少了捣域,但是healthd每10分鐘喚醒在圖上體現(xiàn)不出來(lái)
2.有2次喚醒后啼染,系統(tǒng)被鎖住10多鐘才休眠下去
查看Alarm狀態(tài)宴合,可以很明顯看到上層沒(méi)有再去wake up
但是驅(qū)動(dòng)中還看到有被RTC喚醒,經(jīng)過(guò)驗(yàn)證是healthd喚醒的迹鹅,不插充電的時(shí)候10分鐘卦洽,插充電的時(shí)候1分鐘間隔。這個(gè)喚醒后就更新battery的信息斜棚,上層Baterry更新下阀蒂,UI刷新下。
系統(tǒng)被鎖住10幾分鐘弟蚀,通過(guò)log分析在wifi斷開(kāi)的時(shí)候蚤霞,gms剛好去連接服務(wù)器,通訊很久造成wake 比較久义钉。從下面的信息可以判斷昧绣,系統(tǒng)目前wake lock線程最多的是gms線程。
Wake lock 在Android的電源管理系統(tǒng)中扮演一個(gè)核心的角色捶闸,wakelock是一種鎖的機(jī)制, 只要有task拿著這個(gè)鎖, 系統(tǒng)就無(wú)法進(jìn)入休眠, 可以被用戶態(tài)進(jìn)程和內(nèi)核線程獲得滞乙。這個(gè)鎖可以是有超時(shí)的或者是沒(méi)有超時(shí)的, 超時(shí)的鎖會(huì)在時(shí)間過(guò)去以后自動(dòng)解鎖。如果沒(méi)有鎖了或者超時(shí)了, 內(nèi)核就會(huì)啟動(dòng)標(biāo)準(zhǔn)Linux的那套休眠機(jī)制機(jī)制來(lái)進(jìn)入休眠鉴嗤。
4.結(jié)論分析
提高電池續(xù)航斩启,也就意味著減少系統(tǒng)和程序的電量消耗。為此 經(jīng)過(guò)測(cè)試發(fā)現(xiàn)醉锅,每次喚醒設(shè)備兔簇,1-2秒的時(shí)候,都會(huì)消耗2分鐘(個(gè)別應(yīng)用更久)的待機(jī)電量硬耍,可見(jiàn)每次喚醒設(shè)備的時(shí)候垄琐,不僅僅是點(diǎn)亮了屏幕,系統(tǒng)也在后臺(tái)處理很多事情经柴。
電池消耗比較大狸窘,從系統(tǒng)的行為上分析,有兩個(gè)地方影響最大
1.系統(tǒng)在被喚醒的期間坯认,被一些應(yīng)用wake lock比較久翻擒,造成很久時(shí)間無(wú)法再進(jìn)入二級(jí)休眠。
2.系統(tǒng)頻繁的被喚醒牛哺,系統(tǒng)被喚醒目前包含三個(gè)喚醒源
(1).系統(tǒng)上層通過(guò)AlarmMananger的接口注冊(cè)rtc喚醒陋气,
(2).wifi芯片自動(dòng)喚醒,
(3).電池healthd定頻喚醒引润。
所以如果應(yīng)用比較多的時(shí)候巩趁,應(yīng)用在喚醒期間動(dòng)作比較多,容易造成系統(tǒng)被wake lock淳附,從而不會(huì)很快的進(jìn)入二級(jí)休眠议慰。
通過(guò)上述的分析來(lái)看蠢古,系統(tǒng)可以優(yōu)化的地方有4個(gè)方面。
1).查看系統(tǒng)wake lock最多的線程别凹,看能不能優(yōu)化草讶。
2).系統(tǒng)上層過(guò)濾的應(yīng)用喚醒行為,從而降低喚醒頻率番川。AlarmManager包含四種類型定時(shí)策略到涂,AlarmManager.ELAPSED_REALTIME脊框、AlarmManager.ELAPSED_REALTIME_WAKEUP颁督、AlarmManager.RTC、AlarmManager.RTC_WAKEUP浇雹、AlarmManager.POWER_OFF_WAKEUP沉御。
其中應(yīng)用申請(qǐng)RTC_WAKEUP或ELAPSED_REALTIME_WAKEUP的Alarm在系統(tǒng)休眠的情況下會(huì)喚醒系統(tǒng)。通過(guò)建立白名單或者黑名單的方式過(guò)濾此種應(yīng)用的喚醒行為
3).定時(shí)批處理一批操作昭灵,壓縮硬件喚醒時(shí)間吠裆,就像心跳一樣,讓硬件充分休息烂完,還有就是精確監(jiān)測(cè)應(yīng)用請(qǐng)求试疙,智能安排請(qǐng)求執(zhí)行時(shí)間,讓資源利用最大化抠蚣。
4).擴(kuò)大healthd的定頻喚醒間隔(適度不然造成電池電量不準(zhǔn))
最后改一張調(diào)整過(guò)的電池狀態(tài)圖: