BatteryService服务分析

Posted zhenjie_chang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BatteryService服务分析相关的知识,希望对你有一定的参考价值。

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

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

1.BatteryService的构造方法

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

电量统计服务
mBatteryStats = BatteryStatsService.getService();
        //电池危急电量
        mCriticalBatteryLevel = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
        //电池低电量模式警告电量
        mLowBatteryWarningLevel = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lowBatteryWarningLevel);
        //关闭低电量模式警告电量
        mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
        //电池关机温度
        mShutdownBatteryTemperature = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_shutdownBatteryTemperature);

2.BatteryService onStart方法

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

public void onStart() 
        IBinder b = ServiceManager.getService("batteryproperties");
        final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
                IBatteryPropertiesRegistrar.Stub.asInterface(b);
        try 
            //注册底层电量变化的监听,调用update更新电池信息
            batteryPropertiesRegistrar.registerListener(new BatteryListener());
        ……
        //注册BatteryService服务
        publishBinderService("battery", new BinderService());
        publishLocalService(BatteryManagerInternal.class, new LocalService());
    

3.onBootPhase方法

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

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

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

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

 private void updateBatteryWarningLevelLocked() 
        final ContentResolver resolver = mContext.getContentResolver();
        //获取默认的警告电量值
        int defWarnLevel = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lowBatteryWarningLevel);
        //获取自己设置的警告电量值
        mLowBatteryWarningLevel = Settings.Global.getInt(resolver,
                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
        //如果自己没有设置,就去默认的值
        if (mLowBatteryWarningLevel == 0) 
            mLowBatteryWarningLevel = defWarnLevel;
        
        //警告电量值不能低于危险电量值
        if (mLowBatteryWarningLevel < mCriticalBatteryLevel) 
            mLowBatteryWarningLevel = mCriticalBatteryLevel;
        
        //计算出关闭警告的电量值
        mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
        //调用该方法来真正的更新电池信息
        processValuesLocked(true);
    

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

processValuesLocked方法分析

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

计算当前是否是危险电量
mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
        if (mBatteryProps.chargerAcOnline) 
            //充电状态
            mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
         else if (mBatteryProps.chargerUsbOnline) 
            //Usb链接状态
            mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
         else if (mBatteryProps.chargerWirelessOnline) 
            //无线充电状态
            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
         else 
            //未充电状态
            mPlugType = BATTERY_PLUGGED_NONE;
        

processValuesLocked第一部分主要工作 

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

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

继续着看该方法的实现

 try 
           //调用该方法通知电量统计服务batteryStats,来跟踪目前电池的状态
           //稍后再分析
            mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
                    mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
                    mBatteryProps.batteryVoltage);
         catch (RemoteException e) 
            
        
        //没有电的时候关机
        shutdownIfNoPowerLocked();
        //当前电池温度过高关机
        shutdownIfOverTempLocked();

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

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

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

   //计算未充电时间时长
                dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
            

            if (!mBatteryLevelLow) 
                if (mPlugType == BATTERY_PLUGGED_NONE
                        && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) 
                //当前未充电,且当前电量<提醒电量,设置低电量为true,表示进入低电量
                    mBatteryLevelLow = true;
                
             else 
                if (mPlugType != BATTERY_PLUGGED_NONE) 
                    //低电量的时候,当前变成的充电状态,退出低电量提醒
                    mBatteryLevelLow = false;
                 else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel)  
                    //当前电量 > 关闭低电量提醒电量,退出低电量提醒
                    mBatteryLevelLow = false;
                 else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) 
                    //强制退出
                    mBatteryLevelLow = false;
                
            
            //发送电池电量变化的广播
            sendIntentLocked();
            //根据不同的情况发送连接电源,电源断开,进入低电量,退出低电量等广播
            if (mPlugType != 0 && mLastPlugType == 0) 
                mHandler.post(new Runnable() 
                    @Override
                    public void run() 
                        Intent statusIntent = new I ntent(Intent.ACTION_POWER_CONNECTED);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    
                );
            
           ^

            //更新LED等显示
            mLed.updateLightsLocked();

            //将新的电池信息更新到变量中
            mLastBatteryStatus = mBatteryProps.batteryStatus;
            mLastBatteryHealth = mBatteryProps.batteryHealth;
            ……
            mLastInvalidCharger = mInvalidCharger;
        

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

public void updateLightsLocked() 
            final int level = mBatteryProps.batteryLevel;
            final int status = mBatteryProps.batteryStatus;
            //电量低于BatteryWarning的电量
            if (level < mLowBatteryWarningLevel) 
                //已经连接上充电
                if (status == BatteryManager.BATTERY_STATUS_CHARGING) 
                    //指示灯显示红色
                    mBatteryLight.setColor(mBatteryLowARGB);
                 else 
                    //没有连接充电线,红灯闪烁
                    mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
                            mBatteryLedOn, mBatteryLedOff);
                
             else if (status == BatteryManager.BATTERY_STATUS_CHARGING
                    || status == BatteryManager.BATTERY_STATUS_FULL) 
                //当前正在充电或者当前电量已经充满
                if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) 
                    //当电池已经充满或者快要充满的时候指示灯显示绿色
                    mBatteryLight.setColor(mBatteryFullARGB);
                 else 
                    //当正在充电或者电量超过一半的时候,指示灯显示橘黄色
                    mBatteryLight.setColor(mBatteryMediumARGB);
                
             else 
                //其他正常情况指示灯关闭
                mBatteryLight.turnOff();
            
        

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

 

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

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

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

public void setBatteryStateLocked(int status, int health, int plugType, int level,
            int temp, int volt) 
		//判断当前是否是电池供电
        final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
        ……
        int oldStatus = mHistoryCur.batteryStatus;
        if (onBattery) 
			//如果是电池供电,则记录下当前的未充电的电量
            mDischargeCurrentLevel = level;
            if (!mRecordingHistory) 
                mRecordingHistory = true;
				//将当前的电池状态添加到历史记录
                startRecordingHistory(elapsedRealtime, uptime, true);
            
         
		……
        if (onBattery != mOnBattery) 
			//充电状态发生了变化
            mHistoryCur.batteryLevel = (byte)level;
            ……
            mHistoryCur.batteryVoltage = (char)volt;
			//调用setOnBatteryLocked()处理充电状态发生变化的逻辑
            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
         else 
			//充电状态没有发生变化
            boolean changed = false;
			//统计电量的各种状态等是否发生变化
            if (mHistoryCur.batteryLevel != level) 
                mHistoryCur.batteryLevel = (byte)level;
                changed = true;
            ……

            ……
            
            if (changed) 
				//如果电量信息发生变化就讲当前的状态添加到历史记录
                addHistoryRecordLocked(elapsedRealtime, uptime);
            
        
    

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

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

void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
            final int oldStatus, final int level) 
……
        if (onBattery) 
            //如果拔去充电器的时候电量是满的
			//或者,当前电量大于90
			//或者是从一个很低的电量充电到很高的电量,未充电时小于20,冲完成是大于80
			//或者电量历史记录的数据太大
			//重置电量统计的相关信息,清除当前的电量统计
            boolean reset = false;
            if (!mNoAutoReset && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
                    || level >= 90
                    || (mDischargeCurrentLevel < 20 && level >= 80)
                    || (getHighDischargeAmountSinceCharge() >= 200
                            && mHistoryBuffer.dataSize() >= MAX_HISTORY_BUFFER))) 
               
			    //重置电量统计的相关信息,清除当前的电量统计
                resetAllStatsLocked();
              
            
            ……
			//由充电变为不充电,记录下变成不充电状态时的电量
            mDischargeCurrentLevel = mDischargeUnplugLevel = level;
            ……
			//更新TimeBase,和电量统计计时器有关
            updateTimeBasesLocked(true, !screenOn, uptime, realtime);
         else 
            ……
			//记录变成充电状态时的电量
            mDischargeCurrentLevel = mDischargePlugLevel = level;
			
			//当前电量低于断开电源时的电量,表示电量消耗了
            if (level < mDischargeUnplugLevel) 
				//记录下电池用电时的电量消耗
                mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
                mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
            
			
			//更新TimeBase,和电量统计计时器有关
			updateTimeBasesLocked(false, !screenOn, uptime, realtime);
            ……
        

    

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

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

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

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


以上是关于BatteryService服务分析的主要内容,如果未能解决你的问题,请参考以下文章

Android源码笔记--电量

Android耗电量一体化监控: Battery Historian + APM

android6.0系统Healthd分析及低电量自动关机流程

电池电量状态 (0x2A1B) 蓝牙规范是啥意思?

BatteryService服务分析

BatteryStatsService电池电量统计服务分析