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

Commit a069cade authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Log energy consumer result attribution data" into sc-dev am: 208c4707

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13432183

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I7a84a17e22e95b638804dd1e4f7ff4e746be8afc
parents 53a956bc 208c4707
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -191,6 +191,14 @@ message EnergyConsumerProto {
    optional string name = 4;
}

message EnergyConsumerAttributionProto {
    /** Android ID / Linux UID, the accumulated energy should be attributed to. */
    optional int32 uid = 1;

    /** Accumulated energy since boot in microwatt-seconds (uWs) for this AID. */
    optional int64 energy_uws = 2;
}

/**
 * Energy consumer result:
 * An estimate of energy consumption since boot for the subsystem identified
@@ -205,6 +213,9 @@ message EnergyConsumerResultProto {

    /** Accumulated energy since device boot in microwatt-seconds (uWs) */
    optional int64 energy_uws = 3;

    /** Optional attribution per UID for this EnergyConsumer. */
    repeated EnergyConsumerAttributionProto attribution = 4;
}

/**
+21 −9
Original line number Diff line number Diff line
@@ -53,8 +53,9 @@ import java.io.IOException;
public final class PowerStatsLogger extends Handler {
    private static final String TAG = PowerStatsLogger.class.getSimpleName();
    private static final boolean DEBUG = false;
    protected static final int MSG_LOG_TO_DATA_STORAGE_TIMER = 0;
    protected static final int MSG_LOG_TO_DATA_STORAGE_BATTERY_DROP = 1;
    protected static final int MSG_LOG_TO_DATA_STORAGE_BATTERY_DROP = 0;
    protected static final int MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY = 1;
    protected static final int MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY = 2;

    private final PowerStatsDataStorage mPowerStatsMeterStorage;
    private final PowerStatsDataStorage mPowerStatsModelStorage;
@@ -64,8 +65,8 @@ public final class PowerStatsLogger extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_LOG_TO_DATA_STORAGE_TIMER:
                if (DEBUG) Slog.d(TAG, "Logging to data storage on timer");
            case MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY:
                if (DEBUG) Slog.d(TAG, "Logging to data storage on high frequency timer");

                // Log power meter data.
                EnergyMeasurement[] energyMeasurements =
@@ -74,12 +75,23 @@ public final class PowerStatsLogger extends Handler {
                        EnergyMeasurementUtils.getProtoBytes(energyMeasurements));
                if (DEBUG) EnergyMeasurementUtils.print(energyMeasurements);

                // Log power model data.
                EnergyConsumerResult[] energyConsumerResults =
                // Log power model data without attribution data.
                EnergyConsumerResult[] ecrNoAttribution =
                    mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
                mPowerStatsModelStorage.write(
                        EnergyConsumerResultUtils.getProtoBytes(energyConsumerResults));
                if (DEBUG) EnergyConsumerResultUtils.print(energyConsumerResults);
                        EnergyConsumerResultUtils.getProtoBytes(ecrNoAttribution, false));
                if (DEBUG) EnergyConsumerResultUtils.print(ecrNoAttribution);
                break;

            case MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY:
                if (DEBUG) Slog.d(TAG, "Logging to data storage on low frequency timer");

                // Log power model data with attribution data.
                EnergyConsumerResult[] ecrAttribution =
                    mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
                mPowerStatsModelStorage.write(
                        EnergyConsumerResultUtils.getProtoBytes(ecrAttribution, true));
                if (DEBUG) EnergyConsumerResultUtils.print(ecrAttribution);
                break;

            case MSG_LOG_TO_DATA_STORAGE_BATTERY_DROP:
@@ -163,7 +175,7 @@ public final class PowerStatsLogger extends Handler {
                        // deserialize, then re-serialize.  This is computationally inefficient.
                        EnergyConsumerResult[] energyConsumerResult =
                            EnergyConsumerResultUtils.unpackProtoMessage(data);
                        EnergyConsumerResultUtils.packProtoMessage(energyConsumerResult, pos);
                        EnergyConsumerResultUtils.packProtoMessage(energyConsumerResult, pos, true);
                        if (DEBUG) EnergyConsumerResultUtils.print(energyConsumerResult);
                    } catch (IOException e) {
                        Slog.e(TAG, "Failed to write energy model data to incident report.");
+80 −8
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ 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;
@@ -433,23 +434,40 @@ public class ProtoStreamUtils {
    }

    static class EnergyConsumerResultUtils {
        public static byte[] getProtoBytes(EnergyConsumerResult[] energyConsumerResult) {
        public static byte[] getProtoBytes(EnergyConsumerResult[] energyConsumerResult,
                boolean includeAttribution) {
            ProtoOutputStream pos = new ProtoOutputStream();
            packProtoMessage(energyConsumerResult, pos);
            packProtoMessage(energyConsumerResult, pos, includeAttribution);
            return pos.getBytes();
        }

        public static void packProtoMessage(EnergyConsumerResult[] energyConsumerResult,
                ProtoOutputStream pos) {
                ProtoOutputStream pos, boolean includeAttribution) {
            if (energyConsumerResult == null) return;

            for (int i = 0; i < energyConsumerResult.length; i++) {
                long token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT);
                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);
                pos.end(token);

                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);
            }
        }

@@ -480,9 +498,45 @@ public class ProtoStreamUtils {
            }
        }

        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 {
@@ -501,7 +555,18 @@ public class ProtoStreamUtils {
                                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:
@@ -520,9 +585,16 @@ public class ProtoStreamUtils {
            if (energyConsumerResult == null) return;

            for (int i = 0; i < energyConsumerResult.length; i++) {
                Slog.d(TAG, "EnergyConsumerId: " + energyConsumerResult[i].id
                        + ", Timestamp (ms): " + energyConsumerResult[i].timestampMs
                        + ", Energy (uWs): " + energyConsumerResult[i].energyUWs);
                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);
                }
            }
        }
    }
+20 −7
Original line number Diff line number Diff line
@@ -29,18 +29,30 @@ public final class TimerTrigger extends PowerStatsLogTrigger {
    private static final String TAG = TimerTrigger.class.getSimpleName();
    private static final boolean DEBUG = false;
    // TODO(b/166689029): Make configurable through global settings.
    private static final long LOG_PERIOD_MS = 120 * 1000;
    private static final long LOG_PERIOD_MS_LOW_FREQUENCY = 60 * 60 * 1000; // 1 hour
    private static final long LOG_PERIOD_MS_HIGH_FREQUENCY = 2 * 60 * 1000; // 2 minutes

    private final Handler mHandler;

    private Runnable mLogData = new Runnable() {
    private Runnable mLogDataLowFrequency = new Runnable() {
        @Override
        public void run() {
            // Do not wake the device for these messages.  Opportunistically log rail data every
            // LOG_PERIOD_MS.
            mHandler.postDelayed(mLogData, LOG_PERIOD_MS);
            if (DEBUG) Slog.d(TAG, "Received delayed message.  Log rail data");
            logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_TIMER);
            // LOG_PERIOD_MS_LOW_FREQUENCY.
            mHandler.postDelayed(mLogDataLowFrequency, LOG_PERIOD_MS_LOW_FREQUENCY);
            if (DEBUG) Slog.d(TAG, "Received delayed message.  Log rail data low frequency");
            logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY);
        }
    };

    private Runnable mLogDataHighFrequency = new Runnable() {
        @Override
        public void run() {
            // Do not wake the device for these messages.  Opportunistically log rail data every
            // LOG_PERIOD_MS_HIGH_FREQUENCY.
            mHandler.postDelayed(mLogDataHighFrequency, LOG_PERIOD_MS_HIGH_FREQUENCY);
            if (DEBUG) Slog.d(TAG, "Received delayed message.  Log rail data high frequency");
            logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY);
        }
    };

@@ -50,7 +62,8 @@ public final class TimerTrigger extends PowerStatsLogTrigger {
        mHandler = mContext.getMainThreadHandler();

        if (triggerEnabled) {
            mLogData.run();
            mLogDataLowFrequency.run();
            mLogDataHighFrequency.run();
        }
    }
}
+17 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static org.junit.Assert.fail;
import android.content.Context;
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;
@@ -73,6 +74,7 @@ public class PowerStatsServiceTest {
    private static final String ENERGY_CONSUMER_NAME = "energyconsumer";
    private static final int ENERGY_METER_COUNT = 8;
    private static final int ENERGY_CONSUMER_COUNT = 2;
    private static final int ENERGY_CONSUMER_ATTRIBUTION_COUNT = 5;
    private static final int POWER_ENTITY_COUNT = 3;
    private static final int STATE_INFO_COUNT = 5;
    private static final int STATE_RESIDENCY_COUNT = 4;
@@ -204,6 +206,13 @@ public class PowerStatsServiceTest {
                energyConsumedList[i].id = i;
                energyConsumedList[i].timestampMs = i;
                energyConsumedList[i].energyUWs = i;
                energyConsumedList[i].attribution =
                    new EnergyConsumerAttribution[ENERGY_CONSUMER_ATTRIBUTION_COUNT];
                for (int j = 0; j < energyConsumedList[i].attribution.length; j++) {
                    energyConsumedList[i].attribution[j] = new EnergyConsumerAttribution();
                    energyConsumedList[i].attribution[j].uid = j;
                    energyConsumedList[i].attribution[j].energyUWs = j;
                }
            }
            return energyConsumedList;
        }
@@ -250,7 +259,7 @@ public class PowerStatsServiceTest {
        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);

        // Write data to on-device storage.
        mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_TIMER);
        mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_HIGH_FREQUENCY);

        // The above call puts a message on a handler.  Wait for
        // it to be processed.
@@ -293,7 +302,7 @@ public class PowerStatsServiceTest {
        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);

        // Write data to on-device storage.
        mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_TIMER);
        mTimerTrigger.logPowerStatsData(PowerStatsLogger.MSG_LOG_TO_DATA_STORAGE_LOW_FREQUENCY);

        // The above call puts a message on a handler.  Wait for
        // it to be processed.
@@ -324,6 +333,12 @@ public class PowerStatsServiceTest {
            assertTrue(pssProto.energyConsumerResult[i].id == i);
            assertTrue(pssProto.energyConsumerResult[i].timestampMs == i);
            assertTrue(pssProto.energyConsumerResult[i].energyUws == i);
            assertTrue(pssProto.energyConsumerResult[i].attribution.length
                    == ENERGY_CONSUMER_ATTRIBUTION_COUNT);
            for (int j = 0; j < pssProto.energyConsumerResult[i].attribution.length; j++) {
                assertTrue(pssProto.energyConsumerResult[i].attribution[j].uid == j);
                assertTrue(pssProto.energyConsumerResult[i].attribution[j].energyUws  == j);
            }
        }
    }

Loading