1. 程式人生 > >基於DTL-RK3288 硬體平臺的Android5.1電源休眠管理

基於DTL-RK3288 硬體平臺的Android5.1電源休眠管理


Linux 電源管理機制為裝置低功耗的實現提供了方法。
在不同核心版本Linux、Android,休眠機制、流程有所差異。這裡DLT-RK3288 Android 5.1 原始碼為例。


標準Linux 的電源狀態:
- On(on)                                               S0 -  Working  
                                                                      - 正常的工作狀態
- Standby (standby)                              S1 -  CPU and RAM are powered but not executed   
                                                                        - CPU和DDR都供著電,但沒執行任何命令。
- Suspend to RAM(mem)                        S3 -  RAM is powered and the running content is saved to RAM
                                                                        -  掛起到記憶體,簡稱待機。CPU、EMMC、LCD等都斷了電,只有DDR供著電,以儲存休眠前的工作狀態。
- Suspend to Disk,Hibernation(disk)    S4 -  All content is saved to Disk and power down
                                                                        -  掛起到硬碟,簡稱休眠。機器執行狀態儲存到硬碟中,並關機。


DLT-RK3288的 kernel/include/linux/suspend.h 中 可以看到常用的幾種狀態
1.#define PM_SUSPEND_ON                ((__force suspend_state_t) 0)
2.#define PM_SUSPEND_FREEZE        ((__force suspend_state_t) 1)
3.#define PM_SUSPEND_STANDBY        ((__force suspend_state_t) 2)
4.#define PM_SUSPEND_MEM                ((__force suspend_state_t) 3)


休眠相關核心原始碼:
kernel/kernel/power/main.c
kernel/kernel/power/suspend.c
kernel/kernel/power/wakelock.c
kernel/kernel/power/autosleep.c
main.c 主要是向用戶空間提供檔案介面。檔案介面有以下:

 

suspend.c 是進入休眠前所執行的程式碼。主要函式呼叫流程: pm_suspend -- enter_state -- suspend_prepare -- suspend_devices_and_enter 。
autosleep.c 主要負責自動進入休眠流程。
低版本的linux核心 還有earlysuspend.c,earlysuspend是假休眠(只關閉部分外設的電源)的一種機制,linux 3.10中已被拋棄。


如何進入休眠?
1、當autosleep開啟,當所有wakelock都釋放時,自動進入休眠。
     autosleep.c 中,try_to_suspend 函式呼叫 pm_get_wakeup_count ,執行:
1.  for (;;) {
2.               prepare_to_wait(&wakeup_count_wait_queue, &wait,
3.              TASK_INTERRUPTIBLE);


    可以看出,一直等到wakelock 被釋放,pm_get_wakeup_count 才返回。進入呼叫 pm_suspend或hibernate休眠。
2、echo mem > /sys/power/state ,強制進入休眠。
       執行該命令,系統會直接進入休眠,不再判斷是否有沒釋放的wakelock。(低版本核心中,執行該命令,仍需要等待wakelock釋放)。


wakelock 是為休眠喚醒而存在的。可以查詢相關資料進一步瞭解。
cat /sys/power/wake_lock可以看到當前哪個Android鎖處於啟用狀態。(/sys/power/wake_lock 並不統計核心的鎖)。


如何禁止自動進入休眠?

1、在驅動原始碼中,初始化一個wakelock,並上鎖,不釋放。
1.#include <linux/wakelock.h>
2.struct wake_lock no_suspend_lock;


核心中的鎖型別很簡單,只有WAKE_LOCK_SUSPEND。(低版本核心中多了WAKE_LOCK_IDLE)。
   缺點: 只能保證不進入休眠,螢幕卻被滅了。


2、在Android中加鎖
Android 定義了以下幾種WakeLock型別:
       *  FULL_WAKE_LOCK    保持螢幕全亮、鍵盤背光燈點亮和CPU執行。
        *  SCREEN_BRIGHT_WAKE_LOCK   保持螢幕全亮和CPU執行。
        *  SCREEN_DIM_WAKE_LOCK   保持螢幕開啟(但是讓它變暗)和CPU執行。


        *  PARTIAL_WAKE_LOCK   保持CPU執行。

可以根據需要,申請不同的鎖型別。