Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 329f5f38 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add rate limiter to sendHint API call"

parents ea89a254 56093a77
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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);
    }

+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ cc_library_shared {
        "libpowermanager",
        "android.hardware.configstore@1.0",
        "android.hardware.configstore-utils",
        "android.hardware.power-V4-ndk",
        "libnativedisplay",
    ],

+25 −3
Original line number Diff line number Diff line
@@ -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;
}

+9 −2
Original line number Diff line number Diff line
@@ -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);