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.proto.ProtoOutputStream;
21 
22 import com.android.modules.utils.TypedXmlPullParser;
23 import com.android.modules.utils.TypedXmlSerializer;
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 
31 /**
32  * Contains power consumption data across the entire device.
33  *
34  * {@hide}
35  */
36 @android.ravenwood.annotation.RavenwoodKeepWholeClass
37 public final class AggregateBatteryConsumer extends BatteryConsumer {
38     static final int CONSUMER_TYPE_AGGREGATE = 0;
39 
40     static final int COLUMN_INDEX_SCOPE = BatteryConsumer.COLUMN_COUNT;
41     static final int COLUMN_INDEX_CONSUMED_POWER = COLUMN_INDEX_SCOPE + 1;
42     static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 2;
43 
AggregateBatteryConsumer(BatteryConsumerData data)44     AggregateBatteryConsumer(BatteryConsumerData data) {
45         super(data);
46     }
47 
AggregateBatteryConsumer(@onNull Builder builder)48     private AggregateBatteryConsumer(@NonNull Builder builder) {
49         super(builder.mData, builder.mPowerComponentsBuilder.build());
50     }
51 
getScope()52     int getScope() {
53         return mData.getInt(COLUMN_INDEX_SCOPE);
54     }
55 
56     @Override
dump(PrintWriter pw, boolean skipEmptyComponents)57     public void dump(PrintWriter pw, boolean skipEmptyComponents) {
58         mPowerComponents.dump(pw, skipEmptyComponents);
59     }
60 
61     @Override
getConsumedPower()62     public double getConsumedPower() {
63         return mData.getDouble(COLUMN_INDEX_CONSUMED_POWER);
64     }
65 
66     /** Serializes this object to XML */
writeToXml(TypedXmlSerializer serializer, @BatteryUsageStats.AggregateBatteryConsumerScope int scope)67     void writeToXml(TypedXmlSerializer serializer,
68             @BatteryUsageStats.AggregateBatteryConsumerScope int scope) throws IOException {
69         serializer.startTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
70         serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_SCOPE, scope);
71         serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, getConsumedPower());
72         mPowerComponents.writeToXml(serializer);
73         serializer.endTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
74     }
75 
76     /** Parses an XML representation and populates the BatteryUsageStats builder */
parseXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)77     static void parseXml(TypedXmlPullParser parser, BatteryUsageStats.Builder builder)
78             throws XmlPullParserException, IOException {
79         final int scope = parser.getAttributeInt(null, BatteryUsageStats.XML_ATTR_SCOPE);
80         final Builder consumerBuilder = builder.getAggregateBatteryConsumerBuilder(scope);
81 
82         int eventType = parser.getEventType();
83         if (eventType != XmlPullParser.START_TAG || !parser.getName().equals(
84                 BatteryUsageStats.XML_TAG_AGGREGATE)) {
85             throw new XmlPullParserException("Invalid XML parser state");
86         }
87 
88         consumerBuilder.setConsumedPower(
89                 parser.getAttributeDouble(null, BatteryUsageStats.XML_ATTR_POWER));
90 
91         while (!(eventType == XmlPullParser.END_TAG && parser.getName().equals(
92                 BatteryUsageStats.XML_TAG_AGGREGATE))
93                 && eventType != XmlPullParser.END_DOCUMENT) {
94             if (eventType == XmlPullParser.START_TAG) {
95                 if (parser.getName().equals(BatteryUsageStats.XML_TAG_POWER_COMPONENTS)) {
96                     PowerComponents.parseXml(parser, consumerBuilder.mPowerComponentsBuilder);
97                 }
98             }
99             eventType = parser.next();
100         }
101     }
102 
writePowerComponentModelProto(@onNull ProtoOutputStream proto)103     void writePowerComponentModelProto(@NonNull ProtoOutputStream proto) {
104         for (int i = 0; i < POWER_COMPONENT_COUNT; i++) {
105             final int powerModel = getPowerModel(i);
106             if (powerModel == BatteryConsumer.POWER_MODEL_UNDEFINED) continue;
107 
108             final long token = proto.start(BatteryUsageStatsAtomsProto.COMPONENT_MODELS);
109             proto.write(BatteryUsageStatsAtomsProto.PowerComponentModel.COMPONENT, i);
110             proto.write(BatteryUsageStatsAtomsProto.PowerComponentModel.POWER_MODEL,
111                     powerModelToProtoEnum(powerModel));
112             proto.end(token);
113         }
114     }
115 
116     /**
117      * Builder for DeviceBatteryConsumer.
118      */
119     public static final class Builder extends BaseBuilder<AggregateBatteryConsumer.Builder> {
Builder(BatteryConsumer.BatteryConsumerData data, int scope, double minConsumedPowerThreshold)120         public Builder(BatteryConsumer.BatteryConsumerData data, int scope,
121                 double minConsumedPowerThreshold) {
122             super(data, CONSUMER_TYPE_AGGREGATE, minConsumedPowerThreshold);
123             data.putInt(COLUMN_INDEX_SCOPE, scope);
124         }
125 
126         /**
127          * Sets the total power included in this aggregate.
128          */
setConsumedPower(double consumedPowerMah)129         public Builder setConsumedPower(double consumedPowerMah) {
130             mData.putDouble(COLUMN_INDEX_CONSUMED_POWER, consumedPowerMah);
131             return this;
132         }
133 
134         /**
135          * Adds power and usage duration from the supplied AggregateBatteryConsumer.
136          */
add(AggregateBatteryConsumer aggregateBatteryConsumer)137         public void add(AggregateBatteryConsumer aggregateBatteryConsumer) {
138             setConsumedPower(mData.getDouble(COLUMN_INDEX_CONSUMED_POWER)
139                     + aggregateBatteryConsumer.getConsumedPower());
140             mPowerComponentsBuilder.addPowerAndDuration(aggregateBatteryConsumer.mPowerComponents);
141         }
142 
143         /**
144          * Creates a read-only object out of the Builder values.
145          */
146         @NonNull
build()147         public AggregateBatteryConsumer build() {
148             return new AggregateBatteryConsumer(this);
149         }
150     }
151 }
152