Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 721bb447 authored by Thierry Strudel's avatar Thierry Strudel
Browse files

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: default avatarThierry Strudel <tstrudel@google.com>
Change-Id: I5ae8e2fe22f1ab9ea960e5be8fef4e9fb1cc10f0
parent b21761e7
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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) */
+22 −0
Original line number Diff line number Diff line
@@ -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;

+26 −0
Original line number Diff line number Diff line
@@ -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();
+6 −3
Original line number Diff line number Diff line
@@ -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());
            }
        }
    }