一、应用层当系统未处于 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; }