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