android待机唤醒方法怎么设置

Android 休眠唤醒频繁问题分析的一些工具 - 简书
Android 休眠唤醒频繁问题分析的一些工具
大家都知道目前的手机,平板等电子设备耗电都比较大,Android系统因为历史和开源等原因,一直对耗电支持的不是很好。特别现在很多apk完全不care耗电,动不动给你装上全家桶,还会相互间互相唤醒进程,简直就是流氓软件。从现有的应用来说,为了他们商业目的,有很多是类似要求长期后台运行的,或者定时运行的,这些服务对耗电影响都非常大。虽然Android每次版本大更新,都对其进行了优化,加入了很多特性。比如在Android 5.0加入了JobScheduler API机制(批处理);在Android 6.0加入App Standby(应用待机),Doze休眠机制;并且在Android7.0谷歌对Doze休眠机制做了进一步的优化,只要手动在后台删掉应用卡片,关屏后该应用就会被很快深度休眠。但是应用开发工程师由于各种原因没有使用新的特性,导致用户感觉设备耗电还是很大。所以国内很多手机厂家都有对android系统的耗电进行优化,从原理来说,目前这些厂家也是主要对两方面进行优化:1.减少定时休眠唤醒频率,比如合并应用申请的定时唤醒闹钟来唤醒已经休眠的设备。2.减少wake lock的频率和时间。只要系统中存在任一有效的wake_lock,系统就不能进入深度休眠,但可以进行设备的浅度休眠操作。wake_lock一般在关闭lcd、tp但系统仍然需要正常运行的情况下使用,比如听歌、传输很大的文件等。1.通过kernel log来查看唤醒次数
可通过如下打印来确认唤醒源:&4&[ ] wakeup gpio0: 具体意思如下:gpio0:表示是GPIO0:表示的是GPIO分组从高到低四个字节分别是:DCBA,每个字节的0-7bit就表示D7-D0
A7-A0.从这里可以看出上面唤醒的GPIO是:GPIO0 PA4,对应的是RTC的中断脚。2.通过上层dumpsys信息来查看
2.1dumpsys alarm
通过dumpsys alarm命令打印可以看到哪个应用唤醒次数比较多,和总共占用的时间:
Alarm Stats:
com.google.android.gsf +20ms running, 1 wakeups:// alarm唤醒一次
+20ms 1 wakes 1 alarms: cmp={com.google.android.gsf/com.google.android.gsf.checkin.EventLogService$Receiver}
android +44s431ms running, 2 wakeups:// alarm唤醒两次
+41s632ms 0 wakes 1 alarms: act=com.android.server.action.NETWORK_STATS_POLL
+5s33ms 2 wakes 2 alarms: act=android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED
+4s219ms 0 wakes 1 alarms: act=com.android.server.NetworkTimeUpdateService.action.POLL
+2s202ms 0 wakes 19 alarms: act=android.intent.action.TIME_TICK
com.android.providers.calendar +40s25ms running, 3 wakeups:
这里的唤醒统计的是:应用申请RTC_WAKEUP 或 ELAPSED_REALTIME_WAKEUP的Alarm。不管系统是否在休眠,都会产生Alarm,所以这里的Alarm次数与第一章中说的kernel中统计的被RTC中断唤醒的次数是匹配不上的,前都会大于后者。看下Android系统定义的休眠唤醒不同的类型。
* Alarm time in {@link android.os.SystemClock#elapsedRealtime
* SystemClock.elapsedRealtime()} (time since boot, including sleep),
* which will wake up the device when it goes off.
public static final int ELAPSED_REALTIME_WAKEUP = 2;
* Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()}
* (wall clock time in UTC), which will wake up the device when it goes off.
public static final int RTC_WAKEUP = 0;
2.2 dumpsys batterystats这个信息可以通过Project Volta里的工具historian.py将其图形化显示。先导出bugreportadb bugreport & bugreport.txt将其转换成图形化结果(目前好像只有百度浏览器才能打开这个html)python historian.py -a bugreport.txt | tee battery.html
dumpsys batterystats
简单说明如下:1.横轴是时间2. wifi_scan指的是wifi处于扫描3. wifi_running指的是wifi打开状态4. screen指的是屏亮的状态5. plugged指的是插入外设6. wake_lock指的是kernel中被锁住的状态3.系统状态分析可通过screen与wake_lock来初步确认系统是否被唤醒,如果screen是关的,然后又有wake_lock,也表明系统被唤醒并被锁住一段时间。把上层的唤醒和wifi唤醒都关了,测试了39个小时消耗30%电量有以下几个问题:1.唤醒次数的确少了,但是healthd每10分钟唤醒在图上体现不出来2.有2次唤醒后,系统被锁住10多钟才休眠下去查看Alarm状态,可以很明显看到上层没有再去wake up
alarm status
但是驱动中还看到有被RTC唤醒,经过验证是healthd唤醒的,不插充电的时候10分钟,插充电的时候1分钟间隔。这个唤醒后就更新battery的信息,上层Baterry更新下,UI刷新下。系统被锁住10几分钟,通过log分析在wifi断开的时候,gms刚好去连接服务器,通讯很久造成wake 比较久。从下面的信息可以判断,系统目前wake lock线程最多的是gms线程。
Wake lock 在Android的电源管理系统中扮演一个核心的角色,wakelock是一种锁的机制, 只要有task拿着这个锁, 系统就无法进入休眠, 可以被用户态进程和内核线程获得。这个锁可以是有超时的或者是没有超时的, 超时的锁会在时间过去以后自动解锁。如果没有锁了或者超时了, 内核就会启动标准Linux的那套休眠机制机制来进入休眠。4.结论分析提高电池续航,也就意味着减少系统和程序的电量消耗。为此 经过测试发现,每次唤醒设备,1-2秒的时候,都会消耗2分钟(个别应用更久)的待机电量,可见每次唤醒设备的时候,不仅仅是点亮了屏幕,系统也在后台处理很多事情。电池消耗比较大,从系统的行为上分析,有两个地方影响最大1.系统在被唤醒的期间,被一些应用wake lock比较久,造成很久时间无法再进入二级休眠。2.系统频繁的被唤醒,系统被唤醒目前包含三个唤醒源(1).系统上层通过AlarmMananger的接口注册rtc唤醒,(2).wifi芯片自动唤醒,(3).电池healthd定频唤醒。所以如果应用比较多的时候,应用在唤醒期间动作比较多,容易造成系统被wake lock,从而不会很快的进入二级休眠。通过上述的分析来看,系统可以优化的地方有4个方面。1).查看系统wake lock最多的线程,看能不能优化。2).系统上层过滤的应用唤醒行为,从而降低唤醒频率。AlarmManager包含四种类型定时策略,AlarmManager.ELAPSED_REALTIME、AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。其中应用申请RTC_WAKEUP或ELAPSED_REALTIME_WAKEUP的Alarm在系统休眠的情况下会唤醒系统。通过建立白名单或者黑名单的方式过滤此种应用的唤醒行为3).定时批处理一批操作,压缩硬件唤醒时间,就像心跳一样,让硬件充分休息,还有就是精确监测应用请求,智能安排请求执行时间,让资源利用最大化。4).扩大healthd的定频唤醒间隔(适度不然造成电池电量不准)最后改一张调整过的电池状态图:
android 系统优化、家狗狮
~~记录自己10年解决的系统重大缺陷~
( 缺陷的是我自己遗留的。。。谢谢)
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金 相信有很多...
基于V2.0版本的battery historian请先看 battery historian安装与使用 (1).横坐标 横坐标就是一个时间范围,咱们的例子中统计的数据是以重置为起点,获取bugreport内容时刻为终点。我们一共采集了多长时间的数据 (2).纵坐标 关键的...
Android为了确保应用程序中关键代码的正确执行,提供了WakeLock的API,使得应用程序有权限通过代码阻止AP进入休眠状态。Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠,可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的...
一、Timer TimerTask 参考Java中的Timer和TimerTask在Android中的用法 在开发中我们有时会有这样的需求,即在固定的每隔一段时间执行某一个任务。比如UI上的控件需要随着时间改变,我们可以使用Java为我们提供的计时器的工具类,即Timer和...
一、前言 当手机运行的时候,处理各种任务,硬件就会消耗电量。用户可以通过手机自带的电量监测功能来查看电量使用情况: 一旦用户发现你的APP耗电量特别大,那可就麻烦了。因此我们需要在设计app的时候,就应该下功夫,充分考虑电量优化的问题。 二、电量消耗理论与分析 写出耗电量低...
听书《共享经济》 “共享经济”是个比较火的概念,源于互联网技术对于生产力的解放,商业对生产消费的变革;比如说,滴滴优步,比如共享单车,比如airbnb,闲鱼…… 我有个不成熟的观点是,共享首先是个人资源,小范围的,限定地域内的;然后再是企业资源,大范围的,跨地域的;到后面就...
枸杞富含多种微量元素和维生素,能滋阴,护眼,增强免疫力,历代医家治疗肝血不足、肾阴亏虚引起的视物昏花和夜盲症,常使用枸杞。最在研究中发现了枸杞延缓衰老的功效,但只有在坚持食用的情况下,枸杞子才有药物价值,偶尔吃一两次是没有效果的。用枸杞泡水喝是最常见的,但枸杞中所含的维生素...
跟一个盆友聊天 我就跟她说我最近干嘛这个好烦那个有点不错 然后她突然说 我觉得你好惨 妈的气死我了 气的我写了个freestyle Hey yo Mc vivi 我告诉你我的生活 我只想和你分享 你不懂我的想法 别跟我哔哔 我有我的style 我可以自己嗨皮 嘿 我觉得你好...
怎么才能好好的活在这个世界上,人生下来就是来受苦的,有的人受得了,他活下去了,有的人受不了,他死了。还有一些人,他受不了但是又不愿意死,于是他在整日整夜的抱怨中活着,或者更确切的说是动着。
其实要想活下去很简单,有一个诀窍,就是你得让自己变蠢,而且你还不知道自己有多蠢。...
『文 | 拾壹啊』 读史是件很有意思的事儿,读理科生写的史书更有意思,理科生读理科生写的史书特别有意思。 初中时期学习历史,印象多停留在了唐宋元明和世界史上,近代史涉及部分很少,高中开始详细讲近代史了又恰逢分文理科,理科生的历史课不是补觉,就是补作业,也没怎么正经听讲,更何...安卓L为何如此省电?秘密在于App对齐唤醒
  【PConline 资讯】Google已经公布了最新一代安卓系统 L,并开放了Android L开发者预览版系统镜像。有媒体测试后发现,。为何安卓L会如此省电呢?现在,有分析指出,这主要得益于安卓L使用了App对齐唤醒机制的技术。伏特计划(Project Volta)为安卓L引进了App对齐唤醒机制  一般来说,Google在研发某一代安卓系统时,会有一个特别计划来解决系统问题。比如说,安卓4.1的黄油计划(Poject Butter)解决流畅度问题,安卓4.4瘦身计划(Project Svelt)解决臃肿问题,而这次安卓L的伏特计划(Project Volta)解决的就是电量消耗问题。Google在安卓L中使用了名为&App对齐唤醒&的机制,能够大大减少App唤醒系统造成的额外耗电。  在待机状态下,如果系统和App没有发出动作,安卓其实是很省电的。不过,安卓App频频唤醒后台,令安卓耗电大增。App每次唤醒设备1到2秒,待机时间就会减少2分钟。这并不仅仅指的是点亮屏幕,还有系统在处理应用的后台任务。而安卓L中,Google新加入了一个新的API JobScheduler,API JobScheduler可以使得系统能够有效的处理一些不合理的应用唤醒要求,叫做对齐唤醒机制。这个机制能够定时处理App唤醒操作,压缩硬件唤醒时间,同时也减少了电量消耗。  实际证明,这一机制的确非常有效,安卓L得到了更加出色的续航表现。对齐唤醒机制并不是首次出现,在之前某些ROM和系统App已经可以实现类似功能,Google将对齐唤醒机制引入安卓原生系统,对于用户而言的确是个不错的举动。相关阅读:罗永浩炮轰跑分:锤子将针对跑分App劣化旧版已停止使用!12306安卓版发布更新界面焕然一新!安卓 5.0发布下载超实用的小小神器!教你改进安卓文件关联&
最新资讯离线随时看
聊天吐槽赢奖品
相关软件:
大小:1.93 MB
授权:免费
大小:62.51 MB
授权:免费唤醒休眠的Android设备并做适当UI提醒的总结与思考
我的图书馆
唤醒休眠的Android设备并做适当UI提醒的总结与思考
&&& 最近在做的一个Android APP项目,需要实现这样的效果:当Android设备处于任何界面时(该APP正在后台运行),当有消息来到时,需要立刻弹出一个对话框提示;而如果设备是休眠状态时,需要立刻唤醒设备,提示对话框。这有点类似于Android手机上的qq消息提示。主要的难点是:如何唤醒设备,如何让对话框显示出来。&&&& 对于唤醒设备,很明显,是需要权限的。在Androidmanifest.xml添加了相应的权限,貌似没有作用。后台在贴吧上找到了一个说法,在oncreate函数中添加了下面的代码:&final android.view.Window win = getWindow(); &&& &&& & win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED &&& &&& &&&&&&&&&&&& | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD &&& &&& &&&&&&&&&&&& | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON &&& &&& &&&&&&&&&&&& | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);& &&&&&& 通过命名就可以知道,这部分获取到窗口的一个实例并添加了相应的标志位,就可以实现休眠唤醒。对于这个部分,没有太多可以说的,也不再深究。&&&&&& 而对于第二个问题,确实费了一番功夫。首先,对话框可以用一个activity来实现,改变其大小为合适大小。但是此时,你会发现背景色还是有的,当然希望将背景色改为透明。但是这还不是大问题,大问题是当有多条信息来到时,会有多个这样的对话框来到,用户需要多次点击屏幕才能清理这些对话框。这样的效果肯定是不能接收的。而且,如果在接收多条信息之前设备在别的应用或在桌面时,看不到这个对话框,只有进入该应用才可以看到。网上有人提到了affinity属性,也有人提到使用“singleTask”启动这个activity。试了一下,可以,但是当有多条信息到来时,仍然有问题,它始终显示的是第一条信息的内容,这也很容易让用户认为是个错误。所以,必须弄清楚其本质原理才能解决这个问题。通过查阅资料,终于明白了其中的原理。各位看官,看笔者娓娓道来。背景知识&&&& 1 Android task&&&& 一般情况下,同一个应用中启动的activity都在同一个task中。Android task是一个具有栈结构的容器,启动一个应用,系统就会为之创建一个task,来放置根activity。默认情况下,一个activity启动另一个activity时,二者会放在同一个task中,后者被压入前者所在的task栈。系统task和task之间是相互独立的,正在运行一个应用时,按下home键回到主屏,实际上是将该应用对应的task转移到后台,系统task转移到前台。(其实这里的系统task特指的就是lancher,它有系统启动,可以理解为特殊的一个应用)&&&&& 每一个activity都有一个affinity(亲和力)的属性,该属性像身份证一样,通过它可以知道该activity所在的task,拥有相同affinity的多个activity同属于同一个task(但可能属于不同的应用,这点后面会讲到)&&&& 2 Intent几种常见的flags&&&& 1)FLAG_ACTIVITY_NEW_TASK 当Intent对象包含这个标记是,系统会寻找或创建一个新的task来放置activity,根据要启动的activity的affinity属性进行匹配,若找到,则压入那个task中,若没有则创建一个新task,那么该task的Affinity设置为要启动的Activity的Affinity,这个新task的根就是这个开启的activity。&& 在一个应用A中的某个activity以标准模式使用Intent启动另一个应用B的某个activity,这个activity会被直接压入到应用A的task中;但如果这个Intent被设置了上面的参数,则在启动B中的activity时会创建一个新的task,并将B中的这个activity放在这个新的task中。&&&& 2)FLAG_ACTIVITY_CLEAR_TOP:当Intent对象包含这个标记时,如果栈中发现存在activity实例,则清空这个实例之上的activity,使其处于栈顶。如果这个activity的启动模式是“standard”,且没有在Intent另外设置FLAG_ACTIVITY_SINGLE_TOP标记,则该activity将先销毁自己,再重建。如果设置了FLAG_ACTIVITY_SINGLE_TOP标记,则会使用已存在的实例,Intent被传递到这个实例的onNewIntent()中。如果该activity的启动模式是其他模式,则不管设置FLAG_ACTIVITY_SINGLE_TOP与否,都会使用已存在的实例。&&&& 3)FLAG_ACTIVITY_SINGLE_TOP当task存在目标activity实例且位于栈的顶端时,直接使用这个实例。&&&& 4)FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 如果一个Intent包含这个属性,它转向的那个activity以及那个activity之上的所有activity都会在task重置时被清除出task。特别地,当我们将一个后台的task重新回到前台时,系统会在特定情况下为这个动作附带一个FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记,即必要时重置task,一旦触发重置,则会执行清理操作。&&&& 5)FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 这个标记在以下情况下会生效:1.启动Activity时创建新的task来放置Activity实例;2.已存在的task被放置于前台。系统会根据affinity对指定的task进行重置操作,task会压入某些Activity实例或移除某些Activity实例。Android:allowTaskReparenting该属性用来标记一个activity实例在当前应用退居后台后,是否能从启动它的那个task移动到有共同Affinity的task,TRUE表示可以移动,FALSE表示必须呆在当前应用的task中。默认值为FALSE。例如:一个应用A的activity a启动了另一个应用B的activity b。此时a 和 b均在应用A所在的task中。此时应用A回到后台,若该属性为TRUE,则再次启动A时,会显示activity a,如果此时再启动B,则直接看到activity b。因为b从A的task(启动它的task移动到有共同Affinity的task)。不过要注意的是,如果当A回到后台,直接启动B,则不会出现上述的移动,移动发生在A再次启动的时候。综上所述:&&&&&& 1:要创建新任务,至少要满足两个条件:不同app和以SingleTask方式启动,否则在同一个app中以SingleTask方式打开Activity是不会新创建任务的。(这里有一个特殊情况,设置Activity的android:taskAffinity属性可以让Activity看起来是属于另一个包,属于另一个Activity)&&&&&& 2.在最近任务中进行多个任务之间的相互切换时不会打乱每个任务中Activity的排列。但是在点击app图标进行多个任务切换时,系统会先判断该任务根Activity的启动模式是否为SingleTask,不是的话,不做任何操作,如果是的话,执行根Activity的onNewIntent方法,把覆盖在根Activity之上的Activity destory掉。&&&&&& 3.当没有创建新任务时,新打开的Activity会一直进行当前任务中进栈,无论这些个Activity是属于哪一个App。现象解释&&&&&&& 有了上面的解释,则上面提到的实验现象是非常好理解的了。首先,刚开始由于activity的启动模式为“standard”,所以,每当有信息到来时,后台的程序会使用Intent启动一个activity,这个activity这就是刚开始收到多条信息会弹出多个对话框的原因。又由于该该activity属于一个在后台的task,所以启动的activity会被压入到该task的栈中,只有当该task重新回到前台才会看到这些对话框。将activity的启动模式设置为了“singleTask”,启动的activity被压入一个新的task的栈中,这就像点击某个图标开启一个应用一样,这个task会到前台来,也就是为什么我们此时可以看到对话框会弹到前台来。至于最后提到的问题,对话框的内容是第一次信息的内容,后面的信息来到时,系统发现该task下已经有了一个这样的activity了,就不再重新创建,而是直接复用,Intent传过来的值直接传给newOnIntent函数。所以只需要在这个对话框的activity中重写newOnIntent函数,把接收到的消息显示到对话框中即可。至此,所有的现象都得到了解释,知其然,知其所以然。
TA的最新馆藏[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢android&休眠与唤醒II
Android 休眠(suspend)
在一个打过android补丁的内核中,
state_store()函数会走另外一条路,会进入到request_suspend_state()中,
这个文件在earlysuspend.c中. 这些功能都 是android系统加的, 后面会对earlysuspend和late
resume 进行介绍.
涉及到的文件:
linux_source/kernel/power/main.c
linux_source/kernel/power/earlysuspend.c
linux_source/kernel/power/wakelock.c
Early Suspend
Early suspend 是android 引进的一种机制, 这种机制在上游备受争议,这里 不做评论.
这个机制作用在关闭显示的时候, 在这个时候, 一些和显示有关的 设备, 比如LCD背光, 比如重力感应器, 触摸屏,
这些设备都会关掉, 但是系统可能还是在运行状态(这时候还有wake lock)进行任务的处理, 例如在扫描 SD卡上的文件等.
在嵌入式设备中, 背光是一个很大的电源消耗,所以 android会加入这样一种机制.
Late Resume
Late Resume 是和suspend 配套的一种机制, 是在内核唤醒完毕开始执行的. 主要就是唤醒在Early
Suspend的时候休眠的设备.
Wake Lock 在Android的电源管理系统中扮演一个核心的角色. Wake Lock是一种锁的机制, 只要有人拿着这个锁,
系统就无法进入休眠, 可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的, 超时的锁会在时间过去以后自动解锁.
如果没有锁了或者超时了, 内核就会启动休眠的那套机制来进入休眠.
Android Suspend
当用户写入mem 或者 standby到 /sys/power/state中的时候, state_store()会被调用,
然后Android会在这里调用 request_suspend_state()
而标准的Linux会在这里进入enter_state()这个函数. 如果请求的是休眠,
那么early_suspend这个workqueue就会被调用,并且进入early_suspend状态.
void request_suspend_state(suspend_state_t new_state)
spin_lock_irqsave(&state_lock, irqflags);
old_sleep = state & SUSPEND_REQUESTED;
if (debug_mask & DEBUG_USER_STATE) {
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
struct rtc_
&&&&&&&&&&&&&&&
getnstimeofday(&ts);
&&&&&&&&&&&&&&&
rtc_time_to_tm(ts.tv_sec, &tm);
&&&&&&&&&&&&&&&
pr_info("request_suspend_state: %s (%d-&%d) at %lld
&&&&&&&&&&&&&&&&&&&&&&
"(%d-d-d d:d:d. lu UTC)",
&&&&&&&&&&&&&&&&&&&&&&&
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);
} 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_
spin_unlock_irqrestore(&state_lock, irqflags);
Early Suspend
在early_suspend()函数中, 首先会检查现在请求的状态还是否是suspend,
来防止suspend的请求会在这个时候取消掉(因为这个时候用户进程还在运行),如 果需要退出, 就简单的退出了. 如果没有,
这个函数就会把early suspend中 注册的一系列的回调都调用一次, 然后同步文件系统, 然后放弃掉
main_wake_lock, 这个wake lock是一个没有超时的锁,如果这个锁不释放, 那 么系统就无法进入休眠.
static void early_suspend(struct work_struct *work)
struct early_suspend *
int abort = 0;
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPEND_REQUESTED)
&&&&&&&&&&&&&&&
state |= SUSPENDED;
&&&&&&&&&&&&&&&
abort = 1;
spin_unlock_irqrestore(&state_lock, irqflags);
if (abort) {
&&&&&&&&&&&&&&&
if (debug_mask & DEBUG_SUSPEND)
&&&&&&&&&&&&&&&&&&&&&&&
pr_info("early_suspend: abort, state %d", state);
&&&&&&&&&&&&&&&
mutex_unlock(&early_suspend_lock);
&&&&&&&&&&&&&&&
if (debug_mask & DEBUG_SUSPEND)
&&&&&&&&&&&&&&&
pr_info("early_suspend: call handlers");
list_for_each_entry(pos, &early_suspend_handlers,
&&&&&&&&&&&&&&&
if (pos-&suspend != NULL)
&&&&&&&&&&&&&&&&&&&&&&&
pos-&suspend(pos);
mutex_unlock(&early_suspend_lock);
if (debug_mask & DEBUG_SUSPEND)
&&&&&&&&&&&&&&&
pr_info("early_suspend: sync");
sys_sync();
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
&&&&&&&&&&&&&&&
wake_unlock(&main_wake_lock);
spin_unlock_irqrestore(&state_lock, irqflags);
Late Resume
当所有的唤醒已经结束以后, 用户进程都已经开始运行了, 唤醒通常会是以下的几种原因:
如果是来电,
那么Modem会通过发送命令给rild来让rild通知WindowManager有来电响应,这样就会远程调用PowerManagerService来写"on"
到 /sys/power/state 来执行late resume的设备, 比如点亮屏幕等.
用户按键用户按键事件会送到WindowManager中, WindowManager会处理这些 按键事件,按键分为几种情况,
如果案件不是唤醒键(能够唤醒系统的按键) 那么WindowManager会主动放弃wakeLock来使系统进入再次休眠,
如果按键是唤醒键,那么WindowManger就会调用PowerManagerService中的接口来执行 Late
Late Resume 会依次唤醒前面调用了Early Suspend的设备.
static void late_resume(struct work_struct *work)
struct early_suspend *
int abort = 0;
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPENDED)
&&&&&&&&&&&&&&&
state &= ~SUSPENDED;
&&&&&&&&&&&&&&&
abort = 1;
spin_unlock_irqrestore(&state_lock, irqflags);
if (abort) {
&&&&&&&&&&&&&&&
if (debug_mask & DEBUG_SUSPEND)
&&&&&&&&&&&&&&&&&&&&&&&
pr_info("late_resume: abort, state %d", state);
&&&&&&&&&&&&&&&
if (debug_mask & DEBUG_SUSPEND)
&&&&&&&&&&&&&&&
pr_info("late_resume: call handlers");
list_for_each_entry_reverse(pos,
&early_suspend_handlers, link);
&&&&&&&&&&&&&&&
if (pos-&resume != NULL)
&&&&&&&&&&&&&&&&&&&&&&&
pos-&resume(pos);
if (debug_mask & DEBUG_SUSPEND)
&&&&&&&&&&&&&&&
pr_info("late_resume: done");
mutex_unlock(&early_suspend_lock);
我们接下来看一看wake lock的机制是怎么运行和起作用的, 主要关注 wakelock.c文件就可以了.
wake lock 有加锁和解锁两种状态, 加锁的方式有两种, 一种是永久的锁住, 这样的锁除非显示的放开, 是不会解锁的,
所以这种锁的使用是非常小心的. 第二种是超时锁, 这种锁会锁定系统唤醒一段时间, 如果这个时间过去了, 这个锁会自动解除.
锁有两种类型:
WAKE_LOCK_SUSPEND 这种锁会防止系统进入睡眠
WAKE_LOCK_IDLE 这种锁不会影响系统的休眠, 作用我不是很清楚.
在wake lock中, 会有3个地方让系统直接开始suspend(), 分别是:
在wake_unlock()中, 如果发现解锁以后没有任何其他的wake lock了, 就开始休眠
在定时器都到时间以后, 定时器的回调函数会查看是否有其他的wake lock, 如果没有, 就在这里让系统进入睡眠.
在wake_lock() 中, 对一个wake lock加锁以后, 会再次检查一下有没有锁, 我想这里的检查是没有必要的,
更好的方法是使加锁的这个操作原子化, 而 不是繁冗的检查. 而且这样的检查也有可能漏掉.
当wake_lock 运行 suspend()以后,
在wakelock.c的suspend()函数会被调用,这个函数首先sync文件系统,然后调用pm_suspend(request_suspend_state),接下来pm_suspend()就会调用enter_state()来进入Linux的休眠流程..
static void suspend(struct work_struct *work)
int entry_event_
if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
&&&&&&&&&&&&&&&
if (debug_mask &
DEBUG_SUSPEND)&
&&&&&&&&&&&&&&&&&&&&&&
pr_info("suspend: abort suspend");
&&&&&&&&&&&&&&&
entry_event_num = current_event_
sys_sync();
if (debug_mask & DEBUG_SUSPEND)
&&&&&&&&&&&&&&&
pr_info("suspend: enter suspend");
ret = pm_suspend(requested_suspend_state);
if (current_event_num == entry_event_num) {
&&&&&&&&&&&&&&&
wake_lock_timeout(&unknown_wakeup, HZ / 2);
Android于标准Linux休眠的区别
pm_suspend() 虽然会调用enter_state()来进入标准的Linux休眠流程,但是还 是有一些区别:
当进入冻结进程的时候, android首先会检查有没有wake lock,如果没有, 才会停止这些进程,
因为在开始suspend和冻结进程期间有可能有人申请了 wake lock,如果是这样, 冻结进程会被中断.
在suspend_late()中, 会最后检查一次有没有wake lock, 这有可能是某种快速申请wake
lock,并且快速释放这个锁的进程导致的,如果有这种情况, 这里会返回错误,
整个suspend就会全部放弃.如果pm_suspend()成功了,LOG的输出可以通过在kernel cmd里面增加
"no_console_suspend" 来看到suspend和resume过程中的log输出。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 ps4待机怎么唤醒 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信