首页 > 代码库 > 手机管理应用研究【6】——省电管理篇

手机管理应用研究【6】——省电管理篇

欢迎转载,转载请注明:http://blog.csdn.net/zhgxhuaa


说明


本篇将介绍省电管理篇,主要介绍一下Android的耗电情况和目前市面上《电池助手》类应用涉及到的一些技术点。本篇将对这些知识点做一下总结和分析。主要包括:

A.       电池信息(耗电排行)

B.       省电管理

C.       剩余可用时间估算等


耗电分析


手机耗电分析


以我的手机(小米2S)为例,首先来看一下我的手机的电池使用情况,如下图(在设置->电量中查看):




在手机中应用的耗电情况可以从硬件和软件两个层面分别去衡量。

在硬件层面主要是:

A.       屏幕(一般来说,屏幕尺寸越大、分辨率越高,单位时间耗电也就越多)

B.       CPU(一般来说,CPU运行的核心数越多,主频越高,单位时间耗电越多)

C.       基带(一般来说,Wifi耗电比无线要少,网络好的情况耗电比网络差的情况耗电要少)

在软件层面主要是:

A.       应用运行(普通情况下的应用运行是正常认为行为,是合理的,但应用内过多的推送、通知等会导致额外耗电)

B.       后台常驻Service(消耗系统资源、可能会时不时被唤醒)

C.       长连接(占用基带、为了维持连接会定时唤醒系统)

所以,接下来看一下省电助手中都针对性的做了哪些工作,下面是金山电池医生的截图:




电池充电方式


接下来结合上面的第一幅图定义一下几个名词:

n  快速充电:(0%  ~ 80% )这个阶段中,电池能够快速的充到总电量的80%,但仍需要进行连续式充电才能完成充满。(电流较强,速度较快)

n  连续充电:( 80%~100%)在电池即将充满的状态下,充电电流会逐渐减小,确保电池完成充满。(电流减弱,放缓慢充)

n  涓流充电:(100%~100%)电池充满后进行微小的脉冲电流充电,能让电子保持流动,延长电池使用寿命,但不至于过充。(活跃电子,寿命更长)

下面是一张手机电池充电过程的示意图:




这里可参见:

http://www.apple.com/cn/batteries/iphone.html

http://www.apple.com/cn/batteries/

http://www.apple.com/cn/iphone/battery.html


关于这三种充电方式的一个比较(C为电池容量):




关于涓流充电


“快速充电”和”连续充电“都比较容易理解,这里简单说一下”涓流充电”。那为什么要进行”涓流充电”呢?其实主要是基于如下两个方面的考虑:

A.       在电池充电过程中发生的一些效率上的损失,用来弥补电池在充满电后由于自放电而造成的容量损失。

B.       电池充满后进行小电流充电,能让电子保持流动,延长电池使用寿命。

涓流充电过程一般占充电过程20%左右的时间,百度百科上说这个阶段通常需要30-40分钟。

关于“涓流充电”是否真的有必要,在网上有很多争论。据苹果官方和金山电池医生的测试,还是有一定的用处的。本文就介绍到这里,感兴趣的同学可以自行查阅相关资料,这里不再过多介绍。

 

本小节的一些参考:

http://wenku.baidu.com/view/44709e1da76e58fafab0038e.html

http://wenku.baidu.com/view/c0882e15a2161479171128b8.html

http://baike.baidu.com/view/206627.htm

http://baike.baidu.com/view/10022.htm


省电管理


可以从那些点来做


结合第一节中队耗电情况的分析,我们在省电管理方面有那些工作可以做呢?

n  从硬件层面:

A.       屏幕:屏幕亮度、屏幕超时

B.       CPU:CPU频率、休眠模式

C.       基带:Wifi、蓝牙、3G网络、同步、GPS

n  从软件层面:

A.       后台进程限制(可参考系统”设置->开发者选项->后台进程限制”)

B.       设定不保留活动(用户离开后即销毁每个活动,参见”设置->开发者选项->设定不保留活动”)

C.       通过禁止开机自启动、后台自启动杀死后台常驻进程和清理内存。

D.       通过进程清理杀死后台进程并清理内存(锁屏清理、定时清理)

E.        对长连接采用对齐唤醒策略(绿色守护和小米V5)

F.        限制唤醒锁。

n  其他:

A.       关闭震动

B.       关闭触感(触摸时震动、触摸提示音)

C.       适当调节系统音量

D.       系统动画

下面是电池助手中实现的功能:




可以看出,目前流行的电池助手应用中,也是按照我们前面的思路实现的。


技术实现


屏幕控制


屏幕相关的可以直接调用系统SettingsProvider来设置,具体设置项为:

n  屏幕超时:Settings.System.SCREEN_OFF_TIMEOUT

n  自动调整屏幕亮度:Settings.System.SCREEN_BRIGHTNESS_MODE;

其取值为:SCREEN_BRIGHTNESS_MODE_MANUAL = 0和SCREEN_BRIGHTNESS_MODE_AUTOMATIC= 1

n  屏幕亮度:Settings.System.SCREEN_BRIGHTNESS


CPU频率控制


CPU的频率控制主要涉及到三个方面:

n  CPU工作核心数

通过/sys/devices/system/cpu[id]/cpu1/online

n  CPU模式

通过/sys/devices/system/cpu/cpu[id]/cpufreq/scaling_governor

n  CPU频率

所支持的频率:/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies

当前核心的频率:/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

最大工作频率:/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

最小工作频率:/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq

这里有这么几点需要注意:

A.       并不是所有的CPU都可以控制工作核心数的,这取决于CPU的类型,一般来说采用非对称多处理的CPU是可以控制的,反之采用对称多处理技术(SMP)的CPU是不能控制的。

B.       上述对CPU的控制需要root权限。

C.       CPU限制频率等是需要root权限来实现的。


CPU调节模式


CPU和IO调节模式。不同调节模式对应的性能提升、省电效果不一样


CPU调节模式


ondemand(按需模式)

 

顾名思义,按需调节cpu频率,不操作手机的时候控制在最低频率,滑屏或进入应用后会迅速提升至最高频率,当空闲时迅速降低频率,性能较稳定,但因频率变化幅度过大,省电方面只有一般的水平。

 

powersave(省电模式)

 

按设定最低频率运行,最省电也最龟速,日常没有使用价值,除非配合setcpu情景模式,关屏睡眠时使用此调节模式。

 

performance(高性能模式)

 

和省电模式相反,始终按设定最高菜谱频率运行,最耗电也最刚猛!此模式亦无任何日常使用价值,果断pass。

 

userspace(用户隔离模式)

 

严格来说它并不是一个模式,是允许非内核进程控制cpu频率的设置,现在已经不需要它了,setcpu官方的建议是,“不要使用此选项”。

 

conservative(保守模式)

 

和ondemand模式的调频设定类似,不过有操作时提升cpu频率的速度较慢,空闲时迅速降频,所以名字叫保守模式,性能较低,省电程度略好于ondemand,随着CPU负荷加大,频率逐级上升,在CPU闲时频率逐级下降,因此这个设置相对于ondemand模式省电,但变频不够顺滑,所以会有卡顿现象。总体不推荐

interactive(交互模式)

 

相对于保守模式,这个模式算是高性能版的ondemand,开始操作手机后,频率升至最高,可以带来更好的响应速度,空闲时缓慢降至设定最低频率。电量自然也是要多费一点。

 

关于CPU调节模式的设置可以参见下图:

 

/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor



I/O调节模式


(什么是I/O调节模式?i/o即input/output的缩写,关于数据的读写操作,不同进程请求数据的优先顺序等等。io调度模式比较复杂,这里仅介绍常用的几个模式,部分参考xda、androidforums、wik1pedia、linuxarchive资料)

 

noop

 

这个调度模式会把所有的数据请求直接合并到一个简单的队列里。不适合有机械结构的存储器,因为没有优化顺序,会增加额外的寻道时间。属于最简单的一个调度模式,无视io操作优先级和复杂性,执行完一个再执行一个,如果读写操作繁多的话,就会造成效率降低。

 

anticipatory

 

其实这个有点类似于pc硬盘的NCQ功能,执行有预测性的调度,看起来似乎可以提高效率,不过因为它的预测机制会在进程将要结束一个读写操作时时开始准备下一个的预处理,所以会打乱系统正常的连续io调度,降低随机存取效率。用的人很少,不推荐。

 

deadline

 

顾名思义,用过期时间来排序io操作顺序,保证先出现的io请求有最短的延迟时间,相对于写操作,给读操作更优先的级别。是比较好的一个调度模式。

 

cfq

完全公平队列,是anticipatory模式的替代品,没有过多的做预测性调度,而是根据给定的进程io优先级,直接来分配操作的顺序。这个模式在linux上表现良好,但也许并不是最适合android的io调度模式,太强调均衡,而降低了连续读写数据的性能。

 

vr

 

具有和deadline相似的操作排序机制,有着最高的峰值读写速度,但是性能比较不稳定,也就是说可能跑出最高的分数,但是也会出现最低值。

 

sio

 

虽然基于deadline,但是它和noop一样,不会对io操作进行排序,所以有着noop那样快速的存取速度,但并没有过多优化io操作。如果不喜欢noop完全不参与调度,也可以选择这个。

 

关于I/O Scheduler的设置可以参见下图:

 

/sys/block/{DEVICE-NAME}/queue/scheduler




讲到I/O Scheduler,就不得不同时提一下各类“跑分”软件。

 

目前比较流行的跑分软件是Quadrant象限以及超级兔子评测。而前者的测试结果可谓非常不准确,但大多数人仍然将这个软件的测试成绩作为衡量Android设备性能的标准。

 

鉴于目前各个Android手机,其CPU性能基本不会出现太大波动(超频除外,设置了不恰当的CPU Governor除外),因此影响这个软件最终成绩的,主要是I/O测试以及图形测试。

 

刚刚说过,Android是有读写缓存机制的。而部分ROM/内核修改者,为了让自己修改的ROM或内核的性能看上去很NB,吸引更多人使用,故意针对Quadrant测试做了手脚,将Android磁盘缓存设置得较大,让分数更高。理论上来说,使用更大内存作为磁盘读写缓存确实可以提升I/O性能,但这样也会造成数据丢失的风险进一步增加,如果在配上noop、sio这样没有读写优先级调整的I/O Scheduler,则数据很可能始终无法被真正写入到NAND闪存中。

 

因此,在此代表广大Android用户,强烈鄙视这部分ROM/内核修改者(大部分是国内的,特别是大家经常听说或提到的“X”大,“X”神等)。技术不如人不可怕,使用损人利己的手段达到目的就相当无耻了。

 

而超级兔子评测的准确度相对来说要高不少,特别是其针对I/O部分的测试,测试结果与PC上的CrystalDiskMark等软件差距不大。

 

这一段参考自:http://bbs.gfan.com/android-3588731-1-1.html


网络控制


在电池助手中网络控制主要指控制3G数据、WIFI、蓝牙等的开关,这些系统都有接口提供,直接使用即可。

对于针对软件的一些控制措施很多都已经在手机加速等介绍过,这里只提供一个思路,不做详细介绍了。


软件层控制


前面几小节主要介绍了从屏幕、CPU和网络这些硬件层面的省电控制措施,本小节将简单介绍一下从系统和软件的层面有哪些工作可以做。

A.       控制待机功能(待机模式下关掉不必要的外设,一般平台的待机功耗可以控制在3-5ma)。

B.       手机锁屏时,清理不必要的应用。

C.       框架层中控制partial型wakelock锁的使用。

D.       控制系统层RTC Alarm 唤醒系统的频率。

E.        定时模式切换等。


电池信息


获取电池基本信息


获取电池的基本信息,可以通过监听广播android.intent.action.BATTERY_CHANGED实现,具体的实现代码可以参考:

@/package/app/Settings/src/com/android/settings/BatteryInfo.java




获取耗电排行信息


在Android系统设置中有应用和子系统耗电排行的统计,可以作为我们在实现电池助手软件时的参考,相关代码可以参考目录:@/package/app/Settings/src/com/android/settings/fuelguage/。

电池相关统计信息是由类BatteryStatsImpl服务实现的,获取BatteryStatsImpl的方式如下:




那是不是我们就可以使用BatteryStatsImpl来获取耗电排行信息了呢?实际上是不行的,原因如下:

1)        使用BatteryStatsImpl所需要权限:"android.permission.BATTERY_STATS",而系统对其做了限制 ,非系统应用是无法使用BatteryStatsImpl的。

2)        在通过eclipse开发应用时,是无法饮用com.android.internal这个包内的类的,原因是adt对其做了排除。要想使用可参见http://mogoweb.net/archives/87


估算电池充电时间


关于电池的充放电,电池的厂商一般都会有一个充放电的计算模型。也就是不同厂商的电池产品充放电的曲线是会有差异的。不同的电池技术之前充放电曲线可能会差异较大(如镍镉电池与锂电池),同种技术的电池不同厂商之间差别不会太大。

下面是我从网上找到的一段估算电池充电耗时的计算模型,由于对电池相关技术并不是特别了解,所以这里我也无法确定是否完全可靠,只作为参考吧。

 

1、充电电流小于等于电池容量的5%时:充电时间(小时)=电池容量(mAH)×1.6÷充电电流(mA)

2、充电电流大于电池容量的5%,小于等于10%时: 充电时间(小时)=电池容量(mAH)×1.5÷充电电流(mA)

3、充电电流大于电池容量的10%,小于等于15%时: 充电时间(小时)=电池容量(mAH)×1.3÷充电电流(mA

4、充电电流大于电池容量的15%,小于等于20%时 充电时间(小时)=电池容量(mAH)×1.2÷充电电流(mA)

5、充电电流大于电池容量的20%时: 充电时间(小时)=电池容量(mAH)×1.1÷充电电流(mA)

 

参考:http://wenku.baidu.com/view/c0882e15a2161479171128b8.html

 

这里简单介绍一下在上面的模型中为什么电池容量(mAH)后面都会有一个大于1的系数:其实这里这里大于1的部分就是电池充电过程中的损耗。


估算电池续航时间


简单电池续航时间计算模型:电池续航时间 =电池容量 / 电池放电电流。实际上电池的续航还会受温度和电池使用时间、放电时的电量等因素的影响。在放电时电流越大,就会导致温度越高,发热消耗越大;随着电池充放电次数的增加,电池的容量会不断的衰减。所以,在实际中电池的放电并不是一个简单的线性关系,而是一条比较复杂的曲线。下面是一般锂电池的典型放电曲线图:




在电池管理软件中队电池续航时间的估算,往往分为两种:

A.       总体续航(在正常使用时的续航时间)

B.       特定情境续航(比如可以看视频多长时间、3G通话多长时间、上网多长时间)

无论哪种方式我们在估算续航时间时所需要的数据都是一样的,即:电池电量和电流消耗情况。Android中对于电流的消耗情况是在文件@/frameworks/base/core/res/res/xml/power_profile.xml中定义的,下面是一个截图片段:

 

@/frameworks/base/core/res/res/xml/power_profile.xml




这些信息可以通过@/frameworks/base/core/java/com/android/internel/os/PowerProfile.java来获取。


好了,有关省电的相关内容就先介绍这些了,欢迎交流讨论。