1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.powerstats; 18 19 import android.annotation.Nullable; 20 import android.hardware.power.stats.Channel; 21 import android.hardware.power.stats.EnergyMeasurement; 22 import android.hardware.power.stats.IPowerStats; 23 import android.hardware.power.stats.PowerEntity; 24 import android.hardware.power.stats.StateResidencyResult; 25 import android.os.Binder; 26 import android.os.IBinder; 27 import android.os.RemoteException; 28 import android.os.ServiceManager; 29 import android.util.Slog; 30 31 import com.android.internal.annotations.GuardedBy; 32 33 import java.util.function.Supplier; 34 35 /** 36 * PowerStatsHALWrapper is a wrapper class for the PowerStats HAL API calls. 37 */ 38 public final class PowerStatsHALWrapper { 39 private static final String TAG = PowerStatsHALWrapper.class.getSimpleName(); 40 private static final boolean DEBUG = false; 41 42 /** 43 * IPowerStatsHALWrapper defines the interface to the PowerStatsHAL. 44 */ 45 public interface IPowerStatsHALWrapper { 46 /** 47 * Returns information related to all supported PowerEntity(s) for which state residency 48 * data is available. 49 * 50 * A PowerEntity is defined as a platform subsystem, peripheral, or power domain that 51 * impacts the total device power consumption. 52 * 53 * @return List of information on each PowerEntity. 54 */ 55 @Nullable getPowerEntityInfo()56 android.hardware.power.stats.PowerEntity[] getPowerEntityInfo(); 57 58 /** 59 * Reports the accumulated state residency for each requested PowerEntity. 60 * 61 * Each PowerEntity may reside in one of multiple states. It may also transition from one 62 * state to another. StateResidency is defined as an accumulation of time that a 63 * PowerEntity resided in each of its possible states, the number of times that each state 64 * was entered, and a timestamp corresponding to the last time that state was entered. 65 * 66 * Data is accumulated starting at device boot. 67 * 68 * @param powerEntityIds List of IDs of PowerEntities for which data is requested. Passing 69 * an empty list will return state residency for all available 70 * PowerEntities. ID of each PowerEntity is contained in 71 * PowerEntity. 72 * 73 * @return StateResidency since boot for each requested PowerEntity 74 */ 75 @Nullable getStateResidency(int[] powerEntityIds)76 android.hardware.power.stats.StateResidencyResult[] getStateResidency(int[] powerEntityIds); 77 78 /** 79 * Returns the energy consumer info for all available energy consumers (power models) on the 80 * device. Examples of subsystems for which energy consumer results (power models) may be 81 * available are GPS, display, wifi, etc. The default list of energy consumers can be 82 * found in the PowerStats HAL definition (EnergyConsumerType.aidl). The availability of 83 * energy consumer IDs is hardware dependent. 84 * 85 * @return List of EnergyConsumers all available energy consumers. 86 */ 87 @Nullable getEnergyConsumerInfo()88 android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo(); 89 90 /** 91 * Returns the energy consumer result for all available energy consumers (power models). 92 * Available consumers can be retrieved by calling getEnergyConsumerInfo(). The subsystem 93 * corresponding to the energy consumer result is defined by the energy consumer ID. 94 * 95 * @param energyConsumerIds Array of energy consumer IDs for which energy consumed is being 96 * requested. Energy consumers available on the device can be 97 * queried by calling getEnergyConsumerInfo(). Passing an empty 98 * array will return results for all energy consumers. 99 * 100 * @return List of EnergyConsumerResult objects containing energy consumer results for all 101 * available energy consumers (power models). 102 */ 103 @Nullable getEnergyConsumed( int[] energyConsumerIds)104 android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed( 105 int[] energyConsumerIds); 106 107 /** 108 * Returns channel info for all available energy meters. 109 * 110 * @return List of Channel objects containing channel info for all available energy 111 * meters. 112 */ 113 @Nullable getEnergyMeterInfo()114 android.hardware.power.stats.Channel[] getEnergyMeterInfo(); 115 116 /** 117 * Returns energy measurements for all available energy meters. Available channels can be 118 * retrieved by calling getEnergyMeterInfo(). Energy measurements and channel info can be 119 * linked through the channelId field. 120 * 121 * @param channelIds Array of channel IDs for which energy measurements are being requested. 122 * Channel IDs available on the device can be queried by calling 123 * getEnergyMeterInfo(). Passing an empty array will return energy 124 * measurements for all channels. 125 * 126 * @return List of EnergyMeasurement objects containing energy measurements for all 127 * available energy meters. 128 */ 129 @Nullable readEnergyMeter(int[] channelIds)130 android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(int[] channelIds); 131 132 /** 133 * Returns boolean indicating if connection to power stats HAL was established. 134 * 135 * @return true if connection to power stats HAL was correctly established. 136 */ isInitialized()137 boolean isInitialized(); 138 } 139 140 /** 141 * PowerStatsHALWrapper20Impl is the implementation of the IPowerStatsHALWrapper 142 * used by the PowerStatsService on devices that support only PowerStats HAL 2.0. 143 * Other implementations will be used by the testing framework and will be passed 144 * into the PowerStatsService through an injector. 145 */ 146 public static final class PowerStatsHAL20WrapperImpl implements IPowerStatsHALWrapper { 147 private static Supplier<IPowerStats> sVintfPowerStats; 148 PowerStatsHAL20WrapperImpl()149 public PowerStatsHAL20WrapperImpl() { 150 Supplier<IPowerStats> service = new VintfHalCache(); 151 sVintfPowerStats = null; 152 153 if (service.get() == null) { 154 if (DEBUG) Slog.d(TAG, "PowerStats HAL 2.0 not available on this device."); 155 sVintfPowerStats = null; 156 } else { 157 sVintfPowerStats = service; 158 } 159 } 160 161 @Override getPowerEntityInfo()162 public android.hardware.power.stats.PowerEntity[] getPowerEntityInfo() { 163 android.hardware.power.stats.PowerEntity[] powerEntityHAL = null; 164 165 if (sVintfPowerStats != null) { 166 try { 167 powerEntityHAL = sVintfPowerStats.get().getPowerEntityInfo(); 168 } catch (RemoteException e) { 169 Slog.w(TAG, "Failed to get power entity info: ", e); 170 } 171 } 172 173 return powerEntityHAL; 174 } 175 176 @Override getStateResidency( int[] powerEntityIds)177 public android.hardware.power.stats.StateResidencyResult[] getStateResidency( 178 int[] powerEntityIds) { 179 android.hardware.power.stats.StateResidencyResult[] stateResidencyResultHAL = null; 180 181 if (sVintfPowerStats != null) { 182 try { 183 stateResidencyResultHAL = 184 sVintfPowerStats.get().getStateResidency(powerEntityIds); 185 } catch (RemoteException e) { 186 Slog.w(TAG, "Failed to get state residency: ", e); 187 } 188 } 189 190 return stateResidencyResultHAL; 191 } 192 193 @Override getEnergyConsumerInfo()194 public android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo() { 195 android.hardware.power.stats.EnergyConsumer[] energyConsumerHAL = null; 196 197 if (sVintfPowerStats != null) { 198 try { 199 energyConsumerHAL = sVintfPowerStats.get().getEnergyConsumerInfo(); 200 } catch (RemoteException e) { 201 Slog.w(TAG, "Failed to get energy consumer info: ", e); 202 } 203 } 204 205 return energyConsumerHAL; 206 } 207 208 @Override getEnergyConsumed( int[] energyConsumerIds)209 public android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed( 210 int[] energyConsumerIds) { 211 android.hardware.power.stats.EnergyConsumerResult[] energyConsumedHAL = null; 212 213 if (sVintfPowerStats != null) { 214 try { 215 energyConsumedHAL = 216 sVintfPowerStats.get().getEnergyConsumed(energyConsumerIds); 217 } catch (RemoteException e) { 218 Slog.w(TAG, "Failed to get energy consumer results: ", e); 219 } 220 } 221 222 return energyConsumedHAL; 223 } 224 225 @Override getEnergyMeterInfo()226 public android.hardware.power.stats.Channel[] getEnergyMeterInfo() { 227 android.hardware.power.stats.Channel[] energyMeterInfoHAL = null; 228 229 if (sVintfPowerStats != null) { 230 try { 231 energyMeterInfoHAL = sVintfPowerStats.get().getEnergyMeterInfo(); 232 } catch (RemoteException e) { 233 Slog.w(TAG, "Failed to get energy meter info: ", e); 234 } 235 } 236 237 return energyMeterInfoHAL; 238 } 239 240 @Override readEnergyMeter(int[] channelIds)241 public android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(int[] channelIds) { 242 android.hardware.power.stats.EnergyMeasurement[] energyMeasurementHAL = null; 243 244 if (sVintfPowerStats != null) { 245 try { 246 energyMeasurementHAL = 247 sVintfPowerStats.get().readEnergyMeter(channelIds); 248 } catch (RemoteException e) { 249 Slog.w(TAG, "Failed to get energy measurements: ", e); 250 } 251 } 252 253 return energyMeasurementHAL; 254 } 255 256 @Override isInitialized()257 public boolean isInitialized() { 258 return (sVintfPowerStats != null); 259 } 260 } 261 262 /** 263 * PowerStatsHALWrapper10Impl is the implementation of the IPowerStatsHALWrapper 264 * used by the PowerStatsService on devices that support only PowerStats HAL 1.0. 265 * Other implementations will be used by the testing framework and will be passed 266 * into the PowerStatsService through an injector. 267 */ 268 public static final class PowerStatsHAL10WrapperImpl implements IPowerStatsHALWrapper { 269 private boolean mIsInitialized; 270 271 // PowerStatsHAL 1.0 native functions exposed by JNI layer. nativeInit()272 private static native boolean nativeInit(); nativeGetPowerEntityInfo()273 private static native PowerEntity[] nativeGetPowerEntityInfo(); nativeGetStateResidency(int[] powerEntityIds)274 private static native StateResidencyResult[] nativeGetStateResidency(int[] powerEntityIds); nativeGetEnergyMeterInfo()275 private static native Channel[] nativeGetEnergyMeterInfo(); nativeReadEnergyMeters(int[] channelIds)276 private static native EnergyMeasurement[] nativeReadEnergyMeters(int[] channelIds); 277 PowerStatsHAL10WrapperImpl()278 public PowerStatsHAL10WrapperImpl() { 279 if (nativeInit()) { 280 mIsInitialized = true; 281 } else { 282 if (DEBUG) Slog.d(TAG, "PowerStats HAL 1.0 not available on this device."); 283 mIsInitialized = false; 284 } 285 } 286 287 @Override getPowerEntityInfo()288 public android.hardware.power.stats.PowerEntity[] getPowerEntityInfo() { 289 return nativeGetPowerEntityInfo(); 290 } 291 292 @Override getStateResidency( int[] powerEntityIds)293 public android.hardware.power.stats.StateResidencyResult[] getStateResidency( 294 int[] powerEntityIds) { 295 return nativeGetStateResidency(powerEntityIds); 296 } 297 298 @Override getEnergyConsumerInfo()299 public android.hardware.power.stats.EnergyConsumer[] getEnergyConsumerInfo() { 300 if (DEBUG) Slog.d(TAG, "Energy consumer info is not supported"); 301 return new android.hardware.power.stats.EnergyConsumer[0]; 302 } 303 304 @Override getEnergyConsumed( int[] energyConsumerIds)305 public android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed( 306 int[] energyConsumerIds) { 307 if (DEBUG) Slog.d(TAG, "Energy consumer results are not supported"); 308 return new android.hardware.power.stats.EnergyConsumerResult[0]; 309 } 310 311 @Override getEnergyMeterInfo()312 public android.hardware.power.stats.Channel[] getEnergyMeterInfo() { 313 return nativeGetEnergyMeterInfo(); 314 } 315 316 @Override readEnergyMeter(int[] channelIds)317 public android.hardware.power.stats.EnergyMeasurement[] readEnergyMeter(int[] channelIds) { 318 return nativeReadEnergyMeters(channelIds); 319 } 320 321 @Override isInitialized()322 public boolean isInitialized() { 323 return mIsInitialized; 324 } 325 } 326 327 /** 328 * Returns an instance of an IPowerStatsHALWrapper. If PowerStats HAL 2.0 is supported on the 329 * device, return a PowerStatsHAL20WrapperImpl, else return a PowerStatsHAL10WrapperImpl. 330 * 331 * @return an instance of an IPowerStatsHALWrapper where preference is given to PowerStats HAL 332 * 2.0. 333 */ getPowerStatsHalImpl()334 public static IPowerStatsHALWrapper getPowerStatsHalImpl() { 335 PowerStatsHAL20WrapperImpl powerStatsHAL20WrapperImpl = new PowerStatsHAL20WrapperImpl(); 336 if (powerStatsHAL20WrapperImpl.isInitialized()) { 337 return powerStatsHAL20WrapperImpl; 338 } else { 339 return new PowerStatsHAL10WrapperImpl(); 340 } 341 } 342 343 private static class VintfHalCache implements Supplier<IPowerStats>, IBinder.DeathRecipient { 344 @GuardedBy("this") 345 private IPowerStats mInstance = null; 346 347 @Override get()348 public synchronized IPowerStats get() { 349 if (mInstance == null) { 350 IBinder binder = Binder.allowBlocking(ServiceManager.waitForDeclaredService( 351 "android.hardware.power.stats.IPowerStats/default")); 352 if (binder != null) { 353 mInstance = IPowerStats.Stub.asInterface(binder); 354 try { 355 binder.linkToDeath(this, 0); 356 } catch (RemoteException e) { 357 Slog.e(TAG, "Unable to register DeathRecipient for " + mInstance); 358 } 359 } 360 } 361 return mInstance; 362 } 363 364 @Override binderDied()365 public synchronized void binderDied() { 366 Slog.w(TAG, "PowerStats HAL died"); 367 mInstance = null; 368 } 369 } 370 } 371