From 820bee81d682518fb52fee54d3a0549f5c897b09 Mon Sep 17 00:00:00 2001 From: Dmitri Plotnikov Date: Fri, 19 Feb 2021 14:34:01 -0800 Subject: [PATCH] Transition BatteryInfo and BatteryUtils to BatteryUsageStats API Bug: 173745486 Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.BatteryHistoryPreferenceTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.BatteryInfoLoaderTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.BatteryInfoTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.BatteryUtilsTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.batterytip.detectors Change-Id: I469ff8b88aa3307422c02f51943df4ef1759db56 --- .../AppBatteryPreferenceController.java | 2 +- .../fuelgauge/BatteryHistoryPreference.java | 7 +- .../settings/fuelgauge/BatteryInfo.java | 155 +++++++++--------- .../settings/fuelgauge/BatteryInfoLoader.java | 12 +- .../fuelgauge/BatteryUsageStatsLoader.java | 11 +- .../settings/fuelgauge/BatteryUtils.java | 21 ++- .../fuelgauge/DebugEstimatesLoader.java | 10 +- .../fuelgauge/PowerUsageAdvanced.java | 5 + .../settings/fuelgauge/PowerUsageBase.java | 74 +++++++-- .../settings/fuelgauge/PowerUsageSummary.java | 7 +- .../batterytip/BatteryTipLoader.java | 5 +- .../detectors/HighUsageDetector.java | 8 +- .../fuelgauge/BatteryInfoLoaderTest.java | 27 +-- .../settings/fuelgauge/BatteryInfoTest.java | 91 +++++----- .../settings/fuelgauge/BatteryUtilsTest.java | 7 +- .../fuelgauge/PowerUsageBaseTest.java | 5 + .../batterytip/BatteryTipLoaderTest.java | 2 +- .../detectors/HighUsageDetectorTest.java | 27 ++- 18 files changed, 296 insertions(+), 180 deletions(-) diff --git a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java index 83b42410fad..307ceb1e0a2 100644 --- a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java @@ -230,7 +230,7 @@ public class AppBatteryPreferenceController extends BasePreferenceController @Override @NonNull public Loader onCreateLoader(int id, Bundle args) { - return new BatteryUsageStatsLoader(mContext); + return new BatteryUsageStatsLoader(mContext, /* includeBatteryHistory */ false); } @Override diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java index faca9fbcb67..4d3b9cd2e56 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java +++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java @@ -17,15 +17,16 @@ package com.android.settings.fuelgauge; import android.content.Context; +import android.os.BatteryUsageStats; import android.util.AttributeSet; import android.view.View; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; -import com.android.internal.os.BatteryStatsHelper; import com.android.settings.R; import com.android.settings.widget.UsageView; @@ -50,11 +51,11 @@ public class BatteryHistoryPreference extends Preference { setSelectable(false); } - public void setStats(BatteryStatsHelper batteryStats) { + void setBatteryUsageStats(@NonNull BatteryUsageStats batteryUsageStats) { BatteryInfo.getBatteryInfo(getContext(), info -> { mBatteryInfo = info; notifyChanged(); - }, batteryStats, false); + }, batteryUsageStats, false); } public void setBottomSummary(CharSequence text) { diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java index 5d7b3258717..a4dd86c1fa7 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfo.java +++ b/src/com/android/settings/fuelgauge/BatteryInfo.java @@ -20,16 +20,18 @@ import android.content.IntentFilter; import android.content.res.Resources; import android.os.AsyncTask; import android.os.BatteryManager; -import android.os.BatteryStats; import android.os.BatteryStats.HistoryItem; -import android.os.Bundle; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; import android.os.SystemClock; import android.text.format.Formatter; import android.util.SparseIntArray; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import com.android.internal.os.BatteryStatsHelper; +import com.android.internal.os.BatteryStatsHistoryIterator; import com.android.settings.Utils; import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.UsageView; @@ -52,7 +54,7 @@ public class BatteryInfo { public String statusLabel; public String suggestionLabel; private boolean mCharging; - private BatteryStats mStats; + private BatteryUsageStats mBatteryUsageStats; private static final String LOG_TAG = "BatteryInfo"; private long timePeriod; @@ -126,7 +128,7 @@ public class BatteryInfo { parserList[i] = parsers[i]; } parserList[parsers.length] = parser; - parse(mStats, parserList); + parseBatteryHistory(parserList); String timeString = context.getString(R.string.charge_length_format, Formatter.formatShortElapsedTime(context, timePeriod)); String remaining = ""; @@ -137,22 +139,25 @@ public class BatteryInfo { view.setBottomLabels(new CharSequence[]{timeString, remaining}); } - public static void getBatteryInfo(final Context context, final Callback callback) { - BatteryInfo.getBatteryInfo(context, callback, null /* statsHelper */, - false /* shortString */); - } - public static void getBatteryInfo(final Context context, final Callback callback, boolean shortString) { - BatteryInfo.getBatteryInfo(context, callback, null /* statsHelper */, shortString); + BatteryInfo.getBatteryInfo(context, callback, /* batteryUsageStats */ null, shortString); } public static void getBatteryInfo(final Context context, final Callback callback, - final BatteryStatsHelper statsHelper, boolean shortString) { + @Nullable final BatteryUsageStats batteryUsageStats, + boolean shortString) { new AsyncTask() { @Override protected BatteryInfo doInBackground(Void... params) { - return getBatteryInfo(context, statsHelper, shortString); + BatteryUsageStats stats; + if (batteryUsageStats != null) { + stats = batteryUsageStats; + } else { + stats = context.getSystemService(BatteryStatsManager.class) + .getBatteryUsageStats(); + } + return getBatteryInfo(context, stats, shortString); } @Override @@ -164,18 +169,13 @@ public class BatteryInfo { }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + /** + * Creates a BatteryInfo based on BatteryUsageStats + */ + @WorkerThread public static BatteryInfo getBatteryInfo(final Context context, - final BatteryStatsHelper statsHelper, boolean shortString) { - final BatteryStats stats; + @NonNull final BatteryUsageStats batteryUsageStats, boolean shortString) { final long batteryStatsTime = System.currentTimeMillis(); - if (statsHelper == null) { - final BatteryStatsHelper localStatsHelper = new BatteryStatsHelper(context, - true); - localStatsHelper.create((Bundle) null); - stats = localStatsHelper.getStats(); - } else { - stats = statsHelper.getStats(); - } BatteryUtils.logRuntime(LOG_TAG, "time for getStats", batteryStatsTime); final long startTime = System.currentTimeMillis(); @@ -197,38 +197,38 @@ public class BatteryInfo { Estimate.storeCachedEstimate(context, estimate); BatteryUtils .logRuntime(LOG_TAG, "time for enhanced BatteryInfo", startTime); - return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats, + return BatteryInfo.getBatteryInfo(context, batteryBroadcast, batteryUsageStats, estimate, elapsedRealtimeUs, shortString); } } - final long prediction = discharging - ? stats.computeBatteryTimeRemaining(elapsedRealtimeUs) : 0; + final long prediction = discharging ? batteryUsageStats.getBatteryTimeRemainingMs() : 0; final Estimate estimate = new Estimate( PowerUtil.convertUsToMs(prediction), false, /* isBasedOnUsage */ EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN); BatteryUtils.logRuntime(LOG_TAG, "time for regular BatteryInfo", startTime); - return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats, + return BatteryInfo.getBatteryInfo(context, batteryBroadcast, batteryUsageStats, estimate, elapsedRealtimeUs, shortString); } @WorkerThread public static BatteryInfo getBatteryInfoOld(Context context, Intent batteryBroadcast, - BatteryStats stats, long elapsedRealtimeUs, boolean shortString) { + BatteryUsageStats batteryUsageStats, long elapsedRealtimeUs, boolean shortString) { Estimate estimate = new Estimate( - PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)), + batteryUsageStats.getBatteryTimeRemainingMs(), false, EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN); - return getBatteryInfo(context, batteryBroadcast, stats, estimate, elapsedRealtimeUs, - shortString); + return getBatteryInfo(context, batteryBroadcast, batteryUsageStats, estimate, + elapsedRealtimeUs, shortString); } @WorkerThread public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast, - BatteryStats stats, Estimate estimate, long elapsedRealtimeUs, boolean shortString) { + @NonNull BatteryUsageStats batteryUsageStats, Estimate estimate, + long elapsedRealtimeUs, boolean shortString) { final long startTime = System.currentTimeMillis(); BatteryInfo info = new BatteryInfo(); - info.mStats = stats; + info.mBatteryUsageStats = batteryUsageStats; info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast); info.batteryPercentString = Utils.formatPercentage(info.batteryLevel); info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; @@ -241,16 +241,17 @@ public class BatteryInfo { if (!info.mCharging) { updateBatteryInfoDischarging(context, shortString, estimate, info); } else { - updateBatteryInfoCharging(context, batteryBroadcast, stats, elapsedRealtimeUs, info); + updateBatteryInfoCharging(context, batteryBroadcast, batteryUsageStats, + info); } BatteryUtils.logRuntime(LOG_TAG, "time for getBatteryInfo", startTime); return info; } private static void updateBatteryInfoCharging(Context context, Intent batteryBroadcast, - BatteryStats stats, long elapsedRealtimeUs, BatteryInfo info) { + BatteryUsageStats stats, BatteryInfo info) { final Resources resources = context.getResources(); - final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs); + final long chargeTimeMs = stats.getChargeTimeRemainingMs(); final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN); info.discharging = false; @@ -260,8 +261,8 @@ public class BatteryInfo { int chargingLimitedResId = R.string.power_charging_limited; info.chargeLabel = context.getString(chargingLimitedResId, info.batteryPercentString); - } else if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) { - info.remainingTimeUs = chargeTime; + } else if (chargeTimeMs > 0 && status != BatteryManager.BATTERY_STATUS_FULL) { + info.remainingTimeUs = PowerUtil.convertMsToUs(chargeTimeMs); CharSequence timeString = StringUtil.formatElapsedTime(context, PowerUtil.convertUsToMs(info.remainingTimeUs), false /* withSeconds */); int resId = R.string.power_charging_duration; @@ -313,7 +314,11 @@ public class BatteryInfo { void onParsingDone(); } - public static void parse(BatteryStats stats, BatteryDataParser... parsers) { + /** + * Iterates over battery history included in the BatteryUsageStats that this object + * was initialized with. + */ + public void parseBatteryHistory(BatteryDataParser... parsers) { long startWalltime = 0; long endWalltime = 0; long historyStart = 0; @@ -324,41 +329,41 @@ public class BatteryInfo { int lastInteresting = 0; int pos = 0; boolean first = true; - if (stats.startIteratingHistoryLocked()) { - final HistoryItem rec = new HistoryItem(); - while (stats.getNextHistoryLocked(rec)) { - pos++; - if (first) { - first = false; - historyStart = rec.time; + final BatteryStatsHistoryIterator iterator1 = + mBatteryUsageStats.iterateBatteryStatsHistory(); + final HistoryItem rec = new HistoryItem(); + while (iterator1.next(rec)) { + pos++; + if (first) { + first = false; + historyStart = rec.time; + } + if (rec.cmd == HistoryItem.CMD_CURRENT_TIME + || rec.cmd == HistoryItem.CMD_RESET) { + // If there is a ridiculously large jump in time, then we won't be + // able to create a good chart with that data, so just ignore the + // times we got before and pretend like our data extends back from + // the time we have now. + // Also, if we are getting a time change and we are less than 5 minutes + // since the start of the history real time, then also use this new + // time to compute the base time, since whatever time we had before is + // pretty much just noise. + if (rec.currentTime > (lastWallTime + (180 * 24 * 60 * 60 * 1000L)) + || rec.time < (historyStart + (5 * 60 * 1000L))) { + startWalltime = 0; } - if (rec.cmd == HistoryItem.CMD_CURRENT_TIME - || rec.cmd == HistoryItem.CMD_RESET) { - // If there is a ridiculously large jump in time, then we won't be - // able to create a good chart with that data, so just ignore the - // times we got before and pretend like our data extends back from - // the time we have now. - // Also, if we are getting a time change and we are less than 5 minutes - // since the start of the history real time, then also use this new - // time to compute the base time, since whatever time we had before is - // pretty much just noise. - if (rec.currentTime > (lastWallTime + (180 * 24 * 60 * 60 * 1000L)) - || rec.time < (historyStart + (5 * 60 * 1000L))) { - startWalltime = 0; - } - lastWallTime = rec.currentTime; - lastRealtime = rec.time; - if (startWalltime == 0) { - startWalltime = lastWallTime - (lastRealtime - historyStart); - } - } - if (rec.isDeltaData()) { - lastInteresting = pos; - historyEnd = rec.time; + lastWallTime = rec.currentTime; + lastRealtime = rec.time; + if (startWalltime == 0) { + startWalltime = lastWallTime - (lastRealtime - historyStart); } } + if (rec.isDeltaData()) { + lastInteresting = pos; + historyEnd = rec.time; + } } - stats.finishIteratingHistoryLocked(); + endWalltime = lastWallTime + historyEnd - lastRealtime; int i = 0; @@ -367,9 +372,11 @@ public class BatteryInfo { for (int j = 0; j < parsers.length; j++) { parsers[j].onParsingStarted(startWalltime, endWalltime); } - if (endWalltime > startWalltime && stats.startIteratingHistoryLocked()) { - final HistoryItem rec = new HistoryItem(); - while (stats.getNextHistoryLocked(rec) && i < N) { + + if (endWalltime > startWalltime) { + final BatteryStatsHistoryIterator iterator2 = + mBatteryUsageStats.iterateBatteryStatsHistory(); + while (iterator2.next(rec) && i < N) { if (rec.isDeltaData()) { curWalltime += rec.time - lastRealtime; lastRealtime = rec.time; @@ -404,8 +411,6 @@ public class BatteryInfo { } } - stats.finishIteratingHistoryLocked(); - for (int j = 0; j < parsers.length; j++) { parsers[j].onParsingDone(); } diff --git a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java index cd87612ea7b..ffee4627f70 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java +++ b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java @@ -19,7 +19,6 @@ import android.content.Context; import androidx.annotation.VisibleForTesting; -import com.android.internal.os.BatteryStatsHelper; import com.android.settingslib.utils.AsyncLoaderCompat; /** @@ -28,17 +27,14 @@ import com.android.settingslib.utils.AsyncLoaderCompat; * when not available. */ public class BatteryInfoLoader extends AsyncLoaderCompat{ - - BatteryStatsHelper mStatsHelper; private static final String LOG_TAG = "BatteryInfoLoader"; @VisibleForTesting - BatteryUtils batteryUtils; + BatteryUtils mBatteryUtils; - public BatteryInfoLoader(Context context, BatteryStatsHelper batteryStatsHelper) { + public BatteryInfoLoader(Context context) { super(context); - mStatsHelper = batteryStatsHelper; - batteryUtils = BatteryUtils.getInstance(context); + mBatteryUtils = BatteryUtils.getInstance(context); } @Override @@ -48,6 +44,6 @@ public class BatteryInfoLoader extends AsyncLoaderCompat{ @Override public BatteryInfo loadInBackground() { - return batteryUtils.getBatteryInfo(mStatsHelper, LOG_TAG); + return mBatteryUtils.getBatteryInfo(LOG_TAG); } } diff --git a/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java b/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java index 5b184a9cd52..d35ef82b818 100644 --- a/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java +++ b/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java @@ -19,6 +19,7 @@ package com.android.settings.fuelgauge; import android.content.Context; import android.os.BatteryStatsManager; import android.os.BatteryUsageStats; +import android.os.BatteryUsageStatsQuery; import com.android.settingslib.utils.AsyncLoaderCompat; @@ -27,15 +28,21 @@ import com.android.settingslib.utils.AsyncLoaderCompat; */ public class BatteryUsageStatsLoader extends AsyncLoaderCompat { private final BatteryStatsManager mBatteryStatsManager; + private final boolean mIncludeBatteryHistory; - public BatteryUsageStatsLoader(Context context) { + public BatteryUsageStatsLoader(Context context, boolean includeBatteryHistory) { super(context); mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class); + mIncludeBatteryHistory = includeBatteryHistory; } @Override public BatteryUsageStats loadInBackground() { - return mBatteryStatsManager.getBatteryUsageStats(); + final BatteryUsageStatsQuery.Builder builder = new BatteryUsageStatsQuery.Builder(); + if (mIncludeBatteryHistory) { + builder.includeBatteryHistory(); + } + return mBatteryStatsManager.getBatteryUsageStats(builder.build()); } @Override diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java index 5b1f096d2e7..8c0ab46a347 100644 --- a/src/com/android/settings/fuelgauge/BatteryUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryUtils.java @@ -24,6 +24,9 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.BatteryStats; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; +import android.os.BatteryUsageStatsQuery; import android.os.Build; import android.os.Bundle; import android.os.Process; @@ -103,7 +106,7 @@ public class BatteryUtils { } @VisibleForTesting - BatteryUtils(Context context) { + public BatteryUtils(Context context) { mContext = context; mPackageManager = context.getPackageManager(); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); @@ -472,29 +475,35 @@ public class BatteryUtils { } @WorkerThread - public BatteryInfo getBatteryInfo(final BatteryStatsHelper statsHelper, final String tag) { + public BatteryInfo getBatteryInfo(final String tag) { + final BatteryStatsManager systemService = mContext.getSystemService( + BatteryStatsManager.class); + final BatteryUsageStats batteryUsageStats = systemService.getBatteryUsageStats( + new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build()); + final long startTime = System.currentTimeMillis(); // Stuff we always need to get BatteryInfo final Intent batteryBroadcast = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + final long elapsedRealtimeUs = PowerUtil.convertMsToUs( SystemClock.elapsedRealtime()); - final BatteryStats stats = statsHelper.getStats(); + BatteryInfo batteryInfo; Estimate estimate = getEnhancedEstimate(); // couldn't get estimate from cache or provider, use fallback if (estimate == null) { estimate = new Estimate( - PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)), + PowerUtil.convertUsToMs(batteryUsageStats.getBatteryTimeRemainingMs()), false /* isBasedOnUsage */, EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN); } BatteryUtils.logRuntime(tag, "BatteryInfoLoader post query", startTime); - batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast, stats, - estimate, elapsedRealtimeUs, false /* shortString */); + batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast, + batteryUsageStats, estimate, elapsedRealtimeUs, false /* shortString */); BatteryUtils.logRuntime(tag, "BatteryInfoLoader.loadInBackground", startTime); return batteryInfo; diff --git a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java index c8dbb59a4bb..0623bcb814d 100644 --- a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java +++ b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java @@ -19,6 +19,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryStats; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; import android.os.SystemClock; import com.android.internal.os.BatteryStatsHelper; @@ -56,15 +58,17 @@ public class DebugEstimatesLoader extends AsyncLoaderCompat> { Intent batteryBroadcast = getContext().registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); BatteryStats stats = mStatsHelper.getStats(); - + BatteryUsageStats batteryUsageStats = + context.getSystemService(BatteryStatsManager.class).getBatteryUsageStats(); BatteryInfo oldinfo = BatteryInfo.getBatteryInfoOld(getContext(), batteryBroadcast, - stats, elapsedRealtimeUs, false); + batteryUsageStats, elapsedRealtimeUs, false); Estimate estimate = powerUsageFeatureProvider.getEnhancedBatteryPrediction(context); if (estimate == null) { estimate = new Estimate(0, false, EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN); } - BatteryInfo newInfo = BatteryInfo.getBatteryInfo(getContext(), batteryBroadcast, stats, + BatteryInfo newInfo = BatteryInfo.getBatteryInfo(getContext(), batteryBroadcast, + batteryUsageStats, estimate, elapsedRealtimeUs, false); List infos = new ArrayList<>(); diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java index befede46b9b..86e52d9555f 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java +++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java @@ -141,6 +141,11 @@ public class PowerUsageAdvanced extends PowerUsageBase { return controllers; } + @Override + protected boolean isBatteryHistoryNeeded() { + return true; + } + @Override protected void refreshUi(@BatteryUpdateType int refreshType) { final Context context = getContext(); diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java index 3a5ed6cd3af..29ecedc2f10 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageBase.java +++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java @@ -19,10 +19,12 @@ import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpd import android.app.Activity; import android.content.Context; +import android.os.BatteryUsageStats; import android.os.Bundle; import android.os.UserManager; import android.view.Menu; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; @@ -40,12 +42,29 @@ public abstract class PowerUsageBase extends DashboardFragment { static final int MENU_STATS_REFRESH = Menu.FIRST + 1; private static final String TAG = "PowerUsageBase"; private static final String KEY_REFRESH_TYPE = "refresh_type"; + private static final String KEY_INCLUDE_HISTORY = "include_history"; + + private static final int LOADER_BATTERY_STATS_HELPER = 0; + private static final int LOADER_BATTERY_USAGE_STATS = 1; protected BatteryStatsHelper mStatsHelper; + @VisibleForTesting + BatteryUsageStats mBatteryUsageStats; + protected UserManager mUm; private BatteryBroadcastReceiver mBatteryBroadcastReceiver; protected boolean mIsBatteryPresent = true; + // TODO(b/180630447): switch to BatteryUsageStatsLoader and remove all references to + // BatteryStatsHelper and BatterySipper + @VisibleForTesting + final BatteryStatsHelperLoaderCallbacks mBatteryStatsHelperLoaderCallbacks = + new BatteryStatsHelperLoaderCallbacks(); + + @VisibleForTesting + final BatteryUsageStatsLoaderCallbacks mBatteryUsageStatsLoaderCallbacks = + new BatteryUsageStatsLoaderCallbacks(); + @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -83,42 +102,73 @@ public abstract class PowerUsageBase extends DashboardFragment { protected void restartBatteryStatsLoader(int refreshType) { final Bundle bundle = new Bundle(); bundle.putInt(KEY_REFRESH_TYPE, refreshType); + bundle.putBoolean(KEY_INCLUDE_HISTORY, isBatteryHistoryNeeded()); + getLoaderManager().restartLoader(LOADER_BATTERY_STATS_HELPER, bundle, + mBatteryStatsHelperLoaderCallbacks); + getLoaderManager().restartLoader(LOADER_BATTERY_USAGE_STATS, bundle, + mBatteryUsageStatsLoaderCallbacks); + } - getLoaderManager().restartLoader(0, bundle, new PowerLoaderCallback()); + private void onLoadFinished(@BatteryUpdateType int refreshType) { + // Wait for both loaders to finish before proceeding. + if (mStatsHelper == null || mBatteryUsageStats == null) { + return; + } + + refreshUi(refreshType); } protected abstract void refreshUi(@BatteryUpdateType int refreshType); + protected abstract boolean isBatteryHistoryNeeded(); protected void updatePreference(BatteryHistoryPreference historyPref) { final long startTime = System.currentTimeMillis(); - historyPref.setStats(mStatsHelper); + historyPref.setBatteryUsageStats(mBatteryUsageStats); BatteryUtils.logRuntime(TAG, "updatePreference", startTime); } - /** - * {@link android.app.LoaderManager.LoaderCallbacks} for {@link PowerUsageBase} to load - * the {@link BatteryStatsHelper} - */ - public class PowerLoaderCallback implements LoaderManager.LoaderCallbacks { + private class BatteryStatsHelperLoaderCallbacks + implements LoaderManager.LoaderCallbacks { private int mRefreshType; @Override - public Loader onCreateLoader(int id, - Bundle args) { + public Loader onCreateLoader(int id, Bundle args) { mRefreshType = args.getInt(KEY_REFRESH_TYPE); return new BatteryStatsHelperLoader(getContext()); } @Override public void onLoadFinished(Loader loader, - BatteryStatsHelper statsHelper) { - mStatsHelper = statsHelper; - refreshUi(mRefreshType); + BatteryStatsHelper batteryHelper) { + mStatsHelper = batteryHelper; + PowerUsageBase.this.onLoadFinished(mRefreshType); } @Override public void onLoaderReset(Loader loader) { + } + } + private class BatteryUsageStatsLoaderCallbacks + implements LoaderManager.LoaderCallbacks { + private int mRefreshType; + + @Override + @NonNull + public Loader onCreateLoader(int id, Bundle args) { + mRefreshType = args.getInt(KEY_REFRESH_TYPE); + return new BatteryUsageStatsLoader(getContext(), args.getBoolean(KEY_INCLUDE_HISTORY)); + } + + @Override + public void onLoadFinished(Loader loader, + BatteryUsageStats batteryUsageStats) { + mBatteryUsageStats = batteryUsageStats; + PowerUsageBase.this.onLoadFinished(mRefreshType); + } + + @Override + public void onLoaderReset(Loader loader) { } } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index c00c1313e82..4f8ac628092 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -88,7 +88,7 @@ public class PowerUsageSummary extends PowerUsageBase implements @Override public Loader onCreateLoader(int i, Bundle bundle) { - return new BatteryInfoLoader(getContext(), mStatsHelper); + return new BatteryInfoLoader(getContext()); } @Override @@ -190,6 +190,11 @@ public class PowerUsageSummary extends PowerUsageBase implements return R.string.help_url_battery; } + @Override + protected boolean isBatteryHistoryNeeded() { + return false; + } + protected void refreshUi(@BatteryUpdateType int refreshType) { final Context context = getContext(); if (context == null) { diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java index 0c916b2d4a9..9b80a1f4029 100644 --- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java +++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java @@ -65,12 +65,11 @@ public class BatteryTipLoader extends AsyncLoaderCompat> { } final List tips = new ArrayList<>(); final BatteryTipPolicy policy = new BatteryTipPolicy(getContext()); - final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG); + final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(TAG); final Context context = getContext(); tips.add(new LowBatteryDetector(context, policy, batteryInfo).detect()); - tips.add(new HighUsageDetector(context, policy, mBatteryStatsHelper, - batteryInfo.discharging).detect()); + tips.add(new HighUsageDetector(context, policy, mBatteryStatsHelper, batteryInfo).detect()); tips.add(new SmartBatteryDetector(policy, context.getContentResolver()).detect()); tips.add(new EarlyWarningDetector(policy, context).detect()); tips.add(new BatteryDefenderDetector(batteryInfo).detect()); diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java index 067046ca852..928ae52532c 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java @@ -45,6 +45,7 @@ import java.util.concurrent.TimeUnit; public class HighUsageDetector implements BatteryTipDetector { private BatteryTipPolicy mPolicy; private BatteryStatsHelper mBatteryStatsHelper; + private final BatteryInfo mBatteryInfo; private List mHighUsageAppList; @VisibleForTesting HighUsageDataParser mDataParser; @@ -54,14 +55,15 @@ public class HighUsageDetector implements BatteryTipDetector { boolean mDischarging; public HighUsageDetector(Context context, BatteryTipPolicy policy, - BatteryStatsHelper batteryStatsHelper, boolean discharging) { + BatteryStatsHelper batteryStatsHelper, BatteryInfo batteryInfo) { mPolicy = policy; mBatteryStatsHelper = batteryStatsHelper; + mBatteryInfo = batteryInfo; mHighUsageAppList = new ArrayList<>(); mBatteryUtils = BatteryUtils.getInstance(context); mDataParser = new HighUsageDataParser(mPolicy.highUsagePeriodMs, mPolicy.highUsageBatteryDraining); - mDischarging = discharging; + mDischarging = batteryInfo.discharging; } @Override @@ -115,6 +117,6 @@ public class HighUsageDetector implements BatteryTipDetector { @VisibleForTesting void parseBatteryData() { - BatteryInfo.parse(mBatteryStatsHelper.getStats(), mDataParser); + mBatteryInfo.parseBatteryHistory(mDataParser); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoLoaderTest.java index 6593767a44d..5bcaf0a5cce 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoLoaderTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoLoaderTest.java @@ -19,23 +19,23 @@ package com.android.settings.fuelgauge; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; import android.content.Intent; -import android.os.BatteryStats; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; +import android.os.BatteryUsageStatsQuery; -import com.android.internal.os.BatteryStatsHelper; import com.android.settings.testutils.BatteryTestUtils; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -46,10 +46,10 @@ public class BatteryInfoLoaderTest { private static final long TEST_TIME_REMAINING = 1000L; - @Mock (answer = Answers.RETURNS_DEEP_STUBS) - private BatteryStatsHelper mHelper; - @Mock (answer = Answers.RETURNS_DEEP_STUBS) - private BatteryStats mStats; + @Mock + private BatteryStatsManager mBatteryStatsManager; + @Mock + private BatteryUsageStats mBatteryUsageStats; private Context mContext; @@ -60,8 +60,11 @@ public class BatteryInfoLoaderTest { FakeFeatureFactory.setupForTest().getPowerUsageFeatureProvider(mContext); doReturn(mContext).when(mContext).getApplicationContext(); - when(mStats.computeBatteryTimeRemaining(anyLong())).thenReturn(TEST_TIME_REMAINING); - doReturn(mStats).when(mHelper).getStats(); + when(mContext.getSystemService(eq(Context.BATTERY_STATS_SERVICE))) + .thenReturn(mBatteryStatsManager); + when(mBatteryUsageStats.getBatteryTimeRemainingMs()).thenReturn(TEST_TIME_REMAINING); + when(mBatteryStatsManager.getBatteryUsageStats(any(BatteryUsageStatsQuery.class))) + .thenReturn(mBatteryUsageStats); final Intent dischargingBatteryBroadcast = BatteryTestUtils.getDischargingIntent(); doReturn(dischargingBatteryBroadcast).when(mContext).registerReceiver(any(), any()); @@ -69,8 +72,8 @@ public class BatteryInfoLoaderTest { @Test public void test_loadInBackground_dischargingOldEstimate_dischargingLabelNotNull() { - BatteryInfoLoader loader = new BatteryInfoLoader(mContext, mHelper); - loader.batteryUtils = new BatteryUtils(mContext); + BatteryInfoLoader loader = new BatteryInfoLoader(mContext); + loader.mBatteryUtils = new BatteryUtils(mContext); BatteryInfo info = loader.loadInBackground(); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java index 4c19477d7a9..18c53266438 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java @@ -34,9 +34,11 @@ import android.content.Context; import android.content.Intent; import android.os.BatteryManager; import android.os.BatteryStats; +import android.os.BatteryUsageStats; import android.os.SystemClock; import android.util.SparseIntArray; +import com.android.internal.os.BatteryStatsHistoryIterator; import com.android.settings.testutils.BatteryTestUtils; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.widget.UsageView; @@ -46,7 +48,6 @@ import com.android.settingslib.fuelgauge.Estimate; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -83,9 +84,8 @@ public class BatteryInfoTest { private Intent mChargingBatteryBroadcast; private Context mContext; private FakeFeatureFactory mFeatureFactory; - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private BatteryStats mBatteryStats; + @Mock + private BatteryUsageStats mBatteryUsageStats; @Before public void setUp() { @@ -100,9 +100,10 @@ public class BatteryInfoTest { @Test public void testGetBatteryInfo_hasStatusLabel() { - doReturn(REMAINING_TIME_NULL).when(mBatteryStats).computeBatteryTimeRemaining(anyLong()); + doReturn(REMAINING_TIME_NULL).when(mBatteryUsageStats).getBatteryTimeRemainingMs(); BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, - mDisChargingBatteryBroadcast, mBatteryStats, SystemClock.elapsedRealtime() * 1000, + mDisChargingBatteryBroadcast, mBatteryUsageStats, + SystemClock.elapsedRealtime() * 1000, true /* shortString */); assertThat(info.statusLabel).isEqualTo(STATUS_NOT_CHARGING); @@ -110,28 +111,28 @@ public class BatteryInfoTest { @Test public void testGetBatteryInfo_doNotShowChargingMethod_hasRemainingTime() { - doReturn(REMAINING_TIME).when(mBatteryStats).computeChargeTimeRemaining(anyLong()); + doReturn(REMAINING_TIME).when(mBatteryUsageStats).getChargeTimeRemainingMs(); BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, mChargingBatteryBroadcast, - mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */); + mBatteryUsageStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */); assertThat(info.chargeLabel.toString()).isEqualTo(STATUS_CHARGING_TIME); } @Test public void testGetBatteryInfo_doNotShowChargingMethod_noRemainingTime() { - doReturn(REMAINING_TIME_NULL).when(mBatteryStats).computeChargeTimeRemaining(anyLong()); + doReturn(REMAINING_TIME_NULL).when(mBatteryUsageStats).getChargeTimeRemainingMs(); BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, mChargingBatteryBroadcast, - mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */); + mBatteryUsageStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */); assertThat(info.chargeLabel.toString()).isEqualTo(STATUS_CHARGING_NO_TIME); } @Test public void testGetBatteryInfo_pluggedInUsingShortString_usesCorrectData() { - doReturn(TEST_CHARGE_TIME_REMAINING).when(mBatteryStats).computeChargeTimeRemaining( - anyLong()); + doReturn(TEST_CHARGE_TIME_REMAINING / 1000) + .when(mBatteryUsageStats).getChargeTimeRemainingMs(); BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, mChargingBatteryBroadcast, - mBatteryStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */); + mBatteryUsageStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */); assertThat(info.discharging).isEqualTo(false); assertThat(info.chargeLabel.toString()).isEqualTo("50% - 1 min until charged"); @@ -143,10 +144,10 @@ public class BatteryInfoTest { true /* isBasedOnUsage */, 1000 /* averageDischargeTime */); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000, false /* shortString */); BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000, true /* shortString */); // We only add special mention for the long string @@ -163,10 +164,10 @@ public class BatteryInfoTest { true /* isBasedOnUsage */, 1000 /* averageDischargeTime */); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000, false /* shortString */); BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000, true /* shortString */); // These should be identical in either case @@ -183,7 +184,7 @@ public class BatteryInfoTest { true /* isBasedOnUsage */, 1000 /* averageDischargeTime */); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000, false /* shortString */); assertThat(info.suggestionLabel).doesNotContain(BATTERY_RUN_OUT_PREFIX); @@ -196,7 +197,7 @@ public class BatteryInfoTest { true /* isBasedOnUsage */, 1000 /* averageDischargeTime */); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000, false /* shortString */); // Check that strings are showing less than 15 minutes remaining regardless of exact time. @@ -211,10 +212,10 @@ public class BatteryInfoTest { @Test public void testGetBatteryInfo_basedOnUsageFalse_usesDefaultString() { BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, false /* shortString */); BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast, - mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, true /* shortString */); assertThat(info.remainingLabel.toString()).doesNotContain(ENHANCED_STRING_SUFFIX); @@ -223,12 +224,11 @@ public class BatteryInfoTest { @Test public void testGetBatteryInfo_charging_usesChargeTime() { - doReturn(TEST_CHARGE_TIME_REMAINING) - .when(mBatteryStats) - .computeChargeTimeRemaining(anyLong()); + doReturn(TEST_CHARGE_TIME_REMAINING / 1000) + .when(mBatteryUsageStats).getChargeTimeRemainingMs(); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast, - mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, false /* shortString */); assertThat(info.remainingTimeUs).isEqualTo(TEST_CHARGE_TIME_REMAINING); assertThat(info.remainingLabel.toString()) @@ -240,7 +240,7 @@ public class BatteryInfoTest { mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_LEVEL, 100); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast, - mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, false /* shortString */); assertThat(info.chargeLabel).isEqualTo("100%"); @@ -249,13 +249,13 @@ public class BatteryInfoTest { @Test public void testGetBatteryInfo_chargingWithOverheated_updateChargeLabel() { doReturn(TEST_CHARGE_TIME_REMAINING) - .when(mBatteryStats) - .computeChargeTimeRemaining(anyLong()); + .when(mBatteryUsageStats) + .getChargeTimeRemainingMs(); mChargingBatteryBroadcast .putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast, - mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, + mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000, false /* shortString */); assertThat(info.isOverheated).isTrue(); @@ -264,28 +264,29 @@ public class BatteryInfoTest { // Make our battery stats return a sequence of battery events. private void mockBatteryStatsHistory() { - // Mock out new data every time start...Locked is called. + // Mock out new data every time iterateBatteryStatsHistory is called. doAnswer(invocation -> { - doAnswer(new Answer() { - private int count = 0; - private long[] times = {1000, 1500, 2000}; - private byte[] levels = {99, 98, 97}; + BatteryStatsHistoryIterator iterator = mock(BatteryStatsHistoryIterator.class); + doAnswer(new Answer() { + private int mCount = 0; + private final long[] mTimes = {1000, 1500, 2000}; + private final byte[] mLevels = {99, 98, 97}; @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - if (count == times.length) { + public Boolean answer(InvocationOnMock invocation) throws Throwable { + if (mCount == mTimes.length) { return false; } BatteryStats.HistoryItem record = invocation.getArgument(0); record.cmd = BatteryStats.HistoryItem.CMD_UPDATE; - record.time = times[count]; - record.batteryLevel = levels[count]; - count++; + record.time = mTimes[mCount]; + record.batteryLevel = mLevels[mCount]; + mCount++; return true; } - }).when(mBatteryStats).getNextHistoryLocked(any(BatteryStats.HistoryItem.class)); - return true; - }).when(mBatteryStats).startIteratingHistoryLocked(); + }).when(iterator).next(any(BatteryStats.HistoryItem.class)); + return iterator; + }).when(mBatteryUsageStats).iterateBatteryStatsHistory(); } private void assertOnlyHistory(BatteryInfo info) { @@ -337,9 +338,9 @@ public class BatteryInfoTest { private BatteryInfo getBatteryInfo(boolean charging, boolean enhanced, boolean estimate) { if (charging && estimate) { - doReturn(1000L).when(mBatteryStats).computeChargeTimeRemaining(anyLong()); + doReturn(1000L).when(mBatteryUsageStats).getChargeTimeRemainingMs(); } else { - doReturn(0L).when(mBatteryStats).computeChargeTimeRemaining(anyLong()); + doReturn(0L).when(mBatteryUsageStats).getChargeTimeRemainingMs(); } Estimate batteryEstimate = new Estimate( estimate ? 1000 : 0, @@ -347,7 +348,7 @@ public class BatteryInfoTest { 1000 /* averageDischargeTime */); BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, charging ? mChargingBatteryBroadcast : mDisChargingBatteryBroadcast, - mBatteryStats, batteryEstimate, SystemClock.elapsedRealtime() * 1000, false); + mBatteryUsageStats, batteryEstimate, SystemClock.elapsedRealtime() * 1000, false); doReturn(enhanced).when(mFeatureFactory.powerUsageFeatureProvider) .isEnhancedBatteryPredictionEnabled(mContext); return info; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java index f393da8b65c..c8fdf8c9562 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java @@ -48,6 +48,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.BatteryStats; +import android.os.BatteryStatsManager; import android.os.Build; import android.os.Bundle; import android.os.Process; @@ -157,6 +158,8 @@ public class BatteryUtilsTest { private ApplicationInfo mApplicationInfo; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private BatteryStatsHelper mBatteryStatsHelper; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private BatteryStatsManager mBatteryStatsManager; @Mock private ApplicationInfo mHighApplicationInfo; @Mock @@ -228,6 +231,8 @@ public class BatteryUtilsTest { mContext = spy(RuntimeEnvironment.application); doReturn(mPackageManager).when(mContext).getPackageManager(); doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE); + doReturn(mBatteryStatsManager).when(mContext) + .getSystemService(Context.BATTERY_STATS_SERVICE); mBatteryUtils = spy(new BatteryUtils(mContext)); mBatteryUtils.mPowerUsageFeatureProvider = mProvider; doReturn(0L).when(mBatteryUtils) @@ -741,7 +746,7 @@ public class BatteryUtilsTest { any(IntentFilter.class))).thenReturn(new Intent()); //Should not crash - assertThat(mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG)).isNotNull(); + assertThat(mBatteryUtils.getBatteryInfo(TAG)).isNotNull(); } @Test diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java index cd1b1780d2c..87547008d2f 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java @@ -74,6 +74,11 @@ public class PowerUsageBaseTest { return 0; } + @Override + protected boolean isBatteryHistoryNeeded() { + return false; + } + @Override protected void refreshUi(int refreshType) { // Do nothing diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java index 8cc17d8d98f..c97d79ff2a1 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java @@ -77,7 +77,7 @@ public class BatteryTipLoaderTest { doReturn(mContext).when(mContext).getApplicationContext(); doReturn(mPowerManager).when(mContext).getSystemService(Context.POWER_SERVICE); doReturn(mIntent).when(mContext).registerReceiver(any(), any()); - doReturn(mBatteryInfo).when(mBatteryUtils).getBatteryInfo(any(), any()); + doReturn(mBatteryInfo).when(mBatteryUtils).getBatteryInfo(any()); mBatteryTipLoader = new BatteryTipLoader(mContext, mBatteryStatsHelper); mBatteryTipLoader.mBatteryUtils = mBatteryUtils; } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java index 5c56f46c4bd..93005d51093 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java @@ -18,7 +18,9 @@ package com.android.settings.fuelgauge.batterytip.detectors; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -26,8 +28,11 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.Intent; import android.os.BatteryStats; -import android.text.format.DateUtils; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; +import android.os.BatteryUsageStatsQuery; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; @@ -53,6 +58,8 @@ import java.util.List; @RunWith(RobolectricTestRunner.class) public class HighUsageDetectorTest { + private static final String TAG = "HighUsageDetectorTest"; + private static final int UID_HIGH = 123; private static final int UID_LOW = 345; private static final double POWER_HIGH = 20000; @@ -68,6 +75,10 @@ public class HighUsageDetectorTest { private BatterySipper mSystemBatterySipper; @Mock private HighUsageDataParser mDataParser; + @Mock + private BatteryUsageStats mBatteryUsageStats; + @Mock + private BatteryStatsManager mBatteryStatsManager; private AppInfo mHighAppInfo; private AppInfo mLowAppInfo; @@ -80,11 +91,19 @@ public class HighUsageDetectorTest { public void setUp() { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; + mContext = spy(RuntimeEnvironment.application); mPolicy = spy(new BatteryTipPolicy(mContext)); - mBatteryUtils = spy(BatteryUtils.getInstance(mContext)); + mBatteryUtils = spy(new BatteryUtils(mContext)); + + when(mContext.getSystemService(eq(Context.BATTERY_STATS_SERVICE))) + .thenReturn(mBatteryStatsManager); + when(mBatteryStatsManager.getBatteryUsageStats(any(BatteryUsageStatsQuery.class))) + .thenReturn(mBatteryUsageStats); + + mContext.sendStickyBroadcast(new Intent(Intent.ACTION_BATTERY_CHANGED)); + mHighUsageDetector = spy(new HighUsageDetector(mContext, mPolicy, mBatteryStatsHelper, - true /* mDischarging */)); + mBatteryUtils.getBatteryInfo(TAG))); mHighUsageDetector.mBatteryUtils = mBatteryUtils; mHighUsageDetector.mDataParser = mDataParser; doNothing().when(mHighUsageDetector).parseBatteryData();