BlastBufferQueue: Add support for auto refresh

When BQ is in shared bufer mode, the client can request
the consumer to aquire frames as fast as possible before
waiting for a frame to be available. To support this for
BLAST, pass the state via a transaction.

Fixes: 168506187
Test: atest SurfaceViewBufferTests
Change-Id: I25ddd98671a08e56798612b7e5dc72095b2c4b7b
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 6db6112..e6aa02a 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -289,6 +289,11 @@
     t->setDesiredPresentTime(bufferItem.mTimestamp);
     t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber);
 
+    if (mAutoRefresh != bufferItem.mAutoRefresh) {
+        t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
+        mAutoRefresh = bufferItem.mAutoRefresh;
+    }
+
     if (applyTransaction) {
         t->apply();
     }
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 90999fa..7d2c7b8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -61,7 +61,9 @@
         frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT),
         shouldBeSeamless(true),
         fixedTransformHint(ui::Transform::ROT_INVALID),
-        frameNumber(0) {
+        frameNumber(0),
+        frameTimelineVsyncId(ISurfaceComposer::INVALID_VSYNC_ID),
+        autoRefresh(false) {
     matrix.dsdx = matrix.dtdy = 1.0f;
     matrix.dsdy = matrix.dtdx = 0.0f;
     hdrMetadata.validTypes = 0;
@@ -149,6 +151,7 @@
     SAFE_PARCEL(output.writeUint32, fixedTransformHint);
     SAFE_PARCEL(output.writeUint64, frameNumber);
     SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId);
+    SAFE_PARCEL(output.writeBool, autoRefresh);
 
     SAFE_PARCEL(output.writeUint32, blurRegions.size());
     for (auto region : blurRegions) {
@@ -269,6 +272,7 @@
     fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
     SAFE_PARCEL(input.readUint64, &frameNumber);
     SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId);
+    SAFE_PARCEL(input.readBool, &autoRefresh);
 
     uint32_t numRegions = 0;
     SAFE_PARCEL(input.readUint32, &numRegions);
@@ -534,6 +538,20 @@
         what |= eFrameNumberChanged;
         frameNumber = other.frameNumber;
     }
+    if (other.what & eFrameTimelineVsyncChanged) {
+        // When merging vsync Ids we take the oldest valid one
+        if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID &&
+            other.frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
+            frameTimelineVsyncId = std::max(frameTimelineVsyncId, other.frameTimelineVsyncId);
+        } else if (frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) {
+            frameTimelineVsyncId = other.frameTimelineVsyncId;
+        }
+        what |= eFrameTimelineVsyncChanged;
+    }
+    if (other.what & eAutoRefreshChanged) {
+        what |= eAutoRefreshChanged;
+        autoRefresh = other.autoRefresh;
+    }
     if ((other.what & what) != other.what) {
         ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
               "other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a822598..47a08ab 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1527,6 +1527,19 @@
     return *this;
 }
 
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAutoRefresh(
+        const sp<SurfaceControl>& sc, bool autoRefresh) {
+    layer_state_t* s = getLayerState(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
+
+    s->what |= layer_state_t::eAutoRefreshChanged;
+    s->autoRefresh = autoRefresh;
+    return *this;
+}
+
 // ---------------------------------------------------------------------------
 
 DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 42427c0..9fb7d6f 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -139,6 +139,10 @@
     // If set to true, the next queue buffer will wait until the shadow queue has been processed by
     // the adapter.
     bool mFlushShadowQueue = false;
+    // Last requested auto refresh state set by the producer. The state indicates that the consumer
+    // should acquire the next frame as soon as it can and not wait for a frame to become available.
+    // This is only relevant for shared buffer mode.
+    bool mAutoRefresh GUARDED_BY(mMutex) = false;
 };
 
 } // namespace android
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index d9f2806..f1c5d67 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -130,6 +130,7 @@
         eFrameNumberChanged = 0x400'00000000,
         eFrameTimelineVsyncChanged = 0x800'00000000,
         eBlurRegionsChanged = 0x1000'00000000,
+        eAutoRefreshChanged = 0x2000'00000000,
     };
 
     layer_state_t();
@@ -234,6 +235,11 @@
     uint64_t frameNumber;
 
     int64_t frameTimelineVsyncId;
+
+    // Indicates that the consumer should acquire the next frame as soon as it
+    // can and not wait for a frame to become available. This is only relevant
+    // in shared buffer mode.
+    bool autoRefresh;
 };
 
 struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 6289c6a..2eb97f2 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -541,6 +541,11 @@
         Transaction& setFrameTimelineVsync(const sp<SurfaceControl>& sc,
                 int64_t frameTimelineVsyncId);
 
+        // Indicates that the consumer should acquire the next frame as soon as it
+        // can and not wait for a frame to become available. This is only relevant
+        // in shared buffer mode.
+        Transaction& setAutoRefresh(const sp<SurfaceControl>& sc, bool autoRefresh);
+
         status_t setDisplaySurface(const sp<IBinder>& token,
                 const sp<IGraphicBufferProducer>& bufferProducer);
 
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index deaf846..63dfe5f 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -178,13 +178,17 @@
     /// the mStateLock.
     ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
 
+    bool getAutoRefresh() const { return mAutoRefresh; }
+    bool getSidebandStreamChanged() const { return mSidebandStreamChanged; }
+
+    std::atomic<bool> mAutoRefresh{false};
+    std::atomic<bool> mSidebandStreamChanged{false};
+
 private:
     virtual bool fenceHasSignaled() const = 0;
     virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0;
     virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0;
 
-    virtual bool getAutoRefresh() const = 0;
-    virtual bool getSidebandStreamChanged() const = 0;
 
     // Latch sideband stream and returns true if the dirty region should be updated.
     virtual bool latchSidebandStream(bool& recomputeVisibleRegions) = 0;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 71b05fd..dc99986 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -196,14 +196,6 @@
     return frameNumber;
 }
 
-bool BufferQueueLayer::getAutoRefresh() const {
-    return mAutoRefresh;
-}
-
-bool BufferQueueLayer::getSidebandStreamChanged() const {
-    return mSidebandStreamChanged;
-}
-
 bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
     // We need to update the sideband stream if the layer has both a buffer and a sideband stream.
     const bool updateSidebandStream = hasFrameUpdate() && mSidebandStream.get();
@@ -265,8 +257,10 @@
     const uint64_t maxFrameNumberToAcquire =
             std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
 
-    status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
+    bool autoRefresh;
+    status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &autoRefresh,
                                                       &queuedBuffer, maxFrameNumberToAcquire);
+    mAutoRefresh = autoRefresh;
     if (updateResult == BufferQueue::PRESENT_LATER) {
         // Producer doesn't want buffer to be displayed yet.  Signal a
         // layer update so we check again at the next opportunity.
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index fb8a0c2..b45900e 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -90,9 +90,6 @@
 private:
     uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
 
-    bool getAutoRefresh() const override;
-    bool getSidebandStreamChanged() const override;
-
     bool latchSidebandStream(bool& recomputeVisibleRegions) override;
     void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
 
@@ -140,11 +137,8 @@
     std::vector<BufferData> mQueueItems;
     std::atomic<uint64_t> mLastFrameNumberReceived{0};
 
-    bool mAutoRefresh{false};
-
     // thread-safe
     std::atomic<int32_t> mQueuedFrames{0};
-    std::atomic<bool> mSidebandStreamChanged{false};
 
     sp<ContentsChangedListener> mContentsChangedListener;
 
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 234b6e2..963e541 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -482,13 +482,10 @@
     return mCurrentState.frameNumber;
 }
 
-bool BufferStateLayer::getAutoRefresh() const {
-    // TODO(marissaw): support shared buffer mode
-    return false;
-}
-
-bool BufferStateLayer::getSidebandStreamChanged() const {
-    return mSidebandStreamChanged.load();
+void BufferStateLayer::setAutoRefresh(bool autoRefresh) {
+    if (!mAutoRefresh.exchange(autoRefresh)) {
+        mFlinger->signalLayerUpdate();
+    }
 }
 
 bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 104a13b..42be62a 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -100,6 +100,7 @@
     Rect getBufferSize(const State& s) const override;
     FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
     Layer::RoundedCornerState getRoundedCornerState() const override;
+    void setAutoRefresh(bool autoRefresh) override;
 
     // -----------------------------------------------------------------------
 
@@ -123,9 +124,6 @@
 
     uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
 
-    bool getAutoRefresh() const override;
-    bool getSidebandStreamChanged() const override;
-
     bool latchSidebandStream(bool& recomputeVisibleRegions) override;
 
     bool hasFrameUpdate() const override;
@@ -149,8 +147,6 @@
 
     std::unique_ptr<renderengine::Image> mTextureImage;
 
-    std::atomic<bool> mSidebandStreamChanged{false};
-
     mutable uint64_t mFrameNumber{0};
     uint64_t mFrameCounter{0};
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1a784aa..8d67ce5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -444,6 +444,7 @@
     virtual bool setColorSpaceAgnostic(const bool agnostic);
     virtual bool setFrameRateSelectionPriority(int32_t priority);
     virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint);
+    virtual void setAutoRefresh(bool /* autoRefresh */) {}
     //  If the variable is not set on the layer, it traverses up the tree to inherit the frame
     //  rate priority from its parent.
     virtual int32_t getFrameRateSelectionPriority() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 91f050c..4e398d3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3796,6 +3796,9 @@
             flags |= eTraversalNeeded | eTransformHintUpdateNeeded;
         }
     }
+    if (what & layer_state_t::eAutoRefreshChanged) {
+        layer->setAutoRefresh(s.autoRefresh);
+    }
     // This has to happen after we reparent children because when we reparent to null we remove
     // child layers from current state and remove its relative z. If the children are reparented in
     // the same transaction, then we have to make sure we reparent the children first so we do not