SF: Don't bump to PERFORMANCE refresh rate with infrequent updates

Testing scenario:
1. Set brightness around 50%-55%, set dark theme.
2. Open Chrome.
3. Click search bar.
4. Can see the cursor show up.
Notice the flickering of the screen.

Explanation:
Kernel idle timer detects inactivity after 100ms, and turns the refresh rate to 60Hz.
When a cursor update happens (every 500ms), SF receives a new frame, notifies kernel,
the refresh rate bumps to 90Hz. After 100ms the kernel again decreases the refresh rate to 60Hz.

Desired goals:
Stop the flickering (eg. changing between 60-90Hz too often).
Continue having low battery impact.

Solution in this AG:
Add logic to SF to detect infrequent updates (for all layers). Description of the algorithm:
1) Store the timestamp of the last two buffers.
2) If the first buffer is older than 250 ms, detect inactivity, go into DEFAULT refresh rate.
3) EXIT: on touch event, layer requests 2 or more frames in less than 250ms.
NOTE: if the application is explicitly requesting 90Hz, SF does not override that. Idle kernel
still kicks in, and the flickering happens.

tested on Chrome v74 Beta, and messaging app.

Test: manual, b/135009095
Bug: 135718869
Change-Id: I72d8cd48b3ec900989afcf0fab1cdc3046b87274
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index e762af3..f80c233 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -46,11 +46,13 @@
 LayerHistory::~LayerHistory() = default;
 
 std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name,
+                                                                     float minRefreshRate,
                                                                      float maxRefreshRate) {
     const int64_t id = sNextId++;
 
     std::lock_guard lock(mLock);
-    mInactiveLayerInfos.emplace(id, std::make_shared<LayerInfo>(name, maxRefreshRate));
+    mInactiveLayerInfos.emplace(id,
+                                std::make_shared<LayerInfo>(name, minRefreshRate, maxRefreshRate));
     return std::make_unique<LayerHistory::LayerHandle>(*this, id);
 }
 
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 2569b46..5598cc1 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -53,7 +53,8 @@
     ~LayerHistory();
 
     // When the layer is first created, register it.
-    std::unique_ptr<LayerHandle> createLayer(const std::string name, float maxRefreshRate);
+    std::unique_ptr<LayerHandle> createLayer(const std::string name, float minRefreshRate,
+                                             float maxRefreshRate);
 
     // Method for inserting layers and their requested present time into the unordered map.
     void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, bool isHdr);
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 3104724..beddb9b 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -24,9 +24,10 @@
 namespace android {
 namespace scheduler {
 
-LayerInfo::LayerInfo(const std::string name, float maxRefreshRate)
+LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate)
       : mName(name),
         mMinRefreshDuration(1e9f / maxRefreshRate),
+        mLowActivityRefreshDuration(1e9f / minRefreshRate),
         mRefreshRateHistory(mMinRefreshDuration) {}
 
 LayerInfo::~LayerInfo() = default;
@@ -47,7 +48,7 @@
     const nsecs_t timeDiff = lastPresentTime - mLastPresentTime;
     mLastPresentTime = lastPresentTime;
     // Ignore time diff that are too high - those are stale values
-    if (timeDiff > TIME_EPSILON_NS.count()) return;
+    if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return;
     const nsecs_t refreshDuration = (timeDiff > 0) ? timeDiff : mMinRefreshDuration;
     mRefreshRateHistory.insertRefreshRate(refreshDuration);
 }
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 90d4269..2c50053 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -96,8 +96,9 @@
                 return false;
             }
 
-            // The last update should not be older than TIME_EPSILON_NS nanoseconds.
-            const int64_t obsoleteEpsilon = systemTime() - scheduler::TIME_EPSILON_NS.count();
+            // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds.
+            const int64_t obsoleteEpsilon =
+                    systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count();
             if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) {
                 return false;
             }
@@ -105,6 +106,25 @@
             return true;
         }
 
+        bool isLowActivityLayer() const {
+            // We want to make sure that we received more than two frames from the layer
+            // in order to check low activity.
+            if (mElements.size() < 2) {
+                return false;
+            }
+
+            const int64_t obsoleteEpsilon =
+                    systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count();
+            // Check the frame before last to determine whether there is low activity.
+            // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending
+            // infrequent updates.
+            if (mElements.at(mElements.size() - 2) < obsoleteEpsilon) {
+                return true;
+            }
+
+            return false;
+        }
+
         void clearHistory() { mElements.clear(); }
 
     private:
@@ -114,7 +134,7 @@
     };
 
 public:
-    LayerInfo(const std::string name, float maxRefreshRate);
+    LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate);
     ~LayerInfo();
 
     LayerInfo(const LayerInfo&) = delete;
@@ -144,6 +164,10 @@
     // Calculate the average refresh rate.
     float getDesiredRefreshRate() const {
         std::lock_guard lock(mLock);
+
+        if (mPresentTimeHistory.isLowActivityLayer()) {
+            return 1e9f / mLowActivityRefreshDuration;
+        }
         return mRefreshRateHistory.getRefreshRateAvg();
     }
 
@@ -175,6 +199,7 @@
 private:
     const std::string mName;
     const nsecs_t mMinRefreshDuration;
+    const nsecs_t mLowActivityRefreshDuration;
     mutable std::mutex mLock;
     nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0;
     nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index bb24f73..99d6fae 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -330,8 +330,11 @@
             : RefreshRateType::PERFORMANCE;
 
     const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType);
-    const uint32_t fps = (refreshRate) ? refreshRate->fps : 0;
-    return mLayerHistory.createLayer(name, fps);
+    const uint32_t performanceFps = (refreshRate) ? refreshRate->fps : 0;
+
+    const auto defaultRefreshRate = mRefreshRateConfigs.getRefreshRate(RefreshRateType::DEFAULT);
+    const uint32_t defaultFps = (defaultRefreshRate) ? defaultRefreshRate->fps : 0;
+    return mLayerHistory.createLayer(name, defaultFps, performanceFps);
 }
 
 void Scheduler::addLayerPresentTimeAndHDR(
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
index d3b1bd0..ced1899 100644
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h
@@ -36,13 +36,16 @@
 static constexpr int SCREEN_OFF_CONFIG_ID = -1;
 static constexpr uint32_t HWC2_SCREEN_OFF_CONFIG_ID = 0xffffffff;
 
-// This number is used when we try to determine how long does a given layer stay relevant.
-// The value is set based on testing different scenarios.
-static constexpr std::chrono::nanoseconds TIME_EPSILON_NS = 200ms;
-
 // This number is used when we try to determine how long do we keep layer information around
-// before we remove it.
-static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 200ms;
+// before we remove it. It is also used to determine how long the layer stays relevant.
+// This time period captures infrequent updates when playing YouTube video with static image,
+// or waiting idle in messaging app, when cursor is blinking.
+static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms;
+
+// Layer is considered low activity if the buffers come more than LOW_ACTIVITY_EPSILON_NS
+// apart. This is helping SF to vote for lower refresh rates when there is not activity
+// in screen.
+static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms;
 
 // Calculates the statistical mean (average) in the data structure (array, vector). The
 // function does not modify the contents of the array.