Change mLayersWithQueuedFrames to be an unordered_set

It was possible for mLayersWithQueuedFrames to grow unbounded for very
long GPU work, which causes additional calls into the kernel in
latchBuffer() to repeatedly call into the kernel to check the status of
the same fence. Instead, mLayersWithQueuedFrames should be a set so that
duplicate layers are skipped.

Fixes: 167300366
Test: systrace
Change-Id: I0c54ea6265ce901192e430c8f446a04547e1b833
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 240db35..5400365 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2057,7 +2057,7 @@
             refreshArgs.layers.push_back(layerFE);
     });
     refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
-    for (sp<Layer> layer : mLayersWithQueuedFrames) {
+    for (auto layer : mLayersWithQueuedFrames) {
         if (auto layerFE = layer->getCompositionEngineLayerFE())
             refreshArgs.layersWithQueuedFrames.push_back(layerFE);
     }
@@ -2220,7 +2220,7 @@
     ALOGV("postComposition");
 
     nsecs_t dequeueReadyTime = systemTime();
-    for (auto& layer : mLayersWithQueuedFrames) {
+    for (auto layer : mLayersWithQueuedFrames) {
         layer->releasePendingBuffer(dequeueReadyTime);
     }
 
@@ -3138,7 +3138,7 @@
         if (layer->hasReadyFrame()) {
             frameQueued = true;
             if (layer->shouldPresentNow(expectedPresentTime)) {
-                mLayersWithQueuedFrames.push_back(layer);
+                mLayersWithQueuedFrames.emplace(layer);
             } else {
                 ATRACE_NAME("!layer->shouldPresentNow()");
                 layer->useEmptyDamage();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 37cafe9..0d54c3e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1080,7 +1080,11 @@
     bool mInputInfoChanged = false;
     bool mGeometryInvalid = false;
     bool mAnimCompositionPending = false;
-    std::vector<sp<Layer>> mLayersWithQueuedFrames;
+
+    // Tracks layers that have pending frames which are candidates for being
+    // latched. Because this contains a set of raw layer pointers, can only be
+    // mutated on the main thread.
+    std::unordered_set<Layer*> mLayersWithQueuedFrames;
     // Tracks layers that need to update a display's dirty region.
     std::vector<sp<Layer>> mLayersPendingRefresh;
     std::array<sp<Fence>, 2> mPreviousPresentFences = {Fence::NO_FENCE, Fence::NO_FENCE};