Remove references to BatterStatsHelper from BatteryUsageStatsProvider

Also, add BatteryUsageStatsQuery.getMaxStatsAge() to allow throttling
of battery stats sync.

Bug: 174186345
Test: atest FrameworksCoreTests:com.android.internal.os.BatteryStatsTests
Change-Id: I097c6b9575422837a522cf313a320e83221cdfab
This commit is contained in:
Dmitri Plotnikov
2021-03-22 18:24:08 -07:00
parent e289502447
commit b8b58ebd2f
6 changed files with 76 additions and 23 deletions

View File

@@ -60,14 +60,18 @@ public final class BatteryUsageStatsQuery implements Parcelable {
*/
public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY = 2;
private static final long DEFAULT_MAX_STATS_AGE_MS = 5 * 60 * 1000;
private final int mFlags;
@NonNull
private final int[] mUserIds;
private final long mMaxStatsAgeMs;
private BatteryUsageStatsQuery(@NonNull Builder builder) {
mFlags = builder.mFlags;
mUserIds = builder.mUserIds != null ? builder.mUserIds.toArray()
: new int[]{UserHandle.USER_ALL};
mMaxStatsAgeMs = builder.mMaxStatsAgeMs;
}
@BatteryUsageStatsFlags
@@ -94,10 +98,19 @@ public final class BatteryUsageStatsQuery implements Parcelable {
return (mFlags & FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL) != 0;
}
/**
* Returns the client's tolerance for stale battery stats. The data is allowed to be up to
* this many milliseconds out-of-date.
*/
public long getMaxStatsAge() {
return mMaxStatsAgeMs;
}
private BatteryUsageStatsQuery(Parcel in) {
mFlags = in.readInt();
mUserIds = new int[in.readInt()];
in.readIntArray(mUserIds);
mMaxStatsAgeMs = in.readLong();
}
@Override
@@ -105,6 +118,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
dest.writeInt(mFlags);
dest.writeInt(mUserIds.length);
dest.writeIntArray(mUserIds);
dest.writeLong(mMaxStatsAgeMs);
}
@Override
@@ -132,6 +146,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
public static final class Builder {
private int mFlags;
private IntArray mUserIds;
private long mMaxStatsAgeMs = DEFAULT_MAX_STATS_AGE_MS;
/**
* Builds a read-only BatteryUsageStatsQuery object.
@@ -170,5 +185,14 @@ public final class BatteryUsageStatsQuery implements Parcelable {
mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL;
return this;
}
/**
* Set the client's tolerance for stale battery stats. The data may be up to
* this many milliseconds out-of-date.
*/
public Builder setMaxStatsAgeMs(long maxStatsAgeMs) {
mMaxStatsAgeMs = maxStatsAgeMs;
return this;
}
}
}

View File

@@ -16598,6 +16598,8 @@ public class BatteryStatsImpl extends BatteryStats {
// Pull the clock time. This may update the time and make a new history entry
// if we had originally pulled a time before the RTC was set.
getStartClockTime();
updateSystemServiceCallStats();
}
public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {

View File

@@ -21,9 +21,7 @@ import android.hardware.SensorManager;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.Bundle;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -87,30 +85,32 @@ public class BatteryUsageStatsProvider {
return mPowerCalculators;
}
/**
* Returns true if the last update was too long ago for the tolerances specified
* by the supplied queries.
*/
public boolean shouldUpdateStats(List<BatteryUsageStatsQuery> queries,
long lastUpdateTimeStampMs) {
long allowableStatsAge = Long.MAX_VALUE;
for (int i = queries.size() - 1; i >= 0; i--) {
BatteryUsageStatsQuery query = queries.get(i);
allowableStatsAge = Math.min(allowableStatsAge, query.getMaxStatsAge());
}
return mStats.mClocks.elapsedRealtime() - lastUpdateTimeStampMs > allowableStatsAge;
}
/**
* Returns snapshots of battery attribution data, one per supplied query.
*/
public List<BatteryUsageStats> getBatteryUsageStats(List<BatteryUsageStatsQuery> queries) {
// TODO(b/174186345): instead of BatteryStatsHelper, use PowerCalculators directly.
final BatteryStatsHelper batteryStatsHelper = new BatteryStatsHelper(mContext,
false /* collectBatteryBroadcast */);
batteryStatsHelper.create((Bundle) null);
final List<UserHandle> users = new ArrayList<>();
for (int i = 0; i < queries.size(); i++) {
BatteryUsageStatsQuery query = queries.get(i);
for (int userId : query.getUserIds()) {
UserHandle userHandle = UserHandle.of(userId);
if (!users.contains(userHandle)) {
users.add(userHandle);
}
}
}
batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, users);
ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
for (int i = 0; i < queries.size(); i++) {
results.add(getBatteryUsageStats(queries.get(i)));
synchronized (mStats) {
mStats.prepareForDumpLocked();
for (int i = 0; i < queries.size(); i++) {
results.add(getBatteryUsageStats(queries.get(i)));
}
}
return results;
}

View File

@@ -158,4 +158,22 @@ public class BatteryUsageStatsProviderTest {
assertThat(item.time).isEqualTo(elapsedTimeMs);
}
@Test
public void shouldUpdateStats() {
Context context = InstrumentationRegistry.getContext();
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context,
mStatsRule.getBatteryStats());
final List<BatteryUsageStatsQuery> queries = List.of(
new BatteryUsageStatsQuery.Builder().setMaxStatsAgeMs(1000).build(),
new BatteryUsageStatsQuery.Builder().setMaxStatsAgeMs(2000).build()
);
mStatsRule.setTime(10500, 0);
assertThat(provider.shouldUpdateStats(queries, 10000)).isFalse();
mStatsRule.setTime(11500, 0);
assertThat(provider.shouldUpdateStats(queries, 10000)).isTrue();
}
}

View File

@@ -487,8 +487,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
Slog.wtf(TAG, "Error updating external stats: ", e);
}
synchronized (BatteryExternalStatsWorker.this) {
mLastCollectionTimeStamp = SystemClock.elapsedRealtime();
if ((updateFlags & UPDATE_ALL) == UPDATE_ALL) {
synchronized (BatteryExternalStatsWorker.this) {
mLastCollectionTimeStamp = SystemClock.elapsedRealtime();
}
}
}
};

View File

@@ -674,6 +674,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public List<BatteryUsageStats> getBatteryUsageStats(List<BatteryUsageStatsQuery> queries) {
mContext.enforceCallingPermission(
android.Manifest.permission.BATTERY_STATS, null);
awaitCompletion();
if (mBatteryUsageStatsProvider.shouldUpdateStats(queries,
mWorker.getLastCollectionTimeStamp())) {
syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL);
}
return mBatteryUsageStatsProvider.getBatteryUsageStats(queries);
}