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