Send load up hint for cache rendering

cache buffer rendering supposes to utilize the cpu gap after current
frame finised and before the next frame. But it could take long and
delay the next frame start time and cause jank eventually.
Sending CPU LOAD UP hint to prevent stealing time from the next frame.

Bug: 285991802
Test: PtsUiBench QHD
Change-Id: Id619a8166ae253fef815a25a35fc4b82066144a9
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index d93e25e..09bc467 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -37,6 +37,15 @@
     half4 color;
     std::vector<int32_t> layerIds;
 };
+
+// Interface of composition engine power hint callback.
+struct ICEPowerCallback {
+    virtual void notifyCpuLoadUp() = 0;
+
+protected:
+    ~ICEPowerCallback() = default;
+};
+
 /**
  * A parameter object for refreshing a set of outputs
  */
@@ -96,6 +105,8 @@
     std::vector<BorderRenderInfo> borderInfoList;
 
     bool hasTrustedPresentationListener = false;
+
+    ICEPowerCallback* powerCallback = nullptr;
 };
 
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index a3fda61..28c6e92 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -32,6 +32,7 @@
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
+#include <compositionengine/CompositionRefreshArgs.h>
 #include <compositionengine/ProjectionSpace.h>
 #include <renderengine/BorderRenderInfo.h>
 #include <ui/LayerStack.h>
@@ -167,6 +168,8 @@
     uint64_t lastOutputLayerHash = 0;
     uint64_t outputLayerHash = 0;
 
+    ICEPowerCallback* powerCallback = nullptr;
+
     // Debugging
     void dump(std::string& result) const;
 };
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 793959c..1205a2c 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -843,6 +843,7 @@
 
     editState().earliestPresentTime = refreshArgs.earliestPresentTime;
     editState().expectedPresentTime = refreshArgs.expectedPresentTime;
+    editState().powerCallback = refreshArgs.powerCallback;
 
     compositionengine::OutputLayer* peekThroughLayer = nullptr;
     sp<GraphicBuffer> previousOverride = nullptr;
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index 8ced0ac..a6521bb 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -162,6 +162,9 @@
                        const OutputCompositionState& outputState,
                        bool deviceHandlesColorTransform) {
     ATRACE_CALL();
+    if (outputState.powerCallback) {
+        outputState.powerCallback->notifyCpuLoadUp();
+    }
     const Rect& viewport = outputState.layerStackSpace.getContent();
     const ui::Dataspace& outputDataspace = outputState.dataspace;
     const ui::Transform::RotationFlags orientation =
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index 961ec80..f74ef4c 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -34,6 +34,7 @@
     MOCK_METHOD(void, setExpensiveRenderingExpected, (DisplayId displayId, bool expected),
                 (override));
     MOCK_METHOD(bool, isUsingExpensiveRendering, (), (override));
+    MOCK_METHOD(void, notifyCpuLoadUp, (), (override));
     MOCK_METHOD(void, notifyDisplayUpdateImminentAndCpuReset, (), (override));
     MOCK_METHOD(bool, usePowerHintSession, (), (override));
     MOCK_METHOD(bool, supportsPowerHintSession, (), (override));
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index f8b466c..9c7576e 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -138,6 +138,21 @@
     }
 }
 
+void PowerAdvisor::notifyCpuLoadUp() {
+    // Only start sending this notification once the system has booted so we don't introduce an
+    // early-boot dependency on Power HAL
+    if (!mBootFinished.load()) {
+        return;
+    }
+    if (usePowerHintSession() && ensurePowerHintSessionRunning()) {
+        std::lock_guard lock(mHintSessionMutex);
+        auto ret = mHintSession->sendHint(SessionHint::CPU_LOAD_UP);
+        if (!ret.isOk()) {
+            mHintSessionRunning = false;
+        }
+    }
+}
+
 void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
     // Only start sending this notification once the system has booted so we don't introduce an
     // early-boot dependency on Power HAL
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index f0d3fd8..cfaa135 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -49,6 +49,7 @@
     virtual void onBootFinished() = 0;
     virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
     virtual bool isUsingExpensiveRendering() = 0;
+    virtual void notifyCpuLoadUp() = 0;
     virtual void notifyDisplayUpdateImminentAndCpuReset() = 0;
     // Checks both if it supports and if it's enabled
     virtual bool usePowerHintSession() = 0;
@@ -108,6 +109,7 @@
     void onBootFinished() override;
     void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
     bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; };
+    void notifyCpuLoadUp() override;
     void notifyDisplayUpdateImminentAndCpuReset() override;
     bool usePowerHintSession() override;
     bool supportsPowerHintSession() override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fe2db94..ee5251a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2568,6 +2568,7 @@
     ATRACE_FORMAT("%s %" PRId64, __func__, vsyncId.value);
 
     compositionengine::CompositionRefreshArgs refreshArgs;
+    refreshArgs.powerCallback = this;
     const auto& displays = FTL_FAKE_GUARD(mStateLock, mDisplays);
     refreshArgs.outputs.reserve(displays.size());
     std::vector<DisplayId> displayIds;
@@ -3926,6 +3927,10 @@
     mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
 }
 
+void SurfaceFlinger::notifyCpuLoadUp() {
+    mPowerAdvisor->notifyCpuLoadUp();
+}
+
 void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
     using namespace scheduler;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0bc506f..4b29be8 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -194,7 +194,8 @@
                        private IBinder::DeathRecipient,
                        private HWC2::ComposerCallback,
                        private ICompositor,
-                       private scheduler::ISchedulerCallback {
+                       private scheduler::ISchedulerCallback,
+                       private compositionengine::ICEPowerCallback {
 public:
     struct SkipInitializationTag {};
 
@@ -645,6 +646,9 @@
     void kernelTimerChanged(bool expired) override;
     void triggerOnFrameRateOverridesChanged() override;
 
+    // ICEPowerCallback overrides:
+    void notifyCpuLoadUp() override;
+
     // Toggles the kernel idle timer on or off depending the policy decisions around refresh rates.
     void toggleKernelIdleTimer() REQUIRES(mStateLock);
 
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index 3caa2b9..d635508 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -32,6 +32,7 @@
     MOCK_METHOD(void, setExpensiveRenderingExpected, (DisplayId displayId, bool expected),
                 (override));
     MOCK_METHOD(bool, isUsingExpensiveRendering, (), (override));
+    MOCK_METHOD(void, notifyCpuLoadUp, (), (override));
     MOCK_METHOD(void, notifyDisplayUpdateImminentAndCpuReset, (), (override));
     MOCK_METHOD(bool, usePowerHintSession, (), (override));
     MOCK_METHOD(bool, supportsPowerHintSession, (), (override));