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 
21 import com.android.modules.utils.TypedXmlPullParser;
22 import com.android.modules.utils.TypedXmlSerializer;
23 
24 import org.xmlpull.v1.XmlPullParser;
25 import org.xmlpull.v1.XmlPullParserException;
26 
27 import java.io.IOException;
28 import java.io.PrintWriter;
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  * Contains power consumption data attributed to a {@link UserHandle}.
34  *
35  * {@hide}
36  */
37 public class UserBatteryConsumer extends BatteryConsumer {
38     static final int CONSUMER_TYPE_USER = 2;
39 
40     private static final int COLUMN_INDEX_USER_ID = BatteryConsumer.COLUMN_COUNT;
41 
42     static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 1;
43 
UserBatteryConsumer(BatteryConsumerData data)44     UserBatteryConsumer(BatteryConsumerData data) {
45         super(data);
46     }
47 
UserBatteryConsumer(@onNull UserBatteryConsumer.Builder builder)48     private UserBatteryConsumer(@NonNull UserBatteryConsumer.Builder builder) {
49         super(builder.mData, builder.mPowerComponentsBuilder.build());
50     }
51 
getUserId()52     public int getUserId() {
53         return mData.getInt(COLUMN_INDEX_USER_ID);
54     }
55 
56     @Override
dump(PrintWriter pw, boolean skipEmptyComponents)57     public void dump(PrintWriter pw, boolean skipEmptyComponents) {
58         final double consumedPower = getConsumedPower();
59         pw.print("User ");
60         pw.print(getUserId());
61         pw.print(": ");
62         pw.print(BatteryStats.formatCharge(consumedPower));
63         pw.print(" ( ");
64         mPowerComponents.dump(pw, skipEmptyComponents  /* skipTotalPowerComponent */);
65         pw.print(" ) ");
66     }
67 
68     /** Serializes this object to XML */
writeToXml(TypedXmlSerializer serializer)69     void writeToXml(TypedXmlSerializer serializer) throws IOException {
70         if (getConsumedPower() == 0) {
71             return;
72         }
73 
74         serializer.startTag(null, BatteryUsageStats.XML_TAG_USER);
75         serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_USER_ID, getUserId());
76         mPowerComponents.writeToXml(serializer);
77         serializer.endTag(null, BatteryUsageStats.XML_TAG_USER);
78     }
79 
80     /** Parses an XML representation and populates the BatteryUsageStats builder */
createFromXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)81     static void createFromXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)
82             throws XmlPullParserException, IOException {
83         final int userId = parser.getAttributeInt(null, BatteryUsageStats.XML_ATTR_USER_ID);
84         final UserBatteryConsumer.Builder consumerBuilder =
85                 builder.getOrCreateUserBatteryConsumerBuilder(userId);
86 
87         int eventType = parser.getEventType();
88         if (eventType != XmlPullParser.START_TAG
89                 || !parser.getName().equals(BatteryUsageStats.XML_TAG_USER)) {
90             throw new XmlPullParserException("Invalid XML parser state");
91         }
92         while (!(eventType == XmlPullParser.END_TAG
93                 && parser.getName().equals(BatteryUsageStats.XML_TAG_USER))
94                 && eventType != XmlPullParser.END_DOCUMENT) {
95             if (eventType == XmlPullParser.START_TAG) {
96                 if (parser.getName().equals(BatteryUsageStats.XML_TAG_POWER_COMPONENTS)) {
97                     PowerComponents.parseXml(parser, consumerBuilder.mPowerComponentsBuilder);
98                 }
99             }
100             eventType = parser.next();
101         }
102     }
103 
104     /**
105      * Builder for UserBatteryConsumer.
106      */
107     public static final class Builder extends BaseBuilder<Builder> {
108         private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
109 
Builder(BatteryConsumerData data, int userId, double minConsumedPowerThreshold)110         Builder(BatteryConsumerData data, int userId, double minConsumedPowerThreshold) {
111             super(data, CONSUMER_TYPE_USER, minConsumedPowerThreshold);
112             data.putLong(COLUMN_INDEX_USER_ID, userId);
113         }
114 
115         /**
116          * Add a UidBatteryConsumer to this UserBatteryConsumer.
117          * <p>
118          * Calculated power and duration components of the added UID battery consumers
119          * are aggregated at the time the UserBatteryConsumer is built by the {@link #build()}
120          * method.
121          * </p>
122          */
addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder)123         public void addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder) {
124             if (mUidBatteryConsumers == null) {
125                 mUidBatteryConsumers = new ArrayList<>();
126             }
127             mUidBatteryConsumers.add(uidBatteryConsumerBuilder);
128         }
129 
130         /**
131          * Creates a read-only object out of the Builder values.
132          */
133         @NonNull
build()134         public UserBatteryConsumer build() {
135             if (mUidBatteryConsumers != null) {
136                 for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) {
137                     UidBatteryConsumer.Builder uidBatteryConsumer = mUidBatteryConsumers.get(i);
138                     mPowerComponentsBuilder.addPowerAndDuration(
139                             uidBatteryConsumer.mPowerComponentsBuilder);
140                 }
141             }
142             return new UserBatteryConsumer(this);
143         }
144     }
145 }
146