SurfaceFlinger: enhance refresh rate selection

Enhance the refresh rate selection algorithm to allow having multiple
refresh rate. The new process attaches scores to each one of the available
refresh rate and chooses the refresh rate with the highest score.
This behavior is currently controlled by the sysprop flag
'debug.sf.use_content_detection_v2' and currently turned off.

This algorithm stills needs some tunings which will be done in
layer CLs.

Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test
Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Test: go/90hzscenarios manual tests
Bug: 147516364
Fixes: 146068419
Change-Id: I06e07459e469482799ff80fa54fa8dd311325e0e
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6d18922..adf5f9f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -540,6 +540,11 @@
             const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy();
             changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None);
         }
+
+        if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
+            mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
+            mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate());
+        }
     }));
 }
 
@@ -1779,7 +1784,13 @@
 
             // Layers need to get updated (in the previous line) before we can use them for
             // choosing the refresh rate.
-            mScheduler->chooseRefreshRateForContent();
+            // Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
+            // and may eventually call to ~Layer() if it holds the last reference
+            {
+                Mutex::Autolock _l(mStateLock);
+                mScheduler->chooseRefreshRateForContent();
+            }
+
             if (performSetActiveConfig()) {
                 break;
             }
@@ -2378,6 +2389,9 @@
                     }
                     if (state.width != draw[i].width || state.height != draw[i].height) {
                         display->setDisplaySize(state.width, state.height);
+                        if (display->isPrimary()) {
+                            mScheduler->onPrimaryDisplayAreaChanged(state.width * state.height);
+                        }
                     }
                 }
             }
@@ -2450,6 +2464,12 @@
                         LOG_ALWAYS_FATAL_IF(!displayId);
                         dispatchDisplayHotplugEvent(displayId->value, true);
                     }
+
+                    const auto displayDevice = mDisplays[displayToken];
+                    if (displayDevice->isPrimary()) {
+                        mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() *
+                                                                displayDevice->getHeight());
+                    }
                 }
             }
         }
@@ -2647,8 +2667,12 @@
 }
 
 void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate,
-                                       Scheduler::ConfigEvent event) {
-    Mutex::Autolock lock(mStateLock);
+                                       Scheduler::ConfigEvent event) NO_THREAD_SAFETY_ANALYSIS {
+    // If this is called from the main thread mStateLock must be locked before
+    // Currently the only way to call this function from the main thread is from
+    // Sheduler::chooseRefreshRateForContent
+
+    ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
     changeRefreshRateLocked(refreshRate, event);
 }