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
This commit is contained in:
Dmitri Plotnikov
2021-02-19 14:34:01 -08:00
parent e604c56241
commit 820bee81d6
18 changed files with 296 additions and 180 deletions

View File

@@ -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<Void, Void, BatteryInfo>() {
@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();
}