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

Commit 208c4707 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Log energy consumer result attribution data" into sc-dev

parents fb05a7f1 3bf71912
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