android 4.4 电池电量显示分析(低电量提醒与电池图标)Java 层

2019-04-13 15:54发布

转自http://blog.csdn.net/daweibalang717/article/details/40615453   先贴一张类与类之间的关系图:     android开机过程中会加载系统BatteryService ,说一下电池电量相关的,本文主要讲述关于JAVA 层代码。文件路径:frameworksaseservicesjavacomandroidserverBatteryService.java   下面贴出源码。我把注释加上。个人理解,仅参考。   [java] view plain copy
  1. /* 
  2.  * Copyright (C) 2006 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.android.server;  
  18.   
  19. import android.os.BatteryStats;  
  20. import com.android.internal.app.IBatteryStats;  
  21. import com.android.server.am.BatteryStatsService;  
  22.   
  23. import android.app.ActivityManagerNative;  
  24. import android.content.ContentResolver;  
  25. import android.content.Context;  
  26. import android.content.Intent;  
  27. import android.content.pm.PackageManager;  
  28. import android.os.BatteryManager;  
  29. import android.os.BatteryProperties;  
  30. import android.os.Binder;  
  31. import android.os.FileUtils;  
  32. import android.os.Handler;  
  33. import android.os.IBatteryPropertiesListener;  
  34. import android.os.IBatteryPropertiesRegistrar;  
  35. import android.os.IBinder;  
  36. import android.os.DropBoxManager;  
  37. import android.os.RemoteException;  
  38. import android.os.ServiceManager;  
  39. import android.os.SystemClock;  
  40. import android.os.UEventObserver;  
  41. import android.os.UserHandle;  
  42. import android.provider.Settings;  
  43. import android.util.EventLog;  
  44. import android.util.Slog;  
  45.   
  46. import java.io.File;  
  47. import java.io.FileDescriptor;  
  48. import java.io.FileOutputStream;  
  49. import java.io.IOException;  
  50. import java.io.PrintWriter;  
  51.   
  52.   
  53. /** 
  54.  * 

    BatteryService monitors the charging status, and charge level of the device 

  55.  * battery.  When these values change this service broadcasts the new values 
  56.  * to all {@link android.content.BroadcastReceiver IntentReceivers} that are 
  57.  * watching the {@link android.content.Intent#ACTION_BATTERY_CHANGED 
  58.  * BATTERY_CHANGED} action.

     
  59.  * 

    The new values are stored in the Intent data and can be retrieved by 

  60.  * calling {@link android.content.Intent#getExtra Intent.getExtra} with the 
  61.  * following keys:

     
  62.  * 

    "scale" - int, the maximum value for the charge level

     
  63.  * 

    "level" - int, charge level, from 0 through "scale" inclusive

     
  64.  * 

    "status" - String, the current charging status. 

  65.  * 

    "health" - String, the current battery health. 

  66.  * 

    "present" - boolean, true if the battery is present 

  67.  * 

    "icon-small" - int, suggested small icon to use for this state

     
  68.  * 

    "plugged" - int, 0 if the device is not plugged in; 1 if plugged 

  69.  * into an AC power adapter; 2 if plugged in via USB.

     
  70.  * 

    "voltage" - int, current battery voltage in millivolts

     
  71.  * 

    "temperature" - int, current battery temperature in tenths of 

  72.  * a degree Centigrade

     
  73.  * 

    "technology" - String, the type of battery installed, e.g. "Li-ion"

     
  74.  * 
  75.  * 

     

  76.  * The battery service may be called by the power manager while holding its locks so 
  77.  * we take care to post all outcalls into the activity manager to a handler. 
  78.  * 
  79.  * FIXME: Ideally the power manager would perform all of its calls into the battery 
  80.  * service asynchronously itself. 
  81.  * 

     
  82.  */  
  83. public final class BatteryService extends Binder {  
  84.     private static final String TAG = BatteryService.class.getSimpleName();  
  85.   
  86.     private static final boolean DEBUG = false;  
  87.   
  88.     private static final int BATTERY_SCALE = 100;    // battery capacity is a percentage  
  89.   
  90.     // Used locally for determining when to make a last ditch effort to log  
  91.     // discharge stats before the device dies.  
  92.     private int mCriticalBatteryLevel;  
  93.   
  94.     private static final int DUMP_MAX_LENGTH = 24 * 1024;  
  95.     private static final String[] DUMPSYS_ARGS = new String[] { "--checkin""--unplugged" };  
  96.   
  97.     private static final String DUMPSYS_DATA_PATH = "/data/system/";  
  98.   
  99.     // This should probably be exposed in the API, though it's not critical  
  100.     private static final int BATTERY_PLUGGED_NONE = 0;  
  101.   
  102.     private final Context mContext;  
  103.     private final IBatteryStats mBatteryStats;  
  104.     private final Handler mHandler;  
  105.   
  106.     private final Object mLock = new Object();  
  107.   
  108.     private BatteryProperties mBatteryProps;  
  109.     private boolean mBatteryLevelCritical;  
  110.     private int mLastBatteryStatus;  
  111.     private int mLastBatteryHealth;  
  112.     private boolean mLastBatteryPresent;  
  113.     private int mLastBatteryLevel;  
  114.     private int mLastBatteryVoltage;  
  115.     private int mLastBatteryTemperature;  
  116.     private boolean mLastBatteryLevelCritical;  
  117.   
  118.     private int mInvalidCharger;  
  119.     private int mLastInvalidCharger;  
  120.   
  121.     private int mLowBatteryWarningLevel;  
  122.     private int mLowBatteryCloseWarningLevel;  
  123.     private int mShutdownBatteryTemperature;  
  124.   
  125.     private int mPlugType;  
  126.     private int mLastPlugType = -1// Extra state so we can detect first run  
  127.   
  128.     private long mDischargeStartTime;  
  129.     private int mDischargeStartLevel;  
  130.   
  131.     private boolean mUpdatesStopped;  
  132.   
  133.     private Led mLed;  
  134.   
  135.     private boolean mSentLowBatteryBroadcast = false;  
  136.   
  137.     private BatteryListener mBatteryPropertiesListener;  
  138.     private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;  
  139. //构造函数  
  140.     public BatteryService(Context context, LightsService lights) {  
  141.         mContext = context;  
  142.         mHandler = new Handler(true /*async*/);  
  143.         mLed = new Led(context, lights);//这个应该是指示灯,没实验  
  144.         mBatteryStats = BatteryStatsService.getService();  
  145.   
  146.  //低电量临界值,这个数我看的源码版本值是4(在这个类里只是用来写日志)  
  147.         mCriticalBatteryLevel = mContext.getResources().getInteger(  
  148.                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);  
  149.   
  150. //低电量告警值,值15,下面会根据这个变量发送低电量的广播Intent.ACTION_BATTERY_LOW(这个跟系统低电量提醒没关系,只是发出去了)  
  151.         mLowBatteryWarningLevel = mContext.getResources().getInteger(  
  152.                 com.android.internal.R.integer.config_lowBatteryWarningLevel);  
  153.   
  154. //电量告警取消值,值20 , 就是手机电量大于等于20的话发送Intent.ACTION_BATTERY_OKAY  
  155.         mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(  
  156.                 com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);  
  157.   
  158. //值是680 ,温度过高,超过这个值就发送广播,跳转到将要关机提醒。  
  159.        mShutdownBatteryTemperature = mContext.getResources().getInteger(  
  160.                 com.android.internal.R.integer.config_shutdownBatteryTemperature);  
  161.   
  162.         // watch for invalid charger messages if the invalid_charger switch exists  
  163.         if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {  
  164.             mInvalidChargerObserver.startObserving(  
  165.                     "DEVPATH=/devices/virtual/switch/invalid_charger");  
  166.         }  
  167. //电池监听,这个应该是注册到底层去了。当底层电量改变会调用此监听。然后执行update(BatteryProperties props);  
  168.         mBatteryPropertiesListener = new BatteryListener();  
  169.   
  170.         IBinder b = ServiceManager.getService("batterypropreg");  
  171.         mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);  
  172.   
  173.         try {  
  174. //这里注册  
  175.           mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);  
  176.         } catch (RemoteException e) {  
  177.             // Should never happen.  
  178.         }  
  179.     }  
  180. //开机后先去看看是否没电了或者温度太高了。如果是,就关机提示(关机提示我等会介绍)。  
  181.     void systemReady() {  
  182.         // check our power situation now that it is safe to display the shutdown dialog.  
  183.         synchronized (mLock) {  
  184.             shutdownIfNoPowerLocked();  
  185.             shutdownIfOverTempLocked();  
  186.         }  
  187.     }  
  188. //返回是否在充电,这个函数在PowerManagerService.java 中调用  
  189.     /** 
  190.      * Returns true if the device is plugged into any of the specified plug types. 
  191.      */  
  192.     public boolean isPowered(int plugTypeSet) {  
  193.         synchronized (mLock) {  
  194.             return isPoweredLocked(plugTypeSet);  
  195.         }  
  196.     }  
  197. //就是这里,通过充电器类型判断是否充电  
  198.     private boolean isPoweredLocked(int plugTypeSet) {  
  199. //我这英语小白猜着翻译下:就是开机后,电池状态不明了,那我们就认为就在充电,以便设备正常工作。  
  200.         // assume we are powered if battery state is unknown so  
  201.         // the "stay on while plugged in" option will work.  
  202.         if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {  
  203.             return true;  
  204.         }  
  205. //充电器  
  206.         if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mBatteryProps.chargerAcOnline) {  
  207.             return true;  
  208.         }  
  209. //USB,插电脑上充电  
  210.       if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mBatteryProps.chargerUsbOnline) {  
  211.             return true;  
  212.         }  
  213. //电源是无线的。 (我没见过...)  
  214.         if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mBatteryProps.chargerWirelessOnline) {  
  215.             return true;  
  216.         }  
  217.         return false;  
  218.     }  
  219.   
  220.     /** 
  221.      * Returns the current plug type. 
  222.      */  
  223. //充电器类型  
  224.    public int getPlugType() {  
  225.         synchronized (mLock) {  
  226.             return mPlugType;  
  227.         }  
  228.     }  
  229.   
  230.     /** 
  231.      * Returns battery level as a percentage. 
  232.      */  
  233. //电池属性:电量等级(0-100)  
  234.     public int getBatteryLevel() {  
  235.         synchronized (mLock) {  
  236.             return mBatteryProps.batteryLevel;  
  237.         }  
  238.     }  
  239.   
  240.     /** 
  241.      * Returns true if battery level is below the first warning threshold. 
  242.      */  
  243. //低电量  
  244.      public boolean isBatteryLow() {  
  245.         synchronized (mLock) {  
  246.             return mBatteryProps.batteryPresent && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel;  
  247.         }  
  248.     }  
  249.   
  250.     /** 
  251.      * Returns a non-zero value if an  unsupported charger is attached. 
  252.      */  
  253. //不支持的充电器类型    
  254.     public int getInvalidCharger() {  
  255.         synchronized (mLock) {  
  256.             return mInvalidCharger;  
  257.         }  
  258.     }  
  259.   
  260. //这里就是没电了,要关机的提示。  
  261.     private void shutdownIfNoPowerLocked() {  
  262.         // shut down gracefully if our battery is critically low and we are not powered.  
  263.         // wait until the system has booted before attempting to display the shutdown dialog.  
  264.         if (mBatteryProps.batteryLevel == 0 && (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING)) {  
  265.             mHandler.post(new Runnable() {  
  266.                 @Override  
  267.                 public void run() {  
  268.                     if (ActivityManagerNative.isSystemReady()) {  
  269.                         Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");//ACTION_REQUEST_SHUTDOWN  
  270.                         intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);  
  271.                         intent.putExtra("cant_be_cancel_by_button"true);  
  272.                         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  273.                         mContext.startActivityAsUser(intent, UserHandle.CURRENT);  
  274.                     }  
  275.                 }  
  276.             });  
  277.         }  
  278.     }  
  279.   
  280. //温度过高,关机提示(个人感觉这里有问题,温度过高为啥子跳转到没电关机提示界面)   
  281.     private void shutdownIfOverTempLocked() {  
  282.         // shut down gracefully if temperature is too high (> 68.0C by default)  
  283.         // wait until the system has booted before attempting to display the  
  284.         // shutdown dialog.  
  285.         if (mBatteryProps.batteryTemperature > mShutdownBatteryTemperature) {  
  286.             mHandler.post(new Runnable() {  
  287.                 @Override  
  288.                 public void run() {  
  289.                     if (ActivityManagerNative.isSystemReady()) {  
  290.                         Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");//ACTION_REQUEST_SHUTDOWN  
  291.                         intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);  
  292.                         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  293.                         mContext.startActivityAsUser(intent, UserHandle.CURRENT);  
  294.                     }  
  295.                 }  
  296.             });  
  297.         }  
  298.     }  
  299. //这个方法就是被JNI回调的。用来更新上层状态的方法。  
  300.     private void update(BatteryProperties props) {  
  301.         synchronized (mLock) {  
  302.             if (!mUpdatesStopped) {  
  303.                 mBatteryProps = props;  
  304.                 // Process the new values.  
  305.                 processValuesLocked();  
  306.             }  
  307.         }  
  308.     }  
  309. //嗯。这个就是最主要的方法了。  
  310.     private void processValuesLocked() {  
  311.         boolean logOutlier = false;  
  312.         long dischargeDuration = 0;  
  313.   
  314.         mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);  
  315. //充电器类型   
  316.        if (mBatteryProps.chargerAcOnline) {  
  317.             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;  
  318.         } else if (mBatteryProps.chargerUsbOnline) {  
  319.             mPlugType = BatteryManager.BATTERY_PLUGGED_USB;  
  320.         } else if (mBatteryProps.chargerWirelessOnline) {  
  321.             mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;  
  322.         } else {  
  323.             mPlugType = BATTERY_PLUGGED_NONE;  
  324.         }  
  325.   
  326.         if (DEBUG) {//日志,略过  
  327.             Slog.d(TAG, "Processing new values: "  
  328.                     + "chargerAcOnline=" + mBatteryProps.chargerAcOnline  
  329.                     + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline  
  330.                     + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline  
  331.                     + ", batteryStatus=" + mBatteryProps.batteryStatus  
  332.                     + ", batteryHealth=" + mBatteryProps.batteryHealth  
  333.                     + ", batteryPresent=" + mBatteryProps.batteryPresent  
  334.                     + ", batteryLevel=" + mBatteryProps.batteryLevel  
  335.                     + ", batteryTechnology=" + mBatteryProps.batteryTechnology  
  336.                     + ", batteryVoltage=" + mBatteryProps.batteryVoltage  
  337.                     + ", batteryCurrentNow=" + mBatteryProps.batteryCurrentNow  
  338.                     + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter  
  339.                     + ", batteryTemperature=" + mBatteryProps.batteryTemperature  
  340.                     + ", mBatteryLevelCritical=" + mBatteryLevelCritical  
  341.                     + ", mPlugType=" + mPlugType);  
  342.         }  
  343.   
  344.         // Let the battery stats keep track of the current level.  
  345.         try {  
  346. //把电池属性放到状态里面  
  347.            mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,  
  348.                     mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,  
  349.                     mBatteryProps.batteryVoltage);  
  350.         } catch (RemoteException e) {  
  351.             // Should never happen.  
  352.         }  
  353. //没电了  
  354.         shutdownIfNoPowerLocked();  
  355. //温度过高了  
  356.        shutdownIfOverTempLocked();  
  357.   
  358.         if (mBatteryProps.batteryStatus != mLastBatteryStatus ||  
  359.                 mBatteryProps.batteryHealth != mLastBatteryHealth ||  
  360.                 mBatteryProps.batteryPresent != mLastBatteryPresent ||  
  361.                 mBatteryProps.batteryLevel != mLastBatteryLevel ||  
  362.                 mPlugType != mLastPlugType ||  
  363.                 mBatteryProps.batteryVoltage != mLastBatteryVoltage ||  
  364.                 mBatteryProps.batteryTemperature != mLastBatteryTemperature ||  
  365.                 mInvalidCharger != mLastInvalidCharger) {  
  366.   
  367.             if (mPlugType != mLastPlugType) {//当前充电器类型与上次的不一样  
  368. //并且上次充电器类型是no one ,那就可以知道,现在是插上充电器了。  
  369.                if (mLastPlugType == BATTERY_PLUGGED_NONE) {  
  370.                     // discharging -> charging  
  371.   
  372.                     // There's no value in this data unless we've discharged at least once and the  
  373.                     // battery level has changed; so don't log until it does.  
  374.                     if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {  
  375.                         dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;  
  376.                         logOutlier = true;  
  377.                         EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,  
  378.                                 mDischargeStartLevel, mBatteryProps.batteryLevel);  
  379.                         // make sure we see a discharge event before logging again  
  380.                         mDischargeStartTime = 0;  
  381.                     }  
  382. //并且本次充电器类型是no one ,那就可以知道,现在是拔掉充电器了。  
  383.                 } else if (mPlugType == BATTERY_PLUGGED_NONE) {  
  384.                     // charging -> discharging or we just powered up  
  385.                     mDischargeStartTime = SystemClock.elapsedRealtime();  
  386.                     mDischargeStartLevel = mBatteryProps.batteryLevel;  
  387.                 }  
  388.             }  
  389.             if (mBatteryProps.batteryStatus != mLastBatteryStatus ||//写日志,略过  
  390.                     mBatteryProps.batteryHealth != mLastBatteryHealth ||  
  391.                     mBatteryProps.batteryPresent != mLastBatteryPresent ||  
  392.                     mPlugType != mLastPlugType) {  
  393.                 EventLog.writeEvent(EventLogTags.BATTERY_STATUS,  
  394.                         mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,  
  395.                         mPlugType, mBatteryProps.batteryTechnology);  
  396.             }  
  397.             if (mBatteryProps.batteryLevel != mLastBatteryLevel) {  
  398.                 // Don't do this just from voltage or temperature changes, that is  
  399.                 // too noisy.  
  400.                 EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,  
  401.                         mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);  
  402.             }  
  403.             if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&  
  404.                     mPlugType == BATTERY_PLUGGED_NONE) {  
  405.                 // We want to make sure we log discharge cycle outliers  
  406.                 // if the battery is about to die.  
  407.                 dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;  
  408.                 logOutlier = true;  
  409.             }  
  410. //本次调用,当前的充电状态  
  411.             final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE;  
  412. //本次调用,上次调用的充电状态    
  413.             final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE;  
  414.   
  415.             /* The ACTION_BATTERY_LOW broadcast is sent in these situations: 
  416.              * - is just un-plugged (previously was plugged) and battery level is 
  417.              *   less than or equal to WARNING, or 
  418.              * - is not plugged and battery level falls to WARNING boundary