月度归档:2013年04月

Defy电池跳电详解

翻译自xda-developer论坛一位乌克兰的网友,原帖地址
http://forum.xda-developers.com/showthread.php?t=1778492
最近很多人刷完新ROM后都遇到了MOTO公司Defy手机电池跳电的现象。比如,电量突然从67%跳到49%,从34%跳到19%,从7%跳到4%等等。
使用官方2.2系统一年多后我也改刷了CM7.2系统,刷完系统我也碰到了跳电问题。于是我在网上各种论坛搜索跳电问题的解决方法,然而没有任何一种方法有实际效果。
终于,在做了很多试验后,我发现了一些有意思的理论来解释电池跳电的缘由。
我们的Defy有一个非常简单的电池控制系统(被MOTO称作cpcap系统)。这个系统只提供电池的实时电压和电流,并不计算或者提供电池百分比信息。安卓系统上进行这项工作的是battd守护进程,它使用一套非常非常复杂的估算方法对电池剩余百分比进行计算(我在battd源码中看到了Coulomb计数方法—Coulomb counter technique)。
5%、20%、50%、80%、100%这几个百分比是电池的电量检测点,而battd提供的是这几个检测点中间的百分比与电池电压的对应关系。当电池电压下降到一个电量检测点时,电量百分比会一下子跳到对应的检测点时的百分比。而其他所有的电量百分比是由battd结合电池电压进行估算得到的。这个估算方法与电池最大容量(从电池本身属性得到)和电池有效电流相关。一个Defy官方原配电池显示是1500mAh,而我的一个中国1700mAh的电池仅显示为1200mAh(应该就这么多,中国山寨电池,你懂的——译者注)。battd把最后计算出的电量百分比和电池电压存放在/data/battd/cc_data文件中。cc_data文件中的信息在开机的时候被读取,读取出的电量百分比成为开机后系统的基准百分比。电池使用过程中,电量百分比也随之减少。当你删除了cc_data并重启后,battd利用实时电池电压寻找最近的电量检测点的电压值并显示对应的电量百分比。
我是如何发现上面提到的电量检测点值的呢?
假设我们有一个全新的原装Defy电池,电量剩余25%。
如果你删除了cc_data文件并且重启,battd将重新创建这个文件并向电池控制系统请求当前电池状态。电池控制系统将返回50%这个值,battd显示出49%(是49%而不是50%,因为这个值受复杂计算过程中的一次最小的整数取整结果影响)。但是电池实际剩余电量是25%!现在让电池放电,系统会显示48%,47%,46%等等。好,但是在40-44%的时候电池电量百分比会立刻跳到19%,因为电池控制系统会告诉battd电池实际剩余20%,这样就会让battd强制把它的估计值替换为电池控制系统提供的实际值。
当一个电池本身的最大容量因为使用次数增加而减少的时候,比如说1500mAh的电池可能使用一年后容量会变成1300mAh。但是电池依然报告给系统它是一块1500mAh的电池,battd就根据报告的值来进行百分比的计算。对于这块有损耗的电池来说,battd本应该让计算出的电量百分比减少得更快一些,但实际上它还是使用了和全新的1500mAh一样的百分比减少的速度。当电池电压达到一个电量检测点时,battd就立刻把电量百分比更新为检测点的百分比值,从而就出现了一次跳电。
battd与/pds/public/battd文件夹中的电池信息有一定的关系。这个文件夹中的数据帮助battd更准确地估计电量百分比,文件夹中含有三个文件:

  1. batt_offset_data
  2. batt_phasing_data
  3. batt_tuning_data

没有这几个相关的文件,即使在使用全新的电池时,你也可能遇到轻微的跳电现象。
对于Defy来说,至少有2个版本的battd守护进程(Defy+使用的是另一个battd)。我们简单的将2个版本的battd文件称作新版和旧版。你通过查看/data/battd/cc_data文件的大小可以判断你使用的是哪个版本。

  1. cc_data = 16 bytes – 旧版,
  2. cc_data = 24 bytes – 新版。

早期的官方2.2系统使用的是旧版,新一些的官方系统用的是新版的battd。CM7.2使用的就是新版的。
不同的battd版本在电量计算的过程中有区别吗?答案是肯定的。区别在于battd这个守护进程是由哪个用户运行的。
旧版的battd使用了mot_accy账户运行,而新版的battd使用的是system账户。/pds/public/battd文件夹和其中文件的所有者和用户组应该被设置成与battd版本相对应的账户,否则battd将没有足够的权限从/pds/public/battd文件夹读取电池数据,这就意味着battd将使用默认的电池数据,从而导致不准确的电池剩余电量百分比的估计。
如果你是用的是官方的2.2系统或者更老的系统,你的battd就是旧版的。/pds/public/battd文件夹的权限应该设置成mot_accy账户所有。
然后你又安装了使用新版battd的CM7.2系统,系统就不能从/pds/public/battd文件夹读取电池数据了,因为新版的battd使用了system用户运行。这样即使你使用一个全新的电池,你的电量百分比也会不准确。
这就是为啥一些机友在CM7.2系统中替换旧版的battd(和对应的lib-libbattd.so)后解决了电池跳电的问题。
如果你在使用CM7.2或者一些更新的CM系统,简单的把/pds/public/battd文件夹和其中文件的所有者和用户组改成system就可以让新版的battd读取电池信息,一定程度解决跳电问题。
如果你的手机依然跳电,这就意味着你的电池已经有一定程度的损耗了,battd不能准确在电量检测点间准确的估计电池电量百分比。
是否有可能解决这个问题?答案是有可能。
我曾经可以修改电量检测点的电压值并消除了到达电量检测点的跳电问题。但是!电池消耗速度仍然和原来一样,所以导致我从100%到10%都没有跳电问题,而手机在10%时自动关机了,因为这时电池电压已经减少到了3.050V(在电池这个电压下就不能提供手机正常运行的电压了)。
通过修改/pds/public/battd/batt_offset_data文件来修改电量检测点的电压。我把最后的3个byte修改成0xA0,这样就调整了50%、20%和5%对应的电压。
battd_phasing_data文件在我的测试中没有任何作用,这个文件中包括了显示电压、温度、电流修正值。
battd_tuning_data文件不知道是干嘛用的。
所以现在的目标就是找到一种方法强制让电量减少速度与电池损耗程度相协调。最简单的方法就是修改battd,不让它从电池上读取电池容量,而是读取指定的电池容量(例如1300mAh)。
另一种更好的方法是使用自定义的电池驱动,简单地让电池电压和电量百分比对应起来。触摸版的bootmenu使用的就是这种方法,Quarx(Q大)也曾经在他的git上面建立了自定义电池驱动的条目。
重要事项:
电池校准是一个谜!/data/system/batterystats.bin文件和电池充电、寿命、状态无关,这一点Google的工程师也提到过。
对于我们的Defy来说,最好将电池充电到100%后再冲一会儿电。然后断开充电器(电脑),电池电量应该会正确地显示为99%。这就是我们充电时候需要做的事情,不要在电池校准过程中浪费太多时间!
总结:

  • 查看你使用的battd版本。
  • 检查/pds/public/battd文件夹和其中文件的所有者。修改所有者和用户组如果需要。
  • 将你的电池充电至100%,然后在持续充电若干小时。

如果你仍然有跳电现象,说明你的电池已经损耗到一定程度了。跳电百分比的总量表明了你电池相对一个新电池的损耗程度。这时候实际上没有任何可以提高电池寿命的好方法。跳电现象是Defy使用便宜的电池控制系统和Defy不准确的电量估计逻辑的结果。这就是为什么官方的系统只有电量10%的步进——去隐瞒隐藏一些问题。