From 12731cce3dfa7ac40f356cc9927219a2550cb068 Mon Sep 17 00:00:00 2001 From: Salvador Martinez Date: Fri, 17 May 2019 15:36:55 -0700 Subject: [PATCH] Break infinite refresh loop in battery estimates There was an infinite loop that could occur in BatterySaverUtils what was caused by battery saver utils updating the battery estimate which then told the page to check for an estimate and then it would repeat from there. This cleans up the logic in that loop slightly to prevent it from refreshing more than is necessary. Test: atest BatteryUtilsTest Bug: 132751712 Change-Id: I918484747ecd9735315570ad608489e0f61d7578 --- .../settings/fuelgauge/BatteryUtils.java | 31 +++++++++++++------ .../settings/fuelgauge/BatteryUtilsTest.java | 14 +++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java index b293695ab82..788403ea188 100644 --- a/src/com/android/settings/fuelgauge/BatteryUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryUtils.java @@ -55,6 +55,8 @@ import com.android.settingslib.utils.ThreadUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Duration; +import java.time.Instant; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -450,16 +452,10 @@ public class BatteryUtils { SystemClock.elapsedRealtime()); final BatteryStats stats = statsHelper.getStats(); BatteryInfo batteryInfo; - Estimate estimate = null; - // Get enhanced prediction if available - if (mPowerUsageFeatureProvider != null && - mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(mContext)) { - estimate = mPowerUsageFeatureProvider.getEnhancedBatteryPrediction(mContext); - } + Estimate estimate = getEnhancedEstimate(); - if (estimate != null) { - Estimate.storeCachedEstimate(mContext, estimate); - } else { + // couldn't get estimate from cache or provider, use fallback + if (estimate == null) { estimate = new Estimate( PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)), false /* isBasedOnUsage */, @@ -474,6 +470,23 @@ public class BatteryUtils { return batteryInfo; } + @VisibleForTesting + Estimate getEnhancedEstimate() { + Estimate estimate = null; + // Get enhanced prediction if available + if (Duration.between(Estimate.getLastCacheUpdateTime(mContext), Instant.now()) + .compareTo(Duration.ofSeconds(10)) < 0) { + estimate = Estimate.getCachedEstimateIfAvailable(mContext); + } else if (mPowerUsageFeatureProvider != null && + mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(mContext)) { + estimate = mPowerUsageFeatureProvider.getEnhancedBatteryPrediction(mContext); + if (estimate != null) { + Estimate.storeCachedEstimate(mContext, estimate); + } + } + return estimate; + } + /** * Find the {@link BatterySipper} with the corresponding {@link BatterySipper.DrainType} */ diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java index a60460b8ce2..aa07e04e0c8 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java @@ -62,6 +62,7 @@ import com.android.settings.fuelgauge.batterytip.AnomalyInfo; import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowThreadUtils; +import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.fuelgauge.PowerWhitelistBackend; import org.junit.Before; @@ -728,4 +729,17 @@ public class BatteryUtilsTest { //Should not crash assertThat(mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG)).isNotNull(); } + + @Test + public void getEnhancedEstimate_doesNotUpdateCache_ifEstimateFresh() { + Estimate estimate = new Estimate(1000, true, 1000); + Estimate.storeCachedEstimate(mContext, estimate); + + estimate = mBatteryUtils.getEnhancedEstimate(); + + // only pass if estimate has not changed + assertThat(estimate).isNotNull(); + assertThat(estimate.isBasedOnUsage()).isTrue(); + assertThat(estimate.getAverageDischargeTime()).isEqualTo(1000); + } }