Morrison.J Android Dev Engineer

Android BatteryService


本文记录对BatteryService(Android7.0)的阅读理解。Android中,获得电池的方法是监听来自BatteryService(本文简称BS)发出的系统广播,App通过注册广播接收器获得电池的状态信息.

带着问题阅读

  • 广播是如何发送出来的,什么情况下会发送广播?
  • BS跟硬件电池有什么关系,它的电量信息是如何获取的?
  • BS跟PowerManagerService的关系是什么?
  • 为什么手机的电池曲线老是不正常,为什么不是线性的(假设长时间功耗相同)?
  • 如何计算某一个进程的耗电量?

先盗一张网络图片,表明了BS、PMS和AMS之间在Battery上的关系:

入口

frameworks/base/services/core/java/com/android/server/BatteryService.java

20 import android.os.BatteryStats;                                                                                                             
24 import com.android.internal.app.IBatteryStats;
25 import com.android.server.am.BatteryStatsService;

或者我们dumpsys中获得有关电池的信息

dupsys -l grep battery
$ dumpsys -l | grep battery
  battery
  batteryproperties
  batterystats

BS/BSS的启动

BS的启动 ·SystemServer - startCoreServices - mSystemServiceManager.startService(BatteryService.class);

BSS在AMS中启动

2616         mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);                                                              
2617         mBatteryStatsService.getActiveStatistics().readLocked();
2618         mBatteryStatsService.scheduleWriteToDisk();
2619         mOnBattery = DEBUG_POWER ? true
2620                 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
2621         mBatteryStatsService.getActiveStatistics().setCallback(this);

BS 构造函数

150     public BatteryService(Context context) {
151         super(context);//SystemService构造函数
152
153         mContext = context;
154         mHandler = new Handler(true /*async*/);
            //获得LightManger
155         mLed = new Led(context, getLocalService(LightsManager.class));
            //获得BSS
156         mBatteryStats = BatteryStatsService.getService();
157
            //配置信息:警告电压
158         mCriticalBatteryLevel = mContext.getResources().getInteger(
159                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
            //低电提醒电压
160         mLowBatteryWarningLevel = mContext.getResources().getInteger(
161                 com.android.internal.R.integer.config_lowBatteryWarningLevel);
            //?
162         mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
163                 com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
            //关机电池温度
164         mShutdownBatteryTemperature = mContext.getResources().getInteger(
165                 com.android.internal.R.integer.config_shutdownBatteryTemperature);
166
167         // watch for invalid charger messages if the invalid_charger switch exists
            //  利用UEventObserver监听是否有无效的充电设备
168         if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
169             UEventObserver invalidChargerObserver = new UEventObserver() {
170                 @Override
171                 public void onUEvent(UEvent event) {                                                                                        
172                     final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
173                     synchronized (mLock) {
174                         if (mInvalidCharger != invalidCharger) {
175                             mInvalidCharger = invalidCharger;
176                         }
177                     }
178                 }
179             };
                //开始监听
180             invalidChargerObserver.startObserving(
181                     "DEVPATH=/devices/virtual/switch/invalid_charger");
182         }
183     }

不妨去看看这些配置信息在AOSP中的设置
frameworks/base/core/res/res/values/config.xml

896     <!-- Display low battery warning when battery level dips to this value.
897          Also, the battery stats are flushed to disk when we hit this level.  -->
898     <integer name="config_criticalBatteryWarningLevel">5</integer>                                                                         
899
900     <!-- Shutdown if the battery temperature exceeds (this value * 0.1) Celsius. -->
901     <integer name="config_shutdownBatteryTemperature">680</integer>
902
903     <!-- Display low battery warning when battery level dips to this value -->
904     <integer name="config_lowBatteryWarningLevel">15</integer>
905
906     <!-- Close low battery warning when battery level reaches the lowBatteryWarningLevel
907          plus this -->
908     <integer name="config_lowBatteryCloseWarningBump">5</integer>

所以:

  • 5% : Show Warning and Save the data to disk, and close the warning.
  • 15% : Show Warning
  • 68.0 摄氏度:Shotdown the device

BS onStart onBootPhase

onStart

  • ServiceManager.getService(“batteryproperties”)
  • 创建一个BatteryListener并注册到BatteryPropertiesService中
    • 监听底层的变化,Listener会执行:
      • BatteryService.this.update(props);
      • updateBatteryWarningLevelLocked(false)
  • 注册BS到ServiceManager和LocalServices

onBootPhase

  • 监听Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL的变化
    • 一旦有变化执行updateBatteryWarningLevelLocked(true)
  • updateBatteryWarningLevelLocked();
    • 更新 mLowBatteryWarningLevel mCriticalBatteryLevel mLowBatteryCloseWarningLevel
    • processValuesLocked(true):根据update()函数获得的mBatteryProps更新电池信息,发送广播。
      • 设置mBatteryLevelCritical
      • 设置mPlugType(充电类型)
      • mBatteryStats.setBatteryState
      • 发送广播
      • 更新很多很多类变量

batteryproperties服务

前面看到,BS在onStart的时候获得batteryproperties服务,并向其注册一个BatteryListener。一旦底层电池信息有变化,将通过这个Binder通知BS,BS随即更新自己的信息、也保存到BatteryStatsService中,并发送广播。

那么,这个batteryproperties服务是如何知道电池信息有变,又是如何获得这些信息的呢?

batteryproperties服务的创建

system/core/healthd/healthd.cpp
system/core/healthd/BatteryPropertiesRegistrar.cpp

init.rc中启动服务

619 service healthd /sbin/healthd                                                                                                               
620     class core
621     critical
622     seclabel u:r:healthd:s0
623     group root system wakelock

batteryproperties的注册

healthd_mode_android_init:

60     gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();
61     gBatteryPropertiesRegistrar->publish(gBatteryPropertiesRegistrar);

batteryproperties的listener通知

32 void healthd_mode_android_battery_update(
33     struct android::BatteryProperties *props) {
34     if (gBatteryPropertiesRegistrar != NULL)
35         gBatteryPropertiesRegistrar->notifyListeners(*props);
36
37     return;
38 }

batteryproperties获得电量信息

BatteryMonitor::init中while读取/sys/class/power_supply/*中的内容。

ls: sys/class/power_supply//ac: Permission denied
ls: sys/class/power_supply//usb: Permission denied
ls: sys/class/power_supply//wireless: Permission denied
ls: sys/class/power_supply//battery: Permission denied

供电类型ac/usb/wireless:读取子目录下的 online 供电类型/battery,获取里面的详细信息,例如:health/status/capacity等等

batteryproperties小结

从这里可以看到,batteryproperties服务是在cpp中创建的,在init.rc中启动。它负责往listener中传递电池信息props(数据串行化)。
batteryproperties需要与PMU驱动进行交互,交互方式就是读取设备文件/sys/class/power_supply/*。

参考文献

Android UEventObserver
Android6.0 healthd深入分析
Android PMU 驱动


Similar Posts

Comments