summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/BatteryService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/BatteryService.java')
-rw-r--r--services/java/com/android/server/BatteryService.java282
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>&quot;technology&quot; - 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) {