BatteryService服务分析

 

目录(?)[+]

 

BatteryService是在systemServer启动核心服务的时候启动的。

同样我们按照PMS启动的流程来分析BatteryService的启动流程。

 

1.BatteryService的构造方法

 

BatteryService的构造方法比较简单,只是从资源中获取一些预定的值

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. 电量统计服务  
  2. mBatteryStats = BatteryStatsService.getService();  
  3.         //电池危急电量  
  4.         mCriticalBatteryLevel = mContext.getResources().getInteger(  
  5.                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);  
  6.         //电池低电量模式警告电量  
  7.         mLowBatteryWarningLevel = mContext.getResources().getInteger(  
  8.                 com.android.internal.R.integer.config_lowBatteryWarningLevel);  
  9.         //关闭低电量模式警告电量  
  10.         mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(  
  11.                 com.android.internal.R.integer.config_lowBatteryCloseWarningBump);  
  12.         //电池关机温度  
  13.         mShutdownBatteryTemperature = mContext.getResources().getInteger(  
  14.                 com.android.internal.R.integer.config_shutdownBatteryTemperature);  

2.BatteryService onStart方法

onStart方法中 将BatteryService服务注册到ServiceManager,注册了底层电量变换的回调方法,最终调用BatteryService的update方法更新电池信息

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void onStart() {  
  2.         IBinder b = ServiceManager.getService("batteryproperties");  
  3.         final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =  
  4.                 IBatteryPropertiesRegistrar.Stub.asInterface(b);  
  5.         try {  
  6.             //注册底层电量变化的监听,调用update更新电池信息  
  7.             batteryPropertiesRegistrar.registerListener(new BatteryListener());  
  8.         ……  
  9.         //注册BatteryService服务  
  10.         publishBinderService("battery", new BinderService());  
  11.         publishLocalService(BatteryManagerInternal.class, new LocalService());  
  12.     }  

3.onBootPhase方法

当ActivityManager启动完成的时候,回调onBootPhase方法

onBootPhase方法很简单,就是注册了一个关于ContentObserver

来监测设置中关于低电量警告的电量值是否改变

如果该电量值发生变化,回调updateBatteryWarningLevelLocked()方法。

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. private void updateBatteryWarningLevelLocked() {  
  2.        final ContentResolver resolver = mContext.getContentResolver();  
  3.        //获取默认的警告电量值  
  4.        int defWarnLevel = mContext.getResources().getInteger(  
  5.                com.android.internal.R.integer.config_lowBatteryWarningLevel);  
  6.        //获取自己设置的警告电量值  
  7.        mLowBatteryWarningLevel = Settings.Global.getInt(resolver,  
  8.                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);  
  9.        //如果自己没有设置,就去默认的值  
  10.        if (mLowBatteryWarningLevel == 0) {  
  11.            mLowBatteryWarningLevel = defWarnLevel;  
  12.        }  
  13.        //警告电量值不能低于危险电量值  
  14.        if (mLowBatteryWarningLevel < mCriticalBatteryLevel) {  
  15.            mLowBatteryWarningLevel = mCriticalBatteryLevel;  
  16.        }  
  17.        //计算出关闭警告的电量值  
  18.        mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(  
  19.                com.android.internal.R.integer.config_lowBatteryCloseWarningBump);  
  20.        //调用该方法来真正的更新电池信息  
  21.        processValuesLocked(true);  
  22.    }  

在该方法中主要来计算获取警告的电量值和关闭警告的电量值,然后调用processValuesLocked()方法来做真正的更新。我们知道当监听的底层电池电量发生变化的时候,回调update()方法,最终也会调用该方法来更新,那就来分析下该方法的具体实现。

 

processValuesLocked方法分析

 

首先我们先看该方法的第一部分:

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. 计算当前是否是危险电量  
  2. mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);  
  3.         if (mBatteryProps.chargerAcOnline) {  
  4.             //充电状态  
  5.             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;  
  6.         } else if (mBatteryProps.chargerUsbOnline) {  
  7.             //Usb链接状态  
  8.             mPlugType = BatteryManager.BATTERY_PLUGGED_USB;  
  9.         } else if (mBatteryProps.chargerWirelessOnline) {  
  10.             //无线充电状态  
  11.             mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;  
  12.         } else {  
  13.             //未充电状态  
  14.             mPlugType = BATTERY_PLUGGED_NONE;  
  15.         }  

processValuesLocked第一部分主要工作 

1. 判断当前是否是危险电量状态

2. 根据底层提供的电池数据,判断当前手机的充电状态

继续着看该方法的实现

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. try {  
  2.           //调用该方法通知电量统计服务batteryStats,来跟踪目前电池的状态  
  3.           //稍后再分析  
  4.            mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,  
  5.                    mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,  
  6.                    mBatteryProps.batteryVoltage);  
  7.        } catch (RemoteException e) {  
  8.              
  9.        }  
  10.        //没有电的时候关机  
  11.        shutdownIfNoPowerLocked();  
  12.        //当前电池温度过高关机  
  13.        shutdownIfOverTempLocked();  

这部分首先调用BatteryStats.setBatteryState()方法来通知电量统计服务跟踪统计电池状态信息

然后当电量低于危险电量的时候关机

当电池温度大于定义的电池温度后关机

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. //计算未充电时间时长  
  2.              dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;  
  3.          }  
  4.   
  5.          if (!mBatteryLevelLow) {  
  6.              if (mPlugType == BATTERY_PLUGGED_NONE  
  7.                      && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {  
  8.              //当前未充电,且当前电量<提醒电量,设置低电量为true,表示进入低电量  
  9.                  mBatteryLevelLow = true;  
  10.              }  
  11.          } else {  
  12.              if (mPlugType != BATTERY_PLUGGED_NONE) {  
  13.                  //低电量的时候,当前变成的充电状态,退出低电量提醒  
  14.                  mBatteryLevelLow = false;  
  15.              } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel)  {  
  16.                  //当前电量 > 关闭低电量提醒电量,退出低电量提醒  
  17.                  mBatteryLevelLow = false;  
  18.              } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {  
  19.                  //强制退出  
  20.                  mBatteryLevelLow = false;  
  21.              }  
  22.          }  
  23.          //发送电池电量变化的广播  
  24.          sendIntentLocked();  
  25.          //根据不同的情况发送连接电源,电源断开,进入低电量,退出低电量等广播  
  26.          if (mPlugType != 0 && mLastPlugType == 0) {  
  27.              mHandler.post(new Runnable() {  
  28.                  @Override  
  29.                  public void run() {  
  30.                      Intent statusIntent = new I ntent(Intent.ACTION_POWER_CONNECTED);  
  31.                      statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);  
  32.                      mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);  
  33.                  }  
  34.              });  
  35.          }  
  36.         ^  
  37.   
  38.          //更新LED等显示  
  39.          mLed.updateLightsLocked();  
  40.   
  41.          //将新的电池信息更新到变量中  
  42.          mLastBatteryStatus = mBatteryProps.batteryStatus;  
  43.          mLastBatteryHealth = mBatteryProps.batteryHealth;  
  44.          ……  
  45.          mLastInvalidCharger = mInvalidCharger;  
  46.      }  

每当电池信息发生变化都会调用processValueLocked方法来更新电池信息。该方法的包括的基本内容在代码注释中已经标注过了,下面我们来看下其中更新LED等的逻辑mLed.updateLightsLocked

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void updateLightsLocked() {  
  2.             final int level = mBatteryProps.batteryLevel;  
  3.             final int status = mBatteryProps.batteryStatus;  
  4.             //电量低于BatteryWarning的电量  
  5.             if (level < mLowBatteryWarningLevel) {  
  6.                 //已经连接上充电  
  7.                 if (status == BatteryManager.BATTERY_STATUS_CHARGING) {  
  8.                     //指示灯显示红色  
  9.                     mBatteryLight.setColor(mBatteryLowARGB);  
  10.                 } else {  
  11.                     //没有连接充电线,红灯闪烁  
  12.                     mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,  
  13.                             mBatteryLedOn, mBatteryLedOff);  
  14.                 }  
  15.             } else if (status == BatteryManager.BATTERY_STATUS_CHARGING  
  16.                     || status == BatteryManager.BATTERY_STATUS_FULL) {  
  17.                 //当前正在充电或者当前电量已经充满  
  18.                 if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {  
  19.                     //当电池已经充满或者快要充满的时候指示灯显示绿色  
  20.                     mBatteryLight.setColor(mBatteryFullARGB);  
  21.                 } else {  
  22.                     //当正在充电或者电量超过一半的时候,指示灯显示橘黄色  
  23.                     mBatteryLight.setColor(mBatteryMediumARGB);  
  24.                 }  
  25.             } else {  
  26.                 //其他正常情况指示灯关闭  
  27.                 mBatteryLight.turnOff();  
  28.             }  
  29.         }  

更新LED等方法主要根据电池电量和充电状态来决定LED指示灯的颜色和显示方式。低于警告电量的时候LED指示灯显示红色,当电池充满电的时候指示灯显示绿色

 

现在我们分析下BatteryStats.setBatteryState()方法。

setBatteryState()方法最终调用到BatteryStatsImpl类的setBatteryStateLocked()方法中

下面我们来看下关键代码。

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void setBatteryStateLocked(int status, int health, int plugType, int level,  
  2.             int temp, int volt) {  
  3.         //判断当前是否是电池供电  
  4.         final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;  
  5.         ……  
  6.         int oldStatus = mHistoryCur.batteryStatus;  
  7.         if (onBattery) {  
  8.             //如果是电池供电,则记录下当前的未充电的电量  
  9.             mDischargeCurrentLevel = level;  
  10.             if (!mRecordingHistory) {  
  11.                 mRecordingHistory = true;  
  12.                 //将当前的电池状态添加到历史记录  
  13.                 startRecordingHistory(elapsedRealtime, uptime, true);  
  14.             }  
  15.         }   
  16.         ……  
  17.         if (onBattery != mOnBattery) {  
  18.             //充电状态发生了变化  
  19.             mHistoryCur.batteryLevel = (byte)level;  
  20.             ……  
  21.             mHistoryCur.batteryVoltage = (char)volt;  
  22.             //调用setOnBatteryLocked()处理充电状态发生变化的逻辑  
  23.             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);  
  24.         } else {  
  25.             //充电状态没有发生变化  
  26.             boolean changed = false;  
  27.             //统计电量的各种状态等是否发生变化  
  28.             if (mHistoryCur.batteryLevel != level) {  
  29.                 mHistoryCur.batteryLevel = (byte)level;  
  30.                 changed = true;  
  31.             ……  
  32.   
  33.             ……  
  34.             }  
  35.             if (changed) {  
  36.                 //如果电量信息发生变化就讲当前的状态添加到历史记录  
  37.                 addHistoryRecordLocked(elapsedRealtime, uptime);  
  38.             }  
  39.         }  
  40.     }  

该方法中首先判断当前是否是未充电状态,如果是未充电状态,就记录下当前的电池电量mDischargeCurrentLevel = level,然后判断充电状态是否发生了变化,如果没有发生变化,则判断当前电量的各种属性,如电池电量,电池信息是否发生变化,如果电量属性发生了变化,就将当前的电量添加到历史记录中。

如果充电状态发生了变化,则调用setOnBatteryLocked()方法处理相关的逻辑

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,  
  2.             final int oldStatus, final int level) {  
  3. ……  
  4.         if (onBattery) {  
  5.             //如果拔去充电器的时候电量是满的  
  6.             //或者,当前电量大于90  
  7.             //或者是从一个很低的电量充电到很高的电量,未充电时小于20,冲完成是大于80  
  8.             //或者电量历史记录的数据太大  
  9.             //重置电量统计的相关信息,清除当前的电量统计  
  10.             boolean reset = false;  
  11.             if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL  
  12.                     || level >= 90  
  13.                     || (mDischargeCurrentLevel < 20 && level >= 80)  
  14.                     || (getHighDischargeAmountSinceCharge() >= 200  
  15.                             && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) {  
  16.                  
  17.                 //重置电量统计的相关信息,清除当前的电量统计  
  18.                 resetAllStatsLocked();  
  19.                 
  20.             }  
  21.             ……  
  22.             //由充电变为不充电,记录下变成不充电状态时的电量  
  23.             mDischargeCurrentLevel = mDischargeUnplugLevel = level;  
  24.             ……  
  25.             //更新TimeBase,和电量统计计时器有关  
  26.             updateTimeBasesLocked(true, !screenOn, uptime, realtime);  
  27.         } else {  
  28.             ……  
  29.             //记录变成充电状态时的电量  
  30.             mDischargeCurrentLevel = mDischargePlugLevel = level;  
  31.               
  32.             //当前电量低于断开电源时的电量,表示电量消耗了  
  33.             if (level < mDischargeUnplugLevel) {  
  34.                 //记录下电池用电时的电量消耗  
  35.                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;  
  36.                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;  
  37.             }  
  38.               
  39.             //更新TimeBase,和电量统计计时器有关  
  40.             updateTimeBasesLocked(false, !screenOn, uptime, realtime);  
  41.             ……  
  42.         }  
  43.   
  44.     }  

setOnBatteryLocked方法中代码看似很多,其实主要内容就是根据充电状态变化后,根据当前的充电状态来做相应的处理

由充电变为未充电,根据逻辑判断是否需要重置电量统计信息。比如当充电电量大于90的时候,拔掉充电器,设置中电池电量相关的统计信息会重置清空

由为充电变为充电,记录了使用电池期间消耗的电量

下面我们使用流程图来总结下BatteryService服务processValueLocked方法的处理流程。

AA

posted on 2016-10-26 19:04  jamboo  阅读(1440)  评论(0编辑  收藏  举报

导航