• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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