转自http://blog.csdn.net/daweibalang717/article/details/40615453
先贴一张类与类之间的关系图:
android开机过程中会加载系统BatteryService ,说一下电池电量相关的,本文主要讲述关于JAVA 层代码。文件路径:frameworksaseservicesjavacomandroidserverBatteryService.java 下面贴出源码。
我把注释加上。个人理解,仅参考。
[java]
view plain copy
- /*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- package com.android.server;
-
- import android.os.BatteryStats;
- import com.android.internal.app.IBatteryStats;
- import com.android.server.am.BatteryStatsService;
-
- import android.app.ActivityManagerNative;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.pm.PackageManager;
- import android.os.BatteryManager;
- import android.os.BatteryProperties;
- import android.os.Binder;
- import android.os.FileUtils;
- import android.os.Handler;
- import android.os.IBatteryPropertiesListener;
- import android.os.IBatteryPropertiesRegistrar;
- import android.os.IBinder;
- import android.os.DropBoxManager;
- import android.os.RemoteException;
- import android.os.ServiceManager;
- import android.os.SystemClock;
- import android.os.UEventObserver;
- import android.os.UserHandle;
- import android.provider.Settings;
- import android.util.EventLog;
- import android.util.Slog;
-
- import java.io.File;
- import java.io.FileDescriptor;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintWriter;
-
-
- /**
- *
BatteryService monitors the charging status, and charge level of the device
- * battery. When these values change this service broadcasts the new values
- * to all {@link android.content.BroadcastReceiver IntentReceivers} that are
- * watching the {@link android.content.Intent#ACTION_BATTERY_CHANGED
- * BATTERY_CHANGED} action.
- *
The new values are stored in the Intent data and can be retrieved by
- * calling {@link android.content.Intent#getExtra Intent.getExtra} with the
- * following keys:
- *
"scale" - int, the maximum value for the charge level
- *
"level" - int, charge level, from 0 through "scale" inclusive
- *
"status" - String, the current charging status.
- *
"health" - String, the current battery health.
- *
"present" - boolean, true if the battery is present
- *
"icon-small" - int, suggested small icon to use for this state
- *
"plugged" - int, 0 if the device is not plugged in; 1 if plugged
- * into an AC power adapter; 2 if plugged in via USB.
- *
"voltage" - int, current battery voltage in millivolts
- *
"temperature" - int, current battery temperature in tenths of
- * a degree Centigrade
- *
"technology" - String, the type of battery installed, e.g. "Li-ion"
- *
- *
- * The battery service may be called by the power manager while holding its locks so
- * we take care to post all outcalls into the activity manager to a handler.
- *
- * FIXME: Ideally the power manager would perform all of its calls into the battery
- * service asynchronously itself.
- *
- */
- public final class BatteryService extends Binder {
- private static final String TAG = BatteryService.class.getSimpleName();
-
- private static final boolean DEBUG = false;
-
- private static final int BATTERY_SCALE = 100; // battery capacity is a percentage
-
- // Used locally for determining when to make a last ditch effort to log
- // discharge stats before the device dies.
- private int mCriticalBatteryLevel;
-
- private static final int DUMP_MAX_LENGTH = 24 * 1024;
- private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };
-
- private static final String DUMPSYS_DATA_PATH = "/data/system/";
-
- // This should probably be exposed in the API, though it's not critical
- private static final int BATTERY_PLUGGED_NONE = 0;
-
- private final Context mContext;
- private final IBatteryStats mBatteryStats;
- private final Handler mHandler;
-
- private final Object mLock = new Object();
-
- private BatteryProperties mBatteryProps;
- private boolean mBatteryLevelCritical;
- private int mLastBatteryStatus;
- private int mLastBatteryHealth;
- private boolean mLastBatteryPresent;
- private int mLastBatteryLevel;
- private int mLastBatteryVoltage;
- private int mLastBatteryTemperature;
- private boolean mLastBatteryLevelCritical;
-
- private int mInvalidCharger;
- private int mLastInvalidCharger;
-
- private int mLowBatteryWarningLevel;
- private int mLowBatteryCloseWarningLevel;
- private int mShutdownBatteryTemperature;
-
- private int mPlugType;
- private int mLastPlugType = -1; // Extra state so we can detect first run
-
- private long mDischargeStartTime;
- private int mDischargeStartLevel;
-
- private boolean mUpdatesStopped;
-
- private Led mLed;
-
- private boolean mSentLowBatteryBroadcast = false;
-
- private BatteryListener mBatteryPropertiesListener;
- private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
- //构造函数
- public BatteryService(Context context, LightsService lights) {
- mContext = context;
- mHandler = new Handler(true /*async*/);
- mLed = new Led(context, lights);//这个应该是指示灯,没实验
- mBatteryStats = BatteryStatsService.getService();
-
- //低电量临界值,这个数我看的源码版本值是4(在这个类里只是用来写日志)
- mCriticalBatteryLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_criticalBatteryWarningLevel);
-
- //低电量告警值,值15,下面会根据这个变量发送低电量的广播Intent.ACTION_BATTERY_LOW(这个跟系统低电量提醒没关系,只是发出去了)
- mLowBatteryWarningLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
-
- //电量告警取消值,值20 , 就是手机电量大于等于20的话发送Intent.ACTION_BATTERY_OKAY
- mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
-
- //值是680 ,温度过高,超过这个值就发送广播,跳转到将要关机提醒。
- mShutdownBatteryTemperature = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_shutdownBatteryTemperature);
-
- // watch for invalid charger messages if the invalid_charger switch exists
- if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
- mInvalidChargerObserver.startObserving(
- "DEVPATH=/devices/virtual/switch/invalid_charger");
- }
- //电池监听,这个应该是注册到底层去了。当底层电量改变会调用此监听。然后执行update(BatteryProperties props);
- mBatteryPropertiesListener = new BatteryListener();
-
- IBinder b = ServiceManager.getService("batterypropreg");
- mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
-
- try {
- //这里注册
- mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
- } catch (RemoteException e) {
- // Should never happen.
- }
- }
- //开机后先去看看是否没电了或者温度太高了。如果是,就关机提示(关机提示我等会介绍)。
- void systemReady() {
- // check our power situation now that it is safe to display the shutdown dialog.
- synchronized (mLock) {
- shutdownIfNoPowerLocked();
- shutdownIfOverTempLocked();
- }
- }
- //返回是否在充电,这个函数在PowerManagerService.java 中调用
- /**
- * Returns true if the device is plugged into any of the specified plug types.
- */
- public boolean isPowered(int plugTypeSet) {
- synchronized (mLock) {
- return isPoweredLocked(plugTypeSet);
- }
- }
- //就是这里,通过充电器类型判断是否充电
- private boolean isPoweredLocked(int plugTypeSet) {
- //我这英语小白猜着翻译下:就是开机后,电池状态不明了,那我们就认为就在充电,以便设备正常工作。
- // assume we are powered if battery state is unknown so
- // the "stay on while plugged in" option will work.
- if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
- return true;
- }
- //充电器
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mBatteryProps.chargerAcOnline) {
- return true;
- }
- //USB,插电脑上充电
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mBatteryProps.chargerUsbOnline) {
- return true;
- }
- //电源是无线的。 (我没见过...)
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mBatteryProps.chargerWirelessOnline) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns the current plug type.
- */
- //充电器类型
- public int getPlugType() {
- synchronized (mLock) {
- return mPlugType;
- }
- }
-
- /**
- * Returns battery level as a percentage.
- */
- //电池属性:电量等级(0-100)
- public int getBatteryLevel() {
- synchronized (mLock) {
- return mBatteryProps.batteryLevel;
- }
- }
-
- /**
- * Returns true if battery level is below the first warning threshold.
- */
- //低电量
- public boolean isBatteryLow() {
- synchronized (mLock) {
- return mBatteryProps.batteryPresent && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel;
- }
- }
-
- /**
- * Returns a non-zero value if an unsupported charger is attached.
- */
- //不支持的充电器类型
- public int getInvalidCharger() {
- synchronized (mLock) {
- return mInvalidCharger;
- }
- }
-
- //这里就是没电了,要关机的提示。
- private void shutdownIfNoPowerLocked() {
- // shut down gracefully if our battery is critically low and we are not powered.
- // wait until the system has booted before attempting to display the shutdown dialog.
- if (mBatteryProps.batteryLevel == 0 && (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING)) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (ActivityManagerNative.isSystemReady()) {
- Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");//ACTION_REQUEST_SHUTDOWN
- intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
- intent.putExtra("cant_be_cancel_by_button", true);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- }
- }
- });
- }
- }
-
- //温度过高,关机提示(个人感觉这里有问题,温度过高为啥子跳转到没电关机提示界面)
- private void shutdownIfOverTempLocked() {
- // shut down gracefully if temperature is too high (> 68.0C by default)
- // wait until the system has booted before attempting to display the
- // shutdown dialog.
- if (mBatteryProps.batteryTemperature > mShutdownBatteryTemperature) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (ActivityManagerNative.isSystemReady()) {
- Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");//ACTION_REQUEST_SHUTDOWN
- intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- }
- }
- });
- }
- }
- //这个方法就是被JNI回调的。用来更新上层状态的方法。
- private void update(BatteryProperties props) {
- synchronized (mLock) {
- if (!mUpdatesStopped) {
- mBatteryProps = props;
- // Process the new values.
- processValuesLocked();
- }
- }
- }
- //嗯。这个就是最主要的方法了。
- private void processValuesLocked() {
- boolean logOutlier = false;
- long dischargeDuration = 0;
-
- mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
- //充电器类型
- if (mBatteryProps.chargerAcOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
- } else if (mBatteryProps.chargerUsbOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
- } else if (mBatteryProps.chargerWirelessOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
- } else {
- mPlugType = BATTERY_PLUGGED_NONE;
- }
-
- if (DEBUG) {//日志,略过
- Slog.d(TAG, "Processing new values: "
- + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
- + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
- + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
- + ", batteryStatus=" + mBatteryProps.batteryStatus
- + ", batteryHealth=" + mBatteryProps.batteryHealth
- + ", batteryPresent=" + mBatteryProps.batteryPresent
- + ", batteryLevel=" + mBatteryProps.batteryLevel
- + ", batteryTechnology=" + mBatteryProps.batteryTechnology
- + ", batteryVoltage=" + mBatteryProps.batteryVoltage
- + ", batteryCurrentNow=" + mBatteryProps.batteryCurrentNow
- + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter
- + ", batteryTemperature=" + mBatteryProps.batteryTemperature
- + ", mBatteryLevelCritical=" + mBatteryLevelCritical
- + ", mPlugType=" + mPlugType);
- }
-
- // Let the battery stats keep track of the current level.
- try {
- //把电池属性放到状态里面
- mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
- mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
- mBatteryProps.batteryVoltage);
- } catch (RemoteException e) {
- // Should never happen.
- }
- //没电了
- shutdownIfNoPowerLocked();
- //温度过高了
- shutdownIfOverTempLocked();
-
- if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
- mBatteryProps.batteryHealth != mLastBatteryHealth ||
- mBatteryProps.batteryPresent != mLastBatteryPresent ||
- mBatteryProps.batteryLevel != mLastBatteryLevel ||
- mPlugType != mLastPlugType ||
- mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
- mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
- mInvalidCharger != mLastInvalidCharger) {
-
- if (mPlugType != mLastPlugType) {//当前充电器类型与上次的不一样
- //并且上次充电器类型是no one ,那就可以知道,现在是插上充电器了。
- if (mLastPlugType == BATTERY_PLUGGED_NONE) {
- // discharging -> charging
-
- // There's no value in this data unless we've discharged at least once and the
- // battery level has changed; so don't log until it does.
- if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {
- dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
- logOutlier = true;
- EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
- mDischargeStartLevel, mBatteryProps.batteryLevel);
- // make sure we see a discharge event before logging again
- mDischargeStartTime = 0;
- }
- //并且本次充电器类型是no one ,那就可以知道,现在是拔掉充电器了。
- } else if (mPlugType == BATTERY_PLUGGED_NONE) {
- // charging -> discharging or we just powered up
- mDischargeStartTime = SystemClock.elapsedRealtime();
- mDischargeStartLevel = mBatteryProps.batteryLevel;
- }
- }
- if (mBatteryProps.batteryStatus != mLastBatteryStatus ||//写日志,略过
- mBatteryProps.batteryHealth != mLastBatteryHealth ||
- mBatteryProps.batteryPresent != mLastBatteryPresent ||
- mPlugType != mLastPlugType) {
- EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
- mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
- mPlugType, mBatteryProps.batteryTechnology);
- }
- if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
- // Don't do this just from voltage or temperature changes, that is
- // too noisy.
- EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
- mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
- }
- if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
- mPlugType == BATTERY_PLUGGED_NONE) {
- // We want to make sure we log discharge cycle outliers
- // if the battery is about to die.
- dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
- logOutlier = true;
- }
- //本次调用,当前的充电状态
- final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE;
- //本次调用,上次调用的充电状态
- final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE;
-
- /* The ACTION_BATTERY_LOW broadcast is sent in these situations:
- * - is just un-plugged (previously was plugged) and battery level is
- * less than or equal to WARNING, or
- * - is not plugged and battery level falls to WARNING boundary
-