diff options
| -rw-r--r-- | core/tests/coretests/src/android/os/PerformanceHintManagerTest.java | 3 | ||||
| -rw-r--r-- | native/android/Android.bp | 1 | ||||
| -rw-r--r-- | native/android/performance_hint.cpp | 28 | ||||
| -rw-r--r-- | native/android/tests/performance_hint/PerformanceHintNativeTest.cpp | 11 |
4 files changed, 37 insertions, 6 deletions
diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java index d1d14f6fbcb4..44923b60fbb5 100644 --- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java +++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java @@ -117,7 +117,8 @@ public class PerformanceHintManagerTest { public void testSendHint() { Session s = createSession(); assumeNotNull(s); - s.sendHint(Session.CPU_LOAD_UP); + s.sendHint(Session.CPU_LOAD_RESET); + // ensure we can also send within the rate limit without exception s.sendHint(Session.CPU_LOAD_RESET); } diff --git a/native/android/Android.bp b/native/android/Android.bp index f1b1d79265de..254eb4494ed8 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -95,6 +95,7 @@ cc_library_shared { "libpowermanager", "android.hardware.configstore@1.0", "android.hardware.configstore-utils", + "android.hardware.power-V4-ndk", "libnativedisplay", ], diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index 40eb507a5213..9e97bd33ce9c 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "perf_hint" +#include <aidl/android/hardware/power/SessionHint.h> #include <android/os/IHintManager.h> #include <android/os/IHintSession.h> #include <android/performance_hint.h> @@ -25,14 +26,21 @@ #include <performance_hint_private.h> #include <utils/SystemClock.h> +#include <chrono> #include <utility> #include <vector> using namespace android; using namespace android::os; +using namespace std::chrono_literals; + +using AidlSessionHint = aidl::android::hardware::power::SessionHint; + struct APerformanceHintSession; +constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count(); + struct APerformanceHintManager { public: static APerformanceHintManager* getInstance(); @@ -75,6 +83,8 @@ private: int64_t mFirstTargetMetTimestamp; // Last target hit timestamp int64_t mLastTargetMetTimestamp; + // Last hint reported from sendHint indexed by hint value + std::vector<int64_t> mLastHintSentTimestamp; // Cached samples std::vector<int64_t> mActualDurationsNanos; std::vector<int64_t> mTimestampsNanos; @@ -147,7 +157,12 @@ APerformanceHintSession::APerformanceHintSession(sp<IHintSession> session, mPreferredRateNanos(preferredRateNanos), mTargetDurationNanos(targetDurationNanos), mFirstTargetMetTimestamp(0), - mLastTargetMetTimestamp(0) {} + mLastTargetMetTimestamp(0) { + const std::vector<AidlSessionHint> sessionHintRange{ndk::enum_range<AidlSessionHint>().begin(), + ndk::enum_range<AidlSessionHint>().end()}; + + mLastHintSentTimestamp = std::vector<int64_t>(sessionHintRange.size(), 0); +} APerformanceHintSession::~APerformanceHintSession() { binder::Status ret = mHintSession->close(); @@ -224,10 +239,16 @@ int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNano } int APerformanceHintSession::sendHint(int32_t hint) { - if (hint < 0) { - ALOGE("%s: session hint value must be greater than zero", __FUNCTION__); + if (hint < 0 || hint >= static_cast<int32_t>(mLastHintSentTimestamp.size())) { + ALOGE("%s: invalid session hint %d", __FUNCTION__, hint); return EINVAL; } + int64_t now = elapsedRealtimeNano(); + + // Limit sendHint to a pre-detemined rate for safety + if (now < (mLastHintSentTimestamp[hint] + SEND_HINT_TIMEOUT)) { + return 0; + } binder::Status ret = mHintSession->sendHint(hint); @@ -235,6 +256,7 @@ int APerformanceHintSession::sendHint(int32_t hint) { ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.exceptionMessage().c_str()); return EPIPE; } + mLastHintSentTimestamp[hint] = now; return 0; } diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp index 1881e60b0f16..0c2d3b6cd201 100644 --- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp +++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp @@ -122,9 +122,16 @@ 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)); + EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1)); + result = APerformanceHint_sendHint(session, hintId); + EXPECT_EQ(0, result); + usleep(110000); // Sleep for longer than the update timeout. + EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1)); + result = APerformanceHint_sendHint(session, hintId); + EXPECT_EQ(0, result); + // Expect to get rate limited if we try to send faster than the limiter allows + EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(0)); result = APerformanceHint_sendHint(session, hintId); EXPECT_EQ(0, result); |