Android電源管理基礎知識整理

前言

本文主要圍繞如下問題進行知識收集整理:

  1. 待機况木、睡眠與休眠的區(qū)別启盛?
  2. Android開發(fā)者官網(wǎng)當中提到“idle states”榛了,該如何理解,這個狀態(tài)會對設備及我們的程序造成何種影響名挥?
  3. 進入Doze模式中的idle狀態(tài),我們的程序還能運行嗎主守?
  4. 手機睡眠之后禀倔,為何我們寫Alarm程序、來電顯示程序依舊會生效参淫?

如果你也有以上疑問救湖,那么本文會對你解開疑惑有一定的幫助

ACPI簡介

要理解第一個問題,得先從ACPI(高級配置與電源接口)說起黄刚,ACPI是一種規(guī)范(包含軟件與硬件)捎谨,用來供操作系統(tǒng)應用程序管理所有電源接口。
ACPI將計算機系統(tǒng)的狀態(tài)劃分為四個全局狀態(tài)(G0-G3)憔维,共7個狀態(tài)涛救,其中G0對應S0;G1將低功耗狀態(tài)細分為四個狀態(tài),對應S1-S4;G2业扒、G3代表關機狀態(tài)分別對應S5检吆、S6。

ACPI State Description
S0 正常工作狀態(tài)
S1 CPU與RAM供電正常程储,但CPU不執(zhí)行指令
S2 比S1更深的一個睡眠層次蹭沛,這種模式通常不采用
S3 掛起到內(nèi)存
S4 掛起到硬盤
S5 Soft Off,CPU章鲤、外設等斷電摊灭,但電源依舊會為部分極低耗設備供電
S6 Mechanical Off,全部斷電

這里只需要對ACPI的七個狀態(tài)有個大致了解即可败徊,下一節(jié)會有具體的例子來說明各個狀態(tài)帚呼。

Linux系統(tǒng)電源狀態(tài)

在Linux操作系統(tǒng)中,將電源劃分為如下幾個狀態(tài):

ACPI State Linux State Description
S0 On(on) Working
S1 Standby(standby) CPU and RAM are powered but not executed
S2 ------ ------
S3 Suspend to RAM(mem) CPU is Off,RAM is powered and the running content is saved to RAM
S4 Suspend to Disk(disk) All content is saved to Disk and power down
S5 Shutdown Shutdown the system

On:正常工作狀態(tài)

STR(Suspend to RAM):
掛起到內(nèi)存皱蹦,俗稱待機煤杀、睡眠(Sleep),進入該狀態(tài)沪哺,系統(tǒng)的主要工作如下:
1沈自、將系統(tǒng)當前的運行狀態(tài)等數(shù)據(jù)保存在內(nèi)存中,此時仍需要向RAM供電辜妓,以保證后續(xù)快速恢復至工作狀態(tài)
2枯途、凍結用戶態(tài)的進程和內(nèi)核態(tài)的任務(進入內(nèi)核態(tài)的進程或內(nèi)核自己的task)
3忌怎、關閉外圍設備,如顯示屏柔袁、鼠標等,中斷喚醒外設不會關閉呆躲,如電源鍵
4、CPU停止工作
Standby也屬于睡眠的一種方式捶索,屬于淺睡眠插掂。該模式下CPU并未斷電,依舊可以接收處理某些特定事件腥例,視具體設備而定辅甥,恢復至正常工作狀態(tài)的速度也比STR更快,但也更為耗電燎竖。舉個例子來說璃弄,以該方式進入睡眠時,后續(xù)通過點擊鍵盤也能將系統(tǒng)喚醒构回。而以mem進入的睡眠為深度睡眠夏块,只能通過中斷喚醒設備喚醒系統(tǒng),如電源鍵(此時按電源鍵纤掸,不會經(jīng)過正常的開機流程的BIOS脐供、BOOTLOAD等),此時按鍵盤是無法喚醒系統(tǒng)的借跪。

STD(Suspend to Disk):
掛起到硬盤政己,俗稱休眠(Hibernation)將系統(tǒng)當前的運行狀態(tài)等數(shù)據(jù)保存到硬盤上,并自動關機掏愁。下次開機時便從硬盤上讀取之前保存的數(shù)據(jù)歇由,恢復到休眠關機之前的狀態(tài)。
譬如在休眠關機時果港,桌面打開了一個應用沦泌,那么下一次開機啟動時,該應用也處于打開狀態(tài)辛掠。而正常的關機-開機流程赦肃,該應用是不會打開的。

Linux內(nèi)核代碼聲明如下,位于kernel/power/suspend.c

狀態(tài)定義.png

在新版內(nèi)核中公浪,進程freeze的功能被單獨抽離出來作為一個電源狀態(tài),該狀態(tài)僅僅是凍結進程船侧,并不會使系統(tǒng)進入低功耗狀態(tài)(如切斷CPU時鐘源欠气、關閉外設供電等)。
相關宏定義位于:linux/include/linux/suspend.h

宏定義.png

其中狀態(tài)4就是STD镜撩,所謂的休眠狀態(tài)(Hibernation)

小結:
至此预柒,我們可以知道队塘,睡眠與休眠是2個不同的概念,睡眠屬于STR宜鸯,而休眠屬于STD憔古,切勿混為一談。
網(wǎng)上也有很多關于“Android休眠”的文章淋袖,事實上鸿市,Android手機壓根兒就不支持休眠模式。

查看Linux支持的電源模式

#查看系統(tǒng)支持的電源模式
$ cat /sys/power/state
#休眠系統(tǒng)命令
$ sudo pm-hibernate
Ubutu-17.0.4

看來Ubuntu-17.0.4版本是不支持休眠功能了即碗,state當中并沒有disk焰情,執(zhí)行休眠命令也提示找不到。
在公司測試Ubuntu-16.0.4是支持休眠的剥懒,休眠時會將當前RAM中的數(shù)據(jù)保持至swap分區(qū)内舟,以供后續(xù)恢復。


Ubuntu-16.0.4

查看Android支持的電源模式

Android M

這里我使用的是模擬器查看的初橘,真機也一樣验游,Android手機是不支持休眠模式的,休眠模式需要一塊與RAM大小一致存儲空間保檐,這在移動設備上可是個不小的開銷耕蝉。

Idle State

Android上的Idle狀態(tài)分為二類:Cpu Idle和Device Idle

Cpu Idle

Linux系統(tǒng)運行的基礎是基于進程調(diào)度,實際上內(nèi)核調(diào)度的線程(task)展东,內(nèi)核并不會區(qū)分線程與進程赔硫,都將他們當做一個線程(task)來處理;當所有的進程都沒事兒干的時候盐肃,系統(tǒng)就會啟用idle進程爪膊,使系統(tǒng)進入低功耗狀態(tài)(如關閉一些服務、模塊功能砸王,降低CPU工作頻率等)推盛,即idle狀態(tài),以達到省電的目的谦铃。

idle狀態(tài)又可以劃分為不同的層級耘成,以MTK的芯片為例,通常劃分為以下幾個狀態(tài):

狀態(tài) 描述
soidle(screen on idle) 亮屏 Idle 模式驹闰,該模式下與正常工作狀態(tài)差別不大瘪菌,唯一的區(qū)別就cpu處于空閑狀態(tài)
rgidle 淺度 Idle 模式,cpu處于 WFI(wait for interrupt)嘹朗,屏幕熄滅师妙,同時關閉一些不需要的服務及模塊,注意此狀態(tài)cpu的時鐘源與RTC模塊是工作正常的屹培,此時是可以通過TimerTask的定時觸發(fā)激活系統(tǒng)的默穴,TimerTask依賴于CPU的RTC模塊怔檩,而Alarm則依賴于PMIC的RTC模塊
dpidle(deep idle) 深度idle模式,該模式下cpu的時鐘源和hrtimer(高精度定時器模塊(RTC))被關閉蓄诽,所有進程(包括系統(tǒng)進程)被凍結薛训,即進入上文所述的睡眠狀態(tài)

idle進程是由原始進程(pid=0)在初始化init進程(pid=1)之后演變而來,可以說是init進程的祖先仑氛,關于其詳細介紹可參考如下鏈接:
Linux Idle基礎
魅族內(nèi)核團隊:CPUIDLE 之低功耗定時器

Device Idle

Device Idle屬于Doze模式中概念乙埃,即指當手機屏幕熄屏、不充電调衰、靜置不動,有網(wǎng)友分析了源碼膊爪,指出6.0手機需要靜置1時4分30秒才能進入Doze模式。

Doze模式的限制
網(wǎng)絡接入被暫停
系統(tǒng)忽略wake locks
標準的AlarmManager alarms(包括setExact()和setWindow())被延緩到下一個maintenance window
如果你需要在Doze狀態(tài)下啟動設置的alarms嚎莉,使用setAndAllowWhileIdle()或者setExactAndAllowWhileIdle()米酬。當有setAlarmClock()的alarms啟動時,系統(tǒng)會短暫退出Doze模式
系統(tǒng)不會掃描Wi-Fi
系統(tǒng)不允許sync adapters運行
系統(tǒng)不允許JobScheduler運行

結合上文分析的cpu idle不難發(fā)現(xiàn)Doze模式中的idle狀態(tài)在概念屬于淺idle狀態(tài)趋箩,只是關閉了一些特定服務和模塊赃额,并非立即進入睡眠,當然這個過程當中依舊有可能滿足睡眠條件而進入睡眠狀態(tài)叫确,至于如何進入請參考下文【睡眠觸發(fā)入口】一節(jié)跳芳。

Android Doze模式源碼分析

Android電源管理框架

Android采用linux內(nèi)核,所以電源狀態(tài)整體上是與linux操作系統(tǒng)相同竹勉,下圖是Android的電源管理框架:

電源管理框架

WakeLock

喚醒鎖飞盆,一種鎖機制,用于阻止系統(tǒng)進入睡眠狀態(tài)次乓,只要有應用獲取到改鎖吓歇,那么系統(tǒng)就無法進入睡眠狀態(tài)。
該機制起初是早期Android為Linux內(nèi)核打得一個補丁票腰,并想合入到linux內(nèi)核城看,但被Linux社區(qū)拒絕,后續(xù)Linux內(nèi)核引入自己的Wakelock機制,Android系統(tǒng)也使用的是linux的Wakelock機制杏慰,所以該機制并非Android特有的機制测柠。

Android系統(tǒng)提供了兩種類型的鎖,每一個類型又可分為超時鎖與普通鎖缘滥,超時鎖轰胁,超時會自動釋放,而普通鎖則必需要手動釋放:

類型 描述
WAKE_LOCK_SUSPEND 阻止系統(tǒng)進入睡眠狀態(tài)(STR)
WAKE_LOCK_IDLE 阻止系統(tǒng)從idle進程進入那些具有較大中斷時延朝扼、禁用了較多中斷源的低功耗狀態(tài)(睡眠除外)软吐,持有該類型的鎖,不影響系統(tǒng)進入睡眠狀態(tài)吟税。自Android API-17(對應android linux內(nèi)核版本3.4)移除了該類型的喚醒鎖凹耙。

中斷時延:計算機接收到中斷信號到操作系統(tǒng)作出響應,并完成轉(zhuǎn)入中斷服務程序(ISR)的時間肠仪。

內(nèi)核當中關于WakeLock的主要源碼位于:
kernel_common/include/linux/wakelock.h
kernel_common/kernel/power/wakelock.c

Android Linux內(nèi)核3.0版本

Android Linux內(nèi)核3.4版本

應用層提供的鎖類型如下肖抱,這些鎖都需要手動釋放:

FLAG CPU 屏幕 鍵盤
PARTIAL_WAKE_LOCK 開啟 關閉 關閉
SCREEN_DIM_WAKE_LOCK 開啟 變暗 關閉
SCREEN_BRIGHT_WAKE_LOCK 開啟 變亮 關閉
FULL_WAKE_LOCK 開啟 變亮 變亮
鎖的釋放

Linux3.4內(nèi)核中摒棄了之前的wakelock機制,引入wakeup source機制來進行睡眠管理异旧,為了保證上層接口不變意述,Android的Linux內(nèi)核便將wakeup source包裝成wakelock,WakeLock的數(shù)據(jù)結構如下:


wakelock數(shù)據(jù)結構

當我們應用層釋放鎖之后吮蛹,它并不會馬上消失荤崇。wakelock分為激活和非激活狀態(tài),非激活狀態(tài)300S之內(nèi)潮针,無人在申請wakelock术荤,那么它將從紅黑二叉樹,LRU鏈表當中刪除每篷,如此便可復用鎖瓣戚,節(jié)省系統(tǒng)開銷。

睡眠觸發(fā)入口

在wakelock中焦读,有3個地方可以讓系統(tǒng)從early_suspend進入suspend狀態(tài)子库。

  1. wake_unlock,系統(tǒng)每釋放一個鎖矗晃,就會檢查是否還存其他激活的wakelock仑嗅,若不存在則執(zhí)行Linux的標準suspend流程進入睡眠狀態(tài)
  2. 在超時鎖的超時回調(diào)函數(shù),判斷是否存在其他激活的wakelock张症,若不存在仓技,則進入睡眠狀態(tài)
  3. autosleep機制,android 4.1引入該機制吠冤,亮屏時會向autosleep節(jié)點寫入off浑彰,熄屏則會寫入mem。Android一滅屏拯辙,就會嘗試進入睡眠郭变,失敗之后系統(tǒng)處于idle進程超過一定時間,則又嘗試進入睡眠涯保,判斷標準同上诉濒,若存在wakelock則進入失敗


關于autosleep機制的內(nèi)核源碼分析,可以參考如下文章:
Android autosleep機制

Early Suspend

預掛起機制是Android特有的掛起機制夕春, 這個機制作用是關閉一些與顯示相關的外設未荒,比如LCD背光、重力感應器及志、 觸摸屏片排,但是其他外設如WIFI寨腔、藍牙等模塊等并未關閉。
此時率寡,系統(tǒng)依舊可以處理事件迫卢,如音樂播放軟件,息屏后依舊能播放音樂冶共。
需要注意的是Early Suspend機制與WakeLock機制相互獨立乾蛤,就算有應用持有wakelock鎖,系統(tǒng)依舊可以通過Early Suspend機制關閉與顯示相關的外設捅僵。
注意:
Android 4.4起家卖,也就是引入ART的版本,摒棄了early suspend機制庙楚,改用了fb event通知機制上荡,即后續(xù)版本只有suspend、resume以及runtime suspend醋奠、runtime resume榛臼。

Late Resume

遲喚醒機制,用于喚醒預掛起的設備

睡眠狀態(tài)轉(zhuǎn)換

一般情況下窜司,當我們息屏后沛善,系統(tǒng)將先通過Early Suspend機制進入Idle狀態(tài),如果滿足進入睡眠的條件(沒有進程持有喚醒鎖)則會通過Linux的Suspend機制進入Sleep(睡眠)狀態(tài)塞祈。

睡眠狀態(tài)轉(zhuǎn)換

內(nèi)核源碼流程分析可參考如下文章:
源碼位于kernel_common/kernel/power/main.c
Android中休眠與喚醒之wake_lock, early_suspend, late_resume

看到這兒金刁,不知你是否疑問,既然系統(tǒng)睡眠了议薪,CPU斷電不執(zhí)行指令了尤蛮,為何我們定的Alarm會生效以及能接收到來電?

手機來電與Alarm為何能喚醒系統(tǒng)

原來Android在硬件架構上將處理器分為二類:Application Processor(AP)和Baseband Processor(BP)斯议,AP是ARM架構的處理器产捞,用于運行Linux+Android系統(tǒng),耗電量高哼御;BP用于運行實時操作系統(tǒng)(RTOS)坯临,用于處理手機通信,耗電量低恋昼。


性能優(yōu)化典范截圖

當AP進入睡眠看靠,有來電時,Modem(調(diào)制解調(diào)器)將喚醒AP液肌;而我們平時所用的Alarm在硬件上則是依賴PMIC(電源管理芯片)中的RTC模塊挟炬,所以即使AP斷電進入睡眠,我們定的鬧鐘依舊會生效。


若想更深入的了解谤祖,則可參考Android RIL機制相關的文章婿滓。

總結

  1. 待機、睡眠與休眠的區(qū)別
    實際上待機(standby)與睡眠(mem)屬于不同模式泊脐,但現(xiàn)在大多操作系統(tǒng)都不支持待機模式了空幻,我們也習慣將待機等同于睡眠,睡眠屬于STR容客,休眠屬于STD,Android手機不支持休眠T加簟K跆簟!

  2. Android開發(fā)者官網(wǎng)當中提到“idle state”闲延,該如何理解谜酒,這個狀態(tài)會對設備及我們的程序造成何種影響
    所謂的idle狀態(tài)进鸠,就是指系統(tǒng)進入某個低功耗狀態(tài),以MTK為例芥丧,常見的狀態(tài)有soidle、rgidle以及dpidle坊罢。rgidle只是限制我們程序使用某些模塊续担,如Doze模式中不能訪問網(wǎng)絡;而dpidle則會凍結所有進程活孩,系統(tǒng)進入睡眠物遇。

  3. 進入Doze模式中的idle狀態(tài),我們的程序還能運行嗎憾儒?
    Doze模式中的idle概念上屬于rgidle狀態(tài)询兴,此時我們的程序是能運行的,只是不能訪問網(wǎng)絡等起趾,但是在這個過程中诗舰,系統(tǒng)可能會滿足進入睡眠條件,凍結所有進程训裆,這樣我們的程序就不會得到執(zhí)行眶根。
    可以自己寫個死循環(huán)的線程(普通線程,非looper線程)缭保,強制手機進入Doze的idle模式汛闸,你會發(fā)現(xiàn)你的程序依舊在執(zhí)行,但是靜置在哪兒一段時間后艺骂,你會發(fā)現(xiàn)你的線程被凍結诸老,不會執(zhí)行,當你點亮屏幕,你的線程又會繼續(xù)工作别伏。

  4. 手機睡眠之后蹄衷,為何我們寫Alarm程序、來電顯示程序依舊會生效厘肮?
    Android在硬件架構上將處理器分為AP與BP愧口,應用程序運行與AP之中,睡眠只是將AP斷電类茂,BP(Modem)不會斷電耍属,當有來電時,BP將會喚醒AP巩检。
    Alarm在硬件上依賴的是Modem中的PMIC的RTC模塊厚骗,而不是AP中的RTC模塊,當定時器觸發(fā)時兢哭,可以喚醒AP领舰,使我們的Alarm程序依舊會得到執(zhí)行

參考文章
維基百科ACPI
Linux電源管理子系統(tǒng)專題
Android wacklock獲取、釋放流程分析

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迟螺,一起剝皮案震驚了整個濱河市冲秽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矩父,老刑警劉巖锉桑,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異浙垫,居然都是意外死亡刨仑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門夹姥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杉武,“玉大人,你說我怎么就攤上這事辙售∏岜В” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵旦部,是天一觀的道長祈搜。 經(jīng)常有香客問我,道長士八,這世上最難降的妖魔是什么容燕? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮婚度,結果婚禮上蘸秘,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好醋虏,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布寻咒。 她就那樣靜靜地躺著,像睡著了一般颈嚼。 火紅的嫁衣襯著肌膚如雪毛秘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天阻课,我揣著相機與錄音叫挟,去河邊找鬼。 笑死限煞,一個胖子當著我的面吹牛霞揉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晰骑,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绊序!你這毒婦竟也來了硕舆?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤骤公,失蹤者是張志新(化名)和其女友劉穎抚官,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阶捆,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡凌节,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了洒试。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倍奢。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖垒棋,靈堂內(nèi)的尸體忽然破棺而出卒煞,到底是詐尸還是另有隱情,我是刑警寧澤叼架,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布畔裕,位于F島的核電站,受9級特大地震影響乖订,放射性物質(zhì)發(fā)生泄漏扮饶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一乍构、第九天 我趴在偏房一處隱蔽的房頂上張望甜无。 院中可真熱鬧,春花似錦、人聲如沸毫蚓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽元潘。三九已至畔乙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翩概,已是汗流浹背牲距。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钥庇,地道東北人牍鞠。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像评姨,于是被迫代替她去往敵國和親难述。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容