一、電源管理基礎(chǔ)知識(shí)
1.1電源管理的幾種狀態(tài)
Android kernel源碼中,定義了三種電源狀態(tài),在kernel/power/suspend.c中:
對(duì)應(yīng)的宏定義/include/linux/suspend.h
1.2 電源管理狀態(tài)的介紹:
PM_SUSPEND_ON
設(shè)備處于正常工作狀態(tài)
PM_SUSPEND_STANDBY
設(shè)備處于省電狀態(tài),但還可以接收某些事件
PM_SUSPEND_MEM
設(shè)備進(jìn)入睡眠狀態(tài),保存系統(tǒng)運(yùn)行的上下文至內(nèi)存后掛起系統(tǒng),只有特定外部中斷才可以喚醒設(shè)備
PM_SUSPEND_TO_IDLE
設(shè)備進(jìn)入空閑狀態(tài),凍結(jié)用戶空間并將外圍設(shè)備調(diào)至低耗電模式,強(qiáng)制將 CPU 進(jìn)入idle
ADB 查看支持的電源模式
cat /sys/power/state
1.3 Idle State
Android的Idle狀態(tài)分為二類:CPU Idle和Device Idle
CPU Idle
每一個(gè) CPU 核心都會(huì)有一個(gè) idle 進(jìn)程,idle 進(jìn)程是當(dāng)系統(tǒng)沒(méi)有調(diào)度 CPU 資源的時(shí)候,會(huì)進(jìn)入 idle 進(jìn)程,而 idle 進(jìn)程的作用就是不使用 CPU,以此達(dá)到省電的目的。
有關(guān)CPU idle的內(nèi)容可以查看公眾號(hào)之前的文章《Linux Cpuidle介紹》
Device Idle
Device Idle屬于android Doze模式中的概念,即指手機(jī)屏幕熄屏、不充電、靜置不動(dòng)
在 Doze 模式下,按照google的官方說(shuō)法,Wakelocks,網(wǎng)絡(luò)訪問(wèn),jobshedule,鬧鐘,GPS/WiFi掃描都會(huì)停止。
系統(tǒng)會(huì)定期退出 Doze 一小段時(shí)間,讓應(yīng)用程序完成其延遲的活動(dòng)。在此維護(hù)窗口期間,系統(tǒng)運(yùn)行所有掛起的同步、作業(yè)和警報(bào),并允許應(yīng)用程序訪問(wèn)網(wǎng)絡(luò)。
二、Android電源管理框架
Android系統(tǒng)的電源管理框架分成五個(gè)部分:應(yīng)用層,框架層,Native層,HAL層和內(nèi)核層。電源管理架構(gòu)圖例如下:
應(yīng)用接口層: PowerManager.java 負(fù)責(zé)向應(yīng)用程序提供一系列接口,例如wakelock的申請(qǐng)與釋放,進(jìn)而讓系統(tǒng)休眠或喚醒
框架層: PowerManagerService.java PowerManagerServic是android電源管理的核心服務(wù),向上提供應(yīng)用程序接口.向下通過(guò)hal層和kernel層來(lái)控制待機(jī)狀態(tài)和系統(tǒng)硬件設(shè)備狀態(tài)
HAL層: power.c 接收上層參數(shù),通過(guò)寫節(jié)點(diǎn)與kernel層通信
內(nèi)核層: Kernel/Power 實(shí)現(xiàn)系統(tǒng)電源管理框架機(jī)制,為設(shè)備電源管理提供基礎(chǔ)框架
三、WakeLock
Android中wakelock是一種鎖的機(jī)制,用于阻止系統(tǒng)進(jìn)入睡眠狀態(tài),只要有任意應(yīng)用持有wakelock,那么系統(tǒng)就無(wú)法進(jìn)入睡眠狀態(tài)。
newWakeLock(int flags, String tag)
申請(qǐng)wakelock時(shí)有一個(gè)關(guān)鍵的參數(shù)flags,它有如下幾種情況:
PARTIAL_WAKE_LOCK: Screen off, keyboard light off
SCREEN_DIM_WAKE_LOCK: Screen dim, keyboard light off
SCREEN_BRIGHT_WAKE_LOCK: Screen bright, keyboard light off
FULL_WAKE_LOCK: Screen bright, keyboard bright
上面4種是互斥的,即只能指定其中之一,但可以與下面兩種flag不是互斥的:
ACQUIRE_CAUSES_WAKEUP:一旦有請(qǐng)求鎖時(shí)強(qiáng)制打開Screen和keyboard light
ON_AFTER_RELEASE:在釋放鎖時(shí)reset activity timer
如果系統(tǒng)申請(qǐng)了PARTIAL_WAKE_LOCK,那么即使按power鍵,系統(tǒng)也不會(huì)進(jìn)sleep,如music播放時(shí).如果申請(qǐng)了其它的wakelocks,按power鍵,系統(tǒng)還是會(huì)進(jìn)sleep
wakelock有加鎖和解鎖兩種狀態(tài):
一種是永久性鎖住,這種鎖除非后續(xù)放開,否則不會(huì)解鎖;
另一種是超時(shí)鎖,這種鎖會(huì)鎖定系統(tǒng)一段時(shí)間后會(huì)自動(dòng)解鎖。
電源鎖的兩種類型:
(1)WAKE_LOCK_SUSPEND:阻止系統(tǒng)進(jìn)入睡眠,屬于永久性鎖,超時(shí)鎖為WAKE_LOCK_AUTO_EXPIRE
(2)WAKE_LOCK_IDLE:阻止持有該鎖的系統(tǒng)進(jìn)入idle狀態(tài)
Android中使用兩條鏈表分別保存處于active狀態(tài)的suspend lock和idle lock和保存處于inactive狀態(tài)的wakelock。
系統(tǒng)執(zhí)行加放鎖有兩種機(jī)制,第一種是不計(jì)數(shù)鎖,另一種是計(jì)數(shù)鎖??梢酝ㄟ^(guò)PowerManager.WakeLock.setReferenceCounted(boolean value) 來(lái)指定,默認(rèn)為計(jì)數(shù)機(jī)制。這兩種機(jī)制的區(qū)別在于,前者無(wú)論 acquire() 了多少次,只要通過(guò)一次 release()即可直接解鎖。而后者正真解鎖是在( --count == 0 )的時(shí)候,同樣當(dāng) (count == 0) 的時(shí)候才會(huì)去申請(qǐng)加鎖,其他情況 isHeld 狀態(tài)是不會(huì)改變的。所以 wakeLock 的計(jì)數(shù)機(jī)制并不是正真意義上的對(duì)每次請(qǐng)求進(jìn)行申請(qǐng)/釋放每一把鎖,它只是對(duì)同一把鎖被申請(qǐng)/釋放的次數(shù)進(jìn)行了統(tǒng)計(jì)后才去執(zhí)行操作。
3.1wakelock在framework層
內(nèi)核啟動(dòng)完成后,電源管理系統(tǒng)會(huì)在文件系統(tǒng)中建立兩個(gè)節(jié)點(diǎn):
/sys/power/wake_lock
/sys/power/wake_unlock
應(yīng)用程序可以通過(guò)/sys/power/wake_lock申請(qǐng)一個(gè)WAKE_LOCK_SUSPEND 類型的鎖,通過(guò)/sys/power/wake_unlock則可以釋放一個(gè)鎖。內(nèi)核在進(jìn)入suspend之前如果檢測(cè)到某個(gè)鎖沒(méi)有釋放,則會(huì)放棄本次的suspend過(guò)程,直到這個(gè)鎖釋放為止.Android持有電源鎖后可以讓持鎖的進(jìn)程持續(xù)執(zhí)行,即使進(jìn)入了睡眠模式。
如果應(yīng)用崩掉或退出,系統(tǒng)會(huì)自動(dòng)釋放他們獲取的所有電源鎖;如果是在服務(wù)中獲取的,當(dāng)服務(wù)崩掉或注銷時(shí)也會(huì)自動(dòng)釋放;
Framework層有關(guān)電源鎖的內(nèi)容是通過(guò)PowerManagerService類來(lái)實(shí)現(xiàn),這個(gè)類是用來(lái)管理所有應(yīng)用程序申請(qǐng)的wakelock,比如音視頻播放器,camera等申請(qǐng)的wakelock都是通過(guò)這個(gè)類來(lái)管理的。如:
static final String PARTIAL_NAME = "PowerManagerService"
PARTIAL_NAME作為參數(shù)傳遞到底層去。
ADB 調(diào)試命令
echo lockname > /sys/power/wake_lock
加鎖“l(fā)ockname”
echo lockname > /sys/power/wake_unlock
解鎖“l(fā)ockname”
四、Earlysuspend和Lateresume
Early Suspend和Late Resume是Android在標(biāo)準(zhǔn)Linux的基礎(chǔ)上增加的一項(xiàng)特性。當(dāng)用戶空間申請(qǐng)進(jìn)入suspend時(shí),會(huì)先進(jìn)入early suspend狀態(tài).外設(shè)驅(qū)動(dòng)程序可以注冊(cè)early suspend回調(diào)函數(shù),當(dāng)進(jìn)入early suspend時(shí),內(nèi)核會(huì)逐一地調(diào)用這些回調(diào)函數(shù)。例如在進(jìn)入early suspend后,回調(diào)函數(shù)會(huì)通過(guò)屏幕驅(qū)動(dòng)把屏幕和背光都關(guān)閉, 但此時(shí)系統(tǒng)依然在正常運(yùn)行。進(jìn)入early suspend狀態(tài)以后,一旦所有wakelock被釋放,系統(tǒng)馬上會(huì)進(jìn)入真正的suspend流程.
Android 4.4起,也就是引入ART的版本,摒棄了early suspend機(jī)制,改用了fb event通知機(jī)制,后續(xù)Android版本只有suspend、resume以及runtime suspend、runtime resume。
結(jié)語(yǔ)
本文講述了Android電源管理模塊的主要內(nèi)容,旨在讓讀者對(duì)于Android電源狀態(tài)及wakelock有一個(gè)初步的認(rèn)識(shí),方便以后深入介紹內(nèi)核wakelock的實(shí)現(xiàn)和Android的待機(jī)喚醒流程.
審核編輯:劉清
評(píng)論
查看更多