BLASTBufferQueue: Support setFrameRate

Surface::setFrameRate calls through to SurfaceFlinger
using the IGBP as a token. But of course in the case of BBQ
we have no IGBP on the server side, and this will produce errors.
To fix this we continue overriding Surface methods in the BBQSurface
, and forward through to the SurfaceControl variants of the function.

Bug: 170890018
Test: Existing tests pass
Change-Id: Ia2f5584a1fa871cff9511ddba155e6c957cefc3f
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 82c963b..6ae6df1 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -354,10 +354,15 @@
 }
 
 class BBQSurface : public Surface {
+private:
+    sp<BLASTBufferQueue> mBbq;
 public:
-    BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp) :
-        Surface(igbp, controlledByApp) {
+  BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
+      const sp<BLASTBufferQueue>& bbq) :
+      Surface(igbp, controlledByApp),
+      mBbq(bbq) {
     }
+
     void allocateBuffers() override {
         uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
         uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
@@ -369,10 +374,27 @@
 
         }).detach();
     }
+
+    status_t setFrameRate(float frameRate, int8_t compatibility) override {
+        if (!ValidateFrameRate(frameRate, compatibility, "BBQSurface::setFrameRate")) {
+            return BAD_VALUE;
+        }
+        return mBbq->setFrameRate(frameRate, compatibility);
+    }
 };
 
+// TODO: Can we coalesce this with frame updates? Need to confirm
+// no timing issues.
+status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility) {
+    std::unique_lock _lock{mMutex};
+    SurfaceComposerClient::Transaction t;
+
+    return t.setFrameRate(mSurfaceControl, frameRate, compatibility)
+        .apply();
+}
+
 sp<Surface> BLASTBufferQueue::getSurface() {
-    return new BBQSurface(mProducer, true);
+    return new BBQSurface(mProducer, true, this);
 }
 
 } // namespace android
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index d9644d1..d477bea 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -85,6 +85,8 @@
     void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height);
     void flushShadowQueue() { mFlushShadowQueue = true; }
 
+    status_t setFrameRate(float frameRate, int8_t compatibility);
+
     virtual ~BLASTBufferQueue() = default;
 
 private:
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 800b8ef..6a1eaa2 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -179,7 +179,7 @@
     status_t getUniqueId(uint64_t* outId) const;
     status_t getConsumerUsage(uint64_t* outUsage) const;
 
-    status_t setFrameRate(float frameRate, int8_t compatibility);
+    virtual status_t setFrameRate(float frameRate, int8_t compatibility);
 
 protected:
     virtual ~Surface();