SurfaceFlinger: keep layer history for inactive layers

The current implementation of layer history discards all the history
if a layer is considered inactive. This leads to an issue in the scenario
that a layer is posting infrequent updates so slow, that by the time we
get the next buffer, the layer is considered inactive, and we bump the
refresh rate to Max, instead of detecting that layer as infrequent.

As a fix, we keep around the layer history even if it is inactive.
To avoid cases where detect animations too late, we clear the history
on touch event.

Bug: 156654519
Test: add a new unit test that simulates the buffer pattern
of a Netflix playback

Change-Id: Ie076891806d74dde814fbbb3b1a73c38e0b2ae34
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index 67edef4..6570b1a 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -192,7 +192,7 @@
             trace(weak, LayerHistory::LayerVoteType::NoVote, 0);
         }
 
-        info->clearHistory();
+        info->onLayerInactive(now);
         std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]);
     }
 
@@ -213,7 +213,7 @@
     std::lock_guard lock(mLock);
 
     for (const auto& [layer, info] : activeLayers()) {
-        info->clearHistory();
+        info->clearHistory(systemTime());
     }
 }
 } // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index 276afd8..25dca39 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -57,21 +57,14 @@
 }
 
 bool LayerInfoV2::isFrequent(nsecs_t now) const {
-    // Find the first valid frame time
-    auto it = mFrameTimes.begin();
-    for (; it != mFrameTimes.end(); ++it) {
-        if (isFrameTimeValid(*it)) {
-            break;
-        }
-    }
-
     // If we know nothing about this layer we consider it as frequent as it might be the start
     // of an animation.
-    if (std::distance(it, mFrameTimes.end()) < FREQUENT_LAYER_WINDOW_SIZE) {
+    if (mFrameTimes.size() < FREQUENT_LAYER_WINDOW_SIZE) {
         return true;
     }
 
     // Find the first active frame
+    auto it = mFrameTimes.begin();
     for (; it != mFrameTimes.end(); ++it) {
         if (it->queueTime >= getActiveLayerThreshold(now)) {
             break;
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h
index f2d29c5..5f50d5a 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.h
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h
@@ -83,15 +83,21 @@
     // updated time, the updated time is the present time.
     nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; }
 
-    void clearHistory() {
+    void onLayerInactive(nsecs_t now) {
         // Mark mFrameTimeValidSince to now to ignore all previous frame times.
         // We are not deleting the old frame to keep track of whether we should treat the first
         // buffer as Max as we don't know anything about this layer or Min as this layer is
         // posting infrequent updates.
-        mFrameTimeValidSince = std::chrono::steady_clock::now();
+        const auto timePoint = std::chrono::nanoseconds(now);
+        mFrameTimeValidSince = std::chrono::time_point<std::chrono::steady_clock>(timePoint);
         mLastReportedRefreshRate = 0.0f;
     }
 
+    void clearHistory(nsecs_t now) {
+        onLayerInactive(now);
+        mFrameTimes.clear();
+    }
+
 private:
     // Used to store the layer timestamps
     struct FrameTimeData {