diff options
Diffstat (limited to 'services/java/com/android/server/BatteryService.java')
| -rw-r--r-- | services/java/com/android/server/BatteryService.java | 282 |
1 files changed, 167 insertions, 115 deletions
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index 0b4871d..40758d3 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -40,11 +40,9 @@ import android.util.Slog; import java.io.File; import java.io.FileDescriptor; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.util.Arrays; /** @@ -69,12 +67,12 @@ import java.util.Arrays; * a degree Centigrade</p> * <p>"technology" - String, the type of battery installed, e.g. "Li-ion"</p> */ -public class BatteryService extends Binder { +public final class BatteryService extends Binder { private static final String TAG = BatteryService.class.getSimpleName(); - private static final boolean LOCAL_LOGV = false; + private static final boolean DEBUG = false; - static final int BATTERY_SCALE = 100; // battery capacity is a percentage + 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. @@ -92,6 +90,9 @@ public class BatteryService extends Binder { private final Context mContext; private final IBatteryStats mBatteryStats; + private final Object mLock = new Object(); + + /* Begin native fields: All of these fields are set by native code. */ private boolean mAcOnline; private boolean mUsbOnline; private boolean mWirelessOnline; @@ -103,7 +104,7 @@ public class BatteryService extends Binder { private int mBatteryTemperature; private String mBatteryTechnology; private boolean mBatteryLevelCritical; - private int mInvalidCharger; + /* End native fields. */ private int mLastBatteryStatus; private int mLastBatteryHealth; @@ -112,6 +113,8 @@ public class BatteryService extends Binder { private int mLastBatteryVoltage; private int mLastBatteryTemperature; private boolean mLastBatteryLevelCritical; + + private int mInvalidCharger; private int mLastInvalidCharger; private int mLowBatteryWarningLevel; @@ -124,10 +127,14 @@ public class BatteryService extends Binder { private long mDischargeStartTime; private int mDischargeStartLevel; + private boolean mUpdatesStopped; + private Led mLed; private boolean mSentLowBatteryBroadcast = false; + private native void native_update(); + public BatteryService(Context context, LightsService lights) { mContext = context; mLed = new Led(context, lights); @@ -146,91 +153,91 @@ public class BatteryService extends Binder { // 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"); + mInvalidChargerObserver.startObserving( + "DEVPATH=/devices/virtual/switch/invalid_charger"); } // set initial status - update(); + synchronized (mLock) { + updateLocked(); + } } - public final boolean isPowered() { - // assume we are powered if battery state is unknown so the "stay on while plugged in" option will work. - return (mAcOnline || mUsbOnline || mWirelessOnline - || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN); + void systemReady() { + // check our power situation now that it is safe to display the shutdown dialog. + synchronized (mLock) { + shutdownIfNoPowerLocked(); + shutdownIfOverTempLocked(); + } + } + + /** + * Returns true if the device is plugged into any of the specified plug types. + */ + public boolean isPowered(int plugTypeSet) { + synchronized (mLock) { + return isPoweredLocked(plugTypeSet); + } } - public final boolean isPowered(int 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 (mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) { return true; } - if (plugTypeSet == 0) { - return false; - } - int plugTypeBit = 0; - if (mAcOnline) { - plugTypeBit |= BatteryManager.BATTERY_PLUGGED_AC; + if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mAcOnline) { + return true; } - if (mUsbOnline) { - plugTypeBit |= BatteryManager.BATTERY_PLUGGED_USB; + if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mUsbOnline) { + return true; } - if (mWirelessOnline) { - plugTypeBit |= BatteryManager.BATTERY_PLUGGED_WIRELESS; + if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mWirelessOnline) { + return true; } - return (plugTypeSet & plugTypeBit) != 0; - } - - public final int getPlugType() { - return mPlugType; + return false; } - private UEventObserver mPowerSupplyObserver = new UEventObserver() { - @Override - public void onUEvent(UEventObserver.UEvent event) { - update(); + /** + * Returns the current plug type. + */ + public int getPlugType() { + synchronized (mLock) { + return mPlugType; } - }; - - private UEventObserver mInvalidChargerObserver = new UEventObserver() { - @Override - public void onUEvent(UEventObserver.UEvent event) { - int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0; - if (mInvalidCharger != invalidCharger) { - mInvalidCharger = invalidCharger; - update(); - } - } - }; - - // returns battery level as a percentage - public final int getBatteryLevel() { - return mBatteryLevel; } - // true if battery level is below the first warning threshold - public final boolean isBatteryLow() { - return mBatteryPresent && mBatteryLevel <= mLowBatteryWarningLevel; + /** + * Returns battery level as a percentage. + */ + public int getBatteryLevel() { + synchronized (mLock) { + return mBatteryLevel; + } } - void systemReady() { - // check our power situation now that it is safe to display the shutdown dialog. - shutdownIfNoPower(); - shutdownIfOverTemp(); + /** + * Returns true if battery level is below the first warning threshold. + */ + public boolean isBatteryLow() { + synchronized (mLock) { + return mBatteryPresent && mBatteryLevel <= mLowBatteryWarningLevel; + } } - private final void shutdownIfNoPower() { + 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 (mBatteryLevel == 0 && !isPowered() && ActivityManagerNative.isSystemReady()) { + if (mBatteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY) + && ActivityManagerNative.isSystemReady()) { Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivity(intent); + mContext.startActivityAsUser(intent, UserHandle.CURRENT); } } - private final void shutdownIfOverTemp() { + 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. @@ -239,22 +246,25 @@ public class BatteryService extends Binder { Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivity(intent); + mContext.startActivityAsUser(intent, UserHandle.CURRENT); } } - private native void native_update(); + private void updateLocked() { + if (!mUpdatesStopped) { + // Update the values of mAcOnline, et. all. + native_update(); - private synchronized final void update() { - native_update(); - processValues(); + // Process the new values. + processValuesLocked(); + } } - private void processValues() { + private void processValuesLocked() { boolean logOutlier = false; long dischargeDuration = 0; - mBatteryLevelCritical = mBatteryLevel <= mCriticalBatteryLevel; + mBatteryLevelCritical = (mBatteryLevel <= mCriticalBatteryLevel); if (mAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mUsbOnline) { @@ -265,6 +275,22 @@ public class BatteryService extends Binder { mPlugType = BATTERY_PLUGGED_NONE; } + if (DEBUG) { + Slog.d(TAG, "Processing new values: " + + "mAcOnline=" + mAcOnline + + ", mUsbOnline=" + mUsbOnline + + ", mWirelessOnline=" + mWirelessOnline + + ", mBatteryStatus=" + mBatteryStatus + + ", mBatteryHealth=" + mBatteryHealth + + ", mBatteryPresent=" + mBatteryPresent + + ", mBatteryLevel=" + mBatteryLevel + + ", mBatteryTechnology=" + mBatteryTechnology + + ", mBatteryVoltage=" + mBatteryVoltage + + ", mBatteryTemperature=" + mBatteryTemperature + + ", mBatteryLevelCritical=" + mBatteryLevelCritical + + ", mPlugType=" + mPlugType); + } + // Let the battery stats keep track of the current level. try { mBatteryStats.setBatteryState(mBatteryStatus, mBatteryHealth, @@ -274,8 +300,8 @@ public class BatteryService extends Binder { // Should never happen. } - shutdownIfNoPower(); - shutdownIfOverTemp(); + shutdownIfNoPowerLocked(); + shutdownIfOverTempLocked(); if (mBatteryStatus != mLastBatteryStatus || mBatteryHealth != mLastBatteryHealth || @@ -342,7 +368,7 @@ public class BatteryService extends Binder { && mBatteryLevel <= mLowBatteryWarningLevel && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel); - sendIntent(); + sendIntentLocked(); // Separate broadcast is sent for power connected / not connected // since the standard intent will not wake any applications and some @@ -373,7 +399,7 @@ public class BatteryService extends Binder { // This needs to be done after sendIntent() so that we get the lastest battery stats. if (logOutlier && dischargeDuration != 0) { - logOutlier(dischargeDuration); + logOutlierLocked(dischargeDuration); } mLastBatteryStatus = mBatteryStatus; @@ -388,13 +414,13 @@ public class BatteryService extends Binder { } } - private final void sendIntent() { + private void sendIntentLocked() { // Pack up the values and broadcast them to everyone Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING); - int icon = getIcon(mBatteryLevel); + int icon = getIconLocked(mBatteryLevel); intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryStatus); intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth); @@ -408,22 +434,22 @@ public class BatteryService extends Binder { intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology); intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger); - if (false) { - Slog.d(TAG, "level:" + mBatteryLevel + - " scale:" + BATTERY_SCALE + " status:" + mBatteryStatus + - " health:" + mBatteryHealth + " present:" + mBatteryPresent + - " voltage: " + mBatteryVoltage + - " temperature: " + mBatteryTemperature + - " technology: " + mBatteryTechnology + - " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline + - " Wireless powered:" + mWirelessOnline + - " icon:" + icon + " invalid charger:" + mInvalidCharger); + if (DEBUG) { + Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryLevel + + ", scale:" + BATTERY_SCALE + ", status:" + mBatteryStatus + + ", health:" + mBatteryHealth + ", present:" + mBatteryPresent + + ", voltage: " + mBatteryVoltage + + ", temperature: " + mBatteryTemperature + + ", technology: " + mBatteryTechnology + + ", AC powered:" + mAcOnline + ", USB powered:" + mUsbOnline + + ", Wireless powered:" + mWirelessOnline + + ", icon:" + icon + ", invalid charger:" + mInvalidCharger); } ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); } - private final void logBatteryStats() { + private void logBatteryStatsLocked() { IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME); if (batteryInfoService == null) return; @@ -461,7 +487,7 @@ public class BatteryService extends Binder { } } - private final void logOutlier(long duration) { + private void logOutlierLocked(long duration) { ContentResolver cr = mContext.getContentResolver(); String dischargeThresholdString = Settings.Global.getString(cr, Settings.Global.BATTERY_DISCHARGE_THRESHOLD); @@ -475,11 +501,11 @@ public class BatteryService extends Binder { if (duration <= durationThreshold && mDischargeStartLevel - mBatteryLevel >= dischargeThreshold) { // If the discharge cycle is bad enough we want to know about it. - logBatteryStats(); + logBatteryStatsLocked(); } - if (LOCAL_LOGV) Slog.v(TAG, "duration threshold: " + durationThreshold + + if (DEBUG) Slog.v(TAG, "duration threshold: " + durationThreshold + " discharge threshold: " + dischargeThreshold); - if (LOCAL_LOGV) Slog.v(TAG, "duration: " + duration + " discharge: " + + if (DEBUG) Slog.v(TAG, "duration: " + duration + " discharge: " + (mDischargeStartLevel - mBatteryLevel)); } catch (NumberFormatException e) { Slog.e(TAG, "Invalid DischargeThresholds GService string: " + @@ -489,14 +515,15 @@ public class BatteryService extends Binder { } } - private final int getIcon(int level) { + private int getIconLocked(int level) { if (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) { return com.android.internal.R.drawable.stat_sys_battery_charge; } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) { return com.android.internal.R.drawable.stat_sys_battery; } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING || mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) { - if (isPowered() && mBatteryLevel >= 100) { + if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY) + && mBatteryLevel >= 100) { return com.android.internal.R.drawable.stat_sys_battery_charge; } else { return com.android.internal.R.drawable.stat_sys_battery; @@ -517,9 +544,12 @@ public class BatteryService extends Binder { return; } - if (args == null || args.length == 0 || "-a".equals(args[0])) { - synchronized (this) { + synchronized (mLock) { + if (args == null || args.length == 0 || "-a".equals(args[0])) { pw.println("Current Battery Service state:"); + if (mUpdatesStopped) { + pw.println(" (UPDATES STOPPED -- use 'reset' to restart)"); + } pw.println(" AC powered: " + mAcOnline); pw.println(" USB powered: " + mUsbOnline); pw.println(" Wireless powered: " + mWirelessOnline); @@ -531,10 +561,7 @@ public class BatteryService extends Binder { pw.println(" voltage:" + mBatteryVoltage); pw.println(" temperature: " + mBatteryTemperature); pw.println(" technology: " + mBatteryTechnology); - } - } else if (false) { - // DO NOT SUBMIT WITH THIS TURNED ON - if (args.length == 3 && "set".equals(args[0])) { + } else if (args.length == 3 && "set".equals(args[0])) { String key = args[1]; String value = args[2]; try { @@ -552,52 +579,77 @@ public class BatteryService extends Binder { } else if ("invalid".equals(key)) { mInvalidCharger = Integer.parseInt(value); } else { + pw.println("Unknown set option: " + key); update = false; } if (update) { - processValues(); + mUpdatesStopped = true; + processValuesLocked(); } } catch (NumberFormatException ex) { pw.println("Bad value: " + value); } + } else if (args.length == 1 && "reset".equals(args[0])) { + mUpdatesStopped = false; + updateLocked(); + } else { + pw.println("Dump current battery state, or:"); + pw.println(" set ac|usb|wireless|status|level|invalid <value>"); + pw.println(" reset"); } } } - class Led { - private LightsService mLightsService; - private LightsService.Light mBatteryLight; + private final UEventObserver mPowerSupplyObserver = new UEventObserver() { + @Override + public void onUEvent(UEventObserver.UEvent event) { + synchronized (mLock) { + updateLocked(); + } + } + }; + + private final UEventObserver mInvalidChargerObserver = new UEventObserver() { + @Override + public void onUEvent(UEventObserver.UEvent event) { + final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0; + synchronized (mLock) { + if (mInvalidCharger != invalidCharger) { + mInvalidCharger = invalidCharger; + updateLocked(); + } + } + } + }; - private int mBatteryLowARGB; - private int mBatteryMediumARGB; - private int mBatteryFullARGB; - private int mBatteryLedOn; - private int mBatteryLedOff; + private final class Led { + private final LightsService.Light mBatteryLight; - private boolean mBatteryCharging; - private boolean mBatteryLow; - private boolean mBatteryFull; + private final int mBatteryLowARGB; + private final int mBatteryMediumARGB; + private final int mBatteryFullARGB; + private final int mBatteryLedOn; + private final int mBatteryLedOff; - Led(Context context, LightsService lights) { - mLightsService = lights; + public Led(Context context, LightsService lights) { mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY); - mBatteryLowARGB = mContext.getResources().getInteger( + mBatteryLowARGB = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLowARGB); - mBatteryMediumARGB = mContext.getResources().getInteger( + mBatteryMediumARGB = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryMediumARGB); - mBatteryFullARGB = mContext.getResources().getInteger( + mBatteryFullARGB = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryFullARGB); - mBatteryLedOn = mContext.getResources().getInteger( + mBatteryLedOn = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOn); - mBatteryLedOff = mContext.getResources().getInteger( + mBatteryLedOff = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOff); } /** * Synchronize on BatteryService. */ - void updateLightsLocked() { + public void updateLightsLocked() { final int level = mBatteryLevel; final int status = mBatteryStatus; if (level < mLowBatteryWarningLevel) { |
