From 126c032afaa523bb27dc09a45215bb3d0b0f9196 Mon Sep 17 00:00:00 2001 From: Salvador Martinez Date: Wed, 3 May 2017 18:58:27 -0700 Subject: [PATCH] Add ability to speak to provider for enhanced estimate Added code that checks if the provider for the enhanced battery drain estimate is available. If it is available we use that value instead of the one computed by BatteryStats. Test: Robotests Bug: 37753227 Change-Id: I7eae01b56f85d33eafc42ee0f18bb752779581b2 --- .../fuelgauge/PowerUsageFeatureProvider.java | 23 +++++++ .../PowerUsageFeatureProviderImpl.java | 22 +++++++ .../settings/fuelgauge/PowerUsageSummary.java | 61 ++++++++++++++++++- .../fuelgauge/PowerUsageSummaryTest.java | 25 ++++++-- 4 files changed, 125 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 8d6ba75eef3..91bb9854b3e 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -16,7 +16,10 @@ package com.android.settings.fuelgauge; +import android.content.Context; import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; import com.android.internal.os.BatterySipper; /** @@ -62,4 +65,24 @@ public interface PowerUsageFeatureProvider { * Check whether the anomaly detection is enabled */ boolean isAnomalyDetectionEnabled(); + + /** + * Returns an improved prediction for battery time remaining. + */ + long getEnhancedBatteryPrediction(Context context); + + /** + * Checks whether the toggle for enhanced battery predictions is enabled. + */ + boolean isEnhancedBatteryPredictionEnabled(Context context); + + /** + * Returns the Uri used to query for an enhanced battery prediction from a cursor loader. + */ + Uri getEnhancedBatteryPredictionUri(); + + /** + * Returns the the estimate in the cursor as a long or -1 if the cursor is null + */ + long getTimeRemainingEstimate(Cursor cursor); } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index cc29874d843..4ebe10fde9a 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -19,6 +19,8 @@ package com.android.settings.fuelgauge; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.database.Cursor; +import android.net.Uri; import android.os.Process; import com.android.internal.os.BatterySipper; import com.android.internal.util.ArrayUtils; @@ -89,4 +91,24 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider public boolean isAnomalyDetectionEnabled() { return false; } + + @Override + public long getEnhancedBatteryPrediction(Context context) { + return -1; + } + + @Override + public boolean isEnhancedBatteryPredictionEnabled(Context context) { + return false; + } + + @Override + public Uri getEnhancedBatteryPredictionUri() { + return null; + } + + @Override + public long getTimeRemainingEstimate(Cursor cursor) { + return 0; + } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index cd7b336fb6d..5d65031b2ba 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -19,11 +19,15 @@ package com.android.settings.fuelgauge; import android.app.Activity; import android.app.LoaderManager; import android.content.Context; +import android.content.CursorLoader; import android.content.Intent; import android.content.IntentFilter; import android.content.Loader; import android.content.res.TypedArray; +import android.content.res.Resources; +import android.database.Cursor; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.BatteryStats; import android.os.Build; import android.os.Bundle; @@ -38,9 +42,9 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; import android.text.TextUtils; import android.text.format.DateUtils; +import android.text.format.Formatter; import android.util.Log; import android.util.SparseArray; -import android.util.TypedValue; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -102,6 +106,7 @@ public class PowerUsageSummary extends PowerUsageBase implements @VisibleForTesting static final int ANOMALY_LOADER = 1; + private static final int BATTERY_ESTIMATE_LOADER = 2; private static final int MENU_STATS_TYPE = Menu.FIRST; @VisibleForTesting static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3; @@ -124,6 +129,9 @@ public class PowerUsageSummary extends PowerUsageBase implements PowerUsageFeatureProvider mPowerFeatureProvider; @VisibleForTesting BatteryUtils mBatteryUtils; + @VisibleForTesting + long mEnhancedEstimate = -1; + /** * SparseArray that maps uid to {@link Anomaly}, so we could find {@link Anomaly} by uid */ @@ -158,6 +166,40 @@ public class PowerUsageSummary extends PowerUsageBase implements } }; + private LoaderManager.LoaderCallbacks mBatteryPredictionLoaderCallbacks = + new LoaderManager.LoaderCallbacks() { + + @Override + public Loader onCreateLoader(int i, Bundle bundle) { + final Uri queryUri = mPowerFeatureProvider.getEnhancedBatteryPredictionUri(); + return new CursorLoader(getContext(), queryUri, null, null, null, null); + } + + @Override + public void onLoadFinished(Loader loader, Cursor cursor) { + try { + if (cursor != null && cursor.moveToFirst()) { + mEnhancedEstimate = + mPowerFeatureProvider.getTimeRemainingEstimate(cursor); + } + } finally { + cursor.close(); + } + final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000; + Intent batteryBroadcast = getContext().registerReceiver(null, + new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + BatteryInfo batteryInfo = BatteryInfo.getBatteryInfo(getContext(), + batteryBroadcast, mStatsHelper.getStats(), elapsedRealtimeUs, false); + useEnhancedEstimateIfAvailable(getContext(), batteryInfo); + updateHeaderPreference(batteryInfo); + } + + @Override + public void onLoaderReset(Loader loader) { + // do nothing + } + }; + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -175,6 +217,10 @@ public class PowerUsageSummary extends PowerUsageBase implements mAnomalySparseArray = new SparseArray<>(); initFeatureProvider(); + if (mPowerFeatureProvider != null) { + getLoaderManager().initLoader(BATTERY_ESTIMATE_LOADER, Bundle.EMPTY, + mBatteryPredictionLoaderCallbacks); + } } @Override @@ -454,6 +500,7 @@ public class PowerUsageSummary extends PowerUsageBase implements new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); BatteryInfo batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast, mStatsHelper.getStats(), elapsedRealtimeUs, false); + useEnhancedEstimateIfAvailable(context, batteryInfo); updateHeaderPreference(batteryInfo); final long runningTime = calculateRunningTimeBasedOnStatsType(); @@ -697,6 +744,18 @@ public class PowerUsageSummary extends PowerUsageBase implements } } + @VisibleForTesting + void useEnhancedEstimateIfAvailable(Context context, BatteryInfo batteryInfo) { + if (mEnhancedEstimate > 0) { + final Resources resources = context.getResources(); + batteryInfo.remainingTimeUs = mEnhancedEstimate; + String timeString = Formatter.formatShortElapsedTime(context, mEnhancedEstimate); + batteryInfo.remainingLabel = resources.getString( + com.android.settingslib.R.string.power_remaining_duration_only, + timeString); + } + } + private static List getFakeStats() { ArrayList stats = new ArrayList<>(); float use = 5; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java index bbcd4f281a1..ca45b4bfca2 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java @@ -15,12 +15,14 @@ */ package com.android.settings.fuelgauge; +import java.util.List; +import org.robolectric.RuntimeEnvironment; import android.app.LoaderManager; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.content.ContentResolver; import android.os.PowerManager; -import android.os.Process; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.SparseArray; @@ -51,14 +53,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; -import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.util.ArrayList; -import java.util.List; import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO; import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS; @@ -69,7 +68,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; @@ -146,6 +144,8 @@ public class PowerUsageSummaryTest { private SettingsActivity mSettingsActivity; @Mock private LoaderManager mLoaderManager; + @Mock + private ContentResolver mContentResolver; private List mUsageList; private Context mRealContext; @@ -489,6 +489,21 @@ public class PowerUsageSummaryTest { assertThat(mFragment.mAnomalySparseArray.get(UID_2)).containsExactly(anomaly3); } + @Test + public void testUseEnhancedEstimateIfAvailable() { + // mock out the provider + final long time = 60 * 1000 * 1000; + PowerUsageFeatureProvider provider = mFeatureFactory.getPowerUsageFeatureProvider(mContext); + mFragment.mPowerFeatureProvider = provider; + mFragment.mEnhancedEstimate = time; + + mFragment.useEnhancedEstimateIfAvailable(mRealContext, mBatteryInfo); + + // The string that gets returned always has weird whitespacing to make it fit + // so we're just going to check that it contains the correct value we care about. + assertThat(mBatteryInfo.remainingTimeUs).isEqualTo(time); + assertThat(mBatteryInfo.remainingLabel).contains("About 17 hrs"); + } @Test public void testInitAnomalyDetectionIfPossible_detectionEnabled_init() {