1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 import android.annotation.NonNull; 20 import android.util.TypedXmlPullParser; 21 import android.util.TypedXmlSerializer; 22 23 import com.android.internal.os.PowerCalculator; 24 25 import org.xmlpull.v1.XmlPullParser; 26 import org.xmlpull.v1.XmlPullParserException; 27 28 import java.io.IOException; 29 import java.io.PrintWriter; 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * Contains power consumption data attributed to a {@link UserHandle}. 35 * 36 * {@hide} 37 */ 38 public class UserBatteryConsumer extends BatteryConsumer implements Parcelable { 39 private final int mUserId; 40 getUserId()41 public int getUserId() { 42 return mUserId; 43 } 44 UserBatteryConsumer(@onNull UserBatteryConsumer.Builder builder)45 private UserBatteryConsumer(@NonNull UserBatteryConsumer.Builder builder) { 46 super(builder.mPowerComponentsBuilder.build()); 47 mUserId = builder.mUserId; 48 } 49 UserBatteryConsumer(Parcel in)50 private UserBatteryConsumer(Parcel in) { 51 super(new PowerComponents(in)); 52 mUserId = in.readInt(); 53 } 54 55 /** 56 * Writes the contents into a Parcel. 57 */ 58 @Override writeToParcel(@onNull Parcel dest, int flags)59 public void writeToParcel(@NonNull Parcel dest, int flags) { 60 super.writeToParcel(dest, flags); 61 dest.writeInt(mUserId); 62 } 63 64 @Override dump(PrintWriter pw, boolean skipEmptyComponents)65 public void dump(PrintWriter pw, boolean skipEmptyComponents) { 66 final double consumedPower = getConsumedPower(); 67 pw.print("User "); 68 pw.print(mUserId); 69 pw.print(": "); 70 PowerCalculator.printPowerMah(pw, consumedPower); 71 pw.print(" ( "); 72 mPowerComponents.dump(pw, skipEmptyComponents /* skipTotalPowerComponent */); 73 pw.print(" ) "); 74 } 75 76 public static final Creator<UserBatteryConsumer> CREATOR = 77 new Creator<UserBatteryConsumer>() { 78 @Override 79 public UserBatteryConsumer createFromParcel(Parcel in) { 80 return new UserBatteryConsumer(in); 81 } 82 83 @Override 84 public UserBatteryConsumer[] newArray(int size) { 85 return new UserBatteryConsumer[size]; 86 } 87 }; 88 89 @Override describeContents()90 public int describeContents() { 91 return 0; 92 } 93 94 /** Serializes this object to XML */ writeToXml(TypedXmlSerializer serializer)95 void writeToXml(TypedXmlSerializer serializer) throws IOException { 96 if (getConsumedPower() == 0) { 97 return; 98 } 99 100 serializer.startTag(null, BatteryUsageStats.XML_TAG_USER); 101 serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_USER_ID, getUserId()); 102 mPowerComponents.writeToXml(serializer); 103 serializer.endTag(null, BatteryUsageStats.XML_TAG_USER); 104 } 105 106 /** Parses an XML representation and populates the BatteryUsageStats builder */ createFromXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)107 static void createFromXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder) 108 throws XmlPullParserException, IOException { 109 final int userId = parser.getAttributeInt(null, BatteryUsageStats.XML_ATTR_USER_ID); 110 final UserBatteryConsumer.Builder consumerBuilder = 111 builder.getOrCreateUserBatteryConsumerBuilder(userId); 112 113 int eventType = parser.getEventType(); 114 if (eventType != XmlPullParser.START_TAG 115 || !parser.getName().equals(BatteryUsageStats.XML_TAG_USER)) { 116 throw new XmlPullParserException("Invalid XML parser state"); 117 } 118 while (!(eventType == XmlPullParser.END_TAG 119 && parser.getName().equals(BatteryUsageStats.XML_TAG_USER)) 120 && eventType != XmlPullParser.END_DOCUMENT) { 121 if (eventType == XmlPullParser.START_TAG) { 122 if (parser.getName().equals(BatteryUsageStats.XML_TAG_POWER_COMPONENTS)) { 123 PowerComponents.parseXml(parser, consumerBuilder.mPowerComponentsBuilder); 124 } 125 } 126 eventType = parser.next(); 127 } 128 } 129 130 /** 131 * Builder for UserBatteryConsumer. 132 */ 133 public static final class Builder extends BaseBuilder<Builder> { 134 private final int mUserId; 135 private List<UidBatteryConsumer.Builder> mUidBatteryConsumers; 136 Builder(@onNull String[] customPowerComponentNames, boolean includePowerModels, int userId)137 Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels, 138 int userId) { 139 super(customPowerComponentNames, includePowerModels); 140 mUserId = userId; 141 } 142 143 /** 144 * Add a UidBatteryConsumer to this UserBatteryConsumer. 145 * <p> 146 * Calculated power and duration components of the added UID battery consumers 147 * are aggregated at the time the UserBatteryConsumer is built by the {@link #build()} 148 * method. 149 * </p> 150 */ addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder)151 public void addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder) { 152 if (mUidBatteryConsumers == null) { 153 mUidBatteryConsumers = new ArrayList<>(); 154 } 155 mUidBatteryConsumers.add(uidBatteryConsumerBuilder); 156 } 157 158 /** 159 * Creates a read-only object out of the Builder values. 160 */ 161 @NonNull build()162 public UserBatteryConsumer build() { 163 if (mUidBatteryConsumers != null) { 164 for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) { 165 UidBatteryConsumer.Builder uidBatteryConsumer = mUidBatteryConsumers.get(i); 166 mPowerComponentsBuilder.addPowerAndDuration( 167 uidBatteryConsumer.mPowerComponentsBuilder); 168 } 169 } 170 return new UserBatteryConsumer(this); 171 } 172 } 173 } 174