Android電源管理基礎知識整理

来源:https://www.cnblogs.com/linhaostudy/archive/2019/12/30/12119487.html
-Advertisement-
Play Games

前言 1. 待機、睡眠與休眠的區別? 2. Android開發者官網當中提到“idle states”,該如何理解,這個狀態會對設備及我們的程式造成何種影響? 3. 進入Doze模式中的idle狀態,我們的程式還能運行嗎? 4. 手機睡眠之後,為何我們寫Alarm程式、來電顯示程式依舊會生效? 如果 ...


前言

  1. 待機、睡眠與休眠的區別?
  2. Android開發者官網當中提到“idle states”,該如何理解,這個狀態會對設備及我們的程式造成何種影響?
  3. 進入Doze模式中的idle狀態,我們的程式還能運行嗎?
  4. 手機睡眠之後,為何我們寫Alarm程式、來電顯示程式依舊會生效?

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

ACPI簡介

要理解第一個問題,得先從ACPI(高級配置與電源介面)說起,ACPI是一種規範(包含軟體與硬體),用來供操作系統應用程式管理所有電源介面。

ACPI將電腦系統的狀態劃分為四個全局狀態(G0-G3),共7個狀態,其中G0對應S0;G1將低功耗狀態細分為四個狀態,對應S1-S4;G2、G3代表關機狀態分別對應S5、S6。

ACPI State Description
S0 正常工作狀態
S1 CPU與RAM供電正常,但CPU不執行指令
S2 比S1更深的一個睡眠層次,這種模式通常不採用
S3 掛起到記憶體
S4 掛起到硬碟
S5 Soft Off,CPU、外設等斷電,但電源依舊會為部分極低耗設備供電
S6 Mechanical Off,全部斷電

這裡只需要對ACPI的七個狀態有個大致瞭解即可,下一節會有具體的例子來說明各個狀態。

Linux系統電源狀態

在Linux操作系統中,將電源劃分為如下幾個狀態:

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:正常工作狀態

STR(Suspend to RAM):

掛起到記憶體,俗稱待機、睡眠(Sleep),進入該狀態,系統的主要工作如下:

1、將系統當前的運行狀態等數據保存在記憶體中,此時仍需要向RAM供電,以保證後續快速恢復至工作狀態

2、凍結用戶態的進程和內核態的任務(進入內核態的進程或內核自己的task)

3、關閉外圍設備,如顯示屏、滑鼠等,中斷喚醒外設不會關閉,如電源鍵

4、CPU停止工作

Standby也屬於睡眠的一種方式,屬於淺睡眠。該模式下CPU並未斷電,依舊可以接收處理某些特定事件,視具體設備而定,恢復至正常工作狀態的速度也比STR更快,但也更為耗電。舉個例子來說,以該方式進入睡眠時,後續通過點擊鍵盤也能將系統喚醒。而以mem進入的睡眠為深度睡眠,只能通過中斷喚醒設備喚醒系統,如電源鍵(此時按電源鍵,不會經過正常的開機流程的BIOS、BOOTLOAD等),此時按鍵盤是無法喚醒系統的。

STD(Suspend to Disk):

掛起到硬碟,俗稱休眠(Hibernation)將系統當前的運行狀態等數據保存到硬碟上,並自動關機。下次開機時便從硬碟上讀取之前保存的數據,恢復到休眠關機之前的狀態。

譬如在休眠關機時,桌面打開了一個應用,那麼下一次開機啟動時,該應用也處於打開狀態。而正常的關機-開機流程,該應用是不會打開的。

Linux內核代碼聲明如下,位於kernel/power/suspend.c
image

在新版內核中,進程freeze的功能被單獨抽離出來作為一個電源狀態,該狀態僅僅是凍結進程,並不會使系統進入低功耗狀態(如切斷CPU時鐘源、關閉外設供電等)。

相關巨集定義位於:linux/include/linux/suspend.h

image

其中狀態4就是STD,所謂的休眠狀態(Hibernation)

小結:

至此,我們可以知道,睡眠與休眠是2個不同的概念,睡眠屬於STR,而休眠屬於STD,切勿混為一談。

網上也有很多關於“Android休眠”的文章,事實上,Android手機壓根兒就不支持休眠模式。

查看Linux支持的電源模式

#查看系統支持的電源模式
$ cat /sys/power/state
#休眠系統命令
$ sudo pm-hibernate

image

看來Ubuntu-17.0.4版本是不支持休眠功能了,state當中並沒有disk,執行休眠命令也提示找不到。

在公司測試Ubuntu-16.0.4是支持休眠的,休眠時會將當前RAM中的數據保持至swap分區,以供後續恢復。

image

查看Android支持的電源模式

image

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

Idle State

Android上的Idle狀態分為二類:Cpu Idle和Device Idle

Cpu Idle

Linux系統運行的基礎是基於進程調度,實際上內核調度的線程(task),內核並不會區分線程與進程,都將他們當做一個線程(task)來處理;當所有的進程都沒事兒乾的時候,系統就會啟用idle進程,使系統進入低功耗狀態(如關閉一些服務、模塊功能,降低CPU工作頻率等),即idle狀態,以達到省電的目的。

idle狀態又可以劃分為不同的層級,以MTK的晶元為例,通常劃分為以下幾個狀態:

狀態 描述
soidle(screen on idle) 亮屏 Idle 模式,該模式下與正常工作狀態差別不大,唯一的區別就cpu處於空閑狀態
rgidle 淺度 Idle 模式,cpu處於 WFI(wait for interrupt),屏幕熄滅,同時關閉一些不需要的服務及模塊,註意此狀態cpu的時鐘源與RTC模塊是工作正常的,此時是可以通過TimerTask的定時觸發激活系統的,TimerTask依賴於CPU的RTC模塊,而Alarm則依賴於PMIC的RTC模塊
dpidle(deep idle) 深度idle模式,該模式下cpu的時鐘源和hrtimer(高精度定時器模塊(RTC))被關閉,所有進程(包括系統進程)被凍結,即進入上文所述的睡眠狀態

idle進程是由原始進程(pid=0)在初始化init進程(pid=1)之後演變而來,可以說是init進程的祖先,關於其詳細介紹可參考如下鏈接:

Linux Idle基礎

CPUIDLE 之低功耗定時器

Device Idle

Device Idle屬於Doze模式中概念,即指當手機屏幕熄屏、不充電、靜置不動,有網友分析了源碼,指出6.0手機需要靜置1時4分30秒才能進入Doze模式。

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

結合上文分析的cpu idle不難發現Doze模式中的idle狀態在概念屬於淺idle狀態,只是關閉了一些特定服務和模塊,並非立即進入睡眠,當然這個過程當中依舊有可能滿足睡眠條件而進入睡眠狀態,至於如何進入請參考下文【睡眠觸發入口】一節。

Android Doze模式源碼分析

Android電源管理框架

Android採用linux內核,所以電源狀態整體上是與linux操作系統相同,下圖是Android的電源管理框架:

image

WakeLock

喚醒鎖,一種鎖機制,用於阻止系統進入睡眠狀態,只要有應用獲取到改鎖,那麼系統就無法進入睡眠狀態。

該機制起初是早期Android為Linux內核打得一個補丁,並想合入到linux內核,但被Linux社區拒絕,後續Linux內核引入自己的Wakelock機制,Android系統也使用的是linux的Wakelock機制,所以該機制並非Android特有的機制。

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

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

中斷時延:電腦接收到中斷信號到操作系統作出響應,並完成轉入中斷服務程式(ISR)的時間。

內核當中關於WakeLock的主要源碼位於:

kernel_common/include/linux/wakelock.h

kernel_common/kernel/power/wakelock.c

image

Android Linux內核3.0版本

image

Android Linux內核3.4版本

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

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

鎖的釋放

Linux3.4內核中摒棄了之前的wakelock機制,引入wakeup source機制來進行睡眠管理,為了保證上層介面不變,Android的Linux內核便將wakeup source包裝成wakelock,WakeLock的數據結構如下:

image

wakelock數據結構

當我們應用層釋放鎖之後,它並不會馬上消失。wakelock分為激活和非激活狀態,非激活狀態300S之內,無人在申請wakelock,那麼它將從紅黑二叉樹,LRU鏈表當中刪除,如此便可復用鎖,節省系統開銷。

睡眠觸發入口

在wakelock中,有3個地方可以讓系統從early_suspend進入suspend狀態。

wake_unlock,系統每釋放一個鎖,就會檢查是否還存其他激活的wakelock,若不存在則執行Linux的標準suspend流程進入睡眠狀態
在超時鎖的超時回調函數,判斷是否存在其他激活的wakelock,若不存在,則進入睡眠狀態
autosleep機制,android 4.1引入該機制,亮屏時會向autosleep節點寫入off,熄屏則會寫入mem。Android一滅屏,就會嘗試進入睡眠,失敗之後系統處於idle進程超過一定時間,則又嘗試進入睡眠,判斷標準同上,若存在wakelock則進入失敗

image

關於autosleep機制的內核源碼分析,可以參考如下文章:

Android autosleep機制

Early Suspend

預掛起機制是Android特有的掛起機制, 這個機製作用是關閉一些與顯示相關的外設,比如LCD背光、重力感應器、 觸摸屏,但是其他外設如WIFI、藍牙等模塊等並未關閉。
此時,系統依舊可以處理事件,如音樂播放軟體,息屏後依舊能播放音樂。
需要註意的是Early Suspend機制與WakeLock機制相互獨立,就算有應用持有wakelock鎖,系統依舊可以通過Early Suspend機制關閉與顯示相關的外設。
註意:
Android 4.4起,也就是引入ART的版本,摒棄了early suspend機制,改用了fb event通知機制,即後續版本只有suspend、resume以及runtime suspend、runtime resume。

Late Resume

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

睡眠狀態轉換

一般情況下,當我們息屏後,系統將先通過Early Suspend機制進入Idle狀態,如果滿足進入睡眠的條件(沒有進程持有喚醒鎖)則會通過Linux的Suspend機制進入Sleep(睡眠)狀態。

image

內核源碼流程分析可參考如下文章:
源碼位於kernel_common/kernel/power/main.c

Android中休眠與喚醒之wake_lock, early_suspend, late_resume

看到這兒,不知你是否疑問,既然系統睡眠了,CPU斷電不執行指令了,為何我們定的Alarm會生效以及能接收到來電?

手機來電與Alarm為何能喚醒系統

原來Android在硬體架構上將處理器分為二類:Application Processor(AP)和Baseband Processor(BP),AP是ARM架構的處理器,用於運行Linux+Android系統,耗電量高;BP用於運行實時操作系統(RTOS),用於處理手機通信,耗電量低。

image

當AP進入睡眠,有來電時,Modem(數據機)將喚醒AP;而我們平時所用的Alarm在硬體上則是依賴PMIC(電源管理晶元)中的RTC模塊,所以即使AP斷電進入睡眠,我們定的鬧鐘依舊會生效。

image

若想更深入的瞭解,則可參考Android RIL機制相關的文章。

總結

  1. 待機、睡眠與休眠的區別

實際上待機(standby)與睡眠(mem)屬於不同模式,但現在大多操作系統都不支持待機模式了,我們也習慣將待機等同於睡眠,睡眠屬於STR,休眠屬於STD,Android手機不支持休眠!!!

  1. Android開發者官網當中提到“idle state”,該如何理解,這個狀態會對設備及我們的程式造成何種影響

所謂的idle狀態,就是指系統進入某個低功耗狀態,以MTK為例,常見的狀態有soidle、rgidle以及dpidle。rgidle只是限制我們程式使用某些模塊,如Doze模式中不能訪問網路;而dpidle則會凍結所有進程,系統進入睡眠。

  1. 進入Doze模式中的idle狀態,我們的程式還能運行嗎?

Doze模式中的idle概念上屬於rgidle狀態,此時我們的程式是能運行的,只是不能訪問網路等,但是在這個過程中,系統可能會滿足進入睡眠條件,凍結所有進程,這樣我們的程式就不會得到執行。
可以自己寫個死迴圈的線程(普通線程,非looper線程),強制手機進入Doze的idle模式,你會發現你的程式依舊在執行,但是靜置在哪兒一段時間後,你會發現你的線程被凍結,不會執行,當你點亮屏幕,你的線程又會繼續工作。

  1. 手機睡眠之後,為何我們寫Alarm程式、來電顯示程式依舊會生效?

Android在硬體架構上將處理器分為AP與BP,應用程式運行與AP之中,睡眠只是將AP斷電,BP(Modem)不會斷電,當有來電時,BP將會喚醒AP。

Alarm在硬體上依賴的是Modem中的PMIC的RTC模塊,而不是AP中的RTC模塊,當定時器觸發時,可以喚醒AP,使我們的Alarm程式依舊會得到執行


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在上一篇文章 abp(net core)+easyui+efcore實現倉儲管理系統——ABP WebAPI與EasyUI結合增刪改查之五(三十一) 中我們實現了新增組織部門信息功能,不過還存在一些BUG。今天我們來繼續完善組織部門信息新增功能,併進行測試。 ...
  • 前言 我是從.net 4.5直接跳到.net core 3.x的,感覺asp.net這套東西最初是從4.5中的owin形成的。目前官方文檔重點是講路由,沒有特別說明與傳統路由的區別,本篇主要介紹終結點路由的相關概念和如何使用,不會詳細介紹路由,這個參考官方文檔就ok了。如果將來有機會研究到底層再深度 ...
  • 問題 在開發微信支付的小微商戶進件介面時,需要通過表單來上傳身份證圖片等數據。在微信支付介面文檔也說明瞭,需要使用 multipart/form data 的方式發送請求。.NET 提供了 類型,幫助我們構建表單請求,故有以下代碼: 按照微信支付官方文檔提交之後,一直提示參數錯誤,百思不得其解。 原 ...
  • 一、為什麼有consul? 在微服務,每1個服務都是集群式的,訂單服務在10台伺服器上都有,那麼用戶的請求到達,獲取哪台伺服器的訂單服務呢?如果10臺中的有的訂單服務掛了怎麼辦?10台伺服器扛不住了,水平擴展又新增加了1台伺服器提供訂單服務,怎麼讓用戶請求知道有新的伺服器提供服務了?這時候就需要Co ...
  • "[轉]三分鐘學會.NET Core Jwt 策略授權認證" 一.前言 " " 大家好我又回來了,前幾天講過一個關於Jwt的身份驗證最簡單的案例,但是功能還是不夠強大,不適用於真正的項目,是的,在真正面對複雜而又苛刻的客戶中,我們會不知所措,就現在需要將認證授權這一塊也變的複雜而又實用起來,那在專業 ...
  • 本文更新於2019 12 30。操作系統為Debian 8.9 (jessie)。 以下假設新磁碟為/dev/sdb,要創建一個分區/dev/sdb1,文件系統類型為xfs。請根據實際情況,自行選擇。 使用parted進行分區 1. 安裝parted 1. 使用 查看磁碟/dev/sdb(請使用實際 ...
  • 一.實驗環境準備 需要準備四台Linux操作系統的伺服器,配置參數最好一樣,由於我的虛擬機是之前偽分散式部署而來的,因此我的環境都一致,並且每天虛擬機預設都是Hadoop偽分散式喲!1>.NameNode伺服器(172.20.20.228) 2>.DataNode伺服器(172.20.20.226- ...
  • Linux初級指令 ls ——List ls 介紹 這是我學Linux的第一個命令,相信也是很多人學習Linux的第一個命令。ls全稱list. List information about the FILEs (the current directory by default). Sort ent ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...