android待机详细结合代码分析(一)
2012-09-11 14:26
363 查看
摘要:
android系统的待机,是在linux原生待机enter_state的基础上,添加wakelock-wakeunlock机制,对象场景是增加对屏灭但系统仍后台运行得支持。
linux原生待机
我们是linux开发者,用code沟通最直接吧。
在linux-2.6.32以后,/sys/power节点下,创建state节点,在文件系统调用上,write此节点,将会调用state_store函数,read此节点,将会调用state_show函数。
在/kernel/power/main.c中
linux原生待机的入口函数就在这里,接下来往state_store函数深入,就是待机过程。
android新增待机
android对linux待机机制的修改,是对移动便携设备省电的支持。
在code上,可以追踪红定义HAS_EARLYSUSPEND,可以发现这个宏的开关就是wakelock-wakeunlock机制的开关。
待机的入口节点没变,同linux原生待机一致,在/sys/power/state下,
request_suspend_state(state);函数最后也会调用到linux原生待机入口函数enter_state(state),不过在调用之前需要先完成earlysuspend,所谓的一级待机。
一级待机提供一种机制,使得某些应用可以在屏幕暗下来以后,后台继续运行,如USB transfer、music play、wifi downloade/upload、blooth transfer。
EARLYSUSPEND
那么,如果正确地给你的某一个模块或者应用,注册一级待机回调函数呢?我们以backlight为例
需要包含的头文件:#include <linux/earlysuspend.h>
定义一个一级待机结构体 XX_early_suspend
这个结构体的suspend与resume回调,就是在request_suspend_state(state)中调用,在enter_state(state)之前调用的。
level成员称为函数优先级,earlysuspend实际上就是一个list,在系统启动过程中往这个list上注册了很多的回调函数,但是这些函数的调用需要有一个先后关系;level值越大,优先级越低,函数越靠后被调用。
那么,XX_earlysuspend和XX_lateresume回调,要注意函数参数,还是以backlight为例
这样,回调函数和结构体就写好了,为了规范代码,最好能加上ealrysuspend机制的宏开关, 接下来就是注册结构体到list
在驱动的_probe函数中,一般在靠后位置添加
对应的要在_remove函数中,在靠前位置
wake lock/ wake unlock
接下来,如果给一个需要锁的驱动,添加一把锁呢?
和android上层看到的锁类似,锁有超时锁与非超时锁两种。超时锁我们以USB为例
需要包含的头文件:#include <linux/wakelock.h>
在初始化函数或者_probe函数中,
这样就注册上一个name为"usb_detect"的锁,此锁属性是WAKE_LOCK_SUSPEND,区别与WAKE_LOCK_IDLE。
在锁的初始化上,是不区分超时锁与非超时锁的,而是在申请与释放锁。
我们下面申请一个超时锁,目的是在USB拔掉之后几秒时间内,系统不要进入深度睡眠。
在拔掉和插入USB后,会出发这个handler,从而申请 "usb_detect"的超时锁,超时时间是3秒,3秒后,自动释放这个锁。
可以在串口输入cat proc/wakelocks查看当前系统所有锁情况。
非超时锁,需要手动申请,手动释放,而且需要注意匹配使用申请与释放。我们以alarm为例
同样,先在_probe中初始化一个锁
在_remove中反初始化
然后在set_alarm的时候,申请锁
在alarm结束后释放这个锁
android系统的待机,是在linux原生待机enter_state的基础上,添加wakelock-wakeunlock机制,对象场景是增加对屏灭但系统仍后台运行得支持。
linux原生待机
我们是linux开发者,用code沟通最直接吧。
在linux-2.6.32以后,/sys/power节点下,创建state节点,在文件系统调用上,write此节点,将会调用state_store函数,read此节点,将会调用state_show函数。
#define power_attr(_name) \ static struct kobj_attribute _name##_attr = { \ .attr = { \ .name = __stringify(_name), \ .mode = 0644, \ }, \ .show = _name##_show, \ .store = _name##_store, \ }
在/kernel/power/main.c中
power_attr(state);
linux原生待机的入口函数就在这里,接下来往state_store函数深入,就是待机过程。
android新增待机
android对linux待机机制的修改,是对移动便携设备省电的支持。
在code上,可以追踪红定义HAS_EARLYSUSPEND,可以发现这个宏的开关就是wakelock-wakeunlock机制的开关。
待机的入口节点没变,同linux原生待机一致,在/sys/power/state下,
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; request_suspend_state(state);//区别与原生待机机制的关键函数 } #else error = enter_state(state); #endif #endif Exit: return error ? error : n; }
request_suspend_state(state);函数最后也会调用到linux原生待机入口函数enter_state(state),不过在调用之前需要先完成earlysuspend,所谓的一级待机。
一级待机提供一种机制,使得某些应用可以在屏幕暗下来以后,后台继续运行,如USB transfer、music play、wifi downloade/upload、blooth transfer。
EARLYSUSPEND
那么,如果正确地给你的某一个模块或者应用,注册一级待机回调函数呢?我们以backlight为例
需要包含的头文件:#include <linux/earlysuspend.h>
定义一个一级待机结构体 XX_early_suspend
static struct early_suspend bl_early_suspend = { .suspend = bl_earlysuspend, .resume = bl_lateresume, .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 1, };
这个结构体的suspend与resume回调,就是在request_suspend_state(state)中调用,在enter_state(state)之前调用的。
level成员称为函数优先级,earlysuspend实际上就是一个list,在系统启动过程中往这个list上注册了很多的回调函数,但是这些函数的调用需要有一个先后关系;level值越大,优先级越低,函数越靠后被调用。
那么,XX_earlysuspend和XX_lateresume回调,要注意函数参数,还是以backlight为例
static void bl_earlysuspend(struct early_suspend *h) { } static void bl_lateresume(struct early_suspend *h) { }
这样,回调函数和结构体就写好了,为了规范代码,最好能加上ealrysuspend机制的宏开关, 接下来就是注册结构体到list
在驱动的_probe函数中,一般在靠后位置添加
#ifdef CONFIG_HAS_EARLYSUSPEND register_early_suspend(&bl_early_suspend); #endif
对应的要在_remove函数中,在靠前位置
#ifdef CONFIG_HAS_EARLYSUSPEND unregister_early_suspend(&bl_early_suspend); #endif
wake lock/ wake unlock
接下来,如果给一个需要锁的驱动,添加一把锁呢?
和android上层看到的锁类似,锁有超时锁与非超时锁两种。超时锁我们以USB为例
需要包含的头文件:#include <linux/wakelock.h>
在初始化函数或者_probe函数中,
wake_lock_init(&usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect");
这样就注册上一个name为"usb_detect"的锁,此锁属性是WAKE_LOCK_SUSPEND,区别与WAKE_LOCK_IDLE。
在锁的初始化上,是不区分超时锁与非超时锁的,而是在申请与释放锁。
我们下面申请一个超时锁,目的是在USB拔掉之后几秒时间内,系统不要进入深度睡眠。
static irqreturn_t usb_detect_irq_handler(int irq, void *dev_id) { wake_lock_timeout(&usb_wakelock, 3 * HZ);//3秒的超时时间 schedule_delayed_work(&wakeup_work, HZ / 10); return IRQ_HANDLED; }
在拔掉和插入USB后,会出发这个handler,从而申请 "usb_detect"的超时锁,超时时间是3秒,3秒后,自动释放这个锁。
可以在串口输入cat proc/wakelocks查看当前系统所有锁情况。
非超时锁,需要手动申请,手动释放,而且需要注意匹配使用申请与释放。我们以alarm为例
同样,先在_probe中初始化一个锁
wake_lock_init(&hym8563->wake_lock, WAKE_LOCK_SUSPEND, "rtc_hym8563");
在_remove中反初始化
wake_lock_destroy(&hym8563->wake_lock);
然后在set_alarm的时候,申请锁
wake_lock(&hym8563->wake_lock)
在alarm结束后释放这个锁
wake_unlock(&hym8563->wake_lock)
相关文章推荐
- android待机详细结合代码分析(二)
- android待机详细结合代码分析(二)
- Android 4.1 Netd详细分析(五)代码分析3
- Android RIL代码详细分析
- android通话过程RIL层详细分析(代码)
- Android 4.1 Netd详细分析(四)代码分析2
- Android 4.1 Netd详细分析(五)代码分析3
- WordCount运行原理结合代码详细分析
- android高仿微信表情输入与键盘输入代码(详细实现分析)
- android通话过程RIL层详细分析(代码)
- Android 4.1 Netd详细分析(三)代码分析1
- 第四篇:WordCount运行原理结合代码详细分析
- Android 4.1 Netd详细分析(三)代码分析1
- 关于Android大数据收集,埋点统计的详细讲解以及案例代码分析附github代码
- Android 4.1 Netd详细分析(四)代码分析2
- Android导航栏ActionBar的详细分析
- LeetCode169详细分析并附求解代码
- android recover 系统代码分析 -- 选择进入
- android ARM 汇编学习—— 在 android 设备上编译c/cpp代码并用objdump/readelf等工具分析
- Android GSM驱动模块(rild)详细分析(一)基本架构及初始化