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