Disable expensive rendering during static screen

Locking the GPU frequency to a high value causes a power regression, so
when there's no screen updates we should disable expensive rendering -
previously expensive rendering would always be enabled if the previous
frame required expensive rendering.

Bug: 188625644
Test: Swipe to recents and monitor gpu clock info
Change-Id: Ie41fa6286e851c0390295672b399ce29419ea90b
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index b738096..fc8cb50 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -29,8 +29,10 @@
     PowerAdvisor();
     ~PowerAdvisor() override;
 
+    MOCK_METHOD0(init, void());
     MOCK_METHOD0(onBootFinished, void());
     MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+    MOCK_METHOD0(isUsingExpensiveRendering, bool());
     MOCK_METHOD0(notifyDisplayUpdateImminent, void());
 };
 
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 901e19a..1765caf 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -32,6 +32,7 @@
 #include "../SurfaceFlingerProperties.h"
 
 #include "PowerAdvisor.h"
+#include "SurfaceFlinger.h"
 
 namespace android {
 namespace Hwc2 {
@@ -61,14 +62,22 @@
 
 } // namespace
 
-PowerAdvisor::PowerAdvisor()
-      : mUseUpdateImminentTimer(getUpdateTimeout() > 0),
-        mUpdateImminentTimer(
+PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
+      : mFlinger(flinger),
+        mUseScreenUpdateTimer(getUpdateTimeout() > 0),
+        mScreenUpdateTimer(
                 "UpdateImminentTimer", OneShotTimer::Interval(getUpdateTimeout()),
                 /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
-                /* timeoutCallback */ [this] { mSendUpdateImminent.store(true); }) {
-    if (mUseUpdateImminentTimer) {
-        mUpdateImminentTimer.start();
+                /* timeoutCallback */
+                [this] {
+                    mSendUpdateImminent.store(true);
+                    mFlinger.disableExpensiveRendering();
+                }) {}
+
+void PowerAdvisor::init() {
+    // Defer starting the screen update timer until SurfaceFlinger finishes construction.
+    if (mUseScreenUpdateTimer) {
+        mScreenUpdateTimer.start();
     }
 }
 
@@ -122,8 +131,8 @@
         }
     }
 
-    if (mUseUpdateImminentTimer) {
-        mUpdateImminentTimer.reset();
+    if (mUseScreenUpdateTimer) {
+        mScreenUpdateTimer.reset();
     }
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 95eb0e2..f2d0766 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -25,14 +25,20 @@
 #include "DisplayIdentification.h"
 
 namespace android {
+
+class SurfaceFlinger;
+
 namespace Hwc2 {
 
 class PowerAdvisor {
 public:
     virtual ~PowerAdvisor();
 
+    // Initializes resources that cannot be initialized on construction
+    virtual void init() = 0;
     virtual void onBootFinished() = 0;
     virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
+    virtual bool isUsingExpensiveRendering() = 0;
     virtual void notifyDisplayUpdateImminent() = 0;
 };
 
@@ -50,11 +56,13 @@
         virtual bool notifyDisplayUpdateImminent() = 0;
     };
 
-    PowerAdvisor();
+    PowerAdvisor(SurfaceFlinger& flinger);
     ~PowerAdvisor() override;
 
+    void init() override;
     void onBootFinished() override;
     void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
+    bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; }
     void notifyDisplayUpdateImminent() override;
 
 private:
@@ -67,9 +75,10 @@
     std::unordered_set<DisplayId> mExpensiveDisplays;
     bool mNotifiedExpensiveRendering = false;
 
-    const bool mUseUpdateImminentTimer;
+    SurfaceFlinger& mFlinger;
+    const bool mUseScreenUpdateTimer;
     std::atomic_bool mSendUpdateImminent = true;
-    scheduler::OneShotTimer mUpdateImminentTimer;
+    scheduler::OneShotTimer mScreenUpdateTimer;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e2f3ebb..01433d6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -344,7 +344,8 @@
         mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
         mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),
         mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
-        mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {
+        mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
+        mPowerAdvisor(*this) {
     ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
 
     mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); });
@@ -816,6 +817,8 @@
     // set initial conditions (e.g. unblank default device)
     initializeDisplays();
 
+    mPowerAdvisor.init();
+
     char primeShaderCache[PROPERTY_VALUE_MAX];
     property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
     if (atoi(primeShaderCache)) {
@@ -1273,6 +1276,19 @@
     mSetActiveModePending = true;
 }
 
+void SurfaceFlinger::disableExpensiveRendering() {
+    schedule([=]() MAIN_THREAD {
+        ATRACE_CALL();
+        if (mPowerAdvisor.isUsingExpensiveRendering()) {
+            const auto& displays = ON_MAIN_THREAD(mDisplays);
+            for (const auto& [_, display] : displays) {
+                const static constexpr auto kDisable = false;
+                mPowerAdvisor.setExpensiveRenderingExpected(display->getId(), kDisable);
+            }
+        }
+    }).wait();
+}
+
 std::vector<ColorMode> SurfaceFlinger::getDisplayColorModes(PhysicalDisplayId displayId) {
     auto modes = getHwComposer().getColorModes(displayId);
     bool isInternalDisplay = displayId == getInternalDisplayIdLocked();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f33df86..66cf683 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -329,6 +329,10 @@
     bool mDisableClientCompositionCache = false;
     void setInputWindowsFinished();
 
+    // Disables expensive rendering for all displays
+    // This is scheduled on the main thread
+    void disableExpensiveRendering();
+
 protected:
     // We're reference counted, never destroy SurfaceFlinger directly
     virtual ~SurfaceFlinger();
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index 7450b5d..159bdf1 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -27,8 +27,10 @@
     PowerAdvisor();
     ~PowerAdvisor() override;
 
+    MOCK_METHOD0(init, void());
     MOCK_METHOD0(onBootFinished, void());
     MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+    MOCK_METHOD0(isUsingExpensiveRendering, bool());
     MOCK_METHOD0(notifyDisplayUpdateImminent, void());
 };