一、电源管理基础知识
1.1电源管理的几种状态
Android kernel源码中,定义了三种电源状态,在kernel/power/suspend.c中:

对应的宏定义/include/linux/suspend.h

1.2 电源管理状态的介绍:
PM_SUSPEND_ON
设备处于正常工作状态
PM_SUSPEND_STANDBY
设备处于省电状态,但还可以接收某些事件
PM_SUSPEND_MEM
设备进入睡眠状态,保存系统运行的上下文至内存后挂起系统,只有特定外部中断才可以唤醒设备
PM_SUSPEND_TO_IDLE
设备进入空闲状态,冻结用户空间并将外围设备调至低耗电模式,强制将 CPU 进入idle
ADB 查看支持的电源模式
cat /sys/power/state
1.3 Idle State
Android的Idle状态分为二类:CPU Idle和Device Idle
CPU Idle
每一个 CPU 核心都会有一个 idle 进程,idle 进程是当系统没有调度 CPU 资源的时候,会进入 idle 进程,而 idle 进程的作用就是不使用 CPU,以此达到省电的目的。
有关CPU idle的内容可以查看公众号之前的文章《Linux Cpuidle介绍》
Device Idle
Device Idle属于android Doze模式中的概念,即指手机屏幕熄屏、不充电、静置不动
在 Doze 模式下,按照google的官方说法,Wakelocks,网络访问,jobshedule,闹钟,GPS/WiFi扫描都会停止。

系统会定期退出 Doze 一小段时间,让应用程序完成其延迟的活动。在此维护窗口期间,系统运行所有挂起的同步、作业和警报,并允许应用程序访问网络。

二、Android电源管理框架
Android系统的电源管理框架分成五个部分:应用层,框架层,Native层,HAL层和内核层。电源管理架构图例如下:

应用接口层: PowerManager.java 负责向应用程序提供一系列接口,例如wakelock的申请与释放,进而让系统休眠或唤醒
框架层: PowerManagerService.java PowerManagerServic是android电源管理的核心服务,向上提供应用程序接口.向下通过hal层和kernel层来控制待机状态和系统硬件设备状态
HAL层: power.c 接收上层参数,通过写节点与kernel层通信
内核层: Kernel/Power 实现系统电源管理框架机制,为设备电源管理提供基础框架
三、WakeLock
Android中wakelock是一种锁的机制,用于阻止系统进入睡眠状态,只要有任意应用持有wakelock,那么系统就无法进入睡眠状态。
newWakeLock(int flags, String tag)
申请wakelock时有一个关键的参数flags,它有如下几种情况:
PARTIAL_WAKE_LOCK: Screen off, keyboard light off
SCREEN_DIM_WAKE_LOCK: Screen dim, keyboard light off
SCREEN_BRIGHT_WAKE_LOCK: Screen bright, keyboard light off
FULL_WAKE_LOCK: Screen bright, keyboard bright
上面4种是互斥的,即只能指定其中之一,但可以与下面两种flag不是互斥的:
ACQUIRE_CAUSES_WAKEUP:一旦有请求锁时强制打开Screen和keyboard light
ON_AFTER_RELEASE:在释放锁时reset activity timer
如果系统申请了PARTIAL_WAKE_LOCK,那么即使按power键,系统也不会进sleep,如music播放时.如果申请了其它的wakelocks,按power键,系统还是会进sleep
wakelock有加锁和解锁两种状态:
一种是永久性锁住,这种锁除非后续放开,否则不会解锁;
另一种是超时锁,这种锁会锁定系统一段时间后会自动解锁。
电源锁的两种类型:
(1)WAKE_LOCK_SUSPEND:阻止系统进入睡眠,属于永久性锁,超时锁为WAKE_LOCK_AUTO_EXPIRE
(2)WAKE_LOCK_IDLE:阻止持有该锁的系统进入idle状态
Android中使用两条链表分别保存处于active状态的suspend lock和idle lock和保存处于inactive状态的wakelock。
系统执行加放锁有两种机制,第一种是不计数锁,另一种是计数锁。可以通过PowerManager.WakeLock.setReferenceCounted(boolean value) 来指定,默认为计数机制。这两种机制的区别在于,前者无论 acquire() 了多少次,只要通过一次 release()即可直接解锁。而后者正真解锁是在( --count == 0 )的时候,同样当 (count == 0) 的时候才会去申请加锁,其他情况 isHeld 状态是不会改变的。所以 wakeLock 的计数机制并不是正真意义上的对每次请求进行申请/释放每一把锁,它只是对同一把锁被申请/释放的次数进行了统计后才去执行操作。
3.1wakelock在framework层
内核启动完成后,电源管理系统会在文件系统中建立两个节点:
/sys/power/wake_lock
/sys/power/wake_unlock
应用程序可以通过/sys/power/wake_lock申请一个WAKE_LOCK_SUSPEND 类型的锁,通过/sys/power/wake_unlock则可以释放一个锁。内核在进入suspend之前如果检测到某个锁没有释放,则会放弃本次的suspend过程,直到这个锁释放为止.Android持有电源锁后可以让持锁的进程持续执行,即使进入了睡眠模式。
如果应用崩掉或退出,系统会自动释放他们获取的所有电源锁;如果是在服务中获取的,当服务崩掉或注销时也会自动释放;
Framework层有关电源锁的内容是通过PowerManagerService类来实现,这个类是用来管理所有应用程序申请的wakelock,比如音视频播放器,camera等申请的wakelock都是通过这个类来管理的。如:
static final String PARTIAL_NAME = "PowerManagerService"
PARTIAL_NAME作为参数传递到底层去。
ADB 调试命令
echo lockname > /sys/power/wake_lock
加锁“lockname”
echo lockname > /sys/power/wake_unlock
解锁“lockname”
四、Earlysuspend和Lateresume
Early Suspend和Late Resume是Android在标准Linux的基础上增加的一项特性。当用户空间申请进入suspend时,会先进入early suspend状态.外设驱动程序可以注册early suspend回调函数,当进入early suspend时,内核会逐一地调用这些回调函数。例如在进入early suspend后,回调函数会通过屏幕驱动把屏幕和背光都关闭, 但此时系统依然在正常运行。进入early suspend状态以后,一旦所有wakelock被释放,系统马上会进入真正的suspend流程.
Android 4.4起,也就是引入ART的版本,摒弃了early suspend机制,改用了fb event通知机制,后续Android版本只有suspend、resume以及runtime suspend、runtime resume。
结语
本文讲述了Android电源管理模块的主要内容,旨在让读者对于Android电源状态及wakelock有一个初步的认识,方便以后深入介绍内核wakelock的实现和Android的待机唤醒流程.
引文:
[1]https://developer.android.google.cn/training/monitoring-device-state/doze-standby?hl=en
[2] 深入理解LINUX内核(第三版)(美)博韦,西斯特 著,陈莉君,冯锐,牛欣源 译

长按关注内核工匠微信
Linux内核黑科技| 技术文章 | 精选教程
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
我想用这两种语言中的任何一种(最好是ruby)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生
这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什
我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源
文章目录一基础定义二创建逻辑卷2-1准备物理设备2-2创建物理卷2-3创建卷组2-4创建逻辑卷2-5创建文件系统并挂载文件三扩展卷组和缩减卷组3-1准备物理设备3-2创建物理卷3-3扩展卷组3-4查看卷组的详细信息以验证3-5缩减卷组四扩展逻辑卷4-1检查卷组是否有可用的空间4-2扩展逻辑卷4-3扩展文件系统五删除逻辑卷5-1备份数据5-2卸载文件系统5-3删除逻辑卷5-4删除卷组5-5删除物理卷六LVM逻辑卷缩容6-1缩容注意事项6-2标准缩容步骤一基础定义LVM,LogicalVolumeManger,逻辑卷管理,Linux磁盘分区管理的一种机制,建立在硬盘和分区上的一个逻辑层,提高磁盘分
目录H2数据库入门以及实际开发时的使用1.H2数据库的初识1.1H2数据库介绍1.2为什么要使用嵌入式数据库?1.3嵌入式数据库对比1.3.1性能对比1.4技术选型思考2.H2数据库实战2.1H2数据库下载搭建以及部署2.1.1H2数据库的下载2.1.2数据库启动2.1.2.1windows系统可以在bin目录下执行h2.bat2.1.2.2同理可以通过cmd直接使用命令进行启动:2.1.2.3启动后控制台页面:2.1.3spring整合H2数据库2.1.3.1引入依赖文件2.1.4数据库通过file模式实际保存数据的位置2.2H2数据库操作2.2.1Mysql兼容模式2.2.2Mysql模式