一、应用层当系统未处于 Suspend 状态下用户按下Power键时会在产生一个信号,上层的
WindowManager?
会收到这个上节点的变化而得知当前应该进入休眠状态, 通知PowerManagerService, 它会做如下调用,
路径:./frameworks/base/services/java/com/android/server/PowerManagerService.java” line 1452
private int setScreenStateLocked(boolean on) {
int err = Power.setScreenState(on); ------------------------------------------>在这里调用setScreenState()
if (err == 0) {
mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
if (mUseSoftwareAutoBrightness) {
enableLightSensor(on);
if (!on) {
// make sure button and key backlights are off too
mButtonLight.turnOff();
mKeyboardLight.turnOff();
// clear current value so we will update based on the new conditions
// when the sensor is reenabled.
mLightSensorValue = -1;
// reset our highest light sensor value when the screen turns off
mHighestLightSensorValue = -1;
}
}
}
return err;
}
setScreenState最终会调到hardware/libhardware_legacy/power/power.c 中的set_screen_state
const char * const NEW_PATHS[] = {
"/sys/power/wake_lock",
"/sys/power/wake_unlock",
"/sys/power/state"
};
static const char *off_state = "mem";
static const char *on_state = "on";
下边这个函数打开NEW_PATHS[]中的三个描述符
static int
open_file_descriptors(const char * const paths[])
{
int i;
for (i=0; i<OUR_FD_COUNT; i++) {
int fd = open(paths[i], O_RDWR);
if (fd < 0) {
fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);
g_error = errno;
return -1;
}
g_fds[i] = fd;
}
g_error = 0;
return 0;
}
int
set_screen_state(int on)
{
QEMU_FALLBACK(set_screen_state(on));
LOGI("*** set_screen_state %d", on);
initialize_fds();
//LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime,
// systemTime(), strerror(g_error));
if (g_error) return g_error;
char buf[32];
int len;
if(on)
{
len = sprintf(buf, on_state);
len = write(g_fds[REQUEST_STATE], buf, len);
sys_file = fopen(FILENAME_SYS_3G_RESTART, "w");
if(sys_file)
{
fputc(2, sys_file);
fclose(sys_file);
}
}
else
{
len = sprintf(buf, off_state);
len = write(g_fds[REQUEST_STATE], buf, len); ===> echo mem > /sys/power/state
sys_file = fopen(FILENAME_SYS_3G_RESTART, "w");
if(sys_file)
{
fputc(0, sys_file);
fclose(sys_file);
}
write_resume_state(1);
}
if(len < 0) {
LOGE("Failed setting last user activity: g_error=%d\n", g_error);
}
return 0;
}
到些完成了从按下power键到 echo mem > /sys/power/state 的过程,接下来就是进入内核中
二、内核中的休眠过程分析1、创建 /sys/power/state节点在内核中 kernel/power/main.cpower_attr(state);这是一个宏(定义在kernel/power/power.h),它实现在/sys/power/ 下创建对应节点state,对这个结点进行读写对应的函数为
//写结点时调用的函数
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
//读结点时调用的函数
static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
接上边echo mem > /sys/power/state后state_store被调用
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
#ifdef CONFIG_SUSPEND
#ifdef CONFIG_EARLYSUSPEND
suspend_state_t state = PM_SUSPEND_ON;
#else
suspend_state_t state = PM_SUSPEND_STANDBY;
#endif
const char * const *s;
#endif
char *p;
int len;
int error = -EINVAL;
p = memchr(buf, '\n', n);
len = p ? p - buf : n;
/* First, check if we are requested to hibernate */
if (len == 4 && !strncmp(buf, "disk", len)) {
error = hibernate();
goto Exit;
}
#ifdef CONFIG_SUSPEND
for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
break;
}
if (state < PM_SUSPEND_MAX && *s)
#ifdef CONFIG_EARLYSUSPEND ---------------------------------------------------------------
if (state == PM_SUSPEND_ON || valid_state(state)) { |
error = 0; |->android 添加的部分,如果定义了
request_suspend_state(state); |->earlysuspend则调用request_suspend_state(state); (定义在kernel/power/earlysuspend.c)
} |
#else ---------------------------------------------------------------------------------------
error = enter_state(state); ===========================>标准linux进入休眠的路径
#endif
#endif
Exit:
return error ? error : n;
}
request_suspend_state 位于: kernel/power/earlysuspend.c
void request_suspend_state(suspend_state_t new_state)
{
unsigned long irqflags;
int old_sleep;
spin_lock_irqsave(&state_lock, irqflags);
old_sleep = state & SUSPEND_REQUESTED;
if (debug_mask & DEBUG_USER_STATE) {
struct timespec ts;
struct rtc_time tm;
getnstimeofday(&ts);
rtc_time_to_tm(ts.tv_sec, &tm);
pr_info("request_suspend_state: %s (%d->%d) at %lld "
"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
requested_suspend_state, new_state,
ktime_to_ns(ktime_get()),
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
}
if (!old_sleep && new_state != PM_SUSPEND_ON) {
state |= SUSPEND_REQUESTED;
queue_work(suspend_work_queue, &early_suspend_work);------------- >这个是把工作early_suspend_work添加到工作队列suspend_work_queue中
requested_suspend_state = new_state;
spin_unlock_irqrestore(&state_lock, irqflags);
} else if (old_sleep && new_state == PM_SUSPEND_ON) {
state &= ~SUSPEND_REQUESTED;
wake_lock(&main_wake_lock);
queue_work(suspend_work_queue, &late_resume_work);
requested_suspend_state = new_state;
spin_unlock_irqrestore(&state_lock, irqflags);
mdelay(300);
}
else {
requested_suspend_state = new_state;
spin_unlock_irqrestore(&state_lock, irqflags);
}
}
工作队列suspend_work_queue定义在kernel/power/wakelock.c中在wakelocks_init()函数中对这个工作队列初始化
static int __init wakelocks_init(void)
{
。。。。
suspend_work_queue = create_singlethread_workqueue("suspend"); 创建一个单线程休眠工作队列
if (suspend_work_queue == NULL) {
ret = -ENOMEM;
goto err_suspend_work_queue;
}
。。。。。
return ret;
}