Update dream battery drain monitoring to exclude when charging is being
artificially limited. We may limit charging when battery is overheating, or due to dock defend or other battery defend mechanisms. In these cases, the battery is expected to drain while dreaming since charging is limited. Therefore, do not exit dreams in this case. Test: atest PowerManagerServiceTest Fixes: 258027228 Change-Id: I10ce0c848892b42267d819d07a284d17a97899d1
This commit is contained in:
@@ -46,6 +46,14 @@ public abstract class BatteryManagerInternal {
|
||||
*/
|
||||
public abstract int getBatteryLevel();
|
||||
|
||||
/**
|
||||
* Returns battery health status as an integer representing the current battery health constant.
|
||||
*
|
||||
* This is a simple accessor that's safe to be called from any locks, but internally it may
|
||||
* wait on the battery service lock.
|
||||
*/
|
||||
public abstract int getBatteryHealth();
|
||||
|
||||
/**
|
||||
* Instantaneous battery capacity in uA-h, as defined in the HealthInfo HAL struct.
|
||||
* Please note apparently it could be bigger than {@link #getBatteryFullCharge}.
|
||||
|
||||
@@ -189,6 +189,8 @@ message PowerManagerServiceDumpProto {
|
||||
optional bool is_enhanced_discharge_prediction_personalized = 54;
|
||||
optional bool is_low_power_standby_active = 55;
|
||||
optional LowPowerStandbyControllerDumpProto low_power_standby_controller = 56;
|
||||
// The battery level drained by the dream.
|
||||
optional int32 battery_level_drained_while_dreaming = 57;
|
||||
}
|
||||
|
||||
// A com.android.server.power.PowerManagerService.SuspendBlockerImpl object.
|
||||
|
||||
@@ -1286,6 +1286,13 @@ public final class BatteryService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatteryHealth() {
|
||||
synchronized (mLock) {
|
||||
return mHealthInfo.batteryHealth;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBatteryLevelLow() {
|
||||
synchronized (mLock) {
|
||||
|
||||
@@ -419,6 +419,9 @@ public final class PowerManagerService extends SystemService
|
||||
// The current battery level percentage.
|
||||
private int mBatteryLevel;
|
||||
|
||||
// The amount of battery drained while the device has been in a dream state.
|
||||
private int mDreamsBatteryLevelDrain;
|
||||
|
||||
// True if updatePowerStateLocked() is already in progress.
|
||||
// TODO(b/215518989): Remove this once transactions are in place
|
||||
private boolean mUpdatePowerStateInProgress;
|
||||
@@ -451,11 +454,6 @@ public final class PowerManagerService extends SystemService
|
||||
@GuardedBy("mEnhancedDischargeTimeLock")
|
||||
private boolean mEnhancedDischargePredictionIsPersonalized;
|
||||
|
||||
// The battery level percentage at the time the dream started.
|
||||
// This is used to terminate a dream and go to sleep if the battery is
|
||||
// draining faster than it is charging and the user activity timeout has expired.
|
||||
private int mBatteryLevelWhenDreamStarted;
|
||||
|
||||
// The current dock state.
|
||||
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
||||
|
||||
@@ -2448,15 +2446,25 @@ public final class PowerManagerService extends SystemService
|
||||
final int oldPlugType = mPlugType;
|
||||
mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
|
||||
mPlugType = mBatteryManagerInternal.getPlugType();
|
||||
final int oldBatteryLevel = mBatteryLevel;
|
||||
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
|
||||
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
|
||||
final boolean isOverheat = mBatteryManagerInternal.getBatteryHealth()
|
||||
== BatteryManager.BATTERY_HEALTH_OVERHEAT;
|
||||
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
|
||||
+ ", mIsPowered=" + mIsPowered
|
||||
+ ", oldPlugType=" + oldPlugType
|
||||
+ ", mPlugType=" + mPlugType
|
||||
+ ", mBatteryLevel=" + mBatteryLevel);
|
||||
+ ", oldBatteryLevel=" + oldBatteryLevel
|
||||
+ ", mBatteryLevel=" + mBatteryLevel
|
||||
+ ", isOverheat=" + isOverheat);
|
||||
}
|
||||
|
||||
if (!isOverheat && oldBatteryLevel > 0
|
||||
&& getGlobalWakefulnessLocked() == WAKEFULNESS_DREAMING) {
|
||||
mDreamsBatteryLevelDrain += (oldBatteryLevel - mBatteryLevel);
|
||||
}
|
||||
|
||||
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
|
||||
@@ -3278,7 +3286,7 @@ public final class PowerManagerService extends SystemService
|
||||
|
||||
// Remember the initial battery level when the dream started.
|
||||
if (startDreaming && isDreaming) {
|
||||
mBatteryLevelWhenDreamStarted = mBatteryLevel;
|
||||
mDreamsBatteryLevelDrain = 0;
|
||||
if (wakefulness == WAKEFULNESS_DOZING) {
|
||||
Slog.i(TAG, "Dozing...");
|
||||
} else {
|
||||
@@ -3299,16 +3307,15 @@ public final class PowerManagerService extends SystemService
|
||||
if (wakefulness == WAKEFULNESS_DREAMING) {
|
||||
if (isDreaming && canDreamLocked(powerGroup)) {
|
||||
if (mDreamsBatteryLevelDrainCutoffConfig >= 0
|
||||
&& mBatteryLevel < mBatteryLevelWhenDreamStarted
|
||||
- mDreamsBatteryLevelDrainCutoffConfig
|
||||
&& mDreamsBatteryLevelDrain > mDreamsBatteryLevelDrainCutoffConfig
|
||||
&& !isBeingKeptAwakeLocked(powerGroup)) {
|
||||
// If the user activity timeout expired and the battery appears
|
||||
// to be draining faster than it is charging then stop dreaming
|
||||
// and go to sleep.
|
||||
Slog.i(TAG, "Stopping dream because the battery appears to "
|
||||
+ "be draining faster than it is charging. "
|
||||
+ "Battery level when dream started: "
|
||||
+ mBatteryLevelWhenDreamStarted + "%. "
|
||||
+ "Battery level drained while dreaming: "
|
||||
+ mDreamsBatteryLevelDrain + "%. "
|
||||
+ "Battery level now: " + mBatteryLevel + "%.");
|
||||
} else {
|
||||
return; // continue dreaming
|
||||
@@ -3539,6 +3546,11 @@ public final class PowerManagerService extends SystemService
|
||||
mScreenBrightnessBoostInProgress);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
int getDreamsBatteryLevelDrain() {
|
||||
return mDreamsBatteryLevelDrain;
|
||||
}
|
||||
|
||||
private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
|
||||
new DisplayManagerInternal.DisplayPowerCallbacks() {
|
||||
|
||||
@@ -4383,7 +4395,7 @@ public final class PowerManagerService extends SystemService
|
||||
pw.println(" mIsPowered=" + mIsPowered);
|
||||
pw.println(" mPlugType=" + mPlugType);
|
||||
pw.println(" mBatteryLevel=" + mBatteryLevel);
|
||||
pw.println(" mBatteryLevelWhenDreamStarted=" + mBatteryLevelWhenDreamStarted);
|
||||
pw.println(" mDreamsBatteryLevelDrain=" + mDreamsBatteryLevelDrain);
|
||||
pw.println(" mDockState=" + mDockState);
|
||||
pw.println(" mStayOn=" + mStayOn);
|
||||
pw.println(" mProximityPositive=" + mProximityPositive);
|
||||
@@ -4625,8 +4637,8 @@ public final class PowerManagerService extends SystemService
|
||||
proto.write(PowerManagerServiceDumpProto.PLUG_TYPE, mPlugType);
|
||||
proto.write(PowerManagerServiceDumpProto.BATTERY_LEVEL, mBatteryLevel);
|
||||
proto.write(
|
||||
PowerManagerServiceDumpProto.BATTERY_LEVEL_WHEN_DREAM_STARTED,
|
||||
mBatteryLevelWhenDreamStarted);
|
||||
PowerManagerServiceDumpProto.BATTERY_LEVEL_DRAINED_WHILE_DREAMING,
|
||||
mDreamsBatteryLevelDrain);
|
||||
proto.write(PowerManagerServiceDumpProto.DOCK_STATE, mDockState);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_STAY_ON, mStayOn);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive);
|
||||
|
||||
@@ -375,6 +375,18 @@ public class PowerManagerServiceTest {
|
||||
mBatteryReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_BATTERY_CHANGED));
|
||||
}
|
||||
|
||||
private void setBatteryLevel(int batteryLevel) {
|
||||
when(mBatteryManagerInternalMock.getBatteryLevel())
|
||||
.thenReturn(batteryLevel);
|
||||
mBatteryReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_BATTERY_CHANGED));
|
||||
}
|
||||
|
||||
private void setBatteryHealth(int batteryHealth) {
|
||||
when(mBatteryManagerInternalMock.getBatteryHealth())
|
||||
.thenReturn(batteryHealth);
|
||||
mBatteryReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_BATTERY_CHANGED));
|
||||
}
|
||||
|
||||
private void setAttentiveTimeout(int attentiveTimeoutMillis) {
|
||||
Settings.Secure.putInt(
|
||||
mContextSpy.getContentResolver(), Settings.Secure.ATTENTIVE_TIMEOUT,
|
||||
@@ -399,6 +411,12 @@ public class PowerManagerServiceTest {
|
||||
.thenReturn(disable);
|
||||
}
|
||||
|
||||
private void setDreamsBatteryLevelDrainConfig(int threshold) {
|
||||
when(mResourcesSpy.getInteger(
|
||||
com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff)).thenReturn(
|
||||
threshold);
|
||||
}
|
||||
|
||||
private void advanceTime(long timeMs) {
|
||||
mClock.fastForward(timeMs);
|
||||
mTestLooper.dispatchAll();
|
||||
@@ -881,6 +899,41 @@ public class PowerManagerServiceTest {
|
||||
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatteryDrainDuringDream() {
|
||||
Settings.Secure.putInt(mContextSpy.getContentResolver(),
|
||||
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
|
||||
Settings.Secure.putInt(mContextSpy.getContentResolver(),
|
||||
Settings.Secure.SCREENSAVER_ENABLED, 1);
|
||||
|
||||
setMinimumScreenOffTimeoutConfig(100);
|
||||
setDreamsBatteryLevelDrainConfig(5);
|
||||
createService();
|
||||
startSystem();
|
||||
|
||||
doAnswer(inv -> {
|
||||
when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
|
||||
return null;
|
||||
}).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());
|
||||
|
||||
setBatteryLevel(100);
|
||||
setPluggedIn(true);
|
||||
|
||||
forceAwake(); // Needs to be awake first before it can dream.
|
||||
forceDream();
|
||||
advanceTime(10); // Allow async calls to happen
|
||||
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
|
||||
setBatteryLevel(90);
|
||||
advanceTime(10); // Allow async calls to happen
|
||||
assertThat(mService.getDreamsBatteryLevelDrain()).isEqualTo(10);
|
||||
|
||||
// If battery overheat protection is enabled, we shouldn't count battery drain
|
||||
setBatteryHealth(BatteryManager.BATTERY_HEALTH_OVERHEAT);
|
||||
setBatteryLevel(70);
|
||||
advanceTime(10); // Allow async calls to happen
|
||||
assertThat(mService.getDreamsBatteryLevelDrain()).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetDozeOverrideFromDreamManager_triggersSuspendBlocker() {
|
||||
final String suspendBlockerName = "PowerManagerService.Display";
|
||||
|
||||
Reference in New Issue
Block a user