九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 5419|回复: 1
打印 上一主题 下一主题

Android睡眠唤醒机制(HAL -> Kernel)

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-28 11:53:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

一、Kernel与HAL接口分析

        Kernel与HAL接口是通过/sys/power下面的一系统文件来实现的,如:/sys/power/state

        Kernel中/sys/power下的文件实现过程如下:

1. sysfs的属性文件

     在kernel/power/main.c中,定义了一组sysfs的属性文件:

  1. static struct attribute * g[] = {
  2.         &state_attr.attr,
  3. #ifdef CONFIG_PM_TRACE
  4.         &pm_trace_attr.attr,
  5.         &pm_trace_dev_match_attr.attr,
  6. #endif
  7. #ifdef CONFIG_PM_SLEEP
  8.         &pm_async_attr.attr,
  9.         &wakeup_count_attr.attr,
  10. #ifdef CONFIG_PM_DEBUG
  11.         &pm_test_attr.attr,
  12. #endif
  13. #ifdef CONFIG_USER_WAKELOCK
  14.         &wake_lock_attr.attr,
  15.         &wake_unlock_attr.attr,
  16. #endif
  17. #endif
  18.         NULL,
  19. };

  20. static struct attribute_group attr_group = {
  21.         .attrs = g,
  22. };
复制代码
如state_attr定义如下:
  1. power_attr(state);
  2. #define power_attr(_name) \
  3. static struct kobj_attribute _name##_attr = {        \
  4.         .attr        = {                                \
  5.                 .name = __stringify(_name),        \
  6.                 .mode = 0644,                        \
  7.         },                                        \
  8.         .show        = _name##_show,                        \
  9.         .store        = _name##_store,                \
  10. }

  11. 即:
  12. static struct kobj_attribute state_attr = {        \
  13.         .attr        = {                                \
  14.                 .name = "state",        \
  15.                 .mode = 0644,                        \
  16.         },                                        \
  17.         .show        = state_show,                        \
  18.         .store        = state_store,                \
  19. }
复制代码
2. 创建sysfs文件
  1. static int __init pm_init(void)
  2. {
  3.         int error = pm_start_workqueue();
  4.         if (error)
  5.                 return error;
  6.         hibernate_image_size_init();
  7.         hibernate_reserved_size_init();
  8.         power_kobj = kobject_create_and_add("power", NULL);
  9.         if (!power_kobj)
  10.                 return -ENOMEM;
  11.         return sysfs_create_group(power_kobj, &attr_group);
  12. }
复制代码

pm_init函数执行后,会创建/sys/power目录,且目录下会建立一系列属性文件,其中一个是/sys/power/state文件。用户空间该文件将会导致state_store被调用,该文件将会导致state_show函数被调用。

二、HAL代码分析

         HAL代码位于hardware/libhardware_legacy/power/power.c

1. 路径及写入字符串定义        

  1. const char * const NEW_PATHS[] = {
  2.     "/sys/power/wake_lock",
  3.     "/sys/power/wake_unlock",
  4.     "/sys/power/state"
  5. };

  6. static const char *off_state = "mem";
  7. static const char *on_state = "on";
复制代码
2. 打开上面定义的三个文件
  1. static int
  2. open_file_descriptors(const char * const paths[])
  3. {
  4.     int i;
  5.     for (i=0; i<OUR_FD_COUNT; i++) {
  6.         int fd = open(paths[i], O_RDWR);
  7.         if (fd < 0) {
  8.             fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);
  9.             g_error = errno;
  10.             return -1;
  11.         }
  12.         g_fds[i] = fd;
  13.     }

  14.     g_error = 0;
  15.     return 0;
  16. }
复制代码
3. 修改状态
      用户态的电源管理系统会调用set_screen_state函数来触发suspend的流程,该函数实际上就是往/sys/power/state文件写入"mem"或"on"命令字符串。
  1. int
  2. set_screen_state(int on)
  3. {
  4.     QEMU_FALLBACK(set_screen_state(on));

  5.     LOGI("*** set_screen_state %d", on);

  6.     initialize_fds();

  7.     //LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime,
  8.       //      systemTime(), strerror(g_error));

  9.     if (g_error)
  10.         goto failure;

  11.     char buf[32];
  12.     int len;
  13.     if(on)
  14.         len = snprintf(buf, sizeof(buf), "%s", on_state);
  15.     else
  16.         len = snprintf(buf, sizeof(buf), "%s", off_state);

  17.     buf[sizeof(buf) - 1] = '\0';
  18.     len = write(g_fds[REQUEST_STATE], buf, len);
  19.     if(len < 0) {
  20.     failure:
  21.         LOGE("Failed setting last user activity: g_error=%d\n", g_error);
  22.     }
  23.     return 0;
  24. }
复制代码
回复

使用道具 举报

沙发
发表于 2013-2-28 14:38:44 | 只看该作者
好好学习,真厉害
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-5-17 12:05 , Processed in 0.019416 second(s), 18 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表