summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/BatteryManagerInternal.java8
-rw-r--r--core/proto/android/server/powermanagerservice.proto2
-rw-r--r--services/core/java/com/android/server/BatteryService.java7
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java53
5 files changed, 96 insertions, 14 deletions
diff --git a/core/java/android/os/BatteryManagerInternal.java b/core/java/android/os/BatteryManagerInternal.java
index 97ec5940ccb0..9bad0def0626 100644
--- a/core/java/android/os/BatteryManagerInternal.java
+++ b/core/java/android/os/BatteryManagerInternal.java
@@ -47,6 +47,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}.
*
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index bd4f99044b17..004d5d699a31 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -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.
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 4278b3edc3eb..71a4c73a4dac 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -1306,6 +1306,13 @@ public final class BatteryService extends SystemService {
}
@Override
+ public int getBatteryHealth() {
+ synchronized (mLock) {
+ return mHealthInfo.batteryHealth;
+ }
+ }
+
+ @Override
public boolean getBatteryLevelLow() {
synchronized (mLock) {
return mBatteryLevelLow;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 20235eb2c464..9281f4bf75b0 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -423,6 +423,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;
@@ -455,11 +458,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;
@@ -2469,15 +2467,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) {
@@ -3300,7 +3308,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 {
@@ -3321,16 +3329,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
@@ -3561,6 +3568,11 @@ public final class PowerManagerService extends SystemService
mScreenBrightnessBoostInProgress);
}
+ @VisibleForTesting
+ int getDreamsBatteryLevelDrain() {
+ return mDreamsBatteryLevelDrain;
+ }
+
private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
new DisplayManagerInternal.DisplayPowerCallbacks() {
@@ -4405,7 +4417,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);
@@ -4650,8 +4662,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);
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index d0d2b412b1b6..c81db9216c08 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -389,6 +389,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,
@@ -413,6 +425,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();
@@ -987,6 +1005,41 @@ public class PowerManagerServiceTest {
}
@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";
final String tag = "acq_causes_wakeup";