blob: 04f9bf26b43c84e900d1d8babb0db5a834c59c68 [file] [log] [blame]
Mat Bevilacqua81601212020-07-30 17:26:45 -07001/*
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
17package com.android.server.powerstats;
18
19import java.io.FileInputStream;
20import 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 */
27public class PowerStatsServiceProtoParser {
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070028 private static void printEnergyMeterInfo(PowerStatsServiceMeterProto proto) {
Mat Bevilacqua81601212020-07-30 17:26:45 -070029 String csvHeader = new String();
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080030 for (int i = 0; i < proto.getChannelCount(); i++) {
31 ChannelProto energyMeterInfo = proto.getChannel(i);
32 csvHeader += "Index,Timestamp,Duration," + energyMeterInfo.getId()
Mat Bevilacqua1e271f52021-01-27 14:17:49 -080033 + "/" + energyMeterInfo.getName() + "/" + energyMeterInfo.getSubsystem() + ",";
Mat Bevilacqua81601212020-07-30 17:26:45 -070034 }
35 System.out.println(csvHeader);
36 }
37
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070038 private static void printEnergyMeasurements(PowerStatsServiceMeterProto proto) {
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080039 int energyMeterInfoCount = proto.getChannelCount();
Mat Bevilacqua81601212020-07-30 17:26:45 -070040
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070041 if (energyMeterInfoCount > 0) {
42 int energyMeasurementCount = proto.getEnergyMeasurementCount();
43 int energyMeasurementSetCount = energyMeasurementCount / energyMeterInfoCount;
Mat Bevilacqua81601212020-07-30 17:26:45 -070044
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070045 for (int i = 0; i < energyMeasurementSetCount; i++) {
Mat Bevilacqua81601212020-07-30 17:26:45 -070046 String csvRow = new String();
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070047 for (int j = 0; j < energyMeterInfoCount; j++) {
48 EnergyMeasurementProto energyMeasurement =
49 proto.getEnergyMeasurement(i * energyMeterInfoCount + j);
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080050 csvRow += energyMeasurement.getId() + ","
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070051 + energyMeasurement.getTimestampMs() + ","
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080052 + energyMeasurement.getDurationMs() + ","
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070053 + energyMeasurement.getEnergyUws() + ",";
Mat Bevilacqua81601212020-07-30 17:26:45 -070054 }
55 System.out.println(csvRow);
56 }
57 } else {
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070058 System.out.println("Error: energyMeterInfoCount is zero");
59 }
60 }
61
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080062 private static void printEnergyConsumer(PowerStatsServiceModelProto proto) {
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070063 String csvHeader = new String();
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080064 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() + ",";
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070070 }
71 System.out.println(csvHeader);
72 }
73
74 private static void printEnergyConsumerResults(PowerStatsServiceModelProto proto) {
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080075 int energyConsumerCount = proto.getEnergyConsumerCount();
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070076
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080077 if (energyConsumerCount > 0) {
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070078 int energyConsumerResultCount = proto.getEnergyConsumerResultCount();
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080079 int energyConsumerResultSetCount = energyConsumerResultCount / energyConsumerCount;
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070080
81 for (int i = 0; i < energyConsumerResultSetCount; i++) {
82 String csvRow = new String();
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080083 for (int j = 0; j < energyConsumerCount; j++) {
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070084 EnergyConsumerResultProto energyConsumerResult =
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080085 proto.getEnergyConsumerResult(i * energyConsumerCount + j);
86 csvRow += energyConsumerResult.getId() + ","
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070087 + energyConsumerResult.getTimestampMs() + ","
88 + energyConsumerResult.getEnergyUws() + ",";
Mat Bevilacqua3bf71912021-01-19 17:48:50 -080089 for (int k = 0; k < energyConsumerResult.getAttributionCount(); k++) {
90 final EnergyConsumerAttributionProto energyConsumerAttribution =
91 energyConsumerResult.getAttribution(k);
92 csvRow += energyConsumerAttribution.getUid() + ","
93 + energyConsumerAttribution.getEnergyUws() + ",";
94 }
Mat Bevilacquaa375ea02020-09-21 18:59:06 -070095 }
96 System.out.println(csvRow);
97 }
98 } else {
Mat Bevilacqua6058dc22021-01-20 17:45:20 -080099 System.out.println("Error: energyConsumerCount is zero");
Mat Bevilacqua81601212020-07-30 17:26:45 -0700100 }
101 }
102
Mat Bevilacqua723784a2020-12-22 09:57:01 -0800103 private static void printPowerEntityInfo(PowerStatsServiceResidencyProto proto) {
104 String csvHeader = new String();
Mat Bevilacqua6058dc22021-01-20 17:45:20 -0800105 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() + ",";
Mat Bevilacqua723784a2020-12-22 09:57:01 -0800111 }
112 }
113 System.out.println(csvHeader);
114 }
115
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);
Mat Bevilacqua6058dc22021-01-20 17:45:20 -0800121 csvRow += stateResidencyResult.getId() + ",";
Mat Bevilacqua723784a2020-12-22 09:57:01 -0800122
123 for (int j = 0; j < stateResidencyResult.getStateResidencyDataCount(); j++) {
124 StateResidencyProto stateResidency = stateResidencyResult.getStateResidencyData(j);
Mat Bevilacqua6058dc22021-01-20 17:45:20 -0800125 csvRow += stateResidency.getId() + ","
Mat Bevilacqua723784a2020-12-22 09:57:01 -0800126 + stateResidency.getTotalTimeInStateMs() + ","
127 + stateResidency.getTotalStateEntryCount() + ","
128 + stateResidency.getLastEntryTimestampMs() + ",";
129 }
130 System.out.println(csvRow);
131 }
132 }
133
Mat Bevilacqua81601212020-07-30 17:26:45 -0700134 private static void generateCsvFile(String pathToIncidentReport) {
135 try {
Mat Bevilacquaa375ea02020-09-21 18:59:06 -0700136 // Print power meter data.
137 IncidentReportMeterProto irMeterProto =
138 IncidentReportMeterProto.parseFrom(new FileInputStream(pathToIncidentReport));
Mat Bevilacqua81601212020-07-30 17:26:45 -0700139
Mat Bevilacquaa375ea02020-09-21 18:59:06 -0700140 if (irMeterProto.hasIncidentReport()) {
141 PowerStatsServiceMeterProto pssMeterProto = irMeterProto.getIncidentReport();
142 printEnergyMeterInfo(pssMeterProto);
143 printEnergyMeasurements(pssMeterProto);
Mat Bevilacqua81601212020-07-30 17:26:45 -0700144 } else {
Mat Bevilacquaa375ea02020-09-21 18:59:06 -0700145 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();
Mat Bevilacqua6058dc22021-01-20 17:45:20 -0800154 printEnergyConsumer(pssModelProto);
Mat Bevilacquaa375ea02020-09-21 18:59:06 -0700155 printEnergyConsumerResults(pssModelProto);
156 } else {
157 System.out.println("Model incident report not found. Exiting.");
Mat Bevilacqua81601212020-07-30 17:26:45 -0700158 }
Mat Bevilacqua723784a2020-12-22 09:57:01 -0800159
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
Mat Bevilacqua81601212020-07-30 17:26:45 -0700174 } 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 */
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}