Skip to content

Commit

Permalink
rework powered/plugged/charging logic
Browse files Browse the repository at this point in the history
 * Reworks "isPowered/isPluggued/isCharging" code to correctly report
   charging status.  Note that some devices can draw more than 500mA,
   so "plugged" != "charging" (as is assumed in existing code).
   This faulty assumption can result in incorrect charging status
   reported and inability to shutdown at critical battery level.

Change-Id: I6b3282df6513a8c235b0f4cdfd9e16f531e34166
  • Loading branch information
jcsullins authored and fi01 committed Feb 13, 2013
1 parent a1e5b03 commit 9d911b2
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 32 deletions.
11 changes: 7 additions & 4 deletions packages/SystemUI/src/com/android/systemui/power/PowerUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ public void onReceive(Context context, Intent intent) {

final boolean plugged = mPlugType != 0;
final boolean oldPlugged = oldPlugType != 0;
final boolean charging = mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING;
final boolean oldCharging = oldBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING;

int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
int bucket = findBatteryLevelBucket(mBatteryLevel);
Expand All @@ -134,6 +136,7 @@ public void onReceive(Context context, Intent intent) {
Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket);
Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
Slog.d(TAG, "charging " + oldCharging + " --> " + charging);
}

if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
Expand All @@ -147,17 +150,17 @@ public void onReceive(Context context, Intent intent) {
return;
}

if (!plugged
&& (bucket < oldBucket || oldPlugged)
if (!charging
&& (bucket < oldBucket || oldCharging)
&& mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& bucket < 0) {
showLowBatteryWarning();

// only play SFX when the dialog comes up or the bucket changes
if (bucket != oldBucket || oldPlugged) {
if (bucket != oldBucket || oldCharging) {
playLowBatterySound();
}
} else if (plugged || (bucket > oldBucket && bucket > 0)) {
} else if (charging || (bucket > oldBucket && bucket > 0)) {
dismissLowBatteryWarning();
} else if (mBatteryLevelTextView != null) {
showLowBatteryWarning();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class BatteryController extends BroadcastReceiver {
private static final int BATTERY_TEXT_STYLE_MIN = R.string.status_bar_settings_battery_meter_min_format;

private boolean mBatteryPlugged = false;
private boolean mBatteryCharging = false;
private int mBatteryStyle;
private int mBatteryIcon = BATTERY_ICON_STYLE_NORMAL;

Expand Down Expand Up @@ -111,6 +112,7 @@ public void onReceive(Context context, Intent intent) {
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
mBatteryPlugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
mBatteryCharging = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN) == BatteryManager.BATTERY_STATUS_CHARGING;
int N = mIconViews.size();
for (int i=0; i<N; i++) {
ImageView v = mIconViews.get(i);
Expand All @@ -135,12 +137,12 @@ private void updateBattery() {

if (mBatteryStyle == BATTERY_STYLE_NORMAL) {
mIcon = (View.VISIBLE);
mIconStyle = mBatteryPlugged ? BATTERY_ICON_STYLE_CHARGE
mIconStyle = mBatteryCharging ? BATTERY_ICON_STYLE_CHARGE
: BATTERY_ICON_STYLE_NORMAL;
} else if (mBatteryStyle == BATTERY_STYLE_PERCENT) {
mIcon = (View.VISIBLE);
mText = (View.VISIBLE);
mIconStyle = mBatteryPlugged ? BATTERY_ICON_STYLE_CHARGE_MIN
mIconStyle = mBatteryCharging ? BATTERY_ICON_STYLE_CHARGE_MIN
: BATTERY_ICON_STYLE_NORMAL_MIN;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import static android.os.BatteryManager.BATTERY_STATUS_CHARGING;
import static android.os.BatteryManager.BATTERY_STATUS_DISCHARGING;
import static android.os.BatteryManager.BATTERY_STATUS_FULL;
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
Expand Down Expand Up @@ -384,7 +386,7 @@ private void handleBatteryUpdate(BatteryStatus batteryStatus) {
for (int i = 0; i < mInfoCallbacks.size(); i++) {
// TODO: pass BatteryStatus object to onRefreshBatteryInfo() instead...
mInfoCallbacks.get(i).onRefreshBatteryInfo(
shouldShowBatteryInfo(),isPluggedIn(batteryStatus), batteryStatus.level);
shouldShowBatteryInfo(),isCharging(batteryStatus), batteryStatus.level);
}
}
}
Expand Down Expand Up @@ -437,6 +439,10 @@ private static boolean isPluggedIn(BatteryStatus status) {
|| status.plugged == BatteryManager.BATTERY_PLUGGED_USB;
}

private static boolean isCharging(BatteryStatus status) {
return status.status == BatteryManager.BATTERY_STATUS_CHARGING;
}

private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current, Context context) {
final boolean nowPluggedIn = isPluggedIn(current);
final boolean wasPluggedIn = isPluggedIn(old);
Expand Down Expand Up @@ -613,7 +619,7 @@ public void registerInfoCallback(InfoCallback callback) {
if (!mInfoCallbacks.contains(callback)) {
mInfoCallbacks.add(callback);
// Notify listener of the current state
callback.onRefreshBatteryInfo(shouldShowBatteryInfo(),isPluggedIn(mBatteryStatus),
callback.onRefreshBatteryInfo(shouldShowBatteryInfo(),isCharging(mBatteryStatus),
mBatteryStatus.level);
callback.onTimeChanged();
callback.onRingerModeChanged(mRingMode);
Expand Down Expand Up @@ -676,8 +682,10 @@ public int getBatteryLevel() {
}

public boolean shouldShowBatteryInfo() {
return isPluggedIn(mBatteryStatus) || isBatteryLow(mBatteryStatus)
|| shouldAlwaysShowBatteryInfo(mContext);
return (isPluggedIn(mBatteryStatus) && isDeviceCharged())
|| isCharging(mBatteryStatus)
|| isBatteryLow(mBatteryStatus)
|| shouldAlwaysShowBatteryInfo(mContext);
}

public static boolean shouldAlwaysShowBatteryInfo(Context context) {
Expand Down
28 changes: 16 additions & 12 deletions services/java/com/android/server/BatteryService.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,17 @@ public BatteryService(Context context, LightsService lights) {
update();
}

final boolean isPowered() {
// assume we are powered if battery state is unknown so the "stay on while plugged in" option will work.
final boolean isPlugged() {
// assume we are plugged if battery state is unknown so the "stay on while plugged in" option will work
return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN);
}

final boolean isPowered(int plugTypeSet) {
// assume we are powered if battery state is unknown so
final boolean isCharging() {
return (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING);
}

final boolean isPlugged(int plugTypeSet) {
// assume we are plugged if battery state is unknown so
// the "stay on while plugged in" option will work.
if (mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
return true;
Expand Down Expand Up @@ -240,7 +244,7 @@ void systemReady() {
private final void shutdownIfNoPower() {
// 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 && !isCharging() && ActivityManagerNative.isSystemReady()) {
Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Expand Down Expand Up @@ -351,19 +355,19 @@ private void processValues() {
logOutlier = true;
}

final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE;
final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE;
final boolean charging = (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING);
final boolean oldCharging = (mLastBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING);

/* The ACTION_BATTERY_LOW broadcast is sent in these situations:
* - is just un-plugged (previously was plugged) and battery level is
* - just stopped charging (previously was charging) and battery level is
* less than or equal to WARNING, or
* - is not plugged and battery level falls to WARNING boundary
* - is not charging and battery level falls to WARNING boundary
* (becomes <= mLowBatteryWarningLevel).
*/
final boolean sendBatteryLow = !plugged
final boolean sendBatteryLow = !charging
&& mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& mBatteryLevel <= mLowBatteryWarningLevel
&& (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
&& (oldCharging || mLastBatteryLevel > mLowBatteryWarningLevel);

sendIntent();

Expand Down Expand Up @@ -530,7 +534,7 @@ private final int getIcon(int level) {
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 (isPlugged() && mBatteryLevel >= 100) {
return com.android.internal.R.drawable.stat_sys_battery_charge;
} else {
return com.android.internal.R.drawable.stat_sys_battery;
Expand Down
22 changes: 13 additions & 9 deletions services/java/com/android/server/PowerManagerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ public class PowerManagerService extends IPowerManager.Stub
private ScreenBrightnessAnimator mScreenBrightnessAnimator;
private boolean mWaitingForFirstLightSensor = false;
private boolean mStillNeedSleepNotification;
private boolean mIsPowered = false;
private boolean mIsPlugged = false;
private boolean mIsCharging = false;
private IActivityManager mActivityService;
private IBatteryStats mBatteryStats;
private BatteryService mBatteryService;
Expand Down Expand Up @@ -454,10 +455,12 @@ private final class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLocks) {
boolean wasPowered = mIsPowered;
mIsPowered = mBatteryService.isPowered();
boolean wasPlugged = mIsPlugged;
boolean wasCharging = mIsCharging;
mIsPlugged = mBatteryService.isPlugged();
mIsCharging = mBatteryService.isCharging();

if (mIsPowered != wasPowered) {
if (mIsPlugged != wasPlugged) {
// update mStayOnWhilePluggedIn wake lock
updateWakeLockLocked();

Expand All @@ -472,7 +475,7 @@ public void onReceive(Context context, Intent intent) {
// turn on. Some devices want this because they don't have a
// charging LED.
synchronized (mLocks) {
if (!wasPowered || (mPowerState & SCREEN_ON_BIT) != 0 ||
if (!wasPlugged || (mPowerState & SCREEN_ON_BIT) != 0 ||
mUnplugTurnsOnScreen) {
forceUserActivityLocked();
}
Expand Down Expand Up @@ -816,7 +819,7 @@ public void binderDied() {

private void updateWakeLockLocked() {
final int stayOnConditions = getStayOnConditionsLocked();
if (stayOnConditions != 0 && mBatteryService.isPowered(stayOnConditions)) {
if (stayOnConditions != 0 && mBatteryService.isPlugged(stayOnConditions)) {
// keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
mStayOnWhilePluggedInScreenDimLock.acquire();
mStayOnWhilePluggedInPartialLock.acquire();
Expand Down Expand Up @@ -1242,7 +1245,8 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {

synchronized (mLocks) {
pw.println("Power Manager State:");
pw.println(" mIsPowered=" + mIsPowered
pw.println(" mIsPlugged=" + mIsPlugged
+ " mIsCharging=" + mIsCharging
+ " mPowerState=" + mPowerState
+ " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
+ " ms");
Expand Down Expand Up @@ -2056,7 +2060,7 @@ private int screenOffFinishedAnimatingLocked(int reason) {
}

private boolean batteryIsLow() {
return (!mIsPowered &&
return (!mIsCharging &&
mBatteryService.getBatteryLevel() <= LOW_BATTERY_THRESHOLD);
}

Expand Down Expand Up @@ -2183,7 +2187,7 @@ private void updateLightsLocked(int newState, int forceState) {
steps = (int)(ANIM_STEPS*ratio);
}
final int stayOnConditions = getStayOnConditionsLocked();
if (stayOnConditions != 0 && mBatteryService.isPowered(stayOnConditions)) {
if (stayOnConditions != 0 && mBatteryService.isPlugged(stayOnConditions)) {
// If the "stay on while plugged in" option is
// turned on, then the screen will often not
// automatically turn off while plugged in. To
Expand Down
2 changes: 1 addition & 1 deletion services/java/com/android/server/Watchdog.java
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ void retrieveBrutalityAmount() {
* text of why it is not a good time.
*/
String shouldWeBeBrutalLocked(long curTime) {
if (mBattery == null || !mBattery.isPowered()) {
if (mBattery == null || !mBattery.isPlugged()) {
return "battery";
}

Expand Down

0 comments on commit 9d911b2

Please sign in to comment.