Merge "Convert UserPowerCalculator to work with BatteryUsageStats" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ca17fb0be4
@@ -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;
|
||||
|
||||
@@ -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}.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
115
core/java/android/os/UserBatteryConsumer.java
Normal file
115
core/java/android/os/UserBatteryConsumer.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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--) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user