Make Settings and SysUI estimates use same data class
This moves everything over to using a shared data class
for Estimates in SettingsLib which will facilitate a cl
that will help ensure greater consistency across
surfaces where battery estimates are shown.
Test: Tests pass
Bug: 124030091
Change-Id: I0b7f1f3a806255ff4804a00e6d90a7846c484484
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 83dc39e..8581920 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12666,6 +12666,45 @@
public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
/**
+ * A long value indicating how much longer the system battery is estimated to last in
+ * millis. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value
+ * was updated.
+ *
+ * @hide
+ */
+ public static final String TIME_REMAINING_ESTIMATE_MILLIS =
+ "time_remaining_estimate_millis";
+
+ /**
+ * A boolean indicating whether {@link #TIME_REMAINING_ESTIMATE_MILLIS} is based customized
+ * to the devices usage or using global models. See
+ * {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value was updated.
+ *
+ * @hide
+ */
+ public static final String TIME_REMAINING_ESTIMATE_BASED_ON_USAGE =
+ "time_remaining_estimate_based_on_usage";
+
+ /**
+ * A long value indicating how long the system battery takes to deplete from 100% to 0% on
+ * average based on historical drain rates. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME}
+ * for the last time this value was updated.
+ *
+ * @hide
+ */
+ public static final String AVERAGE_TIME_TO_DISCHARGE = "average_time_to_discharge";
+
+ /**
+ * A long indicating the epoch time in milliseconds when
+ * {@link #TIME_REMAINING_ESTIMATE_MILLIS}, {@link #TIME_REMAINING_ESTIMATE_BASED_ON_USAGE},
+ * and {@link #AVERAGE_TIME_TO_DISCHARGE} were last updated.
+ *
+ * @hide
+ */
+ public static final String BATTERY_ESTIMATES_LAST_UPDATE_TIME =
+ "battery_estimates_last_update_time";
+
+ /**
* The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting is not set
* or the value is 0, the default max will be used.
*
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 0e94abc0..cf9a7fc 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -130,8 +130,10 @@
Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
+ Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED,
Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
+ Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
Settings.Global.BROADCAST_BG_CONSTANTS,
Settings.Global.BROADCAST_FG_CONSTANTS,
Settings.Global.BROADCAST_OFFLOAD_CONSTANTS,
@@ -462,6 +464,8 @@
Settings.Global.TEXT_CLASSIFIER_ACTION_MODEL_PARAMS,
Settings.Global.THEATER_MODE_ON,
Settings.Global.TIME_ONLY_MODE_CONSTANTS,
+ Settings.Global.TIME_REMAINING_ESTIMATE_MILLIS,
+ Settings.Global.TIME_REMAINING_ESTIMATE_BASED_ON_USAGE,
Settings.Global.TRANSITION_ANIMATION_SCALE,
Settings.Global.TRUSTED_SOUND,
Settings.Global.TZINFO_UPDATE_CONTENT_URL,
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index fb5c16b..e19ac81 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -37,7 +37,8 @@
/**
* When set to "true" the notification will be a generic confirm message instead of asking the
* user if they want to turn on battery saver. If set to false the dialog will specifically
- * talk about turning on battery saver and provide a button for taking the action.
+ * talk about battery saver without giving the option of turning it on. The only button visible
+ * will be a generic confirmation button to acknowledge the dialog.
*/
public static final String EXTRA_CONFIRM_TEXT_ONLY = "extra_confirm_only";
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt
new file mode 100644
index 0000000..ae8e1e2
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settingslib.fuelgauge
+
+import android.content.Context
+import android.provider.Settings
+import java.time.Duration
+import java.time.Instant
+
+const val AVERAGE_TIME_TO_DISCHARGE_UNKNOWN = -1
+const val ESTIMATE_MILLIS_UNKNOWN = -1
+
+class Estimate(
+ val estimateMillis: Long,
+ val isBasedOnUsage: Boolean,
+ val averageDischargeTime: Long
+) {
+ companion object {
+ /**
+ * Returns the cached estimate if it is available and fresh. Will return null if estimate is
+ * unavailable or older than 2 minutes.
+ *
+ * @param context A valid context
+ * @return An [Estimate] object with the latest battery estimates.
+ */
+ @JvmStatic
+ fun getCachedEstimateIfAvailable(context: Context): Estimate? {
+ // if time > 2 min return null or the estimate otherwise
+ val resolver = context.contentResolver
+ val lastUpdateTime = Instant.ofEpochMilli(
+ Settings.Global.getLong(
+ resolver, Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME, -1))
+ return if (Duration.between(lastUpdateTime,
+ Instant.now()).compareTo(Duration.ofMinutes(2)) > 0) {
+ null
+ } else Estimate(
+ Settings.Global.getLong(resolver,
+ Settings.Global.TIME_REMAINING_ESTIMATE_MILLIS,
+ ESTIMATE_MILLIS_UNKNOWN.toLong()),
+ Settings.Global.getInt(resolver,
+ Settings.Global.TIME_REMAINING_ESTIMATE_BASED_ON_USAGE, 0) == 1,
+ Settings.Global.getLong(resolver, Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
+ AVERAGE_TIME_TO_DISCHARGE_UNKNOWN.toLong()))
+ }
+
+ /**
+ * Stores an estimate to the cache along with a timestamp. Can be obtained via
+ * [.getCachedEstimateIfAvailable].
+ *
+ * @param context A valid context
+ * @param estimate the [Estimate] object to store
+ */
+ @JvmStatic
+ fun storeCachedEstimate(context: Context, estimate: Estimate) {
+ // store the estimate and update the timestamp
+ val resolver = context.contentResolver
+ Settings.Global.putLong(resolver, Settings.Global.TIME_REMAINING_ESTIMATE_MILLIS,
+ estimate.estimateMillis)
+ Settings.Global.putInt(resolver, Settings.Global.TIME_REMAINING_ESTIMATE_BASED_ON_USAGE,
+ if (estimate.isBasedOnUsage) 1 else 0)
+ Settings.Global.putLong(resolver, Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
+ estimate.averageDischargeTime)
+ Settings.Global.putLong(resolver, Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
+ System.currentTimeMillis())
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
index 02ad0f1..f73bc93 100644
--- a/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
+++ b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
@@ -15,6 +15,7 @@
val severeLevelThreshold: Int,
val lowLevelThreshold: Int,
val timeRemainingMillis: Long,
+ val averageTimeToDischargeMillis: Long,
val severeThresholdMillis: Long,
val lowThresholdMillis: Long,
val isBasedOnUsage: Boolean,
@@ -39,18 +40,19 @@
severeLevelThreshold: Int,
lowLevelThreshold: Int
) : this(
- batteryLevel,
- isPowerSaver,
- plugged,
- bucket,
- batteryStatus,
- severeLevelThreshold,
- lowLevelThreshold,
- NO_ESTIMATE_AVAILABLE.toLong(),
- NO_ESTIMATE_AVAILABLE.toLong(),
- NO_ESTIMATE_AVAILABLE.toLong(),
- false,
- true
+ batteryLevel,
+ isPowerSaver,
+ plugged,
+ bucket,
+ batteryStatus,
+ severeLevelThreshold,
+ lowLevelThreshold,
+ NO_ESTIMATE_AVAILABLE.toLong(),
+ NO_ESTIMATE_AVAILABLE.toLong(),
+ NO_ESTIMATE_AVAILABLE.toLong(),
+ NO_ESTIMATE_AVAILABLE.toLong(),
+ false,
+ true
) {
this.isHybrid = false
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java
index a879227..3b46478 100644
--- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java
+++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java
@@ -1,5 +1,7 @@
package com.android.systemui.power;
+import com.android.settingslib.fuelgauge.Estimate;
+
public interface EnhancedEstimates {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
index bfb809e..9b1f23a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
@@ -1,5 +1,7 @@
package com.android.systemui.power;
+import com.android.settingslib.fuelgauge.Estimate;
+
public class EnhancedEstimatesImpl implements EnhancedEstimates {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/power/Estimate.kt b/packages/SystemUI/src/com/android/systemui/power/Estimate.kt
deleted file mode 100644
index dca0d45..0000000
--- a/packages/SystemUI/src/com/android/systemui/power/Estimate.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.android.systemui.power
-
-data class Estimate(val estimateMillis: Long, val isBasedOnUsage: Boolean)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 25d6d94..b57c053 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -42,6 +42,7 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -283,6 +284,7 @@
mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
mLowBatteryReminderLevels[0], estimate.getEstimateMillis(),
+ estimate.getAverageDischargeTime(),
mEnhancedEstimates.getSevereWarningThreshold(),
mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage(),
mEnhancedEstimates.getLowWarningEnabled());
@@ -316,7 +318,8 @@
return estimate;
}
return new Estimate(mLastBatteryStateSnapshot.getTimeRemainingMillis(),
- mLastBatteryStateSnapshot.isBasedOnUsage());
+ mLastBatteryStateSnapshot.isBasedOnUsage(),
+ mLastBatteryStateSnapshot.getAverageTimeToDischargeMillis());
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 273fa55..fde1455 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -31,10 +31,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
+import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.utils.PowerUtil;
import com.android.systemui.Dependency;
import com.android.systemui.power.EnhancedEstimates;
-import com.android.systemui.power.Estimate;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 5928a07..161b409 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -40,6 +40,7 @@
import android.testing.TestableLooper.RunWithLooper;
import android.testing.TestableResources;
+import com.android.settingslib.fuelgauge.Estimate;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.power.PowerUI.WarningsUI;
@@ -358,7 +359,7 @@
@Test
public void testRefreshEstimateIfNeeded_onlyQueriesEstimateOnBatteryLevelChangeOrNull() {
mPowerUI.start();
- Estimate estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true);
+ Estimate estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true, 0);
when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
@@ -371,21 +372,21 @@
assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_HYBRID_THRESHOLD);
BatteryStateSnapshot snapshot = new BatteryStateSnapshot(
BATTERY_LEVEL_10, false, false, 0, BatteryManager.BATTERY_HEALTH_GOOD,
- 0, 0, -1, 0, 0, false, true);
+ 0, 0, -1, 0, 0, 0, false, true);
mPowerUI.mLastBatteryStateSnapshot = snapshot;
// query again since the estimate was -1
- estimate = new Estimate(BELOW_SEVERE_HYBRID_THRESHOLD, true);
+ estimate = new Estimate(BELOW_SEVERE_HYBRID_THRESHOLD, true, 0);
when(mEnhancedEstimates.getEstimate()).thenReturn(estimate);
refreshedEstimate = mPowerUI.refreshEstimateIfNeeded();
assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_SEVERE_HYBRID_THRESHOLD);
snapshot = new BatteryStateSnapshot(
BATTERY_LEVEL_10, false, false, 0, BatteryManager.BATTERY_HEALTH_GOOD, 0,
- 0, BELOW_SEVERE_HYBRID_THRESHOLD, 0, 0, false, true);
+ 0, BELOW_SEVERE_HYBRID_THRESHOLD, 0, 0, 0, false, true);
mPowerUI.mLastBatteryStateSnapshot = snapshot;
// Battery level hasn't changed, so we don't query again
- estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true);
+ estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true, 0);
when(mEnhancedEstimates.getEstimate()).thenReturn(estimate);
refreshedEstimate = mPowerUI.refreshEstimateIfNeeded();
assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_SEVERE_HYBRID_THRESHOLD);
@@ -543,13 +544,14 @@
public boolean mIsBasedOnUsage = true;
public boolean mIsHybrid = true;
public boolean mIsLowLevelWarningEnabled = true;
+ private long mAverageTimeToDischargeMillis = Duration.ofHours(24).toMillis();
public BatteryStateSnapshot get() {
if (mIsHybrid) {
return new BatteryStateSnapshot(mBatteryLevel, mIsPowerSaver, mPlugged, mBucket,
mBatteryStatus, mSevereLevelThreshold, mLowLevelThreshold,
- mTimeRemainingMillis, mSevereThresholdMillis, mLowThresholdMillis,
- mIsBasedOnUsage, mIsLowLevelWarningEnabled);
+ mTimeRemainingMillis, mAverageTimeToDischargeMillis, mSevereThresholdMillis,
+ mLowThresholdMillis, mIsBasedOnUsage, mIsLowLevelWarningEnabled);
} else {
return new BatteryStateSnapshot(mBatteryLevel, mIsPowerSaver, mPlugged, mBucket,
mBatteryStatus, mSevereLevelThreshold, mLowLevelThreshold);