本文转自:http://blog.csdn.net/g_salamander/article/details/7982170

early_suspend是Android休眠流程的第一阶段即浅度休眠,不会受到wake_lock的阻止,一般用于关闭lcd、tp等设备为运行的应用节约电能。Android的PowerManagerService会根据用户的操作情况调整电源状态,如果需要休眠则会调用到HAL层的set_screen_state()接口,在set_screen_state()中会向/sys/power/state节点写入"mem"值让驱动层开始进入休眠流程。

一、休眠唤醒机制及其用户空间接口

Linux系统支持如下休眠唤醒等级

[cpp] view plain copy
  1. constchar*constpm_states[PM_SUSPEND_MAX]={
  2. #ifdefCONFIG_EARLYSUSPEND
  3. [PM_SUSPEND_ON]="on",
  4. #endif
  5. [PM_SUSPEND_STANDBY]="standby",
  6. [PM_SUSPEND_MEM]="mem",
  7. };

但在Android中一般只支持"on"和"mem",其中"on"为唤醒设备,"mem"为休眠设备。/sys/power/state节点的读写操作如下:

[cpp] view plain copy
  1. staticssize_tstate_show(structkobject*kobj,structkobj_attribute*attr,
  2. char*buf)
  3. {
  4. char*s=buf;
  5. #ifdefCONFIG_SUSPEND
  6. inti;
  7. for(i=0;i<PM_SUSPEND_MAX;i++){
  8. if(pm_states[i]&&valid_state(i))
  9. s+=sprintf(s,"%s",pm_states[i]);//打印系统支持的休眠等级
  10. }
  11. #endif
  12. #ifdefCONFIG_HIBERNATION
  13. s+=sprintf(s,"%s\n","disk");
  14. #else
  15. if(s!=buf)
  16. /*convertthelastspacetoanewline*/
  17. *(s-1)='\n';
  18. #endif
  19. return(s-buf);
  20. }
  21. staticssize_tstate_store(structkobject*kobj,structkobj_attribute*attr,
  22. constchar*buf,size_tn)
  23. {
  24. #ifdefCONFIG_SUSPEND
  25. #ifdefCONFIG_EARLYSUSPEND
  26. suspend_state_tstate=PM_SUSPEND_ON;
  27. #else
  28. suspend_state_tstate=PM_SUSPEND_STANDBY;
  29. #endif
  30. constchar*const*s;
  31. #endif
  32. char*p;
  33. intlen;
  34. interror=-EINVAL;
  35. p=memchr(buf,'\n',n);
  36. len=p?p-buf:n;
  37. /*First,checkifwearerequestedtohibernate*/
  38. if(len==4&&!strncmp(buf,"disk",len)){
  39. error=hibernate();
  40. gotoExit;
  41. }
  42. #ifdefCONFIG_SUSPEND
  43. for(s=&pm_states[state];state<PM_SUSPEND_MAX;s++,state++){
  44. if(*s&&len==strlen(*s)&&!strncmp(buf,*s,len))
  45. break;
  46. }
  47. if(state<PM_SUSPEND_MAX&&*s)
  48. #ifdefCONFIG_EARLYSUSPEND
  49. if(state==PM_SUSPEND_ON||valid_state(state)){
  50. error=0;
  51. request_suspend_state(state);//请求进入android的休眠流程
  52. }
  53. #else
  54. error=enter_state(state);//linux的标准休眠流程
  55. #endif
  56. #endif
  57. Exit:
  58. returnerror?error:n;
  59. }
  60. power_attr(state);

其中state_show()为节点的读函数,主要打印出系统支持的休眠等级;state_store()为节点的写函数,根据参数请求休眠或者唤醒流程。节点的创建代码如下:

[cpp] view plain copy
  1. staticstructattribute*g[]={
  2. &state_attr.attr,//state节点
  3. #ifdefCONFIG_PM_TRACE
  4. &pm_trace_attr.attr,
  5. #endif
  6. #ifdefined(CONFIG_PM_SLEEP)&&defined(CONFIG_PM_DEBUG)
  7. &pm_test_attr.attr,//pm_test节点
  8. #endif
  9. #ifdefCONFIG_USER_WAKELOCK
  10. &wake_lock_attr.attr,//wake_lock节点
  11. &wake_unlock_attr.attr,//wake_unlock节点
  12. #endif
  13. NULL,
  14. };
  15. staticstructattribute_groupattr_group={
  16. .attrs=g,
  17. };
  18. staticint__initpm_init(void)
  19. {
  20. interror=pm_start_workqueue();
  21. if(error)
  22. returnerror;
  23. power_kobj=kobject_create_and_add("power",NULL);//创建power节点
  24. if(!power_kobj)
  25. return-ENOMEM;
  26. returnsysfs_create_group(power_kobj,&attr_group);//创建一组属性节点
  27. }
  28. core_initcall(pm_init);

二、early_suspend 实现

1、early_suspend 定义、接口及其用法

[cpp] view plain copy
  1. enum{
  2. EARLY_SUSPEND_LEVEL_BLANK_SCREEN=50,
  3. EARLY_SUSPEND_LEVEL_STOP_DRAWING=100,
  4. EARLY_SUSPEND_LEVEL_DISABLE_FB=150,
  5. };
  6. structearly_suspend{
  7. #ifdefCONFIG_HAS_EARLYSUSPEND
  8. structlist_headlink;//链表节点
  9. intlevel;//优先等级
  10. void(*suspend)(structearly_suspend*h);
  11. void(*resume)(structearly_suspend*h);
  12. #endif
  13. };

可以看到early_suspend由两个函数指针、链表节点、优先等级组成;内核默认定义了3个优先等级,在suspend的时候先执行优先等级低的handler,在resume的时候则先执行等级高的handler,用户可以定义自己的优先等级;early_suspend向内核空间提供了2个接口用于注册和注销handler:

[cpp] view plain copy
  1. voidregister_early_suspend(structearly_suspend*handler);
  2. voidunregister_early_suspend(structearly_suspend*handler);

其中register_early_suspend()用于注册,unregister_early_suspend用于注销;一般early_suspend的使用方式如下:

[cpp] view plain copy
  1. ts->earlysuspend.suspend=sitronix_i2c_suspend_early;
  2. ts->earlysuspend.resume=sitronix_i2c_resume_late;
  3. ts->earlysuspend.level=EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
  4. register_early_suspend(&ts->earlysuspend);

设置好suspend和resume接口,定义优先等级,然后注册结构即可。

2、初始化信息

我们看一下early_suspend需要用到的一些数据:

[cpp] view plain copy
  1. staticDEFINE_MUTEX(early_suspend_lock);
  2. staticLIST_HEAD(early_suspend_handlers);//初始化浅度休眠链表
  3. //声明3个工作队列用于同步、浅度休眠和唤醒
  4. staticvoidearly_sys_sync(structwork_struct*work);
  5. staticvoidearly_suspend(structwork_struct*work);
  6. staticvoidlate_resume(structwork_struct*work);
  7. staticDECLARE_WORK(early_sys_sync_work,early_sys_sync);
  8. staticDECLARE_WORK(early_suspend_work,early_suspend);
  9. staticDECLARE_WORK(late_resume_work,late_resume);
  10. staticDEFINE_SPINLOCK(state_lock);
  11. enum{
  12. SUSPEND_REQUESTED=0x1,//当前正在请求浅度休眠
  13. SUSPENDED=0x2,//浅度休眠完成
  14. SUSPEND_REQUESTED_AND_SUSPENDED=SUSPEND_REQUESTED|SUSPENDED,
  15. };
  16. staticintstate;

初始化了一个链表early_suspend_handlers用于管理early_suspend,还定义读写链表用到的互斥体;另外还声明了3个工作队列,分别用于缓存同步、浅度休眠和唤醒;还声明了early_suspend操作的3个状态。
3、register_early_suspend 和unregister_early_suspend

[cpp] view plain copy
  1. voidregister_early_suspend(structearly_suspend*handler)
  2. {
  3. structlist_head*pos;
  4. mutex_lock(&early_suspend_lock);
  5. //遍历浅度休眠链表
  6. list_for_each(pos,&early_suspend_handlers){
  7. structearly_suspend*e;
  8. e=list_entry(pos,structearly_suspend,link);
  9. //判断当前节点的优先等级是否大于handler的优先等级
  10. //以此决定handler在链表中的顺序
  11. if(e->level>handler->level)
  12. break;
  13. }
  14. //将handler加入当前节点之前,优先等级越低越靠前
  15. list_add_tail(&handler->link,pos);
  16. if((state&SUSPENDED)&&handler->suspend)
  17. handler->suspend(handler);
  18. mutex_unlock(&early_suspend_lock);
  19. }
  20. EXPORT_SYMBOL(register_early_suspend);

注册的流程比较简单,首先遍历链表,依次比较每个节点的优先等级,如果遇到优先等级比新节点优先等级高则跳出,然后将新节点加入优先等级较高的节点前面,这样就确保了链表是优先等级低在前高在后的顺序;在将节点加入链表后查看当前状态是否为浅度休眠完成状态,如果是则执行handler的suspend函数。

[cpp] view plain copy
  1. voidunregister_early_suspend(structearly_suspend*handler)
  2. {
  3. mutex_lock(&early_suspend_lock);
  4. list_del(&handler->link);
  5. mutex_unlock(&early_suspend_lock);
  6. }
  7. EXPORT_SYMBOL(unregister_early_suspend);

注销流程则只是将节点从链表中移除。
4、request_suspend_state

前面我们看到用户空间在写/sys/power/state节点的时候会执行request_suspend_state()函数,该函数代码如下:

[cpp] view plain copy
  1. voidrequest_suspend_state(suspend_state_tnew_state)
  2. {
  3. unsignedlongirqflags;
  4. intold_sleep;
  5. spin_lock_irqsave(&state_lock,irqflags);
  6. old_sleep=state&SUSPEND_REQUESTED;
  7. //打印当前状态
  8. if(debug_mask&DEBUG_USER_STATE){
  9. structtimespects;
  10. structrtc_timetm;
  11. getnstimeofday(&ts);
  12. rtc_time_to_tm(ts.tv_sec,&tm);
  13. pr_info("request_suspend_state:%s(%d->%d)at%lld"
  14. "(%d-%02d-%02d%02d:%02d:%02d.%09luUTC)\n",
  15. new_state!=PM_SUSPEND_ON?"sleep":"wakeup",
  16. requested_suspend_state,new_state,
  17. ktime_to_ns(ktime_get()),
  18. tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,
  19. tm.tm_hour,tm.tm_min,tm.tm_sec,ts.tv_nsec);
  20. }
  21. //如果新状态是休眠状态
  22. if(!old_sleep&&new_state!=PM_SUSPEND_ON){
  23. state|=SUSPEND_REQUESTED;
  24. pr_info("sys_sync_work_queueearly_sys_sync_work.\n");
  25. //执行缓存同步与浅度休眠的工作队列
  26. queue_work(sys_sync_work_queue,&early_sys_sync_work);
  27. queue_work(suspend_work_queue,&early_suspend_work);
  28. }elseif(old_sleep&&new_state==PM_SUSPEND_ON){
  29. //如果新状态是唤醒状态
  30. state&=~SUSPEND_REQUESTED;
  31. //激活内核锁
  32. wake_lock(&main_wake_lock);
  33. //执行浅度唤醒的工作队列
  34. queue_work(suspend_work_queue,&late_resume_work);
  35. }
  36. //更新全局状态
  37. requested_suspend_state=new_state;
  38. spin_unlock_irqrestore(&state_lock,irqflags);
  39. }

函数首先打印出当前状态变化的log,然后判断新状态,如果是休眠状态则置位SUSPEND_REQUESTED标志,然后将同步缓存、浅度休眠工作队列加入相应的内核线程执行;如果新状态是唤醒则首先将main_wake_lock激活,然后再将浅度唤醒工作队列加入内核线程执行;最后更新全局状态变量,因为提供了一个内核空间接口用于获取当前休眠唤醒状态:

[cpp] view plain copy
  1. //返回系统状态值
  2. suspend_state_tget_suspend_state(void)
  3. {
  4. returnrequested_suspend_state;
  5. }

5、early_suspend_work、late_resume_work 和early_sys_sync

[cpp] view plain copy
  1. staticvoidearly_suspend(structwork_struct*work)
  2. {
  3. structearly_suspend*pos;
  4. unsignedlongirqflags;
  5. intabort=0;
  6. mutex_lock(&early_suspend_lock);
  7. spin_lock_irqsave(&state_lock,irqflags);
  8. if(state==SUSPEND_REQUESTED)//判断当前状态是否在请求浅度休眠
  9. state|=SUSPENDED;//如果是则置位SUSPENDED
  10. else
  11. abort=1;
  12. spin_unlock_irqrestore(&state_lock,irqflags);
  13. if(abort){//取消early_suspend
  14. if(debug_mask&DEBUG_SUSPEND)
  15. pr_info("early_suspend:abort,state%d\n",state);
  16. mutex_unlock(&early_suspend_lock);
  17. gotoabort;
  18. }
  19. if(debug_mask&DEBUG_SUSPEND)
  20. pr_info("early_suspend:callhandlers\n");
  21. //遍历浅度休眠链表并执行其中所有suspend函数
  22. //执行顺序根据优先等级而定,等级越低越先执行
  23. list_for_each_entry(pos,&early_suspend_handlers,link){
  24. if(pos->suspend!=NULL)
  25. pos->suspend(pos);
  26. }
  27. mutex_unlock(&early_suspend_lock);
  28. if(debug_mask&DEBUG_SUSPEND)
  29. pr_info("early_suspend:sync\n");
  30. /*Removesys_syncfromearly_suspend,anduseworkqueuetocompletesys_sync*/
  31. //sys_sync();
  32. abort:
  33. spin_lock_irqsave(&state_lock,irqflags);
  34. if(state==SUSPEND_REQUESTED_AND_SUSPENDED)
  35. wake_unlock(&main_wake_lock);
  36. spin_unlock_irqrestore(&state_lock,irqflags);
  37. }

在suspend流程中首先判断当前状态是否为SUSPEND_REQUESTED,如果是则置位SUSPENDED标志,如果不是则取消suspend流程;然后遍历浅度休眠链表,从链表头部到尾部依次调用各节点的suspend()函数,执行完后判断当前状态是否为SUSPEND_REQUESTED_AND_SUSPENDED,如果是则释放main_wake_lock,当前系统中如果只存在main_wake_lock这个有效锁,则会在wake_unlock()里面启动深度休眠线程,如果还有其他其他wake_lock则保持当前状态。

[cpp] view plain copy
  1. staticvoidlate_resume(structwork_struct*work)
  2. {
  3. structearly_suspend*pos;
  4. unsignedlongirqflags;
  5. intabort=0;
  6. mutex_lock(&early_suspend_lock);
  7. spin_lock_irqsave(&state_lock,irqflags);
  8. if(state==SUSPENDED)//清除浅度休眠完成标志
  9. state&=~SUSPENDED;
  10. else
  11. abort=1;
  12. spin_unlock_irqrestore(&state_lock,irqflags);
  13. if(abort){
  14. if(debug_mask&DEBUG_SUSPEND)
  15. pr_info("late_resume:abort,state%d\n",state);
  16. gotoabort;
  17. }
  18. if(debug_mask&DEBUG_SUSPEND)
  19. pr_info("late_resume:callhandlers\n");
  20. //反向遍历浅度休眠链表并执行其中所有resume函数
  21. //执行顺序根据优先等级而定,等级越高越先执行
  22. list_for_each_entry_reverse(pos,&early_suspend_handlers,link)
  23. if(pos->resume!=NULL)
  24. pos->resume(pos);
  25. if(debug_mask&DEBUG_SUSPEND)
  26. pr_info("late_resume:done\n");
  27. abort:
  28. mutex_unlock(&early_suspend_lock);
  29. }

在resume流程中同样首先判断当前状态是否为SUSPENDED,如果是则清除SUSPENDED标志,然后反向遍历浅度休眠链表,按照优先等级从高到低的顺序执行节点的resume()函数。

更多相关文章

  1. Android Activity生命周期和状态
  2. Android 判断网络状态,并且在没有网络的时候,提示网络未开启
  3. Android中程序的停止状态详细介绍
  4. android(java)对网络状态(socket)判断的方法
  5. Android存储设备(U盘,SD卡)状态监测(《Android 2.3 SD卡挂载流程
  6. Android 设置状态栏及Activity横屏或竖屏。
  7. Android获取屏幕高度、标题高度、状态栏高度详解
  8. Android 沉浸式状态栏 头部可拉伸带有一键置顶功能
  9. Android Studio设置 标题栏隐藏, 状态栏隐藏, 改变状态栏文字颜

随机推荐

  1. Android中Service服务详解(一)
  2. Android 滑动效果进阶篇(六)—— 倒影效果
  3. Android自定义UI手势密码改进版源码下载
  4. Android应用开发揭秘(笔记) 第六章 Android
  5. Android集成第三方支付
  6. android 的handler 注意
  7. Could not find SDK_Root\tools\adb.ex
  8. Android(安卓)Studio关于VectorDrawable
  9. (转发)Android:onNewIntent()
  10. android 打包报错