BlastBufferQueue: Update layer size immediately if the buffer can scale

SurfaceView size changes should be reflected immediately instead of
waiting for a new buffer. If the scaling mode is not freeze, the
expected behaviour is for the layer size to be update immediately. If
a buffer is present, it will be scaled to the new size.

If the buffer has scaling mode freeze, then the size changes will
continue to be deferred until we recieve the new buffer of the
new size.

Fixes: 174217687
Test: atest SurfaceViewBufferTests:GeometryTests
Change-Id: I19b6378de63be905db3d9c709cce0f4f26acce18
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 3a3a96f..b9ab561 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -150,6 +150,16 @@
     if (mRequestedSize != newSize) {
         mRequestedSize.set(newSize);
         mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
+        if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
+            // If the buffer supports scaling, update the frame immediately since the client may
+            // want to scale the existing buffer to the new size.
+            mSize = mRequestedSize;
+            SurfaceComposerClient::Transaction t;
+            t.setFrame(mSurfaceControl,
+                       {0, 0, static_cast<int32_t>(mSize.width),
+                        static_cast<int32_t>(mSize.height)});
+            t.apply();
+        }
     }
 }
 
@@ -276,6 +286,8 @@
     // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
     incStrong((void*)transactionCallbackThunk);
 
+    mLastBufferScalingMode = bufferItem.mScalingMode;
+
     t->setBuffer(mSurfaceControl, buffer);
     t->setAcquireFence(mSurfaceControl,
                        bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
@@ -348,7 +360,6 @@
 
 bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
     if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
-        mSize = mRequestedSize;
         // Only reject buffers if scaling mode is freeze.
         return false;
     }
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index bdf128a..1139390 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -146,6 +146,11 @@
     bool mAutoRefresh GUARDED_BY(mMutex) = false;
 
     std::queue<int64_t> mNextFrameTimelineVsyncIdQueue GUARDED_BY(mMutex);
+
+    // Last acquired buffer's scaling mode. This is used to check if we should update the blast
+    // layer size immediately or wait until we get the next buffer. This will support scenarios
+    // where the layer can change sizes and the buffer will scale to fit the new size.
+    uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
 };
 
 } // namespace android