1 /* 2 * Copyright (C) 2020 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 com.android.server.powerstats; 18 19 import java.io.FileInputStream; 20 import java.io.IOException; 21 22 /** 23 * This class implements a utility to parse ODPM data out 24 * of incident reports contained in bugreports. The data 25 * is output to STDOUT in csv format. 26 */ 27 public class PowerStatsServiceProtoParser { printEnergyMeterInfo(PowerStatsServiceMeterProto proto)28 private static void printEnergyMeterInfo(PowerStatsServiceMeterProto proto) { 29 String csvHeader = new String(); 30 for (int i = 0; i < proto.getChannelCount(); i++) { 31 ChannelProto energyMeterInfo = proto.getChannel(i); 32 csvHeader += "Index,Timestamp,Duration," + energyMeterInfo.getId() 33 + "/" + energyMeterInfo.getName() + "/" + energyMeterInfo.getSubsystem() + ","; 34 } 35 System.out.println(csvHeader); 36 } 37 printEnergyMeasurements(PowerStatsServiceMeterProto proto)38 private static void printEnergyMeasurements(PowerStatsServiceMeterProto proto) { 39 int energyMeterInfoCount = proto.getChannelCount(); 40 41 if (energyMeterInfoCount > 0) { 42 int energyMeasurementCount = proto.getEnergyMeasurementCount(); 43 int energyMeasurementSetCount = energyMeasurementCount / energyMeterInfoCount; 44 45 for (int i = 0; i < energyMeasurementSetCount; i++) { 46 String csvRow = new String(); 47 for (int j = 0; j < energyMeterInfoCount; j++) { 48 EnergyMeasurementProto energyMeasurement = 49 proto.getEnergyMeasurement(i * energyMeterInfoCount + j); 50 csvRow += energyMeasurement.getId() + "," 51 + energyMeasurement.getTimestampMs() + "," 52 + energyMeasurement.getDurationMs() + "," 53 + energyMeasurement.getEnergyUws() + ","; 54 } 55 System.out.println(csvRow); 56 } 57 } else { 58 System.out.println("Error: energyMeterInfoCount is zero"); 59 } 60 } 61 printEnergyConsumer(PowerStatsServiceModelProto proto)62 private static void printEnergyConsumer(PowerStatsServiceModelProto proto) { 63 String csvHeader = new String(); 64 for (int i = 0; i < proto.getEnergyConsumerCount(); i++) { 65 EnergyConsumerProto energyConsumer = proto.getEnergyConsumer(i); 66 csvHeader += "Index,Timestamp," + energyConsumer.getId() + "/" 67 + energyConsumer.getOrdinal() + "/" 68 + energyConsumer.getType() + "/" 69 + energyConsumer.getName() + ","; 70 } 71 System.out.println(csvHeader); 72 } 73 printEnergyConsumerResults(PowerStatsServiceModelProto proto)74 private static void printEnergyConsumerResults(PowerStatsServiceModelProto proto) { 75 int energyConsumerCount = proto.getEnergyConsumerCount(); 76 77 if (energyConsumerCount > 0) { 78 int energyConsumerResultCount = proto.getEnergyConsumerResultCount(); 79 int energyConsumerResultSetCount = energyConsumerResultCount / energyConsumerCount; 80 81 for (int i = 0; i < energyConsumerResultSetCount; i++) { 82 String csvRow = new String(); 83 for (int j = 0; j < energyConsumerCount; j++) { 84 EnergyConsumerResultProto energyConsumerResult = 85 proto.getEnergyConsumerResult(i * energyConsumerCount + j); 86 csvRow += energyConsumerResult.getId() + "," 87 + energyConsumerResult.getTimestampMs() + "," 88 + energyConsumerResult.getEnergyUws() + ","; 89 for (int k = 0; k < energyConsumerResult.getAttributionCount(); k++) { 90 final EnergyConsumerAttributionProto energyConsumerAttribution = 91 energyConsumerResult.getAttribution(k); 92 csvRow += energyConsumerAttribution.getUid() + "," 93 + energyConsumerAttribution.getEnergyUws() + ","; 94 } 95 } 96 System.out.println(csvRow); 97 } 98 } else { 99 System.out.println("Error: energyConsumerCount is zero"); 100 } 101 } 102 printPowerEntityInfo(PowerStatsServiceResidencyProto proto)103 private static void printPowerEntityInfo(PowerStatsServiceResidencyProto proto) { 104 String csvHeader = new String(); 105 for (int i = 0; i < proto.getPowerEntityCount(); i++) { 106 PowerEntityProto powerEntity = proto.getPowerEntity(i); 107 csvHeader += powerEntity.getId() + "," + powerEntity.getName() + ","; 108 for (int j = 0; j < powerEntity.getStatesCount(); j++) { 109 StateProto state = powerEntity.getStates(j); 110 csvHeader += state.getId() + "," + state.getName() + ","; 111 } 112 } 113 System.out.println(csvHeader); 114 } 115 printStateResidencyResult(PowerStatsServiceResidencyProto proto)116 private static void printStateResidencyResult(PowerStatsServiceResidencyProto proto) { 117 for (int i = 0; i < proto.getStateResidencyResultCount(); i++) { 118 String csvRow = new String(); 119 120 StateResidencyResultProto stateResidencyResult = proto.getStateResidencyResult(i); 121 csvRow += stateResidencyResult.getId() + ","; 122 123 for (int j = 0; j < stateResidencyResult.getStateResidencyDataCount(); j++) { 124 StateResidencyProto stateResidency = stateResidencyResult.getStateResidencyData(j); 125 csvRow += stateResidency.getId() + "," 126 + stateResidency.getTotalTimeInStateMs() + "," 127 + stateResidency.getTotalStateEntryCount() + "," 128 + stateResidency.getLastEntryTimestampMs() + ","; 129 } 130 System.out.println(csvRow); 131 } 132 } 133 generateCsvFile(String pathToIncidentReport)134 private static void generateCsvFile(String pathToIncidentReport) { 135 try { 136 // Print power meter data. 137 IncidentReportMeterProto irMeterProto = 138 IncidentReportMeterProto.parseFrom(new FileInputStream(pathToIncidentReport)); 139 140 if (irMeterProto.hasIncidentReport()) { 141 PowerStatsServiceMeterProto pssMeterProto = irMeterProto.getIncidentReport(); 142 printEnergyMeterInfo(pssMeterProto); 143 printEnergyMeasurements(pssMeterProto); 144 } else { 145 System.out.println("Meter incident report not found. Exiting."); 146 } 147 148 // Print power model data. 149 IncidentReportModelProto irModelProto = 150 IncidentReportModelProto.parseFrom(new FileInputStream(pathToIncidentReport)); 151 152 if (irModelProto.hasIncidentReport()) { 153 PowerStatsServiceModelProto pssModelProto = irModelProto.getIncidentReport(); 154 printEnergyConsumer(pssModelProto); 155 printEnergyConsumerResults(pssModelProto); 156 } else { 157 System.out.println("Model incident report not found. Exiting."); 158 } 159 160 // Print state residency data. 161 IncidentReportResidencyProto irResidencyProto = 162 IncidentReportResidencyProto.parseFrom( 163 new FileInputStream(pathToIncidentReport)); 164 165 if (irResidencyProto.hasIncidentReport()) { 166 PowerStatsServiceResidencyProto pssResidencyProto = 167 irResidencyProto.getIncidentReport(); 168 printPowerEntityInfo(pssResidencyProto); 169 printStateResidencyResult(pssResidencyProto); 170 } else { 171 System.out.println("Residency incident report not found. Exiting."); 172 } 173 174 } catch (IOException e) { 175 System.out.println("Unable to open incident report file: " + pathToIncidentReport); 176 System.out.println(e); 177 } 178 } 179 180 /** 181 * This is the entry point to parse the ODPM data out of incident reports. 182 * It requires one argument which is the path to the incident_report.proto 183 * file captured in a bugreport. 184 * 185 * @param args Path to incident_report.proto passed in from command line. 186 */ main(String[] args)187 public static void main(String[] args) { 188 if (args.length > 0) { 189 generateCsvFile(args[0]); 190 } else { 191 System.err.println("Usage: PowerStatsServiceProtoParser <incident_report.proto>"); 192 System.err.println("Missing path to incident_report.proto. Exiting."); 193 System.exit(1); 194 } 195 } 196 } 197