diff options
| -rw-r--r-- | core/api/current.txt | 5 | ||||
| -rw-r--r-- | core/java/android/os/IHintSession.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/os/PerformanceHintManager.java | 55 | ||||
| -rw-r--r-- | core/jni/android_os_PerformanceHintManager.cpp | 13 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/os/PerformanceHintManagerTest.java | 17 | ||||
| -rw-r--r-- | native/android/libandroid.map.txt | 1 | ||||
| -rw-r--r-- | native/android/performance_hint.cpp | 22 | ||||
| -rw-r--r-- | native/android/tests/performance_hint/PerformanceHintNativeTest.cpp | 10 | ||||
| -rw-r--r-- | services/core/Android.bp | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/hint/HintManagerService.java | 20 | ||||
| -rw-r--r-- | services/core/jni/Android.bp | 2 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_hint_HintManagerService.cpp | 11 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java | 27 |
13 files changed, 183 insertions, 3 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index ee7cdefa77a1..80bae5bd071d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -32169,7 +32169,12 @@ package android.os { public static class PerformanceHintManager.Session implements java.io.Closeable { method public void close(); method public void reportActualWorkDuration(long); + method public void sendHint(int); method public void updateTargetWorkDuration(long); + field public static final int CPU_LOAD_DOWN = 1; // 0x1 + field public static final int CPU_LOAD_RESET = 2; // 0x2 + field public static final int CPU_LOAD_RESUME = 3; // 0x3 + field public static final int CPU_LOAD_UP = 0; // 0x0 } public final class PersistableBundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { diff --git a/core/java/android/os/IHintSession.aidl b/core/java/android/os/IHintSession.aidl index 09bc4cc4eb7e..0d1dde105c09 100644 --- a/core/java/android/os/IHintSession.aidl +++ b/core/java/android/os/IHintSession.aidl @@ -22,4 +22,5 @@ oneway interface IHintSession { void updateTargetWorkDuration(long targetDurationNanos); void reportActualWorkDuration(in long[] actualDurationNanos, in long[] timeStampNanos); void close(); + void sendHint(int hint); } diff --git a/core/java/android/os/PerformanceHintManager.java b/core/java/android/os/PerformanceHintManager.java index a75b5ef6d65e..86135bcb0abf 100644 --- a/core/java/android/os/PerformanceHintManager.java +++ b/core/java/android/os/PerformanceHintManager.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemService; @@ -24,6 +25,10 @@ import android.content.Context; import com.android.internal.util.Preconditions; import java.io.Closeable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.ref.Reference; + /** The PerformanceHintManager allows apps to send performance hint to system. */ @SystemService(Context.PERFORMANCE_HINT_SERVICE) @@ -104,6 +109,40 @@ public final class PerformanceHintManager { mNativeSessionPtr = nativeSessionPtr; } + /** + * This hint indicates a sudden increase in CPU workload intensity. It means + * that this hint session needs extra CPU resources immediately to meet the + * target duration for the current work cycle. + */ + public static final int CPU_LOAD_UP = 0; + /** + * This hint indicates a decrease in CPU workload intensity. It means that + * this hint session can reduce CPU resources and still meet the target duration. + */ + public static final int CPU_LOAD_DOWN = 1; + /* + * This hint indicates an upcoming CPU workload that is completely changed and + * unknown. It means that the hint session should reset CPU resources to a known + * baseline to prepare for an arbitrary load, and must wake up if inactive. + */ + public static final int CPU_LOAD_RESET = 2; + /* + * This hint indicates that the most recent CPU workload is resuming after a + * period of inactivity. It means that the hint session should allocate similar + * CPU resources to what was used previously, and must wake up if inactive. + */ + public static final int CPU_LOAD_RESUME = 3; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CPU_LOAD_"}, value = { + CPU_LOAD_UP, + CPU_LOAD_DOWN, + CPU_LOAD_RESET, + CPU_LOAD_RESUME + }) + public @interface Hint {} + /** @hide */ @Override protected void finalize() throws Throwable { @@ -152,6 +191,21 @@ public final class PerformanceHintManager { mNativeSessionPtr = 0; } } + + /** + * Sends performance hints to inform the hint session of changes in the workload. + * + * @param hint The hint to send to the session. + */ + public void sendHint(@Hint int hint) { + Preconditions.checkArgumentNonNegative(hint, "the hint ID should be at least" + + " zero."); + try { + nativeSendHint(mNativeSessionPtr, hint); + } finally { + Reference.reachabilityFence(this); + } + } } private static native long nativeAcquireManager(); @@ -163,4 +217,5 @@ public final class PerformanceHintManager { private static native void nativeReportActualWorkDuration(long nativeSessionPtr, long actualDurationNanos); private static native void nativeCloseSession(long nativeSessionPtr); + private static native void nativeSendHint(long nativeSessionPtr, int hint); } diff --git a/core/jni/android_os_PerformanceHintManager.cpp b/core/jni/android_os_PerformanceHintManager.cpp index d05a24fe7c6e..ac1401dbb16d 100644 --- a/core/jni/android_os_PerformanceHintManager.cpp +++ b/core/jni/android_os_PerformanceHintManager.cpp @@ -40,6 +40,7 @@ typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* mana typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t); typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t); typedef void (*APH_closeSession)(APerformanceHintSession* session); +typedef void (*APH_sendHint)(APerformanceHintSession*, int32_t); bool gAPerformanceHintBindingInitialized = false; APH_getManager gAPH_getManagerFn = nullptr; @@ -48,6 +49,7 @@ APH_getPreferredUpdateRateNanos gAPH_getPreferredUpdateRateNanosFn = nullptr; APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr; APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr; APH_closeSession gAPH_closeSessionFn = nullptr; +APH_sendHint gAPH_sendHintFn = nullptr; void ensureAPerformanceHintBindingInitialized() { if (gAPerformanceHintBindingInitialized) return; @@ -88,6 +90,11 @@ void ensureAPerformanceHintBindingInitialized() { LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr, "Failed to find required symbol APerformanceHint_closeSession!"); + gAPH_sendHintFn = (APH_sendHint)dlsym(handle_, "APerformanceHint_sendHint"); + LOG_ALWAYS_FATAL_IF(gAPH_sendHintFn == nullptr, + "Failed to find required symbol " + "APerformanceHint_sendHint!"); + gAPerformanceHintBindingInitialized = true; } @@ -138,6 +145,11 @@ static void nativeCloseSession(JNIEnv* env, jclass clazz, jlong nativeSessionPtr gAPH_closeSessionFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr)); } +static void nativeSendHint(JNIEnv* env, jclass clazz, jlong nativeSessionPtr, jint hint) { + ensureAPerformanceHintBindingInitialized(); + gAPH_sendHintFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr), hint); +} + static const JNINativeMethod gPerformanceHintMethods[] = { {"nativeAcquireManager", "()J", (void*)nativeAcquireManager}, {"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos}, @@ -145,6 +157,7 @@ static const JNINativeMethod gPerformanceHintMethods[] = { {"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration}, {"nativeReportActualWorkDuration", "(JJ)V", (void*)nativeReportActualWorkDuration}, {"nativeCloseSession", "(J)V", (void*)nativeCloseSession}, + {"nativeSendHint", "(JI)V", (void*)nativeSendHint}, }; int register_android_os_PerformanceHintManager(JNIEnv* env) { diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java index 69eb13f7854a..d1d14f6fbcb4 100644 --- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java +++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java @@ -114,6 +114,23 @@ public class PerformanceHintManagerTest { } @Test + public void testSendHint() { + Session s = createSession(); + assumeNotNull(s); + s.sendHint(Session.CPU_LOAD_UP); + s.sendHint(Session.CPU_LOAD_RESET); + } + + @Test + public void testSendHintWithNegativeHint() { + Session s = createSession(); + assumeNotNull(s); + assertThrows(IllegalArgumentException.class, () -> { + s.sendHint(-1); + }); + } + + @Test public void testCloseHintSession() { Session s = createSession(); assumeNotNull(s); diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index cb0f22f974ad..584d0ba2ea8c 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -330,6 +330,7 @@ LIBANDROID { APerformanceHint_updateTargetWorkDuration; # introduced=Tiramisu APerformanceHint_reportActualWorkDuration; # introduced=Tiramisu APerformanceHint_closeSession; # introduced=Tiramisu + APerformanceHint_sendHint; # introduced=UpsideDownCake local: *; }; diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index d627984c7fff..7863a7dba1a7 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -61,6 +61,7 @@ public: int updateTargetWorkDuration(int64_t targetDurationNanos); int reportActualWorkDuration(int64_t actualDurationNanos); + int sendHint(int32_t hint); private: friend struct APerformanceHintManager; @@ -159,7 +160,7 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano } binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos); if (!ret.isOk()) { - ALOGE("%s: HintSessionn updateTargetWorkDuration failed: %s", __FUNCTION__, + ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__, ret.exceptionMessage().c_str()); return EPIPE; } @@ -205,6 +206,21 @@ int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNano return 0; } +int APerformanceHintSession::sendHint(int32_t hint) { + if (hint < 0) { + ALOGE("%s: session hint value must be greater than zero", __FUNCTION__); + return EINVAL; + } + + binder::Status ret = mHintSession->sendHint(hint); + + if (!ret.isOk()) { + ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.exceptionMessage().c_str()); + return EPIPE; + } + return 0; +} + // ===================================== C API APerformanceHintManager* APerformanceHint_getManager() { return APerformanceHintManager::getInstance(); @@ -230,6 +246,10 @@ int APerformanceHint_reportActualWorkDuration(APerformanceHintSession* session, return session->reportActualWorkDuration(actualDurationNanos); } +int APerformanceHint_sendHint(APerformanceHintSession* session, int32_t hint) { + return session->sendHint(hint); +} + void APerformanceHint_closeSession(APerformanceHintSession* session) { delete session; } diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp index b17850e5d1e4..1881e60b0f16 100644 --- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp +++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp @@ -51,6 +51,7 @@ public: (const ::std::vector<int64_t>& actualDurationNanos, const ::std::vector<int64_t>& timeStampNanos), (override)); + MOCK_METHOD(Status, sendHint, (int32_t hints), (override)); MOCK_METHOD(Status, close, (), (override)); MOCK_METHOD(IBinder*, onAsBinder, (), (override)); }; @@ -121,6 +122,15 @@ TEST_F(PerformanceHintTest, TestSession) { result = APerformanceHint_reportActualWorkDuration(session, -1L); EXPECT_EQ(EINVAL, result); + // Send both valid and invalid session hints + int hintId = 2; + EXPECT_CALL(*iSession, sendHint(Eq(2))).Times(Exactly(1)); + result = APerformanceHint_sendHint(session, hintId); + EXPECT_EQ(0, result); + + result = APerformanceHint_sendHint(session, -1); + EXPECT_EQ(EINVAL, result); + EXPECT_CALL(*iSession, close()).Times(Exactly(1)); APerformanceHint_closeSession(session); } diff --git a/services/core/Android.bp b/services/core/Android.bp index 553146d0448d..84f2b63f9775 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -168,7 +168,7 @@ java_library_static { "android.hardware.rebootescrow-V1-java", "android.hardware.soundtrigger-V2.3-java", "android.hardware.power.stats-V1-java", - "android.hardware.power-V3-java", + "android.hardware.power-V4-java", "android.hidl.manager-V1.2-java", "capture_state_listener-aidl-java", "icu4j_calendar_astronomer", 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 dfa12814a138..0d13831abe52 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -24,6 +24,7 @@ import android.os.Binder; import android.os.IBinder; import android.os.IHintManager; import android.os.IHintSession; +import android.os.PerformanceHintManager; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; @@ -147,6 +148,8 @@ public final class HintManagerService extends SystemService { private static native void nativeReportActualWorkDuration( long halPtr, long[] actualDurationNanos, long[] timeStampNanos); + private static native void nativeSendHint(long halPtr, int hint); + private static native long nativeGetHintSessionPreferredRate(); /** Wrapper for HintManager.nativeInit */ @@ -186,6 +189,11 @@ public final class HintManagerService extends SystemService { timeStampNanos); } + /** Wrapper for HintManager.sendHint */ + public void halSendHint(long halPtr, int hint) { + nativeSendHint(halPtr, hint); + } + /** Wrapper for HintManager.nativeGetHintSessionPreferredRate */ public long halGetHintSessionPreferredRate() { return nativeGetHintSessionPreferredRate(); @@ -475,6 +483,18 @@ public final class HintManagerService extends SystemService { } } + @Override + public void sendHint(@PerformanceHintManager.Session.Hint int hint) { + synchronized (mLock) { + if (mHalSessionPtr == 0 || !updateHintAllowed()) { + return; + } + Preconditions.checkArgument(hint >= 0, "the hint ID the hint value should be" + + " greater than zero."); + mNativeWrapper.halSendHint(mHalSessionPtr, hint); + } + } + private void onProcStateChanged() { updateHintAllowed(); } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 3c788197b191..57b977cc865a 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -170,7 +170,7 @@ cc_defaults { "android.hardware.power@1.1", "android.hardware.power@1.2", "android.hardware.power@1.3", - "android.hardware.power-V3-cpp", + "android.hardware.power-V4-cpp", "android.hardware.power.stats@1.0", "android.hardware.power.stats-V1-ndk", "android.hardware.thermal@1.0", diff --git a/services/core/jni/com_android_server_hint_HintManagerService.cpp b/services/core/jni/com_android_server_hint_HintManagerService.cpp index 000cb839002b..d975760cbfc2 100644 --- a/services/core/jni/com_android_server_hint_HintManagerService.cpp +++ b/services/core/jni/com_android_server_hint_HintManagerService.cpp @@ -34,6 +34,7 @@ #include "jni.h" using android::hardware::power::IPowerHintSession; +using android::hardware::power::SessionHint; using android::hardware::power::WorkDuration; using android::base::StringPrintf; @@ -81,6 +82,11 @@ static void reportActualWorkDuration(int64_t session_ptr, appSession->reportActualWorkDuration(actualDurations); } +static void sendHint(int64_t session_ptr, SessionHint hint) { + sp<IPowerHintSession> appSession = reinterpret_cast<IPowerHintSession*>(session_ptr); + appSession->sendHint(hint); +} + static int64_t getHintSessionPreferredRate() { int64_t rate = -1; auto result = gPowerHalController.getHintSessionPreferredRate(); @@ -139,6 +145,10 @@ static void nativeReportActualWorkDuration(JNIEnv* env, jclass /* clazz */, jlon reportActualWorkDuration(session_ptr, actualList); } +static void nativeSendHint(JNIEnv* env, jclass /* clazz */, jlong session_ptr, jint hint) { + sendHint(session_ptr, static_cast<SessionHint>(hint)); +} + static jlong nativeGetHintSessionPreferredRate(JNIEnv* /* env */, jclass /* clazz */) { return static_cast<jlong>(getHintSessionPreferredRate()); } @@ -153,6 +163,7 @@ static const JNINativeMethod sHintManagerServiceMethods[] = { {"nativeCloseHintSession", "(J)V", (void*)nativeCloseHintSession}, {"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration}, {"nativeReportActualWorkDuration", "(J[J[J)V", (void*)nativeReportActualWorkDuration}, + {"nativeSendHint", "(JI)V", (void*)nativeSendHint}, {"nativeGetHintSessionPreferredRate", "()J", (void*)nativeGetHintSessionPreferredRate}, }; diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java index 397770bec822..dcbdcdc98017 100644 --- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java @@ -42,6 +42,7 @@ import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.IHintSession; +import android.os.PerformanceHintManager; import android.os.Process; import com.android.server.FgThread; @@ -250,6 +251,32 @@ public class HintManagerServiceTest { } @Test + public void testSendHint() throws Exception { + HintManagerService service = createService(); + IBinder token = new Binder(); + + AppHintSession a = (AppHintSession) service.getBinderServiceInstance() + .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION); + + a.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET); + verify(mNativeWrapperMock, times(1)).halSendHint(anyLong(), + eq(PerformanceHintManager.Session.CPU_LOAD_RESET)); + + assertThrows(IllegalArgumentException.class, () -> { + a.sendHint(-1); + }); + + reset(mNativeWrapperMock); + // Set session to background, then the duration would not be updated. + service.mUidObserver.onUidStateChanged( + a.mUid, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); + FgThread.getHandler().runWithScissors(() -> { }, 500); + assertFalse(a.updateHintAllowed()); + a.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET); + verify(mNativeWrapperMock, never()).halSendHint(anyLong(), anyInt()); + } + + @Test public void testDoHintInBackground() throws Exception { HintManagerService service = createService(); IBinder token = new Binder(); |