android休眠喚醒流程:
power按鍵事件上報給android系統,最終由windownmanager接收到,當有按鍵事件時判斷是否需要休眠后喚醒系統,然后調用powermanager系統服務去寫/sys/power/state節點.
此節點的寫函數里判斷收到的內容,來執行android的休眠early_suspend/喚醒late_resume流程.
android層:
private int setScreenStateLocked(boolean on) 電源管理服務: frameworks/base/services/java/com/android/server/PowerManagerService.java
int err = Power.setScreenState(on);
在文件frameworks/base/core/java/android/os/Power.java定義
79 public static native int setScreenState(boolean on);
具體實現在:frameworks/base/core/jni/android_os_Power.cpp
static int setScreenState(JNIEnv *env, jobject clazz, jboolean on);
set_screen_state(on); 在文件hardware/libhardware_legacy/power/power.c中定義並實現
write(g_fds[REQUEST_STATE], buf, len); 寫/sys/power/state節點
內核層:
向節點寫內容會調用kernel/power/main.c的寫函數:
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n)
request_suspend_state(state); 調用此函數: 具體實現在./kernel/power/earlysuspend.c中
state: 為休眠則調用early_suspend_work android early_suspen工作隊列
為喚醒則調用late_resume_work android late_resume_work工作隊列
drivers/video/samsung/s3cfb_main.c中早已經注冊屏幕開關
register_early_suspend(&fbdev[i]->early_suspend);
所以
為休眠則調用early_suspend_work中的屏幕休眠函數:
s3cfb_early_suspend()
backlight_on()---->s3cfb_backlight_on() 在文件arch/arm/plat-s5p/dev-fimd-s5p.c中定義 npd->backlight_on = s3cfb_backlight_on;
s3cfb_backlight_on中直接操作用來控制lcd的gpio關閉屏幕 arch/arm/mach-exynos/setup-fb-s5p.c
為喚醒時調用late_resume_work中的屏幕喚醒函數:
s3cfb_late_resume()
backlight_off()---->s3cfb_backlight_off() 在文件arch/arm/plat-s5p/dev-fimd-s5p.c中定義 npd->backlight_off = s3cfb_backlight_off;
s3cfb_backlight_off中直接操作用來控制lcd的gpio使能屏幕
執行完所有的early_suspend后執行解鎖main_wake_lock,以便休眠.
wake_unlock(&main_wake_lock);
mod_timer(&expire_timer, jiffies + has_lock); 在文件/kernel/power/wakelock.c中
此函數將啟用expire_timer定時器,定時器內容即expire_wake_locks
340 static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
有四種方式可以引起休眠
①在wake_unlock()中, 如果發現解鎖以后沒有任何其他的wake lock了, 就開始休眠
②在定時器到時間以后, 定時器的回調函數會查看是否有其他的wake lock, 如果沒有, 就在這里讓系統進入睡眠
③在wake_lock() 中, 對一個wake lock加鎖以后, 會再次檢查一下有沒有鎖, 剛加上鎖,為什么要檢查,有用嗎????
④按power鍵,調用earlysuspend.使系統或應用程序釋放鎖.從而調用上述三個函數進入休眠
if(has_lock ==0)
queue_work(suspend_work_queue,&suspend_work); 由DECLARE_WORK(suspend_work, suspend);知道,隊列中的內容即suspend函數.
suspend(); kernel/power/wakelock.c
pm_suspend(requested_suspend_state);
enter_state(state); kernel/power/suspend.c
suspend_devices_and_enter(state);
suspend_enter(state);
suspend_ops->enter(state); -->調用平台相關的休眠函數,定義在中arch/arm/plat-samsung/pm.c:379:static const struct platform_suspend_ops s3c_pm_ops
即s3c_pm_enter
s3c_pm_arch_stop_clocks() --> 休眠時執行的的最后一個函數.系統停在此處,等待中斷或rtc等喚醒源喚醒.
從此處開始喚醒流程
enable_nonboot_cpus();
suspend_test_start(); ---------->kernel已經被喚醒,當按鍵或中斷來臨后可以執行中斷函數,上報喚醒事件.對於外部中斷來說,上報power按鍵事件.
pm_restore_gfp_mask(); kernel/power/suspend.c
enter_state(state);
pm_suspend(suspend_state_t state);
suspend(); kernel/power/wakelock.c