blob: 8ea29198b8d56c0110e7b3d447d19f7ede0ba9c5 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.powerstats;
import android.annotation.Nullable;
import android.hardware.power.stats.Channel;
import android.hardware.power.stats.EnergyMeasurement;
import android.hardware.power.stats.IPowerStats;
import android.hardware.power.stats.PowerEntity;
import android.hardware.power.stats.StateResidencyResult;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import java.util.function.Supplier;
/**
* PowerStatsHALWrapper is a wrapper class for the PowerStats HAL API calls.
*/
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.
*/
public interface IPowerStatsHALWrapper {
/**
* Returns information related to all supported PowerEntity(s) for which state residency
* data is available.
*
* A PowerEntity is defined as a platform subsystem, peripheral, or power domain that
* impacts the total device power consumption.
*
* @return List of information on each PowerEntity.
*/
@Nullable
android.hardware.power.stats.PowerEntity[] getPowerEntityInfo();
/**
* Reports the accumulated state residency for each requested PowerEntity.
*
* Each PowerEntity may reside in one of multiple states. It may also transition from one
* state to another. StateResidency is defined as an accumulation of time that a
* PowerEntity resided in each of its possible states, the number of times that each state
* was entered, and a timestamp corresponding to the last time that state was entered.
*
* Data is accumulated starting at device boot.
*
* @param powerEntityIds List of IDs of PowerEntities for which data is requested. Passing
* an empty list will return state residency for all available
* PowerEntities. ID of each PowerEntity is contained in
* PowerEntity.
*
* @return StateResidency since boot for each requested PowerEntity
*/
@Nullable
android.hardware.power.stats.StateResidencyResult[] getStateResidency(int[] powerEntityIds);
/**
* Returns the energy consumer info for all available energy consumers (power models) on the
* device. Examples of subsystems for which energy consumer results (power models) may be
* available are GPS, display, wifi, etc. The default list of energy consumers can be
* found in the PowerStats HAL definition (EnergyConsumerType.aidl). The availability of
* energy consumer IDs is hardware dependent.
*
* @return List of EnergyConsumers all available energy consumers.
*/
@Nullable
android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo();
/**
* Returns the energy consumer result for all available energy consumers (power models).
* Available consumers can be retrieved by calling getEnergyConsumerInfo(). The subsystem
* corresponding to the energy consumer result is defined by the energy consumer ID.
*
* @param energyConsumerIds Array of energy consumer IDs for which energy consumed is being
* requested. Energy consumers available on the device can be
* queried by calling getEnergyConsumerInfo(). Passing an empty
* array will return results for all energy consumers.
*
* @return List of EnergyConsumerResult objects containing energy consumer results for all
* available energy consumers (power models).
*/
@Nullable
android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(
int[] energyConsumerIds);
/**
* Returns channel info for all available energy meters.
*
* @return List of Channel objects containing channel info for all available energy
* meters.
*/
@Nullable
android.hardware.power.stats.Channel[] getEnergyMeterInfo();
/**
* Returns energy measurements for all available energy meters. Available channels can be
* retrieved by calling getEnergyMeterInfo(). Energy measurements and channel info can be
* linked through the channelId field.
*
* @param channelIds Array of channel IDs for which energy measurements are being requested.
* Channel IDs available on the device can be queried by calling
* getEnergyMeterInfo(). Passing an empty array will return energy
* measurements for all channels.
*
* @return List of EnergyMeasurement objects containing energy measurements for all
* available energy meters.
*/
@Nullable
android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(int[] channelIds);
/**
* Returns boolean indicating if connection to power stats HAL was established.
*
* @return true if connection to power stats HAL was correctly established.
*/
boolean isInitialized();
}
/**
* 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 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.PowerEntity[] getPowerEntityInfo() {
android.hardware.power.stats.PowerEntity[] powerEntityHAL = null;
if (sVintfPowerStats != null) {
try {
powerEntityHAL = sVintfPowerStats.get().getPowerEntityInfo();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get power entity info: ", e);
}
}
return powerEntityHAL;
}
@Override
public android.hardware.power.stats.StateResidencyResult[] getStateResidency(
int[] powerEntityIds) {
android.hardware.power.stats.StateResidencyResult[] stateResidencyResultHAL = null;
if (sVintfPowerStats != null) {
try {
stateResidencyResultHAL =
sVintfPowerStats.get().getStateResidency(powerEntityIds);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get state residency: ", e);
}
}
return stateResidencyResultHAL;
}
@Override
public android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo() {
android.hardware.power.stats.EnergyConsumer[] energyConsumerHAL = null;
if (sVintfPowerStats != null) {
try {
energyConsumerHAL = sVintfPowerStats.get().getEnergyConsumerInfo();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get energy consumer info: ", e);
}
}
return energyConsumerHAL;
}
@Override
public android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(
int[] energyConsumerIds) {
android.hardware.power.stats.EnergyConsumerResult[] energyConsumedHAL = null;
if (sVintfPowerStats != null) {
try {
energyConsumedHAL =
sVintfPowerStats.get().getEnergyConsumed(energyConsumerIds);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get energy consumer results: ", e);
}
}
return energyConsumedHAL;
}
@Override
public android.hardware.power.stats.Channel[] getEnergyMeterInfo() {
android.hardware.power.stats.Channel[] energyMeterInfoHAL = null;
if (sVintfPowerStats != null) {
try {
energyMeterInfoHAL = sVintfPowerStats.get().getEnergyMeterInfo();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get energy meter info: ", e);
}
}
return energyMeterInfoHAL;
}
@Override
public android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(int[] channelIds) {
android.hardware.power.stats.EnergyMeasurement[] energyMeasurementHAL = null;
if (sVintfPowerStats != null) {
try {
energyMeasurementHAL =
sVintfPowerStats.get().readEnergyMeter(channelIds);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get energy measurements: ", e);
}
}
return energyMeasurementHAL;
}
@Override
public boolean isInitialized() {
return (sVintfPowerStats != null);
}
}
/**
* 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 PowerEntity[] nativeGetPowerEntityInfo();
private static native StateResidencyResult[] nativeGetStateResidency(int[] powerEntityIds);
private static native Channel[] nativeGetEnergyMeterInfo();
private static native EnergyMeasurement[] nativeReadEnergyMeters(int[] channelIds);
public PowerStatsHAL10WrapperImpl() {
if (nativeInit()) {
mIsInitialized = true;
} else {
if (DEBUG) Slog.d(TAG, "PowerStats HAL 1.0 not available on this device.");
mIsInitialized = false;
}
}
@Override
public android.hardware.power.stats.PowerEntity[] getPowerEntityInfo() {
return nativeGetPowerEntityInfo();
}
@Override
public android.hardware.power.stats.StateResidencyResult[] getStateResidency(
int[] powerEntityIds) {
return nativeGetStateResidency(powerEntityIds);
}
@Override
public android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo() {
if (DEBUG) Slog.d(TAG, "Energy consumer info is not supported");
return new android.hardware.power.stats.EnergyConsumer[0];
}
@Override
public android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(
int[] energyConsumerIds) {
if (DEBUG) Slog.d(TAG, "Energy consumer results are not supported");
return new android.hardware.power.stats.EnergyConsumerResult[0];
}
@Override
public android.hardware.power.stats.Channel[] getEnergyMeterInfo() {
return nativeGetEnergyMeterInfo();
}
@Override
public android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(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();
}
}
private static class VintfHalCache implements Supplier<IPowerStats>, IBinder.DeathRecipient {
@GuardedBy("this")
private IPowerStats mInstance = null;
@Override
public synchronized IPowerStats get() {
if (mInstance == null) {
IBinder binder = Binder.allowBlocking(ServiceManager.waitForDeclaredService(
"android.hardware.power.stats.IPowerStats/default"));
if (binder != null) {
mInstance = IPowerStats.Stub.asInterface(binder);
try {
binder.linkToDeath(this, 0);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to register DeathRecipient for " + mInstance);
}
}
}
return mInstance;
}
@Override
public synchronized void binderDied() {
Slog.w(TAG, "PowerStats HAL died");
mInstance = null;
}
}
}