android suspend/resume

  • Post author:
  • Post category:其他


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



版权声明:本文为cuijianzhongswust原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。