Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android的Linux內核的電源管理:Early Suspend

Android的Linux內核的電源管理:Early Suspend

編輯:關於Android編程

1. 用戶空間的接口
在kernel/power/main.c中,定義了一組sysfs的屬性文件,其中一個定義是:
power_attr(state);

把這個宏展開後:

?
 

?
<span style="color: rgb(0, 0, 255);">static struct kobj_attribute state_attr = { \
.attr ={ \
.name = "state", \
.mode = 0644, \
}, \
.show =state_show, \
.store =state_store, \
}
</span>


我們再看看main.c的入口:

?
<span style="color: rgb(0, 0, 255);">static int __init pm_init(void){
power_kobj =kobject_create_and_add("power", NULL);
if (!power_kobj)
return -ENOMEM;
return sysfs_create_group(power_kobj,&attr_group);
}
</span>


顯然,該函數執行後,會在生成/sys/power目錄,該目錄下會建立一系列屬性文件,其中一個是/sys/power/state文件。用戶空間向該文件的寫入將會導致state_store被調用,讀取該文件將會導致state_show函數被調用。

現在回到Android的HAL層中,查看一下代碼:hardware/libhardware_legacy/power/power.c:

?
<span style="color: rgb(0, 0, 255);">//定義寫入/sys/power/state的命令字符串
static const char *off_state = "mem";
static const char *on_state = "on";
//打開/sys/power/state等屬性文件,保存相應的文件描述符
static int
open_file_descriptors(constchar * const paths[]){
int i;
for (i=0; i
//最終,用戶空間的電源管理系統會調用set_screen_state函數來觸發suspend的流程,該函數實際上就是往/sys/power/state文件寫入"mem"或"on"命令字符串。
<pre lang="c" line="1">int
set_screen_state(inton){
initialize_fds();
char buf[32];
int len;
if(on)
len = snprintf(buf, sizeof(buf),"%s", on_state);
else
len = snprintf(buf, sizeof(buf),"%s", off_state);
buf[sizeof(buf) - 1] = '\0';
len = write(g_fds[REQUEST_STATE], buf,len);
return 0;
}
</span>

 

2. 內核中數據結構和接口
與earlysuspend相關的數據結構和接口都在earlysuspend.h中進行了定義。
- early_suspend 結構

?
<span style="color: rgb(0, 0, 255);">struct early_suspend {
#ifdef CONFIG_HAS_EARLYSUSPEND
structlist_head link;
int level;
void(*suspend)(struct early_suspend *h);
void(*resume)(struct early_suspend *h);
#endif
};
</span>


希望執行early suspend的設備,他的設備驅動程序需要向電源管理系統注冊,該結構體用於向電源管理系統注冊earlysuspend/lateresume,當電源管理系統啟動suspend流程時,回調函數suspend會被調用,相反,resume的最後階段,回調函數resume會被調用,level字段用於調整該結構體在注冊鏈表中的位置,suspend時,level的數值越小,回調函數的被調用的時間越早,resume時則反過來。Android預先定義了3個level等級:

?
<span style="color: rgb(0, 0, 255);">enum {
EARLY_SUSPEND_LEVEL_BLANK_SCREEN = 50,
EARLY_SUSPEND_LEVEL_STOP_DRAWING = 100,
EARLY_SUSPEND_LEVEL_DISABLE_FB = 150,
};
</span>


如果你想你的設備在FB設備被禁止之前執行他的early suspend回調,設備驅動程序應該把level值設定為小於150的某個數值,然後向系統注冊early_suspend結構。注冊和反注冊函數是:

?
<span style="color: rgb(0, 0, 255);">void register_early_suspend(struct early_suspend *handler);
void unregister_early_suspend(struct early_suspend *handler);
</span>


early_suspend_handlers鏈表
所有注冊到系統中的early_suspend結構都會按level值按順序加入到全局鏈表early_suspend_handlers中。

3. 工作流程
首先,我們從kernel/power/wakelock.c中的初始化函數開始:

?
<span style="color: rgb(0, 0, 255);">static int __init wakelocks_init(void)
{
int ret;
int i;
......
for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
INIT_LIST_HEAD(&active_wake_locks[i]);
......
wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
wake_lock(&main_wake_lock);
wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");
......
ret = platform_device_register(&power_device);
ret = platform_driver_register(&power_driver);
......
suspend_work_queue = create_singlethread_workqueue("suspend");
......
return 0;
}
</span>


可以看到,顯示初始化active_wake_locks鏈表數組,然後初始化並且鎖住main_wake_lock,注冊平台設備power_device,這些數組、鎖和power_device我們在後續文章再討論,這裡我們關注的最後一個動作:創建了一個工作隊列線程suspend_work_queue,該工作隊列是earlysuspend的核心所在。

系統啟動完成後,相關的驅動程序通過register_early_suspend()函數注冊了early suspend特性,等待一段時間後,如果沒有用戶活動(例如按鍵、觸控等操作),用戶空間的電源管理服務最終會調用第一節提到的set_screen_state()函數,透過sysfs,進而會調用到內核中的state_store():

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved