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

Commit 0484a89b authored by Mat Bevilacqua's avatar Mat Bevilacqua
Browse files

Add PowerStats HAL 1.0 support

Bug: 173123066
Test: atest FrameworksServicesTests:PowerStatsServiceTest
Test: Tested across a range of existing devices with varying degrees of
PowerStats HAL 1.0/2.0 support and no support.

Change-Id: I0e93d5e718ebc1f4e8fa9422d480a3717593ea32
parent 22e6db87
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -250,9 +250,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        mHandler = new Handler(mHandlerThread.getLooper());

        // TODO(b/173077356): Replace directly calling the HAL with PowerStatsService queries
        // Make sure to init Hal Wrapper before creating BatteryStatsImpl.
        mPowerStatsHALWrapper = new PowerStatsHALWrapper.PowerStatsHALWrapperImpl();
        mPowerStatsHALWrapper.initialize();
        mPowerStatsHALWrapper = PowerStatsHALWrapper.getPowerStatsHalImpl();

        mStats = new BatteryStatsImpl(systemDir, handler, this,
                this, mUserManagerUserInfoProvider);
+113 −18
Original line number Diff line number Diff line
@@ -16,7 +16,11 @@

package com.android.server.powerstats;

import android.hardware.power.stats.ChannelInfo;
import android.hardware.power.stats.EnergyMeasurement;
import android.hardware.power.stats.IPowerStats;
import android.hardware.power.stats.PowerEntityInfo;
import android.hardware.power.stats.StateResidencyResult;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -32,6 +36,7 @@ import java.util.function.Supplier;
 */
public final class PowerStatsHALWrapper {
    private static final String TAG = PowerStatsHALWrapper.class.getSimpleName();
    private static final boolean DEBUG = false;

    /**
     * IPowerStatsHALWrapper defines the interface to the PowerStatsHAL.
@@ -122,17 +127,30 @@ public final class PowerStatsHALWrapper {
         *
         * @return true if connection to power stats HAL was correctly established.
         */
        boolean initialize();
        boolean isInitialized();
    }

    /**
     * PowerStatsHALWrapperImpl is the implementation of the IPowerStatsHALWrapper
     * used by the PowerStatsService.  Other implementations will be used by the testing
     * framework and will be passed into the PowerStatsService through an injector.
     * PowerStatsHALWrapper20Impl is the implementation of the IPowerStatsHALWrapper
     * used by the PowerStatsService on devices that support only PowerStats HAL 2.0.
     * Other implementations will be used by the testing framework and will be passed
     * into the PowerStatsService through an injector.
     */
    public static final class PowerStatsHALWrapperImpl implements IPowerStatsHALWrapper {
    public static final class PowerStatsHAL20WrapperImpl implements IPowerStatsHALWrapper {
        private static Supplier<IPowerStats> sVintfPowerStats;

        public PowerStatsHAL20WrapperImpl() {
            Supplier<IPowerStats> service = new VintfHalCache();
            sVintfPowerStats = null;

            if (service.get() == null) {
                if (DEBUG) Slog.d(TAG, "PowerStats HAL 2.0 not available on this device.");
                sVintfPowerStats = null;
            } else {
                sVintfPowerStats = service;
            }
        }

        @Override
        public android.hardware.power.stats.PowerEntityInfo[] getPowerEntityInfo() {
            android.hardware.power.stats.PowerEntityInfo[] powerEntityInfoHAL = null;
@@ -141,7 +159,7 @@ public final class PowerStatsHALWrapper {
                try {
                    powerEntityInfoHAL = sVintfPowerStats.get().getPowerEntityInfo();
                } catch (RemoteException e) {
                    Slog.e(TAG, "Failed to get power entity info from PowerStats HAL");
                    if (DEBUG) Slog.d(TAG, "Failed to get power entity info from PowerStats HAL");
                }
            }

@@ -158,7 +176,7 @@ public final class PowerStatsHALWrapper {
                    stateResidencyResultHAL =
                        sVintfPowerStats.get().getStateResidency(powerEntityIds);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Failed to get state residency from PowerStats HAL");
                    if (DEBUG) Slog.d(TAG, "Failed to get state residency from PowerStats HAL");
                }
            }

@@ -173,7 +191,9 @@ public final class PowerStatsHALWrapper {
                try {
                    energyConsumerInfoHAL = sVintfPowerStats.get().getEnergyConsumerInfo();
                } catch (RemoteException e) {
                    Slog.e(TAG, "Failed to get energy consumer info from PowerStats HAL");
                    if (DEBUG) {
                        Slog.d(TAG, "Failed to get energy consumer info from PowerStats HAL");
                    }
                }
            }

@@ -190,7 +210,9 @@ public final class PowerStatsHALWrapper {
                    energyConsumedHAL =
                        sVintfPowerStats.get().getEnergyConsumed(energyConsumerIds);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Failed to get energy consumer results from PowerStats HAL");
                    if (DEBUG) {
                        Slog.d(TAG, "Failed to get energy consumer results from PowerStats HAL");
                    }
                }
            }

@@ -205,7 +227,7 @@ public final class PowerStatsHALWrapper {
                try {
                    energyMeterInfoHAL = sVintfPowerStats.get().getEnergyMeterInfo();
                } catch (RemoteException e) {
                    Slog.e(TAG, "Failed to get energy meter info from PowerStats HAL");
                    if (DEBUG) Slog.d(TAG, "Failed to get energy meter info from PowerStats HAL");
                }
            }

@@ -221,7 +243,7 @@ public final class PowerStatsHALWrapper {
                    energyMeasurementHAL =
                        sVintfPowerStats.get().readEnergyMeters(channelIds);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Failed to get energy measurements from PowerStats HAL");
                    if (DEBUG) Slog.d(TAG, "Failed to get energy measurements from PowerStats HAL");
                }
            }

@@ -229,16 +251,89 @@ public final class PowerStatsHALWrapper {
        }

        @Override
        public boolean initialize() {
            Supplier<IPowerStats> service = new VintfHalCache();
        public boolean isInitialized() {
            return (sVintfPowerStats != null);
        }
    }

            if (service.get() == null) {
                sVintfPowerStats = null;
                return false;
    /**
     * PowerStatsHALWrapper10Impl is the implementation of the IPowerStatsHALWrapper
     * used by the PowerStatsService on devices that support only PowerStats HAL 1.0.
     * Other implementations will be used by the testing framework and will be passed
     * into the PowerStatsService through an injector.
     */
    public static final class PowerStatsHAL10WrapperImpl implements IPowerStatsHALWrapper {
        private boolean mIsInitialized;

        // PowerStatsHAL 1.0 native functions exposed by JNI layer.
        private static native boolean nativeInit();
        private static native PowerEntityInfo[] nativeGetPowerEntityInfo();
        private static native StateResidencyResult[] nativeGetStateResidency(int[] powerEntityIds);
        private static native ChannelInfo[] nativeGetEnergyMeterInfo();
        private static native EnergyMeasurement[] nativeReadEnergyMeters(int[] channelIds);

        public PowerStatsHAL10WrapperImpl() {
            if (nativeInit()) {
                mIsInitialized = true;
            } else {
                sVintfPowerStats = service;
                return true;
                if (DEBUG) Slog.d(TAG, "PowerStats HAL 1.0 not available on this device.");
                mIsInitialized = false;
            }
        }

        @Override
        public android.hardware.power.stats.PowerEntityInfo[] getPowerEntityInfo() {
            return nativeGetPowerEntityInfo();
        }

        @Override
        public android.hardware.power.stats.StateResidencyResult[] getStateResidency(
                int[] powerEntityIds) {
            return nativeGetStateResidency(powerEntityIds);
        }

        @Override
        public int[] getEnergyConsumerInfo() {
            if (DEBUG) Slog.d(TAG, "Energy consumer info is not supported");
            return null;
        }

        @Override
        public android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(
                int[] energyConsumerIds) {
            if (DEBUG) Slog.d(TAG, "Energy consumer results are not supported");
            return null;
        }

        @Override
        public android.hardware.power.stats.ChannelInfo[] getEnergyMeterInfo() {
            return nativeGetEnergyMeterInfo();
        }

        @Override
        public android.hardware.power.stats.EnergyMeasurement[] readEnergyMeters(int[] channelIds) {
            return nativeReadEnergyMeters(channelIds);
        }

        @Override
        public boolean isInitialized() {
            return mIsInitialized;
        }
    }

    /**
     * Returns an instance of an IPowerStatsHALWrapper.  If PowerStats HAL 2.0 is supported on the
     * device, return a PowerStatsHAL20WrapperImpl, else return a PowerStatsHAL10WrapperImpl.
     *
     * @return an instance of an IPowerStatsHALWrapper where preference is given to PowerStats HAL
     *         2.0.
     */
    public static IPowerStatsHALWrapper getPowerStatsHalImpl() {
        PowerStatsHAL20WrapperImpl powerStatsHAL20WrapperImpl = new PowerStatsHAL20WrapperImpl();
        if (powerStatsHAL20WrapperImpl.isInitialized()) {
            return powerStatsHAL20WrapperImpl;
        } else {
            return new PowerStatsHAL10WrapperImpl();
        }
    }

+2 −3
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
import com.android.server.powerstats.PowerStatsHALWrapper.PowerStatsHALWrapperImpl;
import com.android.server.powerstats.ProtoStreamUtils.ChannelInfoUtils;
import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerIdUtils;
import com.android.server.powerstats.ProtoStreamUtils.PowerEntityInfoUtils;
@@ -78,7 +77,7 @@ public class PowerStatsService extends SystemService {
        }

        IPowerStatsHALWrapper createPowerStatsHALWrapperImpl() {
            return new PowerStatsHALWrapperImpl();
            return PowerStatsHALWrapper.getPowerStatsHalImpl();
        }

        PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
@@ -143,7 +142,7 @@ public class PowerStatsService extends SystemService {
    private void onSystemServiceReady() {
        mPowerStatsHALWrapper = mInjector.createPowerStatsHALWrapperImpl();

        if (mPowerStatsHALWrapper.initialize()) {
        if (mPowerStatsHALWrapper.isInitialized()) {
            if (DEBUG) Slog.d(TAG, "Starting PowerStatsService");

            // Only start logger and triggers if initialization is successful.
+36 −6
Original line number Diff line number Diff line
@@ -46,20 +46,27 @@ public class ProtoStreamUtils {

    static class PowerEntityInfoUtils {
        public static void print(PowerEntityInfo[] powerEntityInfo) {
            if (powerEntityInfo == null) return;

            for (int i = 0; i < powerEntityInfo.length; i++) {
                Slog.d(TAG, "PowerEntityId: " + powerEntityInfo[i].powerEntityId
                        + ", PowerEntityName: " + powerEntityInfo[i].powerEntityName);
                if (powerEntityInfo[i].states != null) {
                    for (int j = 0; j < powerEntityInfo[i].states.length; j++) {
                        Slog.d(TAG, "  StateId: " + powerEntityInfo[i].states[j].stateId
                                + ", StateName: " + powerEntityInfo[i].states[j].stateName);
                    }
                }
            }
        }

        public static void dumpsys(PowerEntityInfo[] powerEntityInfo, PrintWriter pw) {
            if (powerEntityInfo == null) return;

            for (int i = 0; i < powerEntityInfo.length; i++) {
                pw.println("PowerEntityId: " + powerEntityInfo[i].powerEntityId
                        + ", PowerEntityName: " + powerEntityInfo[i].powerEntityName);
                if (powerEntityInfo[i].states != null) {
                    for (int j = 0; j < powerEntityInfo[i].states.length; j++) {
                        pw.println("  StateId: " + powerEntityInfo[i].states[j].stateId
                                + ", StateName: " + powerEntityInfo[i].states[j].stateName);
@@ -67,9 +74,12 @@ public class ProtoStreamUtils {
                }
            }
        }
    }

    static class StateResidencyResultUtils {
        public static void print(StateResidencyResult[] stateResidencyResult) {
            if (stateResidencyResult == null) return;

            for (int i = 0; i < stateResidencyResult.length; i++) {
                Slog.d(TAG, "PowerEntityId: " + stateResidencyResult[i].powerEntityId);
                for (int j = 0; j < stateResidencyResult[i].stateResidencyData.length; j++) {
@@ -90,6 +100,8 @@ public class ProtoStreamUtils {
        public static void packProtoMessage(ChannelInfo[] channelInfo, ProtoOutputStream pos) {
            long token;

            if (channelInfo == null) return;

            for (int i = 0; i < channelInfo.length; i++) {
                token = pos.start(PowerStatsServiceMeterProto.CHANNEL_INFO);
                pos.write(ChannelInfoProto.CHANNEL_ID, channelInfo[i].channelId);
@@ -100,6 +112,8 @@ public class ProtoStreamUtils {
        }

        public static void print(ChannelInfo[] channelInfo) {
            if (channelInfo == null) return;

            for (int i = 0; i < channelInfo.length; i++) {
                Slog.d(TAG, "ChannelId: " + channelInfo[i].channelId
                        + ", ChannelName: " + channelInfo[i].channelName);
@@ -107,6 +121,8 @@ public class ProtoStreamUtils {
        }

        public static void dumpsys(ChannelInfo[] channelInfo, PrintWriter pw) {
            if (channelInfo == null) return;

            for (int i = 0; i < channelInfo.length; i++) {
                pw.println("ChannelId: " + channelInfo[i].channelId
                        + ", ChannelName: " + channelInfo[i].channelName);
@@ -125,6 +141,8 @@ public class ProtoStreamUtils {
                ProtoOutputStream pos) {
            long token;

            if (energyMeasurement == null) return;

            for (int i = 0; i < energyMeasurement.length; i++) {
                token = pos.start(PowerStatsServiceMeterProto.ENERGY_MEASUREMENT);
                pos.write(EnergyMeasurementProto.CHANNEL_ID, energyMeasurement[i].channelId);
@@ -200,6 +218,8 @@ public class ProtoStreamUtils {
        }

        public static void print(EnergyMeasurement[] energyMeasurement) {
            if (energyMeasurement == null) return;

            for (int i = 0; i < energyMeasurement.length; i++) {
                Slog.d(TAG, "ChannelId: " + energyMeasurement[i].channelId
                        + ", Timestamp (ms): " + energyMeasurement[i].timestampMs
@@ -212,6 +232,8 @@ public class ProtoStreamUtils {
        public static void packProtoMessage(int[] energyConsumerId, ProtoOutputStream pos) {
            long token;

            if (energyConsumerId == null) return;

            for (int i = 0; i < energyConsumerId.length; i++) {
                token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_ID);
                pos.write(EnergyConsumerIdProto.ENERGY_CONSUMER_ID, energyConsumerId[i]);
@@ -220,12 +242,16 @@ public class ProtoStreamUtils {
        }

        public static void print(int[] energyConsumerId) {
            if (energyConsumerId == null) return;

            for (int i = 0; i < energyConsumerId.length; i++) {
                Slog.d(TAG, "EnergyConsumerId: " + energyConsumerId[i]);
            }
        }

        public static void dumpsys(int[] energyConsumerId, PrintWriter pw) {
            if (energyConsumerId == null) return;

            for (int i = 0; i < energyConsumerId.length; i++) {
                pw.println("EnergyConsumerId: " + energyConsumerId[i]);
            }
@@ -243,6 +269,8 @@ public class ProtoStreamUtils {
                ProtoOutputStream pos) {
            long token;

            if (energyConsumerResult == null) return;

            for (int i = 0; i < energyConsumerResult.length; i++) {
                token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT);
                pos.write(EnergyConsumerResultProto.ENERGY_CONSUMER_ID,
@@ -321,6 +349,8 @@ public class ProtoStreamUtils {
        }

        public static void print(EnergyConsumerResult[] energyConsumerResult) {
            if (energyConsumerResult == null) return;

            for (int i = 0; i < energyConsumerResult.length; i++) {
                Slog.d(TAG, "EnergyConsumerId: " + energyConsumerResult[i].energyConsumerId
                        + ", Timestamp (ms): " + energyConsumerResult[i].timestampMs
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ cc_library_static {
        "com_android_server_locksettings_SyntheticPasswordManager.cpp",
        "com_android_server_net_NetworkStatsService.cpp",
        "com_android_server_power_PowerManagerService.cpp",
        "com_android_server_powerstats_PowerStatsService.cpp",
        "com_android_server_security_VerityUtils.cpp",
        "com_android_server_SerialService.cpp",
        "com_android_server_soundtrigger_middleware_AudioSessionProviderImpl.cpp",
Loading