summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Xiang Wang <xwxw@google.com> 2024-11-22 19:48:48 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-22 19:48:48 +0000
commit025d338f7778047a412662aff76c123a04d1519a (patch)
tree92be6898a187107862d10a420168366d6abe0cf0
parent51c1d767b887e6e75f7ed2810499371d46f03eb4 (diff)
parent2a6b5a929b9b7cfbe4d173cdb17c9d7f64cbf887 (diff)
Merge "Add support for calculation window size and tids" into main
-rw-r--r--core/api/current.txt9
-rw-r--r--core/java/android/os/CpuHeadroomParams.java70
-rw-r--r--core/java/android/os/CpuHeadroomParamsInternal.aidl2
-rw-r--r--core/java/android/os/GpuHeadroomParams.java44
-rw-r--r--core/java/android/os/GpuHeadroomParamsInternal.aidl1
-rw-r--r--core/java/android/os/IHintManager.aidl6
-rw-r--r--core/java/android/os/health/SystemHealthManager.java28
-rw-r--r--native/android/tests/performance_hint/PerformanceHintNativeTest.cpp4
-rw-r--r--services/core/java/com/android/server/power/hint/HintManagerService.java281
-rw-r--r--services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java159
10 files changed, 388 insertions, 216 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 3af8e7e17dbd..55e1aeccd0fd 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -33612,9 +33612,14 @@ package android.os {
@FlaggedApi("android.os.cpu_gpu_headrooms") public final class CpuHeadroomParams {
ctor public CpuHeadroomParams();
method public int getCalculationType();
+ method @IntRange(from=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) public long getCalculationWindowMillis();
method public void setCalculationType(int);
+ method public void setCalculationWindowMillis(@IntRange(from=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.CpuHeadroomParams.CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int);
+ method public void setTids(@NonNull int...);
field public static final int CPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1; // 0x1
field public static final int CPU_HEADROOM_CALCULATION_TYPE_MIN = 0; // 0x0
+ field public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000; // 0x2710
+ field public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50; // 0x32
}
public final class CpuUsageInfo implements android.os.Parcelable {
@@ -33867,9 +33872,13 @@ package android.os {
@FlaggedApi("android.os.cpu_gpu_headrooms") public final class GpuHeadroomParams {
ctor public GpuHeadroomParams();
method public int getCalculationType();
+ method @IntRange(from=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) public int getCalculationWindowMillis();
method public void setCalculationType(int);
+ method public void setCalculationWindowMillis(@IntRange(from=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to=android.os.GpuHeadroomParams.GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int);
field public static final int GPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1; // 0x1
field public static final int GPU_HEADROOM_CALCULATION_TYPE_MIN = 0; // 0x0
+ field public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000; // 0x2710
+ field public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50; // 0x32
}
public class Handler {
diff --git a/core/java/android/os/CpuHeadroomParams.java b/core/java/android/os/CpuHeadroomParams.java
index f0d4f7d8737f..8e78b7e355f9 100644
--- a/core/java/android/os/CpuHeadroomParams.java
+++ b/core/java/android/os/CpuHeadroomParams.java
@@ -18,10 +18,13 @@ package android.os;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.os.health.SystemHealthManager;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
/**
* Headroom request params used by {@link SystemHealthManager#getCpuHeadroom(CpuHeadroomParams)}.
@@ -54,6 +57,16 @@ public final class CpuHeadroomParams {
public static final int CPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1;
/**
+ * Minimum CPU headroom calculation window size.
+ */
+ public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50;
+
+ /**
+ * Maximum CPU headroom calculation window size.
+ */
+ public static final int CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000;
+
+ /**
* Sets the headroom calculation type.
* <p>
*
@@ -83,6 +96,63 @@ public final class CpuHeadroomParams {
}
/**
+ * Sets the headroom calculation window size in milliseconds.
+ * <p>
+ *
+ * @param windowMillis the window size in milliseconds, ranged from
+ * [{@link #CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN},
+ * {@link #CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX}]. The smaller
+ * the value, the larger fluctuation in value should be expected. The
+ * default value can be retrieved from the
+ * {@link #getCalculationWindowMillis}. The device will try to use the
+ * closest feasible window size to this param.
+ * @throws IllegalArgumentException if the window size is not in allowed range.
+ */
+ public void setCalculationWindowMillis(
+ @IntRange(from = CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to =
+ CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int windowMillis) {
+ if (windowMillis < CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN
+ || windowMillis > CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) {
+ throw new IllegalArgumentException("Invalid calculation window: " + windowMillis);
+ }
+ mInternal.calculationWindowMillis = windowMillis;
+ }
+
+ /**
+ * Gets the headroom calculation window size in milliseconds.
+ * <p>
+ * This will return the default value chosen by the device if not set.
+ */
+ public @IntRange(from = CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to =
+ CPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) long getCalculationWindowMillis() {
+ return mInternal.calculationWindowMillis;
+ }
+
+ /**
+ * Sets the thread TIDs to track.
+ * <p>
+ * The TIDs should belong to the same of the process that will the headroom call. And they
+ * should not have different core affinity.
+ * <p>
+ * If not set, the headroom will be based on the PID of the process making the call.
+ *
+ * @param tids non-empty list of TIDs, maximum 5.
+ * @throws IllegalArgumentException if the list size is not in allowed range or TID is not
+ * positive.
+ */
+ public void setTids(@NonNull int... tids) {
+ if (tids.length == 0 || tids.length > 5) {
+ throw new IllegalArgumentException("Invalid number of TIDs: " + tids.length);
+ }
+ for (int tid : tids) {
+ if (tid <= 0) {
+ throw new IllegalArgumentException("Invalid TID: " + tid);
+ }
+ }
+ mInternal.tids = Arrays.copyOf(tids, tids.length);
+ }
+
+ /**
* @hide
*/
public CpuHeadroomParamsInternal getInternal() {
diff --git a/core/java/android/os/CpuHeadroomParamsInternal.aidl b/core/java/android/os/CpuHeadroomParamsInternal.aidl
index 6cc4699a809e..d572f965579b 100644
--- a/core/java/android/os/CpuHeadroomParamsInternal.aidl
+++ b/core/java/android/os/CpuHeadroomParamsInternal.aidl
@@ -25,6 +25,8 @@ import android.hardware.power.CpuHeadroomParams;
@JavaDerive(equals = true, toString = true)
parcelable CpuHeadroomParamsInternal {
boolean usesDeviceHeadroom = false;
+ int[] tids;
+ int calculationWindowMillis = 1000;
CpuHeadroomParams.CalculationType calculationType = CpuHeadroomParams.CalculationType.MIN;
CpuHeadroomParams.SelectionType selectionType = CpuHeadroomParams.SelectionType.ALL;
}
diff --git a/core/java/android/os/GpuHeadroomParams.java b/core/java/android/os/GpuHeadroomParams.java
index efb2a28ad2b5..4dc98264e57b 100644
--- a/core/java/android/os/GpuHeadroomParams.java
+++ b/core/java/android/os/GpuHeadroomParams.java
@@ -18,6 +18,7 @@ package android.os;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.os.health.SystemHealthManager;
import java.lang.annotation.Retention;
@@ -54,6 +55,16 @@ public final class GpuHeadroomParams {
public static final int GPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1;
/**
+ * Minimum GPU headroom calculation window size.
+ */
+ public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN = 50;
+
+ /**
+ * Maximum GPU headroom calculation window size.
+ */
+ public static final int GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX = 10000;
+
+ /**
* Sets the headroom calculation type.
* <p>
*
@@ -83,6 +94,39 @@ public final class GpuHeadroomParams {
}
/**
+ * Sets the headroom calculation window size in milliseconds.
+ * <p>
+ *
+ * @param windowMillis the window size in milliseconds, ranged from
+ * [{@link #GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN},
+ * {@link #GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX}]. The smaller
+ * the value, the larger fluctuation in value should be expected. The
+ * default value can be retrieved from the
+ * {@link #getCalculationWindowMillis}. If the device will try to use the
+ * closest feasible window size to this param.
+ * @throws IllegalArgumentException if the window is invalid.
+ */
+ public void setCalculationWindowMillis(
+ @IntRange(from = GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to =
+ GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int windowMillis) {
+ if (windowMillis < GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN
+ || windowMillis > GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) {
+ throw new IllegalArgumentException("Invalid calculation window: " + windowMillis);
+ }
+ mInternal.calculationWindowMillis = windowMillis;
+ }
+
+ /**
+ * Gets the headroom calculation window size in milliseconds.
+ * <p>
+ * This will return the default value chosen by the device if not set.
+ */
+ public @IntRange(from = GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MIN, to =
+ GPU_HEADROOM_CALCULATION_WINDOW_MILLIS_MAX) int getCalculationWindowMillis() {
+ return mInternal.calculationWindowMillis;
+ }
+
+ /**
* @hide
*/
public GpuHeadroomParamsInternal getInternal() {
diff --git a/core/java/android/os/GpuHeadroomParamsInternal.aidl b/core/java/android/os/GpuHeadroomParamsInternal.aidl
index 20309e7673f2..40d5d8e409ef 100644
--- a/core/java/android/os/GpuHeadroomParamsInternal.aidl
+++ b/core/java/android/os/GpuHeadroomParamsInternal.aidl
@@ -24,5 +24,6 @@ import android.hardware.power.GpuHeadroomParams;
*/
@JavaDerive(equals = true, toString = true)
parcelable GpuHeadroomParamsInternal {
+ int calculationWindowMillis = 1000;
GpuHeadroomParams.CalculationType calculationType = GpuHeadroomParams.CalculationType.MIN;
}
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl
index a043da9b7a36..f1936b5e0ff9 100644
--- a/core/java/android/os/IHintManager.aidl
+++ b/core/java/android/os/IHintManager.aidl
@@ -21,7 +21,9 @@ import android.os.CpuHeadroomParamsInternal;
import android.os.GpuHeadroomParamsInternal;
import android.os.IHintSession;
import android.os.SessionCreationConfig;
+import android.hardware.power.CpuHeadroomResult;
import android.hardware.power.ChannelConfig;
+import android.hardware.power.GpuHeadroomResult;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
@@ -53,9 +55,9 @@ interface IHintManager {
*/
@nullable ChannelConfig getSessionChannel(in IBinder token);
oneway void closeSessionChannel();
- float[] getCpuHeadroom(in CpuHeadroomParamsInternal params);
+ @nullable CpuHeadroomResult getCpuHeadroom(in CpuHeadroomParamsInternal params);
long getCpuHeadroomMinIntervalMillis();
- float getGpuHeadroom(in GpuHeadroomParamsInternal params);
+ @nullable GpuHeadroomResult getGpuHeadroom(in GpuHeadroomParamsInternal params);
long getGpuHeadroomMinIntervalMillis();
/**
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 4db9bc333e2b..cd79e416531a 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -23,6 +23,8 @@ import android.annotation.Nullable;
import android.annotation.SystemService;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.hardware.power.CpuHeadroomResult;
+import android.hardware.power.GpuHeadroomResult;
import android.os.BatteryStats;
import android.os.Build;
import android.os.Bundle;
@@ -110,15 +112,16 @@ public class SystemHealthManager {
}
/**
- * Provides an estimate of global available CPU headroom of the calling thread.
+ * Provides an estimate of global available CPU headroom.
* <p>
*
* @param params params to customize the CPU headroom calculation, null to use default params.
- * @return a single value a {@code Float.NaN} if it's temporarily unavailable.
+ * @return a single value headroom or a {@code Float.NaN} if it's temporarily unavailable.
* A valid value is ranged from [0, 100], where 0 indicates no more CPU resources can be
* granted.
- * @throws UnsupportedOperationException if the API is unsupported or the request params can't
- * be served.
+ * @throws UnsupportedOperationException if the API is unsupported.
+ * @throws SecurityException if the TIDs of the params don't belong to the same process.
+ * @throws IllegalStateException if the TIDs of the params don't have the same affinity setting.
*/
@FlaggedApi(android.os.Flags.FLAG_CPU_GPU_HEADROOMS)
public @FloatRange(from = 0f, to = 100f) float getCpuHeadroom(
@@ -127,8 +130,12 @@ public class SystemHealthManager {
throw new UnsupportedOperationException();
}
try {
- return mHintManager.getCpuHeadroom(
- params != null ? params.getInternal() : new CpuHeadroomParamsInternal())[0];
+ final CpuHeadroomResult ret = mHintManager.getCpuHeadroom(
+ params != null ? params.getInternal() : new CpuHeadroomParamsInternal());
+ if (ret == null || ret.getTag() != CpuHeadroomResult.globalHeadroom) {
+ return Float.NaN;
+ }
+ return ret.getGlobalHeadroom();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -144,8 +151,7 @@ public class SystemHealthManager {
* @return a single value headroom or a {@code Float.NaN} if it's temporarily unavailable.
* A valid value is ranged from [0, 100], where 0 indicates no more GPU resources can be
* granted.
- * @throws UnsupportedOperationException if the API is unsupported or the request params can't
- * be served.
+ * @throws UnsupportedOperationException if the API is unsupported.
*/
@FlaggedApi(android.os.Flags.FLAG_CPU_GPU_HEADROOMS)
public @FloatRange(from = 0f, to = 100f) float getGpuHeadroom(
@@ -154,8 +160,12 @@ public class SystemHealthManager {
throw new UnsupportedOperationException();
}
try {
- return mHintManager.getGpuHeadroom(
+ final GpuHeadroomResult ret = mHintManager.getGpuHeadroom(
params != null ? params.getInternal() : new GpuHeadroomParamsInternal());
+ if (ret == null || ret.getTag() != GpuHeadroomResult.globalHeadroom) {
+ return Float.NaN;
+ }
+ return ret.getGlobalHeadroom();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index c5fb80840b84..b00658052bde 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -73,13 +73,13 @@ public:
MOCK_METHOD(ScopedAStatus, closeSessionChannel, (), (override));
MOCK_METHOD(ScopedAStatus, getCpuHeadroom,
(const ::aidl::android::os::CpuHeadroomParamsInternal& in_params,
- std::vector<float>* _aidl_return),
+ std::optional<hal::CpuHeadroomResult>* _aidl_return),
(override));
MOCK_METHOD(ScopedAStatus, getCpuHeadroomMinIntervalMillis, (int64_t* _aidl_return),
(override));
MOCK_METHOD(ScopedAStatus, getGpuHeadroom,
(const ::aidl::android::os::GpuHeadroomParamsInternal& in_params,
- float* _aidl_return),
+ std::optional<hal::GpuHeadroomResult>* _aidl_return),
(override));
MOCK_METHOD(ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* _aidl_return),
(override));
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 71f67d82dbec..aba15c83f907 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -34,7 +34,9 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.hardware.power.ChannelConfig;
import android.hardware.power.CpuHeadroomParams;
+import android.hardware.power.CpuHeadroomResult;
import android.hardware.power.GpuHeadroomParams;
+import android.hardware.power.GpuHeadroomResult;
import android.hardware.power.IPower;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
@@ -79,6 +81,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -96,10 +99,10 @@ public final class HintManagerService extends SystemService {
private static final int EVENT_CLEAN_UP_UID = 3;
@VisibleForTesting static final int CLEAN_UP_UID_DELAY_MILLIS = 1000;
+ // The minimum interval between the headroom calls as rate limiting.
private static final int DEFAULT_GPU_HEADROOM_INTERVAL_MILLIS = 1000;
private static final int DEFAULT_CPU_HEADROOM_INTERVAL_MILLIS = 1000;
private static final int HEADROOM_INTERVAL_UNSUPPORTED = -1;
- @VisibleForTesting static final int DEFAULT_HEADROOM_PID = -1;
@VisibleForTesting final long mHintSessionPreferredRate;
@@ -184,73 +187,77 @@ public final class HintManagerService extends SystemService {
private static final String PROPERTY_SF_ENABLE_CPU_HINT = "debug.sf.enable_adpf_cpu_hint";
private static final String PROPERTY_HWUI_ENABLE_HINT_MANAGER = "debug.hwui.use_hint_manager";
private static final String PROPERTY_USE_HAL_HEADROOMS = "persist.hms.use_hal_headrooms";
+ private static final String PROPERTY_CHECK_HEADROOM_TID = "persist.hms.check_headroom_tid";
private Boolean mFMQUsesIntegratedEventFlag = false;
private final Object mCpuHeadroomLock = new Object();
- private static class CpuHeadroomCacheItem {
- long mExpiredTimeMillis;
- CpuHeadroomParamsInternal mParams;
- float[] mHeadroom;
- long mPid;
- CpuHeadroomCacheItem(long expiredTimeMillis, CpuHeadroomParamsInternal params,
- float[] headroom, long pid) {
- mExpiredTimeMillis = expiredTimeMillis;
- mParams = params;
- mPid = pid;
- mHeadroom = headroom;
- }
+ // this cache tracks the expiration time of the items and performs cleanup on lookup
+ private static class HeadroomCache<K, V> {
+ final List<HeadroomCacheItem> mItemList;
+ final Map<K, HeadroomCacheItem> mKeyItemMap;
+ final long mItemExpDurationMillis;
+
+ class HeadroomCacheItem {
+ long mExpTime;
+ K mKey;
+ V mValue;
- private boolean match(CpuHeadroomParamsInternal params, long pid) {
- if (mParams == null && params == null) return true;
- if (mParams != null) {
- return mParams.equals(params) && pid == mPid;
+ HeadroomCacheItem(K k, V v) {
+ mExpTime = System.currentTimeMillis() + mItemExpDurationMillis;
+ mKey = k;
+ mValue = v;
}
- return false;
- }
- private boolean isExpired() {
- return System.currentTimeMillis() > mExpiredTimeMillis;
+ boolean isExpired() {
+ return mExpTime <= System.currentTimeMillis();
+ }
}
- }
-
- @GuardedBy("mCpuHeadroomLock")
- private final List<CpuHeadroomCacheItem> mCpuHeadroomCache;
- private final long mCpuHeadroomIntervalMillis;
-
- private final Object mGpuHeadroomLock = new Object();
- private static class GpuHeadroomCacheItem {
- long mExpiredTimeMillis;
- GpuHeadroomParamsInternal mParams;
- float mHeadroom;
-
- GpuHeadroomCacheItem(long expiredTimeMillis, GpuHeadroomParamsInternal params,
- float headroom) {
- mExpiredTimeMillis = expiredTimeMillis;
- mParams = params;
- mHeadroom = headroom;
+ void add(K key, V value) {
+ if (mKeyItemMap.containsKey(key)) {
+ final HeadroomCacheItem item = mKeyItemMap.get(key);
+ mItemList.remove(item);
+ }
+ final HeadroomCacheItem item = new HeadroomCacheItem(key, value);
+ mItemList.add(item);
+ mKeyItemMap.put(key, item);
}
- private boolean match(GpuHeadroomParamsInternal params) {
- if (mParams == null && params == null) return true;
- if (mParams != null) {
- return mParams.equals(params);
+ V get(K key) {
+ while (!mItemList.isEmpty() && mItemList.getFirst().isExpired()) {
+ mKeyItemMap.remove(mItemList.removeFirst().mKey);
}
- return false;
+ final HeadroomCacheItem item = mKeyItemMap.get(key);
+ if (item == null) {
+ return null;
+ }
+ return item.mValue;
}
- private boolean isExpired() {
- return System.currentTimeMillis() > mExpiredTimeMillis;
+ HeadroomCache(int size, long expDurationMillis) {
+ mItemList = new LinkedList<>();
+ mKeyItemMap = new ArrayMap<>(size);
+ mItemExpDurationMillis = expDurationMillis;
}
}
+ @GuardedBy("mCpuHeadroomLock")
+ private final HeadroomCache<CpuHeadroomParams, CpuHeadroomResult> mCpuHeadroomCache;
+ private final long mCpuHeadroomIntervalMillis;
+
+ private final Object mGpuHeadroomLock = new Object();
+
@GuardedBy("mGpuHeadroomLock")
- private final List<GpuHeadroomCacheItem> mGpuHeadroomCache;
+ private final HeadroomCache<GpuHeadroomParams, GpuHeadroomResult> mGpuHeadroomCache;
private final long mGpuHeadroomIntervalMillis;
+ // these are set to default values in CpuHeadroomParamsInternal and GpuHeadroomParamsInternal
+ private final int mDefaultCpuHeadroomCalculationWindowMillis;
+ private final int mDefaultGpuHeadroomCalculationWindowMillis;
+
@VisibleForTesting
final IHintManager.Stub mService = new BinderService();
@@ -303,26 +310,31 @@ public final class HintManagerService extends SystemService {
}
}
mCpuHeadroomIntervalMillis = cpuHeadroomIntervalMillis;
+ mDefaultCpuHeadroomCalculationWindowMillis =
+ new CpuHeadroomParamsInternal().calculationWindowMillis;
+ mDefaultGpuHeadroomCalculationWindowMillis =
+ new GpuHeadroomParamsInternal().calculationWindowMillis;
mGpuHeadroomIntervalMillis = gpuHeadroomIntervalMillis;
if (mCpuHeadroomIntervalMillis > 0) {
- mCpuHeadroomCache = new ArrayList<>(4);
+ mCpuHeadroomCache = new HeadroomCache<>(2, mCpuHeadroomIntervalMillis);
} else {
mCpuHeadroomCache = null;
}
if (mGpuHeadroomIntervalMillis > 0) {
- mGpuHeadroomCache = new ArrayList<>(2);
+ mGpuHeadroomCache = new HeadroomCache<>(2, mGpuHeadroomIntervalMillis);
} else {
mGpuHeadroomCache = null;
}
}
private long checkCpuHeadroomSupport() {
+ final CpuHeadroomParams params = new CpuHeadroomParams();
+ params.tids = new int[]{Process.myPid()};
try {
synchronized (mCpuHeadroomLock) {
- final CpuHeadroomParams defaultParams = new CpuHeadroomParams();
- defaultParams.pid = Process.myPid();
- float[] ret = mPowerHal.getCpuHeadroom(defaultParams);
- if (ret != null && ret.length > 0) {
+ final CpuHeadroomResult ret = mPowerHal.getCpuHeadroom(params);
+ if (ret != null && ret.getTag() == CpuHeadroomResult.globalHeadroom
+ && !Float.isNaN(ret.getGlobalHeadroom())) {
return Math.max(
DEFAULT_CPU_HEADROOM_INTERVAL_MILLIS,
mPowerHal.getCpuHeadroomMinIntervalMillis());
@@ -330,27 +342,29 @@ public final class HintManagerService extends SystemService {
}
} catch (UnsupportedOperationException e) {
- Slog.w(TAG, "getCpuHeadroom HAL API is not supported", e);
+ Slog.w(TAG, "getCpuHeadroom HAL API is not supported, params: " + params, e);
} catch (RemoteException e) {
- Slog.e(TAG, "getCpuHeadroom HAL API fails, disabling the API", e);
+ Slog.e(TAG, "getCpuHeadroom HAL API fails, disabling the API, params: " + params, e);
}
return HEADROOM_INTERVAL_UNSUPPORTED;
}
private long checkGpuHeadroomSupport() {
+ final GpuHeadroomParams params = new GpuHeadroomParams();
try {
synchronized (mGpuHeadroomLock) {
- float ret = mPowerHal.getGpuHeadroom(new GpuHeadroomParams());
- if (!Float.isNaN(ret)) {
+ final GpuHeadroomResult ret = mPowerHal.getGpuHeadroom(params);
+ if (ret != null && ret.getTag() == GpuHeadroomResult.globalHeadroom && !Float.isNaN(
+ ret.getGlobalHeadroom())) {
return Math.max(
DEFAULT_GPU_HEADROOM_INTERVAL_MILLIS,
mPowerHal.getGpuHeadroomMinIntervalMillis());
}
}
} catch (UnsupportedOperationException e) {
- Slog.w(TAG, "getGpuHeadroom HAL API is not supported", e);
+ Slog.w(TAG, "getGpuHeadroom HAL API is not supported, params: " + params, e);
} catch (RemoteException e) {
- Slog.e(TAG, "getGpuHeadroom HAL API fails, disabling the API", e);
+ Slog.e(TAG, "getGpuHeadroom HAL API fails, disabling the API, params: " + params, e);
}
return HEADROOM_INTERVAL_UNSUPPORTED;
}
@@ -1445,109 +1459,98 @@ public final class HintManagerService extends SystemService {
}
@Override
- public float[] getCpuHeadroom(@Nullable CpuHeadroomParamsInternal params) {
+ public CpuHeadroomResult getCpuHeadroom(@NonNull CpuHeadroomParamsInternal params) {
if (mCpuHeadroomIntervalMillis <= 0) {
throw new UnsupportedOperationException();
}
- CpuHeadroomParams halParams = new CpuHeadroomParams();
- halParams.pid = Binder.getCallingPid();
- if (params != null) {
- halParams.calculationType = params.calculationType;
- halParams.selectionType = params.selectionType;
- if (params.usesDeviceHeadroom) {
- halParams.pid = DEFAULT_HEADROOM_PID;
- }
- }
- synchronized (mCpuHeadroomLock) {
- while (!mCpuHeadroomCache.isEmpty()) {
- if (mCpuHeadroomCache.getFirst().isExpired()) {
- mCpuHeadroomCache.removeFirst();
- } else {
- break;
+ final CpuHeadroomParams halParams = new CpuHeadroomParams();
+ halParams.tids = new int[]{Binder.getCallingPid()};
+ halParams.calculationType = params.calculationType;
+ halParams.calculationWindowMillis = params.calculationWindowMillis;
+ halParams.selectionType = params.selectionType;
+ if (params.usesDeviceHeadroom) {
+ halParams.tids = new int[]{};
+ } else if (params.tids != null && params.tids.length > 0) {
+ if (params.tids.length > 5) {
+ throw new IllegalArgumentException(
+ "More than 5 TIDs is requested: " + params.tids.length);
+ }
+ if (SystemProperties.getBoolean(PROPERTY_CHECK_HEADROOM_TID, true)) {
+ final int tgid = Process.getThreadGroupLeader(Binder.getCallingPid());
+ for (int tid : params.tids) {
+ if (Process.getThreadGroupLeader(tid) != tgid) {
+ throw new SecurityException("TID " + tid
+ + " doesn't belong to the calling process with pid "
+ + tgid);
+ }
}
}
- for (int i = 0; i < mCpuHeadroomCache.size(); ++i) {
- final CpuHeadroomCacheItem item = mCpuHeadroomCache.get(i);
- if (item.match(params, halParams.pid)) {
- item.mExpiredTimeMillis =
- System.currentTimeMillis() + mCpuHeadroomIntervalMillis;
- mCpuHeadroomCache.remove(i);
- mCpuHeadroomCache.add(item);
- return item.mHeadroom;
- }
+ halParams.tids = params.tids;
+ }
+ if (halParams.calculationWindowMillis
+ == mDefaultCpuHeadroomCalculationWindowMillis) {
+ synchronized (mCpuHeadroomLock) {
+ final CpuHeadroomResult res = mCpuHeadroomCache.get(halParams);
+ if (res != null) return res;
}
}
// return from HAL directly
try {
- float[] headroom = mPowerHal.getCpuHeadroom(halParams);
- if (headroom == null || headroom.length == 0) {
- Slog.wtf(TAG,
- "CPU headroom from Power HAL is invalid: " + Arrays.toString(headroom));
- return new float[]{Float.NaN};
- }
- synchronized (mCpuHeadroomLock) {
- mCpuHeadroomCache.add(new CpuHeadroomCacheItem(
- System.currentTimeMillis() + mCpuHeadroomIntervalMillis,
- params, headroom, halParams.pid
- ));
+ final CpuHeadroomResult result = mPowerHal.getCpuHeadroom(halParams);
+ if (result == null) {
+ Slog.wtf(TAG, "CPU headroom from Power HAL is invalid");
+ return null;
+ }
+ if (halParams.calculationWindowMillis
+ == mDefaultCpuHeadroomCalculationWindowMillis) {
+ synchronized (mCpuHeadroomLock) {
+ mCpuHeadroomCache.add(halParams, result);
+ }
}
- return headroom;
-
+ return result;
} catch (RemoteException e) {
- return new float[]{Float.NaN};
+ Slog.e(TAG, "Failed to get CPU headroom from Power HAL", e);
+ return null;
}
}
@Override
- public float getGpuHeadroom(@Nullable GpuHeadroomParamsInternal params) {
+ public GpuHeadroomResult getGpuHeadroom(@NonNull GpuHeadroomParamsInternal params) {
if (mGpuHeadroomIntervalMillis <= 0) {
throw new UnsupportedOperationException();
}
- GpuHeadroomParams halParams = new GpuHeadroomParams();
- if (params != null) {
- halParams.calculationType = params.calculationType;
- }
- synchronized (mGpuHeadroomLock) {
- while (!mGpuHeadroomCache.isEmpty()) {
- if (mGpuHeadroomCache.getFirst().isExpired()) {
- mGpuHeadroomCache.removeFirst();
- } else {
- break;
- }
- }
- for (int i = 0; i < mGpuHeadroomCache.size(); ++i) {
- final GpuHeadroomCacheItem item = mGpuHeadroomCache.get(i);
- if (item.match(params)) {
- item.mExpiredTimeMillis =
- System.currentTimeMillis() + mGpuHeadroomIntervalMillis;
- mGpuHeadroomCache.remove(i);
- mGpuHeadroomCache.add(item);
- return item.mHeadroom;
- }
+ final GpuHeadroomParams halParams = new GpuHeadroomParams();
+ halParams.calculationType = params.calculationType;
+ halParams.calculationWindowMillis = params.calculationWindowMillis;
+ if (halParams.calculationWindowMillis
+ == mDefaultGpuHeadroomCalculationWindowMillis) {
+ synchronized (mGpuHeadroomLock) {
+ final GpuHeadroomResult res = mGpuHeadroomCache.get(halParams);
+ if (res != null) return res;
}
}
// return from HAL directly
try {
- float headroom = mPowerHal.getGpuHeadroom(halParams);
- if (Float.isNaN(headroom)) {
- Slog.wtf(TAG,
- "GPU headroom from Power HAL is NaN");
- return Float.NaN;
- }
- synchronized (mGpuHeadroomLock) {
- mGpuHeadroomCache.add(new GpuHeadroomCacheItem(
- System.currentTimeMillis() + mGpuHeadroomIntervalMillis,
- params, headroom
- ));
+ final GpuHeadroomResult headroom = mPowerHal.getGpuHeadroom(halParams);
+ if (headroom == null) {
+ Slog.wtf(TAG, "GPU headroom from Power HAL is invalid");
+ return null;
+ }
+ if (halParams.calculationWindowMillis
+ == mDefaultGpuHeadroomCalculationWindowMillis) {
+ synchronized (mGpuHeadroomLock) {
+ mGpuHeadroomCache.add(halParams, headroom);
+ }
}
return headroom;
} catch (RemoteException e) {
- return Float.NaN;
+ Slog.e(TAG, "Failed to get GPU headroom from Power HAL", e);
+ return null;
}
}
@Override
- public long getCpuHeadroomMinIntervalMillis() throws RemoteException {
+ public long getCpuHeadroomMinIntervalMillis() {
if (mCpuHeadroomIntervalMillis <= 0) {
throw new UnsupportedOperationException();
}
@@ -1555,7 +1558,7 @@ public final class HintManagerService extends SystemService {
}
@Override
- public long getGpuHeadroomMinIntervalMillis() throws RemoteException {
+ public long getGpuHeadroomMinIntervalMillis() {
if (mGpuHeadroomIntervalMillis <= 0) {
throw new UnsupportedOperationException();
}
@@ -1591,17 +1594,23 @@ public final class HintManagerService extends SystemService {
CpuHeadroomParamsInternal params = new CpuHeadroomParamsInternal();
params.selectionType = CpuHeadroomParams.SelectionType.ALL;
params.usesDeviceHeadroom = true;
- pw.println("CPU headroom: " + Arrays.toString(getCpuHeadroom(params)));
+ CpuHeadroomResult ret = getCpuHeadroom(params);
+ pw.println("CPU headroom: " + (ret == null ? "N/A" : ret.getGlobalHeadroom()));
params = new CpuHeadroomParamsInternal();
params.selectionType = CpuHeadroomParams.SelectionType.PER_CORE;
params.usesDeviceHeadroom = true;
- pw.println("CPU headroom per core: " + Arrays.toString(getCpuHeadroom(params)));
+ ret = getCpuHeadroom(params);
+ pw.println("CPU headroom per core: " + (ret == null ? "N/A"
+ : Arrays.toString(ret.getPerCoreHeadroom())));
} catch (Exception e) {
+ Slog.d(TAG, "Failed to dump CPU headroom", e);
pw.println("CPU headroom: N/A");
}
try {
- pw.println("GPU headroom: " + getGpuHeadroom(null));
+ GpuHeadroomResult ret = getGpuHeadroom(new GpuHeadroomParamsInternal());
+ pw.println("GPU headroom: " + (ret == null ? "N/A" : ret.getGlobalHeadroom()));
} catch (Exception e) {
+ Slog.d(TAG, "Failed to dump GPU headroom", e);
pw.println("GPU headroom: N/A");
}
}
diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
index e631cb66eaf7..313c01d5ce58 100644
--- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -18,7 +18,6 @@ package com.android.server.power.hint;
import static com.android.server.power.hint.HintManagerService.CLEAN_UP_UID_DELAY_MILLIS;
-import static com.android.server.power.hint.HintManagerService.DEFAULT_HEADROOM_PID;
import static com.google.common.truth.Truth.assertThat;
@@ -53,7 +52,9 @@ import android.hardware.common.fmq.MQDescriptor;
import android.hardware.power.ChannelConfig;
import android.hardware.power.ChannelMessage;
import android.hardware.power.CpuHeadroomParams;
+import android.hardware.power.CpuHeadroomResult;
import android.hardware.power.GpuHeadroomParams;
+import android.hardware.power.GpuHeadroomResult;
import android.hardware.power.IPower;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
@@ -1251,67 +1252,98 @@ public class HintManagerServiceTest {
CpuHeadroomParams halParams1 = new CpuHeadroomParams();
halParams1.calculationType = CpuHeadroomParams.CalculationType.MIN;
halParams1.selectionType = CpuHeadroomParams.SelectionType.ALL;
- halParams1.pid = Process.myPid();
+ halParams1.tids = new int[]{Process.myPid()};
CpuHeadroomParamsInternal params2 = new CpuHeadroomParamsInternal();
params2.usesDeviceHeadroom = true;
- params2.calculationType = CpuHeadroomParams.CalculationType.AVERAGE;
+ params2.calculationType = CpuHeadroomParams.CalculationType.MIN;
params2.selectionType = CpuHeadroomParams.SelectionType.PER_CORE;
CpuHeadroomParams halParams2 = new CpuHeadroomParams();
- halParams2.calculationType = CpuHeadroomParams.CalculationType.AVERAGE;
+ halParams2.calculationType = CpuHeadroomParams.CalculationType.MIN;
halParams2.selectionType = CpuHeadroomParams.SelectionType.PER_CORE;
- halParams2.pid = DEFAULT_HEADROOM_PID;
+ halParams2.tids = new int[]{};
+
+ CpuHeadroomParamsInternal params3 = new CpuHeadroomParamsInternal();
+ params3.calculationType = CpuHeadroomParams.CalculationType.AVERAGE;
+ params3.selectionType = CpuHeadroomParams.SelectionType.ALL;
+ CpuHeadroomParams halParams3 = new CpuHeadroomParams();
+ halParams3.calculationType = CpuHeadroomParams.CalculationType.AVERAGE;
+ halParams3.selectionType = CpuHeadroomParams.SelectionType.ALL;
+ halParams3.tids = new int[]{Process.myPid()};
+
+ // this params should not be cached as the window is not default
+ CpuHeadroomParamsInternal params4 = new CpuHeadroomParamsInternal();
+ params4.calculationWindowMillis = 123;
+ CpuHeadroomParams halParams4 = new CpuHeadroomParams();
+ halParams4.calculationType = CpuHeadroomParams.CalculationType.MIN;
+ halParams4.selectionType = CpuHeadroomParams.SelectionType.ALL;
+ halParams4.calculationWindowMillis = 123;
+ halParams4.tids = new int[]{Process.myPid()};
- float[] headroom1 = new float[] {0.1f};
- when(mIPowerMock.getCpuHeadroom(eq(halParams1))).thenReturn(headroom1);
- float[] headroom2 = new float[] {0.1f, 0.5f};
- when(mIPowerMock.getCpuHeadroom(eq(halParams2))).thenReturn(headroom2);
+ float headroom1 = 0.1f;
+ CpuHeadroomResult halRet1 = CpuHeadroomResult.globalHeadroom(headroom1);
+ when(mIPowerMock.getCpuHeadroom(eq(halParams1))).thenReturn(halRet1);
+ float[] headroom2 = new float[] {0.2f, 0.2f};
+ CpuHeadroomResult halRet2 = CpuHeadroomResult.perCoreHeadroom(headroom2);
+ when(mIPowerMock.getCpuHeadroom(eq(halParams2))).thenReturn(halRet2);
+ float headroom3 = 0.3f;
+ CpuHeadroomResult halRet3 = CpuHeadroomResult.globalHeadroom(headroom3);
+ when(mIPowerMock.getCpuHeadroom(eq(halParams3))).thenReturn(halRet3);
+ float headroom4 = 0.4f;
+ CpuHeadroomResult halRet4 = CpuHeadroomResult.globalHeadroom(headroom4);
+ when(mIPowerMock.getCpuHeadroom(eq(halParams4))).thenReturn(halRet4);
HintManagerService service = createService();
clearInvocations(mIPowerMock);
service.getBinderServiceInstance().getCpuHeadroomMinIntervalMillis();
verify(mIPowerMock, times(0)).getCpuHeadroomMinIntervalMillis();
- service.getBinderServiceInstance().getCpuHeadroom(params1);
+ assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams1));
- service.getBinderServiceInstance().getCpuHeadroom(params2);
+ assertEquals(halRet2, service.getBinderServiceInstance().getCpuHeadroom(params2));
verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams2));
+ assertEquals(halRet3, service.getBinderServiceInstance().getCpuHeadroom(params3));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams3));
+ assertEquals(halRet4, service.getBinderServiceInstance().getCpuHeadroom(params4));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams4));
// verify cache is working
clearInvocations(mIPowerMock);
- assertArrayEquals(headroom1, service.getBinderServiceInstance().getCpuHeadroom(params1),
- 0.01f);
- assertArrayEquals(headroom2, service.getBinderServiceInstance().getCpuHeadroom(params2),
- 0.01f);
- verify(mIPowerMock, times(0)).getCpuHeadroom(any());
+ assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
+ assertEquals(halRet2, service.getBinderServiceInstance().getCpuHeadroom(params2));
+ assertEquals(halRet3, service.getBinderServiceInstance().getCpuHeadroom(params3));
+ assertEquals(halRet4, service.getBinderServiceInstance().getCpuHeadroom(params4));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(any());
+ verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams1));
+ verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams2));
+ verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams3));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams4));
// after 1 more second it should be served with cache still
Thread.sleep(1000);
clearInvocations(mIPowerMock);
- assertArrayEquals(headroom1, service.getBinderServiceInstance().getCpuHeadroom(params1),
- 0.01f);
- assertArrayEquals(headroom2, service.getBinderServiceInstance().getCpuHeadroom(params2),
- 0.01f);
- verify(mIPowerMock, times(0)).getCpuHeadroom(any());
-
- // after 1.5 more second it should be served with cache still as timer reset
- Thread.sleep(1500);
- clearInvocations(mIPowerMock);
- assertArrayEquals(headroom1, service.getBinderServiceInstance().getCpuHeadroom(params1),
- 0.01f);
- assertArrayEquals(headroom2, service.getBinderServiceInstance().getCpuHeadroom(params2),
- 0.01f);
- verify(mIPowerMock, times(0)).getCpuHeadroom(any());
+ assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
+ assertEquals(halRet2, service.getBinderServiceInstance().getCpuHeadroom(params2));
+ assertEquals(halRet3, service.getBinderServiceInstance().getCpuHeadroom(params3));
+ assertEquals(halRet4, service.getBinderServiceInstance().getCpuHeadroom(params4));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(any());
+ verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams1));
+ verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams2));
+ verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams3));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams4));
// after 2+ seconds it should be served from HAL as it exceeds 2000 millis interval
- Thread.sleep(2100);
+ Thread.sleep(1100);
clearInvocations(mIPowerMock);
- assertArrayEquals(headroom1, service.getBinderServiceInstance().getCpuHeadroom(params1),
- 0.01f);
- assertArrayEquals(headroom2, service.getBinderServiceInstance().getCpuHeadroom(params2),
- 0.01f);
+ assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
+ assertEquals(halRet2, service.getBinderServiceInstance().getCpuHeadroom(params2));
+ assertEquals(halRet3, service.getBinderServiceInstance().getCpuHeadroom(params3));
+ assertEquals(halRet4, service.getBinderServiceInstance().getCpuHeadroom(params4));
+ verify(mIPowerMock, times(4)).getCpuHeadroom(any());
verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams1));
verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams2));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams3));
+ verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams4));
}
@Test
@@ -1322,59 +1354,52 @@ public class HintManagerServiceTest {
halParams1.calculationType = GpuHeadroomParams.CalculationType.MIN;
GpuHeadroomParamsInternal params2 = new GpuHeadroomParamsInternal();
+ params2.calculationType = GpuHeadroomParams.CalculationType.AVERAGE;
+ params2.calculationWindowMillis = 123;
GpuHeadroomParams halParams2 = new GpuHeadroomParams();
- params2.calculationType =
- halParams2.calculationType = GpuHeadroomParams.CalculationType.AVERAGE;
+ halParams2.calculationType = GpuHeadroomParams.CalculationType.AVERAGE;
+ halParams2.calculationWindowMillis = 123;
float headroom1 = 0.1f;
- when(mIPowerMock.getGpuHeadroom(eq(halParams1))).thenReturn(headroom1);
+ GpuHeadroomResult halRet1 = GpuHeadroomResult.globalHeadroom(headroom1);
+ when(mIPowerMock.getGpuHeadroom(eq(halParams1))).thenReturn(halRet1);
float headroom2 = 0.2f;
- when(mIPowerMock.getGpuHeadroom(eq(halParams2))).thenReturn(headroom2);
+ GpuHeadroomResult halRet2 = GpuHeadroomResult.globalHeadroom(headroom2);
+ when(mIPowerMock.getGpuHeadroom(eq(halParams2))).thenReturn(halRet2);
HintManagerService service = createService();
clearInvocations(mIPowerMock);
service.getBinderServiceInstance().getGpuHeadroomMinIntervalMillis();
verify(mIPowerMock, times(0)).getGpuHeadroomMinIntervalMillis();
- assertEquals(headroom1, service.getBinderServiceInstance().getGpuHeadroom(params1),
- 0.01f);
- assertEquals(headroom2, service.getBinderServiceInstance().getGpuHeadroom(params2),
- 0.01f);
+ assertEquals(halRet1, service.getBinderServiceInstance().getGpuHeadroom(params1));
+ assertEquals(halRet2, service.getBinderServiceInstance().getGpuHeadroom(params2));
+ verify(mIPowerMock, times(2)).getGpuHeadroom(any());
verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams1));
verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
// verify cache is working
clearInvocations(mIPowerMock);
- assertEquals(headroom1, service.getBinderServiceInstance().getGpuHeadroom(params1),
- 0.01f);
- assertEquals(headroom2, service.getBinderServiceInstance().getGpuHeadroom(params2),
- 0.01f);
- verify(mIPowerMock, times(0)).getGpuHeadroom(any());
+ assertEquals(halRet1, service.getBinderServiceInstance().getGpuHeadroom(params1));
+ assertEquals(halRet2, service.getBinderServiceInstance().getGpuHeadroom(params2));
+ verify(mIPowerMock, times(1)).getGpuHeadroom(any());
+ verify(mIPowerMock, times(0)).getGpuHeadroom(eq(halParams1));
+ verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
// after 1 more second it should be served with cache still
Thread.sleep(1000);
clearInvocations(mIPowerMock);
- assertEquals(headroom1, service.getBinderServiceInstance().getGpuHeadroom(params1),
- 0.01f);
- assertEquals(headroom2, service.getBinderServiceInstance().getGpuHeadroom(params2),
- 0.01f);
- verify(mIPowerMock, times(0)).getGpuHeadroom(any());
-
- // after 1.5 more second it should be served with cache still as timer reset
- Thread.sleep(1500);
- clearInvocations(mIPowerMock);
- assertEquals(headroom1, service.getBinderServiceInstance().getGpuHeadroom(params1),
- 0.01f);
- assertEquals(headroom2, service.getBinderServiceInstance().getGpuHeadroom(params2),
- 0.01f);
- verify(mIPowerMock, times(0)).getGpuHeadroom(any());
+ assertEquals(halRet1, service.getBinderServiceInstance().getGpuHeadroom(params1));
+ assertEquals(halRet2, service.getBinderServiceInstance().getGpuHeadroom(params2));
+ verify(mIPowerMock, times(1)).getGpuHeadroom(any());
+ verify(mIPowerMock, times(0)).getGpuHeadroom(eq(halParams1));
+ verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
// after 2+ seconds it should be served from HAL as it exceeds 2000 millis interval
- Thread.sleep(2100);
+ Thread.sleep(1100);
clearInvocations(mIPowerMock);
- assertEquals(headroom1, service.getBinderServiceInstance().getGpuHeadroom(params1),
- 0.01f);
- assertEquals(headroom2, service.getBinderServiceInstance().getGpuHeadroom(params2),
- 0.01f);
+ assertEquals(halRet1, service.getBinderServiceInstance().getGpuHeadroom(params1));
+ assertEquals(halRet2, service.getBinderServiceInstance().getGpuHeadroom(params2));
+ verify(mIPowerMock, times(2)).getGpuHeadroom(any());
verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams1));
verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
}