Merge "Update dream battery drain monitoring to exclude when charging is being artificially limited." into tm-qpr-dev

This commit is contained in:
Lucas Silva
2022-11-19 20:10:37 +00:00
committed by Android (Google) Code Review
5 changed files with 96 additions and 14 deletions

View File

@@ -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}.

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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;
@@ -2462,15 +2460,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) {
@@ -3292,7 +3300,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 {
@@ -3313,16 +3321,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
@@ -3553,6 +3560,11 @@ public final class PowerManagerService extends SystemService
mScreenBrightnessBoostInProgress);
}
@VisibleForTesting
int getDreamsBatteryLevelDrain() {
return mDreamsBatteryLevelDrain;
}
private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
new DisplayManagerInternal.DisplayPowerCallbacks() {
@@ -4397,7 +4409,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);
@@ -4638,8 +4650,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);

View File

@@ -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();
@@ -937,6 +955,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";