Android电源管理基础知识介绍

电源/新能源

3399人已加入

描述

一、电源管理基础知识

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的待机唤醒流程.




审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分