Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a10f281d authored by James Sullins's avatar James Sullins Committed by Gerrit Code Review
Browse files

rework powered/plugged/charging logic

 * 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
parent b9de7e5b
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ public class PowerUI extends SystemUI {

                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);
@@ -134,6 +136,7 @@ public class PowerUI extends SystemUI {
                    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) {
@@ -147,17 +150,17 @@ public class PowerUI extends SystemUI {
                    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();
+4 −2
Original line number Diff line number Diff line
@@ -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;

@@ -111,6 +112,7 @@ public class BatteryController extends BroadcastReceiver {
        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);
@@ -135,12 +137,12 @@ public class BatteryController extends BroadcastReceiver {

        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;
        }

+12 −4
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.content.Context;
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;
@@ -384,7 +386,7 @@ public class KeyguardUpdateMonitor {
            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);
            }
        }
    }
@@ -437,6 +439,10 @@ public class KeyguardUpdateMonitor {
                || 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);
@@ -613,7 +619,7 @@ public class KeyguardUpdateMonitor {
        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);
@@ -676,7 +682,9 @@ public class KeyguardUpdateMonitor {
    }

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

+16 −12
Original line number Diff line number Diff line
@@ -180,13 +180,17 @@ class BatteryService extends Binder {
        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;
@@ -240,7 +244,7 @@ class BatteryService extends Binder {
    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);
@@ -351,19 +355,19 @@ class BatteryService extends Binder {
                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();

@@ -530,7 +534,7 @@ class BatteryService extends Binder {
            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;
+13 −9
Original line number Diff line number Diff line
@@ -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;
@@ -454,10 +455,12 @@ public class PowerManagerService extends IPowerManager.Stub
        @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();

@@ -472,7 +475,7 @@ public class PowerManagerService extends IPowerManager.Stub
                    // 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();
                        }
@@ -816,7 +819,7 @@ public class PowerManagerService extends IPowerManager.Stub

    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();
@@ -1242,7 +1245,8 @@ public class PowerManagerService extends IPowerManager.Stub

        synchronized (mLocks) {
            pw.println("Power Manager State:");
            pw.println("  mIsPowered=" + mIsPowered
            pw.println("  mIsPlugged=" + mIsPlugged
                    + " mIsCharging=" + mIsCharging
                    + " mPowerState=" + mPowerState
                    + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
                    + " ms");
@@ -2056,7 +2060,7 @@ public class PowerManagerService extends IPowerManager.Stub
    }

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

@@ -2183,7 +2187,7 @@ public class PowerManagerService extends IPowerManager.Stub
                        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
Loading