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