Merge "Convert UserPowerCalculator to work with BatteryUsageStats" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-02-09 23:54:12 +00:00
committed by Android (Google) Code Review
19 changed files with 433 additions and 62 deletions

View File

@@ -33,20 +33,33 @@ public final class BatteryUsageStats implements Parcelable {
private final int mDischargePercentage;
private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers;
private final ArrayList<SystemBatteryConsumer> mSystemBatteryConsumers;
private final ArrayList<UserBatteryConsumer> mUserBatteryConsumers;
private BatteryUsageStats(@NonNull Builder builder) {
mConsumedPower = builder.mConsumedPower;
mDischargePercentage = builder.mDischargePercentage;
int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount);
for (int i = 0; i < uidBatteryConsumerCount; i++) {
mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.valueAt(i).build());
UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
builder.mUidBatteryConsumerBuilders.valueAt(i);
if (!uidBatteryConsumerBuilder.isExcludedFromBatteryUsageStats()) {
mUidBatteryConsumers.add(uidBatteryConsumerBuilder.build());
}
}
int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size();
mSystemBatteryConsumers = new ArrayList<>(systemBatteryConsumerCount);
for (int i = 0; i < systemBatteryConsumerCount; i++) {
mSystemBatteryConsumers.add(builder.mSystemBatteryConsumerBuilders.valueAt(i).build());
}
int userBatteryConsumerCount = builder.mUserBatteryConsumerBuilders.size();
mUserBatteryConsumers = new ArrayList<>(userBatteryConsumerCount);
for (int i = 0; i < userBatteryConsumerCount; i++) {
mUserBatteryConsumers.add(builder.mUserBatteryConsumerBuilders.valueAt(i).build());
}
}
/**
@@ -75,6 +88,11 @@ public final class BatteryUsageStats implements Parcelable {
return mSystemBatteryConsumers;
}
@NonNull
public List<UserBatteryConsumer> getUserBatteryConsumers() {
return mUserBatteryConsumers;
}
@Override
public int describeContents() {
return 0;
@@ -85,6 +103,8 @@ public final class BatteryUsageStats implements Parcelable {
source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader());
mSystemBatteryConsumers = new ArrayList<>();
source.readParcelableList(mSystemBatteryConsumers, getClass().getClassLoader());
mUserBatteryConsumers = new ArrayList<>();
source.readParcelableList(mUserBatteryConsumers, getClass().getClassLoader());
mConsumedPower = source.readDouble();
mDischargePercentage = source.readInt();
}
@@ -93,6 +113,7 @@ public final class BatteryUsageStats implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeParcelableList(mUidBatteryConsumers, flags);
dest.writeParcelableList(mSystemBatteryConsumers, flags);
dest.writeParcelableList(mUserBatteryConsumers, flags);
dest.writeDouble(mConsumedPower);
dest.writeInt(mDischargePercentage);
}
@@ -120,6 +141,8 @@ public final class BatteryUsageStats implements Parcelable {
new SparseArray<>();
private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders =
new SparseArray<>();
private final SparseArray<UserBatteryConsumer.Builder> mUserBatteryConsumerBuilders =
new SparseArray<>();
public Builder(int customPowerComponentCount, int customTimeComponentCount) {
mCustomPowerComponentCount = customPowerComponentCount;
@@ -137,7 +160,6 @@ public final class BatteryUsageStats implements Parcelable {
/**
* Sets the battery discharge amount since BatteryStats reset as percentage of the full
* charge.
*
*/
@SuppressLint("PercentageInt") // See b/174188159
@NonNull
@@ -173,8 +195,8 @@ public final class BatteryUsageStats implements Parcelable {
}
/**
* Creates or returns a exiting UidBatteryConsumer, which represents battery attribution
* data for an individual UID.
* Creates or returns a exiting SystemBatteryConsumer, which represents battery attribution
* data for a specific drain type.
*/
@NonNull
public SystemBatteryConsumer.Builder getOrCreateSystemBatteryConsumerBuilder(
@@ -188,6 +210,21 @@ public final class BatteryUsageStats implements Parcelable {
return builder;
}
/**
* Creates or returns a exiting UserBatteryConsumer, which represents battery attribution
* data for an individual {@link UserHandle}.
*/
@NonNull
public UserBatteryConsumer.Builder getOrCreateUserBatteryConsumerBuilder(int userId) {
UserBatteryConsumer.Builder builder = mUserBatteryConsumerBuilders.get(userId);
if (builder == null) {
builder = new UserBatteryConsumer.Builder(mCustomPowerComponentCount,
mCustomTimeComponentCount, userId);
mUserBatteryConsumerBuilders.put(userId, builder);
}
return builder;
}
@NonNull
public SparseArray<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
return mUidBatteryConsumerBuilders;

View File

@@ -18,6 +18,7 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.util.IntArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -53,9 +54,13 @@ public final class BatteryUsageStatsQuery implements Parcelable {
public static final int FLAG_BATTERY_USAGE_STATS_POWER_PROFILE_MODEL = 1;
private final int mFlags;
@NonNull
private final int[] mUserIds;
private BatteryUsageStatsQuery(@NonNull Builder builder) {
mFlags = builder.mFlags;
mUserIds = builder.mUserIds != null ? builder.mUserIds.toArray()
: new int[]{UserHandle.USER_ALL};
}
@BatteryUsageStatsFlags
@@ -63,13 +68,28 @@ public final class BatteryUsageStatsQuery implements Parcelable {
return mFlags;
}
/**
* Returns an array of users for which the attribution is requested. It may
* contain {@link UserHandle#USER_ALL} to indicate that the attribution
* should be performed for all users. Battery consumed by users <b>not</b> included
* in this array will be returned in the aggregated form as {@link UserBatteryConsumer}'s.
*/
@NonNull
public int[] getUserIds() {
return mUserIds;
}
private BatteryUsageStatsQuery(Parcel in) {
mFlags = in.readInt();
mUserIds = new int[in.readInt()];
in.readIntArray(mUserIds);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mFlags);
dest.writeInt(mUserIds.length);
dest.writeIntArray(mUserIds);
}
@Override
@@ -96,6 +116,7 @@ public final class BatteryUsageStatsQuery implements Parcelable {
*/
public static final class Builder {
private int mFlags;
private IntArray mUserIds;
/**
* Builds a read-only BatteryUsageStatsQuery object.
@@ -104,6 +125,18 @@ public final class BatteryUsageStatsQuery implements Parcelable {
return new BatteryUsageStatsQuery(this);
}
/**
* Add a user whose battery stats should be included in the battery usage stats.
* {@link UserHandle#USER_ALL} will be used by default if no users are added explicitly.
*/
public Builder addUser(@NonNull UserHandle userHandle) {
if (mUserIds == null) {
mUserIds = new IntArray(1);
}
mUserIds.add(userHandle.getIdentifier());
return this;
}
/**
* Sets flags to modify the behavior of {@link BatteryStatsManager#getBatteryUsageStats}.
*/

View File

@@ -96,6 +96,7 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
private final int mUid;
private String mPackageWithHighestDrain;
private boolean mSystemComponent;
private boolean mExcludeFromBatteryUsageStats;
public Builder(int customPowerComponentCount, int customTimeComponentCount,
BatteryStats.Uid batteryStatsUid) {
@@ -112,14 +113,6 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
return mUid;
}
/**
* Creates a read-only object out of the Builder values.
*/
@NonNull
public UidBatteryConsumer build() {
return new UidBatteryConsumer(this);
}
/**
* Sets the name of the package owned by this UID that consumed the highest amount
* of power since BatteryStats reset.
@@ -131,12 +124,27 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
}
/**
* Marks the UidBatteryConsumer as part of the system. For example,
* the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID} is considered
* as a system component.
* Marks the UidBatteryConsumer for exclusion from the result set.
*/
public void setSystemComponent(boolean systemComponent) {
mSystemComponent = systemComponent;
public Builder excludeFromBatteryUsageStats() {
mExcludeFromBatteryUsageStats = true;
return this;
}
/**
* Returns true if this UidBatteryConsumer must be excluded from the
* BatteryUsageStats.
*/
public boolean isExcludedFromBatteryUsageStats() {
return mExcludeFromBatteryUsageStats;
}
/**
* Creates a read-only object out of the Builder values.
*/
@NonNull
public UidBatteryConsumer build() {
return new UidBatteryConsumer(this);
}
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os;
import android.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
/**
* Contains power consumption data attributed to a {@link UserHandle}.
*
* {@hide}
*/
public class UserBatteryConsumer extends BatteryConsumer implements Parcelable {
private final int mUserId;
public int getUserId() {
return mUserId;
}
private UserBatteryConsumer(@NonNull UserBatteryConsumer.Builder builder) {
super(builder.mPowerComponentsBuilder.build());
mUserId = builder.mUserId;
}
private UserBatteryConsumer(Parcel in) {
super(new PowerComponents(in));
mUserId = in.readInt();
}
/**
* Writes the contents into a Parcel.
*/
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mUserId);
}
public static final Creator<UserBatteryConsumer> CREATOR =
new Creator<UserBatteryConsumer>() {
@Override
public UserBatteryConsumer createFromParcel(Parcel in) {
return new UserBatteryConsumer(in);
}
@Override
public UserBatteryConsumer[] newArray(int size) {
return new UserBatteryConsumer[size];
}
};
@Override
public int describeContents() {
return 0;
}
/**
* Builder for UserBatteryConsumer.
*/
public static final class Builder extends BaseBuilder<Builder> {
private final int mUserId;
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
Builder(int customPowerComponentCount, int customTimeComponentCount, int userId) {
super(customPowerComponentCount, customTimeComponentCount);
mUserId = userId;
}
/**
* Add a UidBatteryConsumer to this UserBatteryConsumer.
* <p>
* Calculated power and duration components of the added UID battery consumers
* are aggregated at the time the UserBatteryConsumer is built by the {@link #build()}
* method.
* </p>
*/
public void addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder) {
if (mUidBatteryConsumers == null) {
mUidBatteryConsumers = new ArrayList<>();
}
mUidBatteryConsumers.add(uidBatteryConsumerBuilder);
}
/**
* Creates a read-only object out of the Builder values.
*/
@NonNull
public UserBatteryConsumer build() {
if (mUidBatteryConsumers != null) {
for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) {
UidBatteryConsumer.Builder uidBatteryConsumer = mUidBatteryConsumers.get(i);
mPowerComponentsBuilder.addPowerAndDuration(
uidBatteryConsumer.mPowerComponentsBuilder);
}
}
return new UserBatteryConsumer(this);
}
}
}

View File

@@ -43,8 +43,7 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator {
*/
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
final double powerMah = mPowerEstimator.calculatePower(durationMs);

View File

@@ -24,7 +24,6 @@ import android.os.BatteryUsageStatsQuery;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.SparseArray;
import java.util.ArrayList;
@@ -89,26 +88,27 @@ public class BatteryUsageStatsProvider {
final BatteryStatsHelper batteryStatsHelper = new BatteryStatsHelper(mContext,
false /* collectBatteryBroadcast */);
batteryStatsHelper.create((Bundle) null);
final UserManager userManager = mContext.getSystemService(UserManager.class);
final List<UserHandle> asUsers = userManager.getUserProfiles();
final int n = asUsers.size();
SparseArray<UserHandle> users = new SparseArray<>(n);
for (int i = 0; i < n; ++i) {
UserHandle userHandle = asUsers.get(i);
users.put(userHandle.getIdentifier(), userHandle);
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), batteryStatsHelper, users));
results.add(getBatteryUsageStats(queries.get(i), batteryStatsHelper));
}
return results;
}
private BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query,
BatteryStatsHelper batteryStatsHelper, SparseArray<UserHandle> users) {
BatteryStatsHelper batteryStatsHelper) {
// TODO(b/174186358): read extra power component number from configuration
final int customPowerComponentCount = 0;
final int customTimeComponentCount = 0;
@@ -128,8 +128,8 @@ public class BatteryUsageStatsProvider {
final List<PowerCalculator> powerCalculators = getPowerCalculators();
for (PowerCalculator powerCalculator : powerCalculators) {
powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs, query,
users);
powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs,
query);
}
return batteryUsageStatsBuilder.build();

View File

@@ -50,8 +50,7 @@ public class BluetoothPowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
if (!mHasBluetoothPowerController || !batteryStats.hasBluetoothActivityReporting()) {
return;
}
@@ -68,7 +67,7 @@ public class BluetoothPowerCalculator extends PowerCalculator {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
calculateApp(app, total);
if (app.getUid() == Process.BLUETOOTH_UID) {
app.setSystemComponent(true);
app.excludeFromBatteryUsageStats();
systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
}
}

View File

@@ -45,8 +45,7 @@ public class GnssPowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final double averageGnssPowerMa = getAverageGnssPower(batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =

View File

@@ -49,8 +49,7 @@ public class IdlePowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
calculatePowerAndDuration(batteryStats, rawRealtimeUs, rawUptimeUs,
BatteryStats.STATS_SINCE_CHARGED);
if (mPowerMah != 0) {

View File

@@ -26,8 +26,7 @@ public class MemoryPowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
final double powerMah = calculatePower(batteryStats, rawRealtimeUs,

View File

@@ -85,8 +85,7 @@ public class MobileRadioPowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
PowerAndDuration total = new PowerAndDuration();

View File

@@ -39,8 +39,7 @@ public class PhonePowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED) / 1000;
final double phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs);

View File

@@ -67,17 +67,10 @@ public abstract class PowerCalculator {
* @param batteryStats The recorded battery stats.
* @param rawRealtimeUs The raw system realtime in microseconds.
* @param rawUptimeUs The raw system uptime in microseconds.
* @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this
* can only be {@link BatteryStats#STATS_SINCE_CHARGED}, since
* {@link BatteryStats#STATS_CURRENT} and
* {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated.
* @param asUsers An array of users for which the attribution is requested. It may
* contain {@link UserHandle#USER_ALL} to indicate that the attribution
* should be performed for all users.
* @param query The query parameters for the calculator.
*/
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {

View File

@@ -51,8 +51,7 @@ public class ScreenPowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final long durationMs = computeDuration(batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
final double powerMah = computePower(batteryStats, rawRealtimeUs,

View File

@@ -51,10 +51,9 @@ public class SystemServicePowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
SparseArray<UserHandle> asUsers) {
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
calculateSystemServicePower(batteryStats);
super.calculate(builder, batteryStats, rawRealtimeUs, rawUptimeUs, query, asUsers);
super.calculate(builder, batteryStats, rawRealtimeUs, rawUptimeUs, query);
}
@Override

View File

@@ -17,10 +17,15 @@
package com.android.internal.os;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.util.SparseArray;
import com.android.internal.util.ArrayUtils;
import java.util.List;
/**
@@ -28,6 +33,33 @@ import java.util.List;
*/
public class UserPowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final int[] userIds = query.getUserIds();
if (ArrayUtils.contains(userIds, UserHandle.USER_ALL)) {
return;
}
SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
UidBatteryConsumer.Builder uidBuilder = uidBatteryConsumerBuilders.valueAt(i);
final int uid = uidBuilder.getUid();
if (UserHandle.getAppId(uid) < Process.FIRST_APPLICATION_UID) {
continue;
}
final int userId = UserHandle.getUserId(uid);
if (!ArrayUtils.contains(userIds, userId)) {
uidBuilder.excludeFromBatteryUsageStats();
builder.getOrCreateUserBatteryConsumerBuilder(userId)
.addUidBatteryConsumer(uidBuilder);
}
}
}
@Override
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {

View File

@@ -65,6 +65,7 @@ import org.junit.runners.Suite;
ScreenPowerCalculatorTest.class,
SensorPowerCalculatorTest.class,
SystemServicePowerCalculatorTest.class,
UserPowerCalculatorTest.class,
VideoPowerCalculatorTest.class,
com.android.internal.power.MeasuredEnergyStatsTest.class

View File

@@ -28,6 +28,7 @@ import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
import android.os.UserBatteryConsumer;
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
@@ -113,15 +114,21 @@ public class BatteryUsageStatsRule implements TestRule {
mMockClocks.uptime = uptimeUs;
}
void apply(PowerCalculator calculator) {
void apply(PowerCalculator... calculators) {
apply(BatteryUsageStatsQuery.DEFAULT, calculators);
}
void apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(0, 0);
SparseArray<? extends BatteryStats.Uid> uidStats = mBatteryStats.getUidStats();
for (int i = 0; i < uidStats.size(); i++) {
builder.getOrCreateUidBatteryConsumerBuilder(uidStats.valueAt(i));
}
calculator.calculate(builder, mBatteryStats, mMockClocks.realtime, mMockClocks.uptime,
BatteryUsageStatsQuery.DEFAULT, null);
for (PowerCalculator calculator : calculators) {
calculator.calculate(builder, mBatteryStats, mMockClocks.realtime, mMockClocks.uptime,
query);
}
mBatteryUsageStats = builder.build();
}
@@ -144,4 +151,13 @@ public class BatteryUsageStatsRule implements TestRule {
}
return null;
}
public UserBatteryConsumer getUserBatteryConsumer(int userId) {
for (UserBatteryConsumer ubc : mBatteryUsageStats.getUserBatteryConsumers()) {
if (ubc.getUserId() == userId) {
return ubc;
}
}
return null;
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.os;
import static com.google.common.truth.Truth.assertThat;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
import android.os.UserBatteryConsumer;
import android.os.UserHandle;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class UserPowerCalculatorTest {
public static final int USER1 = 0;
public static final int USER2 = 1625;
private static final int APP_UID1 = Process.FIRST_APPLICATION_UID + 42;
private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 272;
private static final int APP_UID3 = Process.FIRST_APPLICATION_UID + 314;
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule();
@Test
public void testAllUsers() {
prepareUidBatteryConsumers();
UserPowerCalculator calculator = new UserPowerCalculator();
mStatsRule.apply(BatteryUsageStatsQuery.DEFAULT, calculator, new FakeAudioPowerCalculator(),
new FakeVideoPowerCalculator());
assertThat(mStatsRule.getUserBatteryConsumer(USER1)).isNull();
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER1, APP_UID1))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_AUDIO)).isEqualTo(3000);
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER1, APP_UID1))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_VIDEO)).isEqualTo(7000);
assertThat(mStatsRule.getUserBatteryConsumer(USER2)).isNull();
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER2, APP_UID2))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_AUDIO)).isEqualTo(5555);
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER2, APP_UID2))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_VIDEO)).isEqualTo(9999);
}
@Test
public void testSpecificUser() {
prepareUidBatteryConsumers();
UserPowerCalculator calculator = new UserPowerCalculator();
mStatsRule.apply(new BatteryUsageStatsQuery.Builder().addUser(UserHandle.of(USER1)).build(),
calculator, new FakeAudioPowerCalculator(), new FakeVideoPowerCalculator());
assertThat(mStatsRule.getUserBatteryConsumer(USER1)).isNull();
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER1, APP_UID1))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_AUDIO)).isEqualTo(3000);
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER1, APP_UID1))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_VIDEO)).isEqualTo(7000);
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER1, APP_UID2))).isNull();
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER1, APP_UID3))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_AUDIO)).isEqualTo(7070);
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER1, APP_UID3))
.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_VIDEO)).isEqualTo(11110);
UserBatteryConsumer user2 = mStatsRule.getUserBatteryConsumer(USER2);
assertThat(user2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_AUDIO))
.isEqualTo(15308);
assertThat(user2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_VIDEO))
.isEqualTo(24196);
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER2, APP_UID1))).isNull();
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER2, APP_UID2))).isNull();
assertThat(mStatsRule.getUidBatteryConsumer(UserHandle.getUid(USER2, APP_UID3))).isNull();
}
private void prepareUidBatteryConsumers() {
prepareUidBatteryConsumer(USER1, APP_UID1, 1000, 2000, 3000, 4000);
prepareUidBatteryConsumer(USER2, APP_UID2, 2222, 3333, 4444, 5555);
prepareUidBatteryConsumer(USER1, APP_UID3, 3030, 4040, 5050, 6060);
prepareUidBatteryConsumer(USER2, APP_UID3, 4321, 5432, 6543, 7654);
}
private void prepareUidBatteryConsumer(int userId, int uid, long audioDuration1Ms,
long audioDuration2Ms, long videoDuration1Ms, long videoDuration2Ms) {
BatteryStatsImpl.Uid uidStats = mStatsRule.getUidStats(UserHandle.getUid(userId, uid));
// Use "audio" and "video" to fake some power consumption. Could be any other type of usage.
uidStats.noteAudioTurnedOnLocked(0);
uidStats.noteAudioTurnedOffLocked(audioDuration1Ms);
uidStats.noteAudioTurnedOnLocked(1000000);
uidStats.noteAudioTurnedOffLocked(1000000 + audioDuration2Ms);
uidStats.noteVideoTurnedOnLocked(0);
uidStats.noteVideoTurnedOffLocked(videoDuration1Ms);
uidStats.noteVideoTurnedOnLocked(2000000);
uidStats.noteVideoTurnedOffLocked(2000000 + videoDuration2Ms);
}
private static class FakeAudioPowerCalculator extends PowerCalculator {
@Override
protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
long durationMs = u.getAudioTurnedOnTimer().getTotalTimeLocked(rawRealtimeUs, 0);
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_AUDIO, durationMs / 1000);
}
}
private static class FakeVideoPowerCalculator extends PowerCalculator {
@Override
protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
long durationMs = u.getVideoTurnedOnTimer().getTotalTimeLocked(rawRealtimeUs, 0);
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_VIDEO, durationMs / 1000);
}
}
}