您的位置:首页 > 移动开发 > Android开发

android suspend/resume

2012-03-12 10:57 337 查看
一、应用层当系统未处于 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: