Change slot generation for BufferState

BufferState layers now do slot generation with buffer death considered
appropriately.  When a buffer dies, the slot will be pushed onto a stack
of available slots to be reused at the next opportunity.  This should
mimic BufferQueue slot behavior and prevent Composer Resources from
growing too large.

Test: build, boot, manual
Bug: 129351223

Change-Id: Icef9592593cacb0b5c6b12f6679fc2c4dabdcd19
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 864a15d..12f0141 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -25,6 +25,8 @@
 #include <system/window.h>
 #include <utils/String8.h>
 
+#include <stack>
+
 namespace android {
 
 class BufferStateLayer : public BufferLayer {
@@ -63,8 +65,8 @@
     bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
     bool setCrop(const Rect& crop) override;
     bool setFrame(const Rect& frame) override;
-    bool setBuffer(const sp<GraphicBuffer>& buffer, nsecs_t postTime,
-                   nsecs_t desiredPresentTime) override;
+    bool setBuffer(const sp<GraphicBuffer>& buffer, nsecs_t postTime, nsecs_t desiredPresentTime,
+                   const client_cache_t& clientCacheId) override;
     bool setAcquireFence(const sp<Fence>& fence) override;
     bool setDataspace(ui::Dataspace dataspace) override;
     bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
@@ -154,6 +156,45 @@
     nsecs_t mDesiredPresentTime = -1;
 
     // TODO(marissaw): support sticky transform for LEGACY camera mode
+
+    class HwcSlotGenerator : public ClientCache::ErasedRecipient {
+    public:
+        HwcSlotGenerator() {
+            for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+                mFreeHwcCacheSlots.push(i);
+            }
+        }
+
+        void bufferErased(const client_cache_t& clientCacheId);
+
+        uint32_t getHwcCacheSlot(const client_cache_t& clientCacheId);
+
+    private:
+        uint32_t addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex);
+        uint32_t getFreeHwcCacheSlot() REQUIRES(mMutex);
+        void evictLeastRecentlyUsed() REQUIRES(mMutex);
+        void eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex);
+
+        struct CachedBufferHash {
+            std::size_t operator()(const client_cache_t& clientCacheId) const {
+                return std::hash<uint64_t>{}(clientCacheId.id);
+            }
+        };
+
+        std::mutex mMutex;
+
+        std::unordered_map<client_cache_t,
+                           std::pair<uint32_t /*HwcCacheSlot*/, uint32_t /*counter*/>,
+                           CachedBufferHash>
+                mCachedBuffers GUARDED_BY(mMutex);
+        std::stack<uint32_t /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex);
+
+        // The cache increments this counter value when a slot is updated or used.
+        // Used to track the least recently-used buffer
+        uint64_t mCounter = 0;
+    };
+
+    sp<HwcSlotGenerator> mHwcSlotGenerator;
 };
 
 } // namespace android