Pass active functor rendering threads to HWUI ADPF session

Test: unit tested

Bug: 329219352

Change-Id: I13e83030e5d0891584ba9d62fe6cc1eb332a7b74
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index abf64d0..1fbd580 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -777,6 +777,8 @@
                                  (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
                                  dequeueBufferDuration - idleDuration;
         mHintSessionWrapper->reportActualWorkDuration(actualDuration);
+        mHintSessionWrapper->setActiveFunctorThreads(
+                WebViewFunctorManager::instance().getRenderingThreadsForActiveFunctors());
     }
 
     mLastDequeueBufferDuration = dequeueBufferDuration;
diff --git a/libs/hwui/renderthread/HintSessionWrapper.cpp b/libs/hwui/renderthread/HintSessionWrapper.cpp
index 2362331..6993d52 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.cpp
+++ b/libs/hwui/renderthread/HintSessionWrapper.cpp
@@ -20,6 +20,7 @@
 #include <private/performance_hint_private.h>
 #include <utils/Log.h>
 
+#include <algorithm>
 #include <chrono>
 #include <vector>
 
@@ -49,6 +50,7 @@
     BIND_APH_METHOD(updateTargetWorkDuration);
     BIND_APH_METHOD(reportActualWorkDuration);
     BIND_APH_METHOD(sendHint);
+    BIND_APH_METHOD(setThreads);
 
     mInitialized = true;
 }
@@ -67,6 +69,10 @@
         mHintSession = mHintSessionFuture->get();
         mHintSessionFuture = std::nullopt;
     }
+    if (mSetThreadsFuture.has_value()) {
+        mSetThreadsFuture->wait();
+        mSetThreadsFuture = std::nullopt;
+    }
     if (mHintSession) {
         mBinding->closeSession(mHintSession);
         mSessionValid = true;
@@ -106,16 +112,16 @@
     APerformanceHintManager* manager = mBinding->getManager();
     if (!manager) return false;
 
-    std::vector<pid_t> tids = CommonPool::getThreadIds();
-    tids.push_back(mUiThreadId);
-    tids.push_back(mRenderThreadId);
+    mPermanentSessionTids = CommonPool::getThreadIds();
+    mPermanentSessionTids.push_back(mUiThreadId);
+    mPermanentSessionTids.push_back(mRenderThreadId);
 
     // Use the cached target value if there is one, otherwise use a default. This is to ensure
     // the cached target and target in PowerHAL are consistent, and that it updates correctly
     // whenever there is a change.
     int64_t targetDurationNanos =
             mLastTargetWorkDuration == 0 ? kDefaultTargetDuration : mLastTargetWorkDuration;
-    mHintSessionFuture = CommonPool::async([=, this, tids = std::move(tids)] {
+    mHintSessionFuture = CommonPool::async([=, this, tids = mPermanentSessionTids] {
         return mBinding->createSession(manager, tids.data(), tids.size(), targetDurationNanos);
     });
     return false;
@@ -143,6 +149,23 @@
     mLastFrameNotification = systemTime();
 }
 
+void HintSessionWrapper::setActiveFunctorThreads(std::vector<pid_t> threadIds) {
+    if (!init()) return;
+    if (!mBinding || !mHintSession) return;
+    // Sort the vector to make sure they're compared as sets.
+    std::sort(threadIds.begin(), threadIds.end());
+    if (threadIds == mActiveFunctorTids) return;
+    mActiveFunctorTids = std::move(threadIds);
+    std::vector<pid_t> combinedTids = mPermanentSessionTids;
+    std::copy(mActiveFunctorTids.begin(), mActiveFunctorTids.end(),
+              std::back_inserter(combinedTids));
+    mSetThreadsFuture = CommonPool::async([this, tids = std::move(combinedTids)] {
+        int ret = mBinding->setThreads(mHintSession, tids.data(), tids.size());
+        ALOGE_IF(ret != 0, "APerformaceHint_setThreads failed: %d", ret);
+        return ret;
+    });
+}
+
 void HintSessionWrapper::sendLoadResetHint() {
     static constexpr int kMaxResetsSinceLastReport = 2;
     if (!init()) return;
diff --git a/libs/hwui/renderthread/HintSessionWrapper.h b/libs/hwui/renderthread/HintSessionWrapper.h
index 41891cd..14e7a53 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.h
+++ b/libs/hwui/renderthread/HintSessionWrapper.h
@@ -20,6 +20,7 @@
 
 #include <future>
 #include <optional>
+#include <vector>
 
 #include "utils/TimeUtils.h"
 
@@ -47,11 +48,15 @@
     nsecs_t getLastUpdate();
     void delayedDestroy(renderthread::RenderThread& rt, nsecs_t delay,
                         std::shared_ptr<HintSessionWrapper> wrapperPtr);
+    // Must be called on Render thread. Otherwise can cause a race condition.
+    void setActiveFunctorThreads(std::vector<pid_t> threadIds);
 
 private:
     APerformanceHintSession* mHintSession = nullptr;
     // This needs to work concurrently for testing
     std::optional<std::shared_future<APerformanceHintSession*>> mHintSessionFuture;
+    // This needs to work concurrently for testing
+    std::optional<std::shared_future<int>> mSetThreadsFuture;
 
     int mResetsSinceLastReport = 0;
     nsecs_t mLastFrameNotification = 0;
@@ -59,6 +64,8 @@
 
     pid_t mUiThreadId;
     pid_t mRenderThreadId;
+    std::vector<pid_t> mPermanentSessionTids;
+    std::vector<pid_t> mActiveFunctorTids;
 
     bool mSessionValid = true;
 
@@ -82,6 +89,8 @@
         void (*reportActualWorkDuration)(APerformanceHintSession* session,
                                          int64_t actualDuration) = nullptr;
         void (*sendHint)(APerformanceHintSession* session, int32_t hintId) = nullptr;
+        int (*setThreads)(APerformanceHintSession* session, const pid_t* tids,
+                          size_t size) = nullptr;
 
     private:
         bool mInitialized = false;