Add support for ADPF HintSession sendHint to JNI

 * Add sendHint API to HintManagerService and PerformanceHintManager
 * Plumb relevant calls through the existing implementation
 * Extend existing tests to cover new API calls
 * Update the relevant build files to use power API v4

Bug: b/243973548
Test: atest PerformanceHintNativeTestCases
Test: atest FrameworksCoreTests:android.os.PerformanceHintManagerTest
Test: atest HintManagerServiceTest

Change-Id: Ice7ed8f32e877bd845afad77fcc6ae16f1a1b78c
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index cb0f22f..584d0ba2 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -330,6 +330,7 @@
     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 d627984..7863a7d 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -61,6 +61,7 @@
 
     int updateTargetWorkDuration(int64_t targetDurationNanos);
     int reportActualWorkDuration(int64_t actualDurationNanos);
+    int sendHint(int32_t hint);
 
 private:
     friend struct APerformanceHintManager;
@@ -159,7 +160,7 @@
     }
     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 @@
     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 @@
     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 b17850e..1881e60 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -51,6 +51,7 @@
                 (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 @@
     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);
 }