Merge changes I08df6527,I16a5537e into tm-dev
* changes: Improve the dumpsys output of the app battery tracker Coalesce the shared GID battery usage into its real UID
This commit is contained in:
commit
26f54bd162
@ -55,6 +55,7 @@ import android.os.BatteryConsumer.Dimensions;
|
||||
import android.os.BatteryStatsInternal;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.BatteryUsageStatsQuery;
|
||||
import android.os.Build;
|
||||
import android.os.PowerExemptionManager;
|
||||
import android.os.PowerExemptionManager.ReasonCode;
|
||||
import android.os.SystemClock;
|
||||
@ -62,6 +63,7 @@ import android.os.UidBatteryConsumer;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
@ -81,6 +83,7 @@ import java.io.PrintWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* The battery usage tracker for apps, currently we are focusing on background + FGS battery here.
|
||||
@ -91,6 +94,9 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
|
||||
static final boolean DEBUG_BACKGROUND_BATTERY_TRACKER = false;
|
||||
|
||||
static final boolean DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE =
|
||||
DEBUG_BACKGROUND_BATTERY_TRACKER | Build.IS_DEBUGGABLE;
|
||||
|
||||
// As we don't support realtime per-UID battery usage stats yet, we're polling the stats
|
||||
// in a regular time basis.
|
||||
private final long mBatteryUsageStatsPollingIntervalMs;
|
||||
@ -170,7 +176,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
private long mLastUidBatteryUsageStartTs;
|
||||
|
||||
// For debug only.
|
||||
private final SparseArray<BatteryUsage> mDebugUidPercentages = new SparseArray<>();
|
||||
private final SparseArray<ImmutableBatteryUsage> mDebugUidPercentages = new SparseArray<>();
|
||||
|
||||
AppBatteryTracker(Context context, AppRestrictionController controller) {
|
||||
this(context, controller, null, null);
|
||||
@ -337,10 +343,12 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
bgPolicy.mBgCurrentDrainExemptedTypes);
|
||||
// It's possible the exemptedUsage could be larger than actualUsage,
|
||||
// as the former one is an approximate value.
|
||||
final BatteryUsage bgUsage = actualUsage.mutate()
|
||||
final ImmutableBatteryUsage bgUsage = actualUsage.mutate()
|
||||
.subtract(exemptedUsage)
|
||||
.calcPercentage(uid, bgPolicy);
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
.calcPercentage(uid, bgPolicy)
|
||||
.unmutate();
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE
|
||||
&& !BATTERY_USAGE_NONE.equals(actualUsage)) {
|
||||
Slog.i(TAG, String.format(
|
||||
"UID %d: %s (%s) | %s | %s over the past %s",
|
||||
uid,
|
||||
@ -420,7 +428,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE) {
|
||||
Slog.i(TAG, "updateBatteryUsageStatsOnce");
|
||||
}
|
||||
|
||||
@ -477,14 +485,17 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
final BatteryUsage lastUsage = mLastUidBatteryUsage.get(uid, BATTERY_USAGE_NONE);
|
||||
final BatteryUsage curUsage = buf.valueAt(i);
|
||||
final BatteryUsage before;
|
||||
final BatteryUsage totalUsage;
|
||||
if (index >= 0) {
|
||||
before = mUidBatteryUsage.valueAt(index);
|
||||
before.subtract(lastUsage).add(curUsage);
|
||||
totalUsage = mUidBatteryUsage.valueAt(index);
|
||||
before = DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE
|
||||
? new BatteryUsage(totalUsage) : BATTERY_USAGE_NONE;
|
||||
totalUsage.subtract(lastUsage).add(curUsage);
|
||||
} else {
|
||||
before = BATTERY_USAGE_NONE;
|
||||
before = totalUsage = BATTERY_USAGE_NONE;
|
||||
mUidBatteryUsage.put(uid, curUsage);
|
||||
}
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE) {
|
||||
final BatteryUsage actualDelta = new BatteryUsage(curUsage).subtract(lastUsage);
|
||||
String msg = "Updating mUidBatteryUsage uid=" + uid + ", before=" + before
|
||||
+ ", after=" + mUidBatteryUsage.get(uid, BATTERY_USAGE_NONE)
|
||||
@ -496,7 +507,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
if (!actualDelta.isValid()) {
|
||||
// Something is wrong, the battery usage shouldn't be negative.
|
||||
Slog.e(TAG, msg);
|
||||
} else {
|
||||
} else if (!BATTERY_USAGE_NONE.equals(actualDelta)) {
|
||||
Slog.i(TAG, msg);
|
||||
}
|
||||
}
|
||||
@ -519,11 +530,16 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
copyUidBatteryUsage(buf, mUidBatteryUsageInWindow);
|
||||
}
|
||||
}
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE) {
|
||||
synchronized (mLock) {
|
||||
for (int i = 0, size = mUidBatteryUsageInWindow.size(); i < size; i++) {
|
||||
final ImmutableBatteryUsage usage = mUidBatteryUsageInWindow.valueAt(i);
|
||||
if (BATTERY_USAGE_NONE.equals(usage)) {
|
||||
// Skip the logging to avoid spamming.
|
||||
continue;
|
||||
}
|
||||
Slog.i(TAG, "mUidBatteryUsageInWindow uid=" + mUidBatteryUsageInWindow.keyAt(i)
|
||||
+ " usage=" + mUidBatteryUsageInWindow.valueAt(i));
|
||||
+ " usage=" + usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -552,7 +568,19 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
for (UidBatteryConsumer uidConsumer : uidConsumers) {
|
||||
// TODO: b/200326767 - as we are not supporting per proc state attribution yet,
|
||||
// we couldn't distinguish between a real FGS vs. a bound FGS proc state.
|
||||
final int uid = uidConsumer.getUid();
|
||||
final int rawUid = uidConsumer.getUid();
|
||||
if (UserHandle.isIsolated(rawUid)) {
|
||||
// Isolated processes should have been attributed to their parent processes.
|
||||
continue;
|
||||
}
|
||||
int uid = rawUid;
|
||||
// Keep the logic in sync with BatteryAppListPreferenceController.java
|
||||
// Check if this UID is a shared GID. If so, we combine it with the OWNER's
|
||||
// actual app UID.
|
||||
final int sharedAppId = UserHandle.getAppIdFromSharedAppGid(uid);
|
||||
if (sharedAppId > 0) {
|
||||
uid = UserHandle.getUid(UserHandle.USER_SYSTEM, sharedAppId);
|
||||
}
|
||||
final BatteryUsage bgUsage = new BatteryUsage(uidConsumer, bgPolicy)
|
||||
.scale(scale);
|
||||
int index = buf.indexOfKey(uid);
|
||||
@ -562,9 +590,13 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
final BatteryUsage before = buf.valueAt(index);
|
||||
before.add(bgUsage);
|
||||
}
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
Slog.i(TAG, "updateBatteryUsageStatsOnceInternal uid=" + uid
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE
|
||||
&& !BATTERY_USAGE_NONE.equals(bgUsage)) {
|
||||
Slog.i(TAG, "updateBatteryUsageStatsOnceInternal uid=" + rawUid
|
||||
+ ", bgUsage=" + bgUsage
|
||||
+ (rawUid == uid ? ""
|
||||
: ", realUid=" + uid
|
||||
+ ", realUsage=" + buf.get(uid))
|
||||
+ ", start=" + start
|
||||
+ ", end=" + end);
|
||||
}
|
||||
@ -616,7 +648,8 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
void setDebugUidPercentage(int[] uids, double[][] percentages) {
|
||||
mDebugUidPercentages.clear();
|
||||
for (int i = 0; i < uids.length; i++) {
|
||||
mDebugUidPercentages.put(uids[i], new BatteryUsage().setPercentage(percentages[i]));
|
||||
mDebugUidPercentages.put(uids[i],
|
||||
new BatteryUsage().setPercentage(percentages[i]).unmutate());
|
||||
}
|
||||
scheduleBgBatteryUsageStatsCheck();
|
||||
}
|
||||
@ -642,7 +675,20 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
void dump(PrintWriter pw, String prefix) {
|
||||
pw.print(prefix);
|
||||
pw.println("APP BATTERY STATE TRACKER:");
|
||||
// Force an update.
|
||||
updateBatteryUsageStatsIfNecessary(mInjector.currentTimeMillis(), true);
|
||||
// Force a check.
|
||||
scheduleBgBatteryUsageStatsCheck();
|
||||
// Wait for its completion (as it runs in handler thread for the sake of thread safe)
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
mBgHandler.getLooper().getQueue().addIdleHandler(() -> {
|
||||
latch.countDown();
|
||||
return false;
|
||||
});
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (mLock) {
|
||||
final SparseArray<ImmutableBatteryUsage> uidConsumers = mUidBatteryUsageInWindow;
|
||||
pw.print(" " + prefix);
|
||||
@ -811,8 +857,12 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
}
|
||||
|
||||
private BatteryUsage setToInternal(@NonNull BatteryUsage other) {
|
||||
for (int i = 0; i < other.mUsage.length; i++) {
|
||||
mUsage[i] = other.mUsage[i];
|
||||
System.arraycopy(other.mUsage, 0, mUsage, 0, other.mUsage.length);
|
||||
if (other.mPercentage != null) {
|
||||
mPercentage = new double[other.mPercentage.length];
|
||||
System.arraycopy(other.mPercentage, 0, mPercentage, 0, other.mPercentage.length);
|
||||
} else {
|
||||
mPercentage = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -1297,11 +1347,12 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
|
||||
/**
|
||||
* List of the packages with significant background battery usage, key is the UID of
|
||||
* the package and value is an array of the timestamps when the UID is found guilty and
|
||||
* should be moved to the next level of restriction.
|
||||
* the package and value is the pair of {timestamp[], battery usage snapshot[]}
|
||||
* when the UID is found guilty and should be moved to the next level of restriction.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArray<long[]> mHighBgBatteryPackages = new SparseArray<>();
|
||||
private final SparseArray<Pair<long[], ImmutableBatteryUsage[]>> mHighBgBatteryPackages =
|
||||
new SparseArray<>();
|
||||
|
||||
@NonNull
|
||||
private final Object mLock;
|
||||
@ -1531,8 +1582,9 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
return RESTRICTION_LEVEL_UNKNOWN;
|
||||
}
|
||||
synchronized (mLock) {
|
||||
final long[] ts = mHighBgBatteryPackages.get(uid);
|
||||
if (ts != null) {
|
||||
final Pair<long[], ImmutableBatteryUsage[]> pair = mHighBgBatteryPackages.get(uid);
|
||||
if (pair != null) {
|
||||
final long[] ts = pair.first;
|
||||
final int restrictedLevel = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] > 0
|
||||
? RESTRICTION_LEVEL_RESTRICTED_BUCKET
|
||||
: RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
|
||||
@ -1601,10 +1653,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
void handleUidBatteryUsage(final int uid, final BatteryUsage usage) {
|
||||
void handleUidBatteryUsage(final int uid, final ImmutableBatteryUsage usage) {
|
||||
final @ReasonCode int reason = shouldExemptUid(uid);
|
||||
if (reason != REASON_DENIED) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE && !BATTERY_USAGE_NONE.equals(usage)) {
|
||||
Slog.i(TAG, "Exempting battery usage in " + UserHandle.formatUid(uid)
|
||||
+ " " + PowerExemptionManager.reasonCodeToString(reason));
|
||||
}
|
||||
@ -1612,6 +1664,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
}
|
||||
boolean notifyController = false;
|
||||
boolean excessive = false;
|
||||
int index = 0;
|
||||
final double rbPercentage = sumPercentageOfTypes(usage.getPercentage(),
|
||||
mBgCurrentDrainRestrictedBucketTypes);
|
||||
final double brPercentage = sumPercentageOfTypes(usage.getPercentage(),
|
||||
@ -1625,33 +1678,41 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
final long now = SystemClock.elapsedRealtime();
|
||||
final int thresholdIndex = getCurrentDrainThresholdIndex(uid, now,
|
||||
mBgCurrentDrainWindowMs);
|
||||
final int index = mHighBgBatteryPackages.indexOfKey(uid);
|
||||
index = mHighBgBatteryPackages.indexOfKey(uid);
|
||||
final boolean decoupleThresholds = mBgCurrentDrainDecoupleThresholds;
|
||||
final double rbThreshold = mBgCurrentDrainRestrictedBucketThreshold[thresholdIndex];
|
||||
final double brThreshold = mBgCurrentDrainBgRestrictedThreshold[thresholdIndex];
|
||||
if (index < 0) {
|
||||
long[] ts = null;
|
||||
ImmutableBatteryUsage[] usages = null;
|
||||
if (rbPercentage >= rbThreshold) {
|
||||
// New findings to us, track it and let the controller know.
|
||||
ts = new long[TIME_STAMP_INDEX_LAST];
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
|
||||
mHighBgBatteryPackages.put(uid, ts);
|
||||
usages = new ImmutableBatteryUsage[TIME_STAMP_INDEX_LAST];
|
||||
usages[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
mHighBgBatteryPackages.put(uid, Pair.create(ts, usages));
|
||||
notifyController = excessive = true;
|
||||
}
|
||||
if (decoupleThresholds && brPercentage >= brThreshold) {
|
||||
if (ts == null) {
|
||||
ts = new long[TIME_STAMP_INDEX_LAST];
|
||||
mHighBgBatteryPackages.put(uid, ts);
|
||||
usages = new ImmutableBatteryUsage[TIME_STAMP_INDEX_LAST];
|
||||
mHighBgBatteryPackages.put(uid, Pair.create(ts, usages));
|
||||
}
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
|
||||
usages[TIME_STAMP_INDEX_BG_RESTRICTED] = usage;
|
||||
notifyController = excessive = true;
|
||||
}
|
||||
} else {
|
||||
final long[] ts = mHighBgBatteryPackages.valueAt(index);
|
||||
final Pair<long[], ImmutableBatteryUsage[]> pair =
|
||||
mHighBgBatteryPackages.valueAt(index);
|
||||
final long[] ts = pair.first;
|
||||
final long lastRestrictBucketTs = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET];
|
||||
if (rbPercentage >= rbThreshold) {
|
||||
if (lastRestrictBucketTs == 0) {
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
|
||||
pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
}
|
||||
notifyController = excessive = true;
|
||||
} else {
|
||||
@ -1670,6 +1731,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
&& (now > lastRestrictBucketTs + mBgCurrentDrainWindowMs));
|
||||
if (notifyController) {
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
|
||||
pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
}
|
||||
excessive = true;
|
||||
} else {
|
||||
@ -1677,13 +1739,14 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
// user consent to unrestrict it; or if it's in restricted bucket level,
|
||||
// resetting this won't lift it from that level.
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED] = 0;
|
||||
pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = null;
|
||||
// Now need to notify the controller.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (excessive) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE) {
|
||||
Slog.i(TAG, "Excessive background current drain " + uid + " "
|
||||
+ usage + " (" + usage.percentageToString() + " ) over "
|
||||
+ TimeUtils.formatDuration(mBgCurrentDrainWindowMs));
|
||||
@ -1694,7 +1757,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE, true);
|
||||
}
|
||||
} else {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
|
||||
if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE && index >= 0) {
|
||||
Slog.i(TAG, "Background current drain backs to normal " + uid + " "
|
||||
+ usage + " (" + usage.percentageToString() + " ) over "
|
||||
+ TimeUtils.formatDuration(mBgCurrentDrainWindowMs));
|
||||
@ -1764,9 +1827,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
synchronized (mLock) {
|
||||
// User has explicitly removed it from background restricted level,
|
||||
// clear the timestamp of the background-restricted
|
||||
final long[] ts = mHighBgBatteryPackages.get(uid);
|
||||
if (ts != null) {
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED] = 0;
|
||||
final Pair<long[], ImmutableBatteryUsage[]> pair = mHighBgBatteryPackages.get(uid);
|
||||
if (pair != null) {
|
||||
pair.first[TIME_STAMP_INDEX_BG_RESTRICTED] = 0;
|
||||
pair.second[TIME_STAMP_INDEX_BG_RESTRICTED] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1841,6 +1905,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
pw.print(KEY_BG_CURRENT_DRAIN_HIGH_THRESHOLD_BY_BG_LOCATION);
|
||||
pw.print('=');
|
||||
pw.println(mBgCurrentDrainHighThresholdByBgLocation);
|
||||
pw.print(prefix);
|
||||
pw.print("Full charge capacity=");
|
||||
pw.print(mBatteryFullChargeMah);
|
||||
pw.println(" mAh");
|
||||
|
||||
pw.print(prefix);
|
||||
pw.println("Excessive current drain detected:");
|
||||
@ -1851,18 +1919,24 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
final long now = SystemClock.elapsedRealtime();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int uid = mHighBgBatteryPackages.keyAt(i);
|
||||
final long[] ts = mHighBgBatteryPackages.valueAt(i);
|
||||
final Pair<long[], ImmutableBatteryUsage[]> pair =
|
||||
mHighBgBatteryPackages.valueAt(i);
|
||||
final long[] ts = pair.first;
|
||||
final ImmutableBatteryUsage[] usages = pair.second;
|
||||
final int thresholdIndex = getCurrentDrainThresholdIndex(uid, now,
|
||||
mBgCurrentDrainWindowMs);
|
||||
pw.format("%s%s: (threshold=%4.2f%%/%4.2f%%) %s/%s\n",
|
||||
pw.format("%s%s: (threshold=%4.2f%%/%4.2f%%) %s / %s\n",
|
||||
prefix,
|
||||
UserHandle.formatUid(uid),
|
||||
mBgCurrentDrainRestrictedBucketThreshold[thresholdIndex],
|
||||
mBgCurrentDrainBgRestrictedThreshold[thresholdIndex],
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] == 0 ? "0"
|
||||
: formatTime(ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET], now),
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED] == 0 ? "0"
|
||||
: formatTime(ts[TIME_STAMP_INDEX_BG_RESTRICTED], now));
|
||||
formatHighBgBatteryRecord(
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET], now,
|
||||
usages[TIME_STAMP_INDEX_RESTRICTED_BUCKET]),
|
||||
formatHighBgBatteryRecord(
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED], now,
|
||||
usages[TIME_STAMP_INDEX_BG_RESTRICTED])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
pw.print(prefix);
|
||||
@ -1871,5 +1945,14 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String formatHighBgBatteryRecord(long ts, long now, ImmutableBatteryUsage usage) {
|
||||
if (ts > 0 && usage != null) {
|
||||
return String.format("%s %s (%s)",
|
||||
formatTime(ts, now), usage.toString(), usage.percentageToString());
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user