PowerStats: adjust time since boot to epoch before writing to disk

Data stored to disk are extracted into an incident report for timeseries
visualization which shows walltime and may span multiple reboot sessions
so storing walltime is better suited than relative time since device boot.

Bug: 179712445
Tests: atest FrameworksServicesTests:PowerStatsServiceTest
Signed-off-by: Thierry Strudel <tstrudel@google.com>
Change-Id: I5ae8e2fe22f1ab9ea960e5be8fef4e9fb1cc10f0
This commit is contained in:
Thierry Strudel
2021-02-17 11:25:26 -08:00
parent b21761e73f
commit 721bb44733
4 changed files with 57 additions and 6 deletions

View File

@@ -144,7 +144,7 @@ message StateResidencyProto {
*/
optional int64 total_state_entry_count = 3;
/**
* Last time this state was entered. Time in milliseconds since boot
* Last time this state was entered. Walltime in milliseconds since Unix epoch.
*/
optional int64 last_entry_timestamp_ms = 4;
}
@@ -208,7 +208,7 @@ message EnergyConsumerResultProto {
/** Unique index identifying the energy consumer. */
optional int32 id = 1;
/** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
/** Walltime in milliseconds since Unix epoch */
optional int64 timestamp_ms = 2;
/** Accumulated energy since device boot in microwatt-seconds (uWs) */
@@ -247,7 +247,7 @@ message EnergyMeasurementProto {
*/
optional int32 id = 1;
/** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
/** Walltime in milliseconds since Unix epoch */
optional int64 timestamp_ms = 2;
/** Accumulated energy since device boot in microwatt-seconds (uWs) */

View File

@@ -16,6 +16,8 @@
package com.android.server.powerstats;
import static java.lang.System.currentTimeMillis;
import android.content.Context;
import android.hardware.power.stats.Channel;
import android.hardware.power.stats.EnergyConsumer;
@@ -26,11 +28,14 @@ import android.hardware.power.stats.StateResidencyResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
import com.android.server.powerstats.ProtoStreamUtils.ChannelUtils;
import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerResultUtils;
@@ -61,6 +66,8 @@ public final class PowerStatsLogger extends Handler {
protected static final int MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY = 1;
protected static final int MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY = 2;
// TODO(b/181240441): Add a listener to update the Wall clock baseline when changed
private final long mStartWallTime;
private final PowerStatsDataStorage mPowerStatsMeterStorage;
private final PowerStatsDataStorage mPowerStatsModelStorage;
private final PowerStatsDataStorage mPowerStatsResidencyStorage;
@@ -79,6 +86,8 @@ public final class PowerStatsLogger extends Handler {
// Log power meter data.
EnergyMeasurement[] energyMeasurements =
mPowerStatsHALWrapper.readEnergyMeter(new int[0]);
EnergyMeasurementUtils.adjustTimeSinceBootToEpoch(energyMeasurements,
mStartWallTime);
mPowerStatsMeterStorage.write(
EnergyMeasurementUtils.getProtoBytes(energyMeasurements));
if (DEBUG) EnergyMeasurementUtils.print(energyMeasurements);
@@ -86,6 +95,8 @@ public final class PowerStatsLogger extends Handler {
// Log power model data without attribution data.
EnergyConsumerResult[] ecrNoAttribution =
mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
EnergyConsumerResultUtils.adjustTimeSinceBootToEpoch(ecrNoAttribution,
mStartWallTime);
mPowerStatsModelStorage.write(
EnergyConsumerResultUtils.getProtoBytes(ecrNoAttribution, false));
if (DEBUG) EnergyConsumerResultUtils.print(ecrNoAttribution);
@@ -97,6 +108,8 @@ public final class PowerStatsLogger extends Handler {
// Log power model data with attribution data.
EnergyConsumerResult[] ecrAttribution =
mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
EnergyConsumerResultUtils.adjustTimeSinceBootToEpoch(ecrAttribution,
mStartWallTime);
mPowerStatsModelStorage.write(
EnergyConsumerResultUtils.getProtoBytes(ecrAttribution, true));
if (DEBUG) EnergyConsumerResultUtils.print(ecrAttribution);
@@ -108,6 +121,8 @@ public final class PowerStatsLogger extends Handler {
// Log state residency data.
StateResidencyResult[] stateResidencyResults =
mPowerStatsHALWrapper.getStateResidency(new int[0]);
StateResidencyResultUtils.adjustTimeSinceBootToEpoch(stateResidencyResults,
mStartWallTime);
mPowerStatsResidencyStorage.write(
StateResidencyResultUtils.getProtoBytes(stateResidencyResults));
if (DEBUG) StateResidencyResultUtils.print(stateResidencyResults);
@@ -293,12 +308,19 @@ public final class PowerStatsLogger extends Handler {
return mDeleteResidencyDataOnBoot;
}
@VisibleForTesting
public long getStartWallTime() {
return mStartWallTime;
}
public PowerStatsLogger(Context context, File dataStoragePath,
String meterFilename, String meterCacheFilename,
String modelFilename, String modelCacheFilename,
String residencyFilename, String residencyCacheFilename,
IPowerStatsHALWrapper powerStatsHALWrapper) {
super(Looper.getMainLooper());
mStartWallTime = currentTimeMillis() - SystemClock.elapsedRealtime();
if (DEBUG) Slog.d(TAG, "mStartWallTime: " + mStartWallTime);
mPowerStatsHALWrapper = powerStatsHALWrapper;
mDataStoragePath = dataStoragePath;

View File

@@ -109,6 +109,18 @@ public class ProtoStreamUtils {
}
static class StateResidencyResultUtils {
public static void adjustTimeSinceBootToEpoch(StateResidencyResult[] stateResidencyResult,
long startWallTime) {
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);
@@ -306,6 +318,13 @@ public class ProtoStreamUtils {
}
static class EnergyMeasurementUtils {
public static void adjustTimeSinceBootToEpoch(EnergyMeasurement[] energyMeasurement,
long startWallTime) {
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);
@@ -518,6 +537,13 @@ public class ProtoStreamUtils {
}
static class EnergyConsumerResultUtils {
public static void adjustTimeSinceBootToEpoch(EnergyConsumerResult[] energyConsumerResult,
long startWallTime) {
for (int i = 0; i < energyConsumerResult.length; i++) {
energyConsumerResult[i].timestampMs += startWallTime;
}
}
public static byte[] getProtoBytes(EnergyConsumerResult[] energyConsumerResult,
boolean includeAttribution) {
ProtoOutputStream pos = new ProtoOutputStream();

View File

@@ -318,7 +318,8 @@ public class PowerStatsServiceTest {
assertTrue(pssProto.energyMeasurement.length == ENERGY_METER_COUNT);
for (int i = 0; i < pssProto.energyMeasurement.length; i++) {
assertTrue(pssProto.energyMeasurement[i].id == i);
assertTrue(pssProto.energyMeasurement[i].timestampMs == i);
assertTrue(pssProto.energyMeasurement[i].timestampMs ==
i + mPowerStatsLogger.getStartWallTime());
assertTrue(pssProto.energyMeasurement[i].durationMs == i);
assertTrue(pssProto.energyMeasurement[i].energyUws == i);
}
@@ -359,7 +360,8 @@ public class PowerStatsServiceTest {
assertTrue(pssProto.energyConsumerResult.length == ENERGY_CONSUMER_COUNT);
for (int i = 0; i < pssProto.energyConsumerResult.length; i++) {
assertTrue(pssProto.energyConsumerResult[i].id == i);
assertTrue(pssProto.energyConsumerResult[i].timestampMs == i);
assertTrue(pssProto.energyConsumerResult[i].timestampMs ==
i + mPowerStatsLogger.getStartWallTime());
assertTrue(pssProto.energyConsumerResult[i].energyUws == i);
assertTrue(pssProto.energyConsumerResult[i].attribution.length
== ENERGY_CONSUMER_ATTRIBUTION_COUNT);
@@ -420,7 +422,8 @@ public class PowerStatsServiceTest {
assertTrue(stateResidency.id == j);
assertTrue(stateResidency.totalTimeInStateMs == j);
assertTrue(stateResidency.totalStateEntryCount == j);
assertTrue(stateResidency.lastEntryTimestampMs == j);
assertTrue(stateResidency.lastEntryTimestampMs ==
j + mPowerStatsLogger.getStartWallTime());
}
}
}