blob: 688f0bf5e55f037215d9aba0d018fa03ac7fa07e [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.powerstats;
import android.hardware.power.stats.Channel;
import android.hardware.power.stats.EnergyConsumer;
import android.hardware.power.stats.EnergyConsumerAttribution;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyMeasurement;
import android.hardware.power.stats.PowerEntity;
import android.hardware.power.stats.State;
import android.hardware.power.stats.StateResidency;
import android.hardware.power.stats.StateResidencyResult;
import android.util.Slog;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
import android.util.proto.WireTypeMismatchException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* ProtoStreamUtils provides helper functions for the PowerStats HAL objects returned from calls
* to the PowerStats HAL APIs. It provides functions to pack/unpack object arrays to/from protobuf
* format. These helper functions are required since frameworks code uses the genstream option
* when generating source code and therefore, getter/setter helper functions are not available. The
* protobufs need to be packed/unpacked in a more manual way using
* ProtoOutputStream/ProtoInputStream. It also provides print() functions for debugging purposes.
*/
public class ProtoStreamUtils {
private static final String TAG = ProtoStreamUtils.class.getSimpleName();
static class PowerEntityUtils {
public static byte[] getProtoBytes(PowerEntity[] powerEntity) {
ProtoOutputStream pos = new ProtoOutputStream();
packProtoMessage(powerEntity, pos);
return pos.getBytes();
}
public static void packProtoMessage(PowerEntity[] powerEntity,
ProtoOutputStream pos) {
if (powerEntity == null) return;
for (int i = 0; i < powerEntity.length; i++) {
long peToken = pos.start(PowerStatsServiceResidencyProto.POWER_ENTITY);
pos.write(PowerEntityProto.ID, powerEntity[i].id);
pos.write(PowerEntityProto.NAME, powerEntity[i].name);
if (powerEntity[i].states != null) {
final int statesLength = powerEntity[i].states.length;
for (int j = 0; j < statesLength; j++) {
final State state = powerEntity[i].states[j];
long stateToken = pos.start(PowerEntityProto.STATES);
pos.write(StateProto.ID, state.id);
pos.write(StateProto.NAME, state.name);
pos.end(stateToken);
}
}
pos.end(peToken);
}
}
public static void print(PowerEntity[] powerEntity) {
if (powerEntity == null) return;
for (int i = 0; i < powerEntity.length; i++) {
Slog.d(TAG, "powerEntityId: " + powerEntity[i].id
+ ", powerEntityName: " + powerEntity[i].name);
if (powerEntity[i].states != null) {
for (int j = 0; j < powerEntity[i].states.length; j++) {
Slog.d(TAG, " StateId: " + powerEntity[i].states[j].id
+ ", StateName: " + powerEntity[i].states[j].name);
}
}
}
}
public static void dumpsys(PowerEntity[] powerEntity, PrintWriter pw) {
if (powerEntity == null) return;
for (int i = 0; i < powerEntity.length; i++) {
pw.println("PowerEntityId: " + powerEntity[i].id
+ ", PowerEntityName: " + powerEntity[i].name);
if (powerEntity[i].states != null) {
for (int j = 0; j < powerEntity[i].states.length; j++) {
pw.println(" StateId: " + powerEntity[i].states[j].id
+ ", StateName: " + powerEntity[i].states[j].name);
}
}
}
}
}
static class StateResidencyResultUtils {
public static void adjustTimeSinceBootToEpoch(StateResidencyResult[] stateResidencyResult,
long startWallTime) {
if (stateResidencyResult == null) return;
for (int i = 0; i < stateResidencyResult.length; i++) {
final int stateLength = stateResidencyResult[i].stateResidencyData.length;
for (int j = 0; j < stateLength; j++) {
final StateResidency stateResidencyData =
stateResidencyResult[i].stateResidencyData[j];
stateResidencyData.lastEntryTimestampMs += startWallTime;
}
}
}
public static byte[] getProtoBytes(StateResidencyResult[] stateResidencyResult) {
ProtoOutputStream pos = new ProtoOutputStream();
packProtoMessage(stateResidencyResult, pos);
return pos.getBytes();
}
public static void packProtoMessage(StateResidencyResult[] stateResidencyResult,
ProtoOutputStream pos) {
if (stateResidencyResult == null) return;
for (int i = 0; i < stateResidencyResult.length; i++) {
final int stateLength = stateResidencyResult[i].stateResidencyData.length;
long srrToken = pos.start(PowerStatsServiceResidencyProto.STATE_RESIDENCY_RESULT);
pos.write(StateResidencyResultProto.ID,
stateResidencyResult[i].id);
for (int j = 0; j < stateLength; j++) {
final StateResidency stateResidencyData =
stateResidencyResult[i].stateResidencyData[j];
long srdToken = pos.start(StateResidencyResultProto.STATE_RESIDENCY_DATA);
pos.write(StateResidencyProto.ID, stateResidencyData.id);
pos.write(StateResidencyProto.TOTAL_TIME_IN_STATE_MS,
stateResidencyData.totalTimeInStateMs);
pos.write(StateResidencyProto.TOTAL_STATE_ENTRY_COUNT,
stateResidencyData.totalStateEntryCount);
pos.write(StateResidencyProto.LAST_ENTRY_TIMESTAMP_MS,
stateResidencyData.lastEntryTimestampMs);
pos.end(srdToken);
}
pos.end(srrToken);
}
}
public static StateResidencyResult[] unpackProtoMessage(byte[] data) throws IOException {
final ProtoInputStream pis = new ProtoInputStream(new ByteArrayInputStream(data));
List<StateResidencyResult> stateResidencyResultList =
new ArrayList<StateResidencyResult>();
while (true) {
try {
int nextField = pis.nextField();
StateResidencyResult stateResidencyResult = new StateResidencyResult();
if (nextField == (int) PowerStatsServiceResidencyProto.STATE_RESIDENCY_RESULT) {
long token =
pis.start(PowerStatsServiceResidencyProto.STATE_RESIDENCY_RESULT);
stateResidencyResultList.add(unpackStateResidencyResultProto(pis));
pis.end(token);
} else if (nextField == ProtoInputStream.NO_MORE_FIELDS) {
return stateResidencyResultList.toArray(
new StateResidencyResult[stateResidencyResultList.size()]);
} else {
Slog.e(TAG, "Unhandled field in PowerStatsServiceResidencyProto: "
+ ProtoUtils.currentFieldToString(pis));
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in PowerStatsServiceResidencyProto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
private static StateResidencyResult unpackStateResidencyResultProto(ProtoInputStream pis)
throws IOException {
StateResidencyResult stateResidencyResult = new StateResidencyResult();
List<StateResidency> stateResidencyList = new ArrayList<StateResidency>();
while (true) {
try {
switch (pis.nextField()) {
case (int) StateResidencyResultProto.ID:
stateResidencyResult.id = pis.readInt(StateResidencyResultProto.ID);
break;
case (int) StateResidencyResultProto.STATE_RESIDENCY_DATA:
long token = pis.start(StateResidencyResultProto.STATE_RESIDENCY_DATA);
stateResidencyList.add(unpackStateResidencyProto(pis));
pis.end(token);
break;
case ProtoInputStream.NO_MORE_FIELDS:
stateResidencyResult.stateResidencyData = stateResidencyList.toArray(
new StateResidency[stateResidencyList.size()]);
return stateResidencyResult;
default:
Slog.e(TAG, "Unhandled field in StateResidencyResultProto: "
+ ProtoUtils.currentFieldToString(pis));
break;
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in StateResidencyResultProto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
private static StateResidency unpackStateResidencyProto(ProtoInputStream pis)
throws IOException {
StateResidency stateResidency = new StateResidency();
while (true) {
try {
switch (pis.nextField()) {
case (int) StateResidencyProto.ID:
stateResidency.id = pis.readInt(StateResidencyProto.ID);
break;
case (int) StateResidencyProto.TOTAL_TIME_IN_STATE_MS:
stateResidency.totalTimeInStateMs =
pis.readLong(StateResidencyProto.TOTAL_TIME_IN_STATE_MS);
break;
case (int) StateResidencyProto.TOTAL_STATE_ENTRY_COUNT:
stateResidency.totalStateEntryCount =
pis.readLong(StateResidencyProto.TOTAL_STATE_ENTRY_COUNT);
break;
case (int) StateResidencyProto.LAST_ENTRY_TIMESTAMP_MS:
stateResidency.lastEntryTimestampMs =
pis.readLong(StateResidencyProto.LAST_ENTRY_TIMESTAMP_MS);
break;
case ProtoInputStream.NO_MORE_FIELDS:
return stateResidency;
default:
Slog.e(TAG, "Unhandled field in StateResidencyProto: "
+ ProtoUtils.currentFieldToString(pis));
break;
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in StateResidencyProto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
public static void print(StateResidencyResult[] stateResidencyResult) {
if (stateResidencyResult == null) return;
for (int i = 0; i < stateResidencyResult.length; i++) {
Slog.d(TAG, "PowerEntityId: " + stateResidencyResult[i].id);
for (int j = 0; j < stateResidencyResult[i].stateResidencyData.length; j++) {
Slog.d(TAG, " StateId: "
+ stateResidencyResult[i].stateResidencyData[j].id
+ ", TotalTimeInStateMs: "
+ stateResidencyResult[i].stateResidencyData[j].totalTimeInStateMs
+ ", TotalStateEntryCount: "
+ stateResidencyResult[i].stateResidencyData[j].totalStateEntryCount
+ ", LastEntryTimestampMs: "
+ stateResidencyResult[i].stateResidencyData[j].lastEntryTimestampMs);
}
}
}
}
static class ChannelUtils {
public static byte[] getProtoBytes(Channel[] channel) {
ProtoOutputStream pos = new ProtoOutputStream();
packProtoMessage(channel, pos);
return pos.getBytes();
}
public static void packProtoMessage(Channel[] channel, ProtoOutputStream pos) {
if (channel == null) return;
for (int i = 0; i < channel.length; i++) {
long token = pos.start(PowerStatsServiceMeterProto.CHANNEL);
pos.write(ChannelProto.ID, channel[i].id);
pos.write(ChannelProto.NAME, channel[i].name);
pos.write(ChannelProto.SUBSYSTEM, channel[i].subsystem);
pos.end(token);
}
}
public static void print(Channel[] channel) {
if (channel == null) return;
for (int i = 0; i < channel.length; i++) {
Slog.d(TAG, "ChannelId: " + channel[i].id
+ ", ChannelName: " + channel[i].name
+ ", ChannelSubsystem: " + channel[i].subsystem);
}
}
public static void dumpsys(Channel[] channel, PrintWriter pw) {
if (channel == null) return;
for (int i = 0; i < channel.length; i++) {
pw.println("ChannelId: " + channel[i].id
+ ", ChannelName: " + channel[i].name
+ ", ChannelSubsystem: " + channel[i].subsystem);
}
}
}
static class EnergyMeasurementUtils {
public static void adjustTimeSinceBootToEpoch(EnergyMeasurement[] energyMeasurement,
long startWallTime) {
if (energyMeasurement == null) return;
for (int i = 0; i < energyMeasurement.length; i++) {
energyMeasurement[i].timestampMs += startWallTime;
}
}
public static byte[] getProtoBytes(EnergyMeasurement[] energyMeasurement) {
ProtoOutputStream pos = new ProtoOutputStream();
packProtoMessage(energyMeasurement, pos);
return pos.getBytes();
}
public static void packProtoMessage(EnergyMeasurement[] energyMeasurement,
ProtoOutputStream pos) {
if (energyMeasurement == null) return;
for (int i = 0; i < energyMeasurement.length; i++) {
long token = pos.start(PowerStatsServiceMeterProto.ENERGY_MEASUREMENT);
pos.write(EnergyMeasurementProto.ID, energyMeasurement[i].id);
pos.write(EnergyMeasurementProto.TIMESTAMP_MS, energyMeasurement[i].timestampMs);
pos.write(EnergyMeasurementProto.DURATION_MS, energyMeasurement[i].durationMs);
pos.write(EnergyMeasurementProto.ENERGY_UWS, energyMeasurement[i].energyUWs);
pos.end(token);
}
}
public static EnergyMeasurement[] unpackProtoMessage(byte[] data) throws IOException {
final ProtoInputStream pis = new ProtoInputStream(new ByteArrayInputStream(data));
List<EnergyMeasurement> energyMeasurementList = new ArrayList<EnergyMeasurement>();
while (true) {
try {
int nextField = pis.nextField();
EnergyMeasurement energyMeasurement = new EnergyMeasurement();
if (nextField == (int) PowerStatsServiceMeterProto.ENERGY_MEASUREMENT) {
long token = pis.start(PowerStatsServiceMeterProto.ENERGY_MEASUREMENT);
energyMeasurementList.add(unpackEnergyMeasurementProto(pis));
pis.end(token);
} else if (nextField == ProtoInputStream.NO_MORE_FIELDS) {
return energyMeasurementList.toArray(
new EnergyMeasurement[energyMeasurementList.size()]);
} else {
Slog.e(TAG, "Unhandled field in proto: "
+ ProtoUtils.currentFieldToString(pis));
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in proto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
private static EnergyMeasurement unpackEnergyMeasurementProto(ProtoInputStream pis)
throws IOException {
EnergyMeasurement energyMeasurement = new EnergyMeasurement();
while (true) {
try {
switch (pis.nextField()) {
case (int) EnergyMeasurementProto.ID:
energyMeasurement.id =
pis.readInt(EnergyMeasurementProto.ID);
break;
case (int) EnergyMeasurementProto.TIMESTAMP_MS:
energyMeasurement.timestampMs =
pis.readLong(EnergyMeasurementProto.TIMESTAMP_MS);
break;
case (int) EnergyMeasurementProto.DURATION_MS:
energyMeasurement.durationMs =
pis.readLong(EnergyMeasurementProto.DURATION_MS);
break;
case (int) EnergyMeasurementProto.ENERGY_UWS:
energyMeasurement.energyUWs =
pis.readLong(EnergyMeasurementProto.ENERGY_UWS);
break;
case ProtoInputStream.NO_MORE_FIELDS:
return energyMeasurement;
default:
Slog.e(TAG, "Unhandled field in EnergyMeasurementProto: "
+ ProtoUtils.currentFieldToString(pis));
break;
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in EnergyMeasurementProto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
public static void print(EnergyMeasurement[] energyMeasurement) {
if (energyMeasurement == null) return;
for (int i = 0; i < energyMeasurement.length; i++) {
Slog.d(TAG, "ChannelId: " + energyMeasurement[i].id
+ ", Timestamp (ms): " + energyMeasurement[i].timestampMs
+ ", Duration (ms): " + energyMeasurement[i].durationMs
+ ", Energy (uWs): " + energyMeasurement[i].energyUWs);
}
}
}
static class EnergyConsumerUtils {
public static byte[] getProtoBytes(EnergyConsumer[] energyConsumer) {
ProtoOutputStream pos = new ProtoOutputStream();
packProtoMessage(energyConsumer, pos);
return pos.getBytes();
}
public static void packProtoMessage(EnergyConsumer[] energyConsumer,
ProtoOutputStream pos) {
if (energyConsumer == null) return;
for (int i = 0; i < energyConsumer.length; i++) {
long token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER);
pos.write(EnergyConsumerProto.ID, energyConsumer[i].id);
pos.write(EnergyConsumerProto.ORDINAL, energyConsumer[i].ordinal);
pos.write(EnergyConsumerProto.TYPE, energyConsumer[i].type);
pos.write(EnergyConsumerProto.NAME, energyConsumer[i].name);
pos.end(token);
}
}
public static EnergyConsumer[] unpackProtoMessage(byte[] data) throws IOException {
final ProtoInputStream pis = new ProtoInputStream(new ByteArrayInputStream(data));
List<EnergyConsumer> energyConsumerList = new ArrayList<EnergyConsumer>();
while (true) {
try {
int nextField = pis.nextField();
EnergyConsumer energyConsumer = new EnergyConsumer();
if (nextField == (int) PowerStatsServiceModelProto.ENERGY_CONSUMER) {
long token = pis.start(PowerStatsServiceModelProto.ENERGY_CONSUMER);
energyConsumerList.add(unpackEnergyConsumerProto(pis));
pis.end(token);
} else if (nextField == ProtoInputStream.NO_MORE_FIELDS) {
return energyConsumerList.toArray(
new EnergyConsumer[energyConsumerList.size()]);
} else {
Slog.e(TAG, "Unhandled field in proto: "
+ ProtoUtils.currentFieldToString(pis));
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in proto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
private static EnergyConsumer unpackEnergyConsumerProto(ProtoInputStream pis)
throws IOException {
final EnergyConsumer energyConsumer = new EnergyConsumer();
while (true) {
try {
switch (pis.nextField()) {
case (int) EnergyConsumerProto.ID:
energyConsumer.id = pis.readInt(EnergyConsumerProto.ID);
break;
case (int) EnergyConsumerProto.ORDINAL:
energyConsumer.ordinal = pis.readInt(EnergyConsumerProto.ORDINAL);
break;
case (int) EnergyConsumerProto.TYPE:
energyConsumer.type = (byte) pis.readInt(EnergyConsumerProto.TYPE);
break;
case (int) EnergyConsumerProto.NAME:
energyConsumer.name = pis.readString(EnergyConsumerProto.NAME);
break;
case ProtoInputStream.NO_MORE_FIELDS:
return energyConsumer;
default:
Slog.e(TAG, "Unhandled field in EnergyConsumerProto: "
+ ProtoUtils.currentFieldToString(pis));
break;
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in EnergyConsumerProto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
public static void print(EnergyConsumer[] energyConsumer) {
if (energyConsumer == null) return;
for (int i = 0; i < energyConsumer.length; i++) {
Slog.d(TAG, "EnergyConsumerId: " + energyConsumer[i].id
+ ", Ordinal: " + energyConsumer[i].ordinal
+ ", Type: " + energyConsumer[i].type
+ ", Name: " + energyConsumer[i].name);
}
}
public static void dumpsys(EnergyConsumer[] energyConsumer, PrintWriter pw) {
if (energyConsumer == null) return;
for (int i = 0; i < energyConsumer.length; i++) {
pw.println("EnergyConsumerId: " + energyConsumer[i].id
+ ", Ordinal: " + energyConsumer[i].ordinal
+ ", Type: " + energyConsumer[i].type
+ ", Name: " + energyConsumer[i].name);
}
}
}
static class EnergyConsumerResultUtils {
public static void adjustTimeSinceBootToEpoch(EnergyConsumerResult[] energyConsumerResult,
long startWallTime) {
if (energyConsumerResult == null) return;
for (int i = 0; i < energyConsumerResult.length; i++) {
energyConsumerResult[i].timestampMs += startWallTime;
}
}
public static byte[] getProtoBytes(EnergyConsumerResult[] energyConsumerResult,
boolean includeAttribution) {
ProtoOutputStream pos = new ProtoOutputStream();
packProtoMessage(energyConsumerResult, pos, includeAttribution);
return pos.getBytes();
}
public static void packProtoMessage(EnergyConsumerResult[] energyConsumerResult,
ProtoOutputStream pos, boolean includeAttribution) {
if (energyConsumerResult == null) return;
for (int i = 0; i < energyConsumerResult.length; i++) {
long ecrToken = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT);
pos.write(EnergyConsumerResultProto.ID, energyConsumerResult[i].id);
pos.write(EnergyConsumerResultProto.TIMESTAMP_MS,
energyConsumerResult[i].timestampMs);
pos.write(EnergyConsumerResultProto.ENERGY_UWS, energyConsumerResult[i].energyUWs);
if (includeAttribution) {
final int attributionLength = energyConsumerResult[i].attribution.length;
for (int j = 0; j < attributionLength; j++) {
final EnergyConsumerAttribution energyConsumerAttribution =
energyConsumerResult[i].attribution[j];
final long ecaToken = pos.start(EnergyConsumerResultProto.ATTRIBUTION);
pos.write(EnergyConsumerAttributionProto.UID,
energyConsumerAttribution.uid);
pos.write(EnergyConsumerAttributionProto.ENERGY_UWS,
energyConsumerAttribution.energyUWs);
pos.end(ecaToken);
}
}
pos.end(ecrToken);
}
}
public static EnergyConsumerResult[] unpackProtoMessage(byte[] data) throws IOException {
final ProtoInputStream pis = new ProtoInputStream(new ByteArrayInputStream(data));
List<EnergyConsumerResult> energyConsumerResultList =
new ArrayList<EnergyConsumerResult>();
while (true) {
try {
int nextField = pis.nextField();
EnergyConsumerResult energyConsumerResult = new EnergyConsumerResult();
if (nextField == (int) PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT) {
long token = pis.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT);
energyConsumerResultList.add(unpackEnergyConsumerResultProto(pis));
pis.end(token);
} else if (nextField == ProtoInputStream.NO_MORE_FIELDS) {
return energyConsumerResultList.toArray(
new EnergyConsumerResult[energyConsumerResultList.size()]);
} else {
Slog.e(TAG, "Unhandled field in proto: "
+ ProtoUtils.currentFieldToString(pis));
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in proto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
private static EnergyConsumerAttribution unpackEnergyConsumerAttributionProto(
ProtoInputStream pis) throws IOException {
final EnergyConsumerAttribution energyConsumerAttribution =
new EnergyConsumerAttribution();
while (true) {
try {
switch (pis.nextField()) {
case (int) EnergyConsumerAttributionProto.UID:
energyConsumerAttribution.uid =
pis.readInt(EnergyConsumerAttributionProto.UID);
break;
case (int) EnergyConsumerAttributionProto.ENERGY_UWS:
energyConsumerAttribution.energyUWs =
pis.readLong(EnergyConsumerAttributionProto.ENERGY_UWS);
break;
case ProtoInputStream.NO_MORE_FIELDS:
return energyConsumerAttribution;
default:
Slog.e(TAG, "Unhandled field in EnergyConsumerAttributionProto: "
+ ProtoUtils.currentFieldToString(pis));
break;
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in EnergyConsumerAttributionProto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
private static EnergyConsumerResult unpackEnergyConsumerResultProto(ProtoInputStream pis)
throws IOException {
EnergyConsumerResult energyConsumerResult = new EnergyConsumerResult();
final List<EnergyConsumerAttribution> energyConsumerAttributionList =
new ArrayList<EnergyConsumerAttribution>();
while (true) {
try {
switch (pis.nextField()) {
case (int) EnergyConsumerResultProto.ID:
energyConsumerResult.id = pis.readInt(EnergyConsumerResultProto.ID);
break;
case (int) EnergyConsumerResultProto.TIMESTAMP_MS:
energyConsumerResult.timestampMs =
pis.readLong(EnergyConsumerResultProto.TIMESTAMP_MS);
break;
case (int) EnergyConsumerResultProto.ENERGY_UWS:
energyConsumerResult.energyUWs =
pis.readLong(EnergyConsumerResultProto.ENERGY_UWS);
break;
case (int) EnergyConsumerResultProto.ATTRIBUTION:
final long token = pis.start(EnergyConsumerResultProto.ATTRIBUTION);
energyConsumerAttributionList.add(
unpackEnergyConsumerAttributionProto(pis));
pis.end(token);
break;
case ProtoInputStream.NO_MORE_FIELDS:
energyConsumerResult.attribution =
energyConsumerAttributionList.toArray(
new EnergyConsumerAttribution[
energyConsumerAttributionList.size()]);
return energyConsumerResult;
default:
Slog.e(TAG, "Unhandled field in EnergyConsumerResultProto: "
+ ProtoUtils.currentFieldToString(pis));
break;
}
} catch (WireTypeMismatchException wtme) {
Slog.e(TAG, "Wire Type mismatch in EnergyConsumerResultProto: "
+ ProtoUtils.currentFieldToString(pis));
}
}
}
public static void print(EnergyConsumerResult[] energyConsumerResult) {
if (energyConsumerResult == null) return;
for (int i = 0; i < energyConsumerResult.length; i++) {
final EnergyConsumerResult result = energyConsumerResult[i];
Slog.d(TAG, "EnergyConsumerId: " + result.id
+ ", Timestamp (ms): " + result.timestampMs
+ ", Energy (uWs): " + result.energyUWs);
final int attributionLength = result.attribution.length;
for (int j = 0; j < attributionLength; j++) {
final EnergyConsumerAttribution attribution = result.attribution[j];
Slog.d(TAG, " UID: " + attribution.uid
+ " Energy (uWs): " + attribution.energyUWs);
}
}
}
}
}