Android 的電源管理也是很重要的一部分。比如在待機的時候關掉不用的設備,timeout之後的屏幕和鍵盤背光的關閉,用戶操作的時候該打開多少設備等等,這些都直接關係到產品的待機時間,以及用戶體驗。
framework層主要有這兩個文件:
frameworks\base\core\java\android\os\PowerManager.java
frameworks\base\services\java\com\android\server\PowerManagerService.java
其中PowerManager.java是提供給應用層調用的,最終的核心還是在PowerManagerService.java。這個類的作用就是提供PowerManager的功能,以及整個電源管理狀態機的運行。裡面函數和類比較多,就從對外和對內分兩塊來說。
先說對外,PowerManagerService如何來進行電源管理,那就要有外部事件的時候去通知它,這個主要是在frameworks\base \services\java\com\android\server\WindowManagerService.java裡面。 WindowManagerService會把用戶的點擊屏幕,按鍵等作為user activity事件來調用userActivity函數,PowerManagerService就會在userActivity裡面判斷事件類型作出反映,是點亮屏幕提供操作,還是完全不理會,或者只亮一下就關掉。供WindowManagerService調用的方法還有gotoSleep和其他一些獲取電源狀態的函數比如screenIsOn等等。
在說對內,作為對外接口的userActivity方法主要是通過setPowerState來完成功能。把要設置的電源狀態比如開關屏幕背光什麼的作為參數調用setPowerState,setPowerState先判斷下所要的狀態能不能完成,比如要點亮屏幕的話但是現在屏幕被lock了那就不能亮了,否則就可以調用Power.setScreenState(true)來透過jni跑到driver裡面去點亮屏幕了。
而電源的狀態循環則主要是通過Handler來實現的。PowerManagerService在init裡面會啟動一個HandlerThread一個後臺消息循環來提供任務的延遲發送,就可以使用Handler來在定製推遲某一任務的執行時間,從而實現狀態機的循環。比如timeout,一段時間之後無操作要讓屏幕變暗,然後關閉,反映在代碼裡如下:
userActivity裡面在調用setPowerState之後會用setTimeoutLocked來設置timeout。然後在 setTimeoutLocked裡面會根據當前的狀態來計算下一個狀態以及時間,判斷完再調用 mHandler.postAtTime(mTimeoutTask, when)來post一個TimeoutTask。這樣在when毫秒後就會執行TimeoutTask。在TimeoutTask裡面則根據設定的狀態來調用setPowerState來改變電源狀態,然後再設定新的狀態,比如現在是把屏幕從亮改暗了,那就再用 setTimeoutLocked(now, SCREEN_OFF)來等下把屏幕完全關掉。如果這次已經是把屏幕關了,那這輪的timeout狀態循環就算是結束了。
如果要定製的話,比如需求是在timeout屏幕關掉之後還要再關掉一些外圍設備等等,那就在TimeoutTask裡面把屏幕關掉之後再加上關閉其他設備的代碼就好了。即使新的狀態需求完全和原來的不一樣,用Handler應該也不難。邏輯理清了把代碼擺在合適的地方就好了。