SF: Make ExternalTexture mockable

Expose GraphicBuffer properties via ExternalTexture class. Within
SurfaceFlinger access the buffer via this proxy interface.
This allows us to inject and mock GraphicBuffers as needed.
Specifically this will be used to recreate layer state from
transaction traces.

Test: compiles
Bug: 200284593

Change-Id: I2e7f6bee28314b70eac477cfadbf9f94c4d70339
diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp
index eabff58..84771c0 100644
--- a/libs/renderengine/ExternalTexture.cpp
+++ b/libs/renderengine/ExternalTexture.cpp
@@ -14,30 +14,32 @@
  * limitations under the License.
  */
 
-#include <renderengine/ExternalTexture.h>
 #include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <ui/GraphicBuffer.h>
 
 #include "log/log_main.h"
 
-namespace android::renderengine {
+namespace android::renderengine::impl {
 
-ExternalTexture::ExternalTexture(const sp<GraphicBuffer>& buffer, RenderEngine& renderEngine,
-                                 uint32_t usage)
+ExternalTexture::ExternalTexture(const sp<GraphicBuffer>& buffer,
+                                 renderengine::RenderEngine& renderEngine, uint32_t usage)
       : mBuffer(buffer), mRenderEngine(renderEngine) {
     LOG_ALWAYS_FATAL_IF(buffer == nullptr,
                         "Attempted to bind a null buffer to an external texture!");
     // GLESRenderEngine has a separate texture cache for output buffers,
-    if (usage == Usage::WRITEABLE &&
-        (mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::GLES ||
-         mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::THREADED)) {
+    if (usage == WRITEABLE &&
+        (mRenderEngine.getRenderEngineType() ==
+                 renderengine::RenderEngine::RenderEngineType::GLES ||
+         mRenderEngine.getRenderEngineType() ==
+                 renderengine::RenderEngine::RenderEngineType::THREADED)) {
         return;
     }
-    mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE);
+    mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & WRITEABLE);
 }
 
 ExternalTexture::~ExternalTexture() {
     mRenderEngine.unmapExternalTextureBuffer(mBuffer);
 }
 
-} // namespace android::renderengine
+} // namespace android::renderengine::impl
diff --git a/libs/renderengine/benchmark/RenderEngineBench.cpp b/libs/renderengine/benchmark/RenderEngineBench.cpp
index 6c8f8e8..ead97cf 100644
--- a/libs/renderengine/benchmark/RenderEngineBench.cpp
+++ b/libs/renderengine/benchmark/RenderEngineBench.cpp
@@ -22,6 +22,7 @@
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/LayerSettings.h>
 #include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
 
 #include <mutex>
 
@@ -115,15 +116,15 @@
                                                        uint32_t height,
                                                        uint64_t extraUsageFlags = 0,
                                                        std::string name = "output") {
-    return std::make_shared<ExternalTexture>(new GraphicBuffer(width, height,
-                                                               HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                               GRALLOC_USAGE_HW_RENDER |
-                                                                       GRALLOC_USAGE_HW_TEXTURE |
-                                                                       extraUsageFlags,
-                                                               std::move(name)),
-                                             re,
-                                             ExternalTexture::Usage::READABLE |
-                                                     ExternalTexture::Usage::WRITEABLE);
+    return std::make_shared<
+            impl::ExternalTexture>(new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+                                                     GRALLOC_USAGE_HW_RENDER |
+                                                             GRALLOC_USAGE_HW_TEXTURE |
+                                                             extraUsageFlags,
+                                                     std::move(name)),
+                                   re,
+                                   impl::ExternalTexture::Usage::READABLE |
+                                           impl::ExternalTexture::Usage::WRITEABLE);
 }
 
 static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h
index 07f0833..621a209 100644
--- a/libs/renderengine/include/renderengine/ExternalTexture.h
+++ b/libs/renderengine/include/renderengine/ExternalTexture.h
@@ -33,28 +33,22 @@
  */
 class ExternalTexture {
 public:
-    // Usage specifies the rendering intent for the buffer.
-    enum Usage : uint32_t {
-        // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a
-        // hint to load the buffer into a separate cache
-        READABLE = 1 << 0,
+    ExternalTexture() = default;
+    virtual ~ExternalTexture() = default;
 
-        // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an
-        // external texture
-        WRITEABLE = 1 << 1,
-    };
-    // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given
-    // usage hint of type Usage.
-    ExternalTexture(const sp<GraphicBuffer>& buffer, RenderEngine& renderEngine, uint32_t usage);
-
-    ~ExternalTexture();
+    virtual bool hasSameBuffer(const ExternalTexture& other) const = 0;
+    virtual uint32_t getWidth() const = 0;
+    virtual uint32_t getHeight() const = 0;
+    virtual uint64_t getId() const = 0;
+    virtual PixelFormat getPixelFormat() const = 0;
+    virtual uint64_t getUsage() const = 0;
 
     // Retrieves the buffer that is bound to this texture.
-    const sp<GraphicBuffer>& getBuffer() const { return mBuffer; }
+    virtual const sp<GraphicBuffer>& getBuffer() const = 0;
 
-private:
-    sp<GraphicBuffer> mBuffer;
-    RenderEngine& mRenderEngine;
+    Rect getBounds() const {
+        return {0, 0, static_cast<int32_t>(getWidth()), static_cast<int32_t>(getHeight())};
+    }
     DISALLOW_COPY_AND_ASSIGN(ExternalTexture);
 };
 
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index d646756..faa84fc 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -76,6 +76,7 @@
 
 namespace impl {
 class RenderEngine;
+class ExternalTexture;
 }
 
 enum class Protection {
@@ -228,7 +229,7 @@
     // avoid any thread synchronization that may be required by directly calling postRenderCleanup.
     virtual bool canSkipPostRenderCleanup() const = 0;
 
-    friend class ExternalTexture;
+    friend class impl::ExternalTexture;
     friend class threaded::RenderEngineThreaded;
     friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test;
     const RenderEngineType mRenderEngineType;
diff --git a/libs/renderengine/include/renderengine/impl/ExternalTexture.h b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
new file mode 100644
index 0000000..c0e24f0
--- /dev/null
+++ b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <renderengine/ExternalTexture.h>
+#include <ui/GraphicBuffer.h>
+
+namespace android::renderengine::impl {
+
+class RenderEngine;
+
+class ExternalTexture : public android::renderengine::ExternalTexture {
+public:
+    // Usage specifies the rendering intent for the buffer.
+    enum Usage : uint32_t {
+        // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a
+        // hint to load the buffer into a separate cache
+        READABLE = 1 << 0,
+
+        // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an
+        // external texture
+        WRITEABLE = 1 << 1,
+    };
+
+    // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given
+    // usage hint of type Usage.
+    ExternalTexture(const sp<GraphicBuffer>& buffer,
+                    android::renderengine::RenderEngine& renderEngine, uint32_t usage);
+    ~ExternalTexture();
+    const sp<GraphicBuffer>& getBuffer() const override { return mBuffer; };
+    uint32_t getWidth() const override { return getBuffer()->getWidth(); }
+    uint32_t getHeight() const override { return getBuffer()->getHeight(); }
+    uint64_t getId() const override { return getBuffer()->getId(); }
+    PixelFormat getPixelFormat() const override { return getBuffer()->getPixelFormat(); }
+    uint64_t getUsage() const override { return getBuffer()->getUsage(); }
+    bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+        return getBuffer() == other.getBuffer();
+    }
+
+private:
+    sp<GraphicBuffer> mBuffer;
+    android::renderengine::RenderEngine& mRenderEngine;
+};
+
+} // namespace android::renderengine::impl
diff --git a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
new file mode 100644
index 0000000..974e0fd
--- /dev/null
+++ b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <renderengine/ExternalTexture.h>
+
+namespace android {
+namespace renderengine {
+namespace mock {
+
+class FakeExternalTexture : public renderengine::ExternalTexture {
+    const sp<GraphicBuffer> mNullBuffer = nullptr;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint64_t mId;
+    PixelFormat mPixelFormat;
+    uint64_t mUsage;
+
+public:
+    FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat,
+                        uint64_t usage)
+          : mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {}
+    const sp<GraphicBuffer>& getBuffer() const { return mNullBuffer; }
+    bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+        return getId() == other.getId();
+    }
+    uint32_t getWidth() const override { return mWidth; }
+    uint32_t getHeight() const override { return mHeight; }
+    uint64_t getId() const override { return mId; }
+    PixelFormat getPixelFormat() const override { return mPixelFormat; }
+    uint64_t getUsage() const override { return mUsage; }
+    ~FakeExternalTexture() = default;
+};
+
+} // namespace mock
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index b18a872..a3a1969 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -19,6 +19,7 @@
 #include "android-base/unique_fd.h"
 #include "renderengine/DisplaySettings.h"
 #include "renderengine/LayerSettings.h"
+#include "renderengine/impl/ExternalTexture.h"
 #include "ui/GraphicBuffer.h"
 #include "ui/GraphicTypes.h"
 #include "ui/PixelFormat.h"
@@ -365,8 +366,8 @@
                                   1, usage, "primeShaderCache_dst");
 
         const auto dstTexture =
-                std::make_shared<ExternalTexture>(dstBuffer, *renderengine,
-                                                  ExternalTexture::Usage::WRITEABLE);
+                std::make_shared<impl::ExternalTexture>(dstBuffer, *renderengine,
+                                                        impl::ExternalTexture::Usage::WRITEABLE);
         // This buffer will be the source for the call to drawImageLayers. Draw
         // something to it as a placeholder for what an app draws. We should draw
         // something, but the details are not important. Make use of the shadow layer drawing step
@@ -375,10 +376,10 @@
                 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
                                   1, usage, "drawImageLayer_src");
 
-        const auto srcTexture =
-                std::make_shared<ExternalTexture>(srcBuffer, *renderengine,
-                                                  ExternalTexture::Usage::READABLE |
-                                                          ExternalTexture::Usage::WRITEABLE);
+        const auto srcTexture = std::make_shared<
+                impl::ExternalTexture>(srcBuffer, *renderengine,
+                                       impl::ExternalTexture::Usage::READABLE |
+                                               impl::ExternalTexture::Usage::WRITEABLE);
         drawHolePunchLayer(renderengine, display, dstTexture);
         drawSolidLayers(renderengine, display, dstTexture);
 
@@ -398,8 +399,8 @@
                 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
                                   1, usageExternal, "primeShaderCache_external");
         const auto externalTexture =
-                std::make_shared<ExternalTexture>(externalBuffer, *renderengine,
-                                                  ExternalTexture::Usage::READABLE);
+                std::make_shared<impl::ExternalTexture>(externalBuffer, *renderengine,
+                                                        impl::ExternalTexture::Usage::READABLE);
         std::vector<const std::shared_ptr<ExternalTexture>> textures =
             {srcTexture, externalTexture};
 
@@ -412,8 +413,8 @@
         status_t error = f16ExternalBuffer->initCheck();
         if (!error) {
             const auto f16ExternalTexture =
-                std::make_shared<ExternalTexture>(f16ExternalBuffer, *renderengine,
-                                                  ExternalTexture::Usage::READABLE);
+                    std::make_shared<impl::ExternalTexture>(f16ExternalBuffer, *renderengine,
+                                                            impl::ExternalTexture::Usage::READABLE);
             textures.push_back(f16ExternalTexture);
         }
 
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index eb2b2dc..2a25b0b 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -26,6 +26,7 @@
 #include <gtest/gtest.h>
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <sync/sync.h>
 #include <system/graphics-base-v1.0.h>
 #include <tonemap/tonemap.h>
@@ -178,7 +179,7 @@
 public:
     std::shared_ptr<renderengine::ExternalTexture> allocateDefaultBuffer() {
         return std::make_shared<
-                renderengine::
+                renderengine::impl::
                         ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH,
                                                            DEFAULT_DISPLAY_HEIGHT,
                                                            HAL_PIXEL_FORMAT_RGBA_8888, 1,
@@ -188,15 +189,16 @@
                                                                    GRALLOC_USAGE_HW_TEXTURE,
                                                            "output"),
                                          *mRE,
-                                         renderengine::ExternalTexture::Usage::READABLE |
-                                                 renderengine::ExternalTexture::Usage::WRITEABLE);
+                                         renderengine::impl::ExternalTexture::Usage::READABLE |
+                                                 renderengine::impl::ExternalTexture::Usage::
+                                                         WRITEABLE);
     }
 
     // Allocates a 1x1 buffer to fill with a solid color
     std::shared_ptr<renderengine::ExternalTexture> allocateSourceBuffer(uint32_t width,
                                                                         uint32_t height) {
         return std::make_shared<
-                renderengine::
+                renderengine::impl::
                         ExternalTexture>(new GraphicBuffer(width, height,
                                                            HAL_PIXEL_FORMAT_RGBA_8888, 1,
                                                            GRALLOC_USAGE_SW_READ_OFTEN |
@@ -204,8 +206,9 @@
                                                                    GRALLOC_USAGE_HW_TEXTURE,
                                                            "input"),
                                          *mRE,
-                                         renderengine::ExternalTexture::Usage::READABLE |
-                                                 renderengine::ExternalTexture::Usage::WRITEABLE);
+                                         renderengine::impl::ExternalTexture::Usage::READABLE |
+                                                 renderengine::impl::ExternalTexture::Usage::
+                                                         WRITEABLE);
     }
 
     std::shared_ptr<renderengine::ExternalTexture> allocateAndFillSourceBuffer(uint32_t width,
@@ -2439,16 +2442,17 @@
     };
 
     auto buf = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
-                                                             HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                             GRALLOC_USAGE_SW_READ_OFTEN |
-                                                                     GRALLOC_USAGE_SW_WRITE_OFTEN |
-                                                                     GRALLOC_USAGE_HW_RENDER |
-                                                                     GRALLOC_USAGE_HW_TEXTURE,
-                                                             "input"),
-                                           *mRE,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, HAL_PIXEL_FORMAT_RGBA_8888,
+                                                       1,
+                                                       GRALLOC_USAGE_SW_READ_OFTEN |
+                                                               GRALLOC_USAGE_SW_WRITE_OFTEN |
+                                                               GRALLOC_USAGE_HW_RENDER |
+                                                               GRALLOC_USAGE_HW_TEXTURE,
+                                                       "input"),
+                                     *mRE,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     ASSERT_EQ(0, buf->getBuffer()->initCheck());
 
     {
@@ -2472,16 +2476,17 @@
     }
 
     mBuffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
-                                                             HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                             GRALLOC_USAGE_SW_READ_OFTEN |
-                                                                     GRALLOC_USAGE_SW_WRITE_OFTEN |
-                                                                     GRALLOC_USAGE_HW_RENDER |
-                                                                     GRALLOC_USAGE_HW_TEXTURE,
-                                                             "output"),
-                                           *mRE,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, HAL_PIXEL_FORMAT_RGBA_8888,
+                                                       1,
+                                                       GRALLOC_USAGE_SW_READ_OFTEN |
+                                                               GRALLOC_USAGE_SW_WRITE_OFTEN |
+                                                               GRALLOC_USAGE_HW_RENDER |
+                                                               GRALLOC_USAGE_HW_TEXTURE,
+                                                       "output"),
+                                     *mRE,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     ASSERT_EQ(0, mBuffer->getBuffer()->initCheck());
 
     const renderengine::LayerSettings layer{
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index db7e12b..9685189 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -17,6 +17,7 @@
 #include <cutils/properties.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include "../threaded/RenderEngineThreaded.h"
 
@@ -174,9 +175,10 @@
     renderengine::DisplaySettings settings;
     std::vector<renderengine::LayerSettings> layers;
     std::shared_ptr<renderengine::ExternalTexture> buffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(), *mRenderEngine,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
 
     base::unique_fd bufferFence;
 
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d61a4cb..649138a 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -164,7 +164,7 @@
     const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
             ((isSecure() || isProtected()) && !targetSettings.isSecure);
     const bool bufferCanBeUsedAsHwTexture =
-            mBufferInfo.mBuffer->getBuffer()->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
+            mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
     compositionengine::LayerFE::LayerSettings& layer = *result;
     if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
         ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
@@ -201,7 +201,7 @@
     }
     layer.source.buffer.maxLuminanceNits = maxLuminance;
     layer.frameNumber = mCurrentFrameNumber;
-    layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()->getId() : 0;
+    layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;
 
     const bool useFiltering =
             targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();
@@ -436,7 +436,7 @@
 
 void BufferLayer::gatherBufferInfo() {
     mBufferInfo.mPixelFormat =
-            !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getBuffer()->format;
+            !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getPixelFormat();
     mBufferInfo.mFrameLatencyNeeded = true;
 }
 
@@ -533,10 +533,10 @@
     }
 
     if (oldBufferInfo.mBuffer != nullptr) {
-        uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
-        uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
-        if (bufWidth != uint32_t(oldBufferInfo.mBuffer->getBuffer()->width) ||
-            bufHeight != uint32_t(oldBufferInfo.mBuffer->getBuffer()->height)) {
+        uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+        uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
+        if (bufWidth != oldBufferInfo.mBuffer->getWidth() ||
+            bufHeight != oldBufferInfo.mBuffer->getHeight()) {
             recomputeVisibleRegions = true;
         }
     }
@@ -558,7 +558,7 @@
 
 bool BufferLayer::isProtected() const {
     return (mBufferInfo.mBuffer != nullptr) &&
-            (mBufferInfo.mBuffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED);
+            (mBufferInfo.mBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
 }
 
 // As documented in libhardware header, formats in the range
@@ -638,8 +638,8 @@
         return Rect::INVALID_RECT;
     }
 
-    uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
-    uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
+    uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+    uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
 
     // Undo any transformations on the buffer and return the result.
     if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
@@ -670,8 +670,8 @@
         return parentBounds;
     }
 
-    uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
-    uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
+    uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+    uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
 
     // Undo any transformations on the buffer and return the result.
     if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
@@ -713,7 +713,7 @@
         return mBufferInfo.mCrop;
     } else if (mBufferInfo.mBuffer != nullptr) {
         // otherwise we use the whole buffer
-        return mBufferInfo.mBuffer->getBuffer()->getBounds();
+        return mBufferInfo.mBuffer->getBounds();
     } else {
         // if we don't have a buffer yet, we use an empty/invalid crop
         return Rect();
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index c79fa11..9ae45fc 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -41,6 +41,7 @@
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
 #include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
@@ -208,8 +209,9 @@
         if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->getBuffer() == nullptr ||
             mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) {
             mImages[item->mSlot] = std::make_shared<
-                    renderengine::ExternalTexture>(item->mGraphicBuffer, mRE,
-                                                   renderengine::ExternalTexture::Usage::READABLE);
+                    renderengine::impl::ExternalTexture>(item->mGraphicBuffer, mRE,
+                                                         renderengine::impl::ExternalTexture::
+                                                                 Usage::READABLE);
         }
     }
 
@@ -462,8 +464,9 @@
         if (oldImage == nullptr || oldImage->getBuffer() == nullptr ||
             oldImage->getBuffer()->getId() != item.mGraphicBuffer->getId()) {
             mImages[item.mSlot] = std::make_shared<
-                    renderengine::ExternalTexture>(item.mGraphicBuffer, mRE,
-                                                   renderengine::ExternalTexture::Usage::READABLE);
+                    renderengine::impl::ExternalTexture>(item.mGraphicBuffer, mRE,
+                                                         renderengine::impl::ExternalTexture::
+                                                                 Usage::READABLE);
         }
     }
 }
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 2fac880..6cecd89 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -295,8 +295,8 @@
         return assignTransform(&mDrawingState.transform, t);
     }
 
-    uint32_t bufferWidth = mDrawingState.buffer->getBuffer()->getWidth();
-    uint32_t bufferHeight = mDrawingState.buffer->getBuffer()->getHeight();
+    uint32_t bufferWidth = mDrawingState.buffer->getWidth();
+    uint32_t bufferHeight = mDrawingState.buffer->getHeight();
     // Undo any transformations on the buffer.
     if (mDrawingState.bufferTransform & ui::Transform::ROT_90) {
         std::swap(bufferWidth, bufferHeight);
@@ -368,46 +368,13 @@
     return true;
 }
 
-std::shared_ptr<renderengine::ExternalTexture> BufferStateLayer::getBufferFromBufferData(
-        const BufferData& bufferData) {
-    bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged);
-    bool bufferSizeExceedsLimit = false;
-    std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
-    if (cacheIdChanged && bufferData.buffer != nullptr) {
-        bufferSizeExceedsLimit =
-                mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
-                                                     bufferData.buffer->getHeight());
-        if (!bufferSizeExceedsLimit) {
-            ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer);
-            buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
-        }
-    } else if (cacheIdChanged) {
-        buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
-    } else if (bufferData.buffer != nullptr) {
-        bufferSizeExceedsLimit =
-                mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
-                                                     bufferData.buffer->getHeight());
-        if (!bufferSizeExceedsLimit) {
-            buffer = std::make_shared<
-                    renderengine::ExternalTexture>(bufferData.buffer, mFlinger->getRenderEngine(),
-                                                   renderengine::ExternalTexture::Usage::READABLE);
-        }
-    }
-    ALOGE_IF(bufferSizeExceedsLimit,
-             "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
-             "limit.",
-             getDebugName());
-    return buffer;
-}
-
-bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime,
+bool BufferStateLayer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
+                                 const BufferData& bufferData, nsecs_t postTime,
                                  nsecs_t desiredPresentTime, bool isAutoTimestamp,
                                  std::optional<nsecs_t> dequeueTime,
                                  const FrameTimelineInfo& info) {
     ATRACE_CALL();
 
-    const std::shared_ptr<renderengine::ExternalTexture>& buffer =
-            getBufferFromBufferData(bufferData);
     if (!buffer) {
         return false;
     }
@@ -419,8 +386,9 @@
 
     if (mDrawingState.buffer) {
         mReleasePreviousBuffer = true;
-        if (mDrawingState.buffer != mBufferInfo.mBuffer ||
-            mDrawingState.frameNumber != mBufferInfo.mFrameNumber) {
+        if (!mBufferInfo.mBuffer ||
+            (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
+             mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
             // If mDrawingState has a buffer, and we are about to update again
             // before swapping to drawing state, then the first buffer will be
             // dropped and we should decrement the pending buffer count and
@@ -448,7 +416,7 @@
 
     mDrawingState.frameNumber = frameNumber;
     mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
-    mDrawingState.buffer = buffer;
+    mDrawingState.buffer = std::move(buffer);
     mDrawingState.clientCacheId = bufferData.cachedBuffer;
 
     mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
@@ -485,7 +453,7 @@
     setFrameTimelineVsyncForBufferTransaction(info, postTime);
 
     if (buffer && dequeueTime && *dequeueTime != 0) {
-        const uint64_t bufferId = buffer->getBuffer()->getId();
+        const uint64_t bufferId = buffer->getId();
         mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
         mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime,
                                                FrameTracer::FrameEvent::DEQUEUE);
@@ -493,8 +461,8 @@
                                                FrameTracer::FrameEvent::QUEUE);
     }
 
-    mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
-    mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
+    mDrawingState.width = mDrawingState.buffer->getWidth();
+    mDrawingState.height = mDrawingState.buffer->getHeight();
     mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint;
     return true;
 }
@@ -599,8 +567,8 @@
         return Rect::INVALID_RECT;
     }
 
-    uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
-    uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
+    uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+    uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
 
     // Undo any transformations on the buffer and return the result.
     if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
@@ -709,7 +677,7 @@
     }
 
     const int32_t layerId = getSequence();
-    const uint64_t bufferId = mDrawingState.buffer->getBuffer()->getId();
+    const uint64_t bufferId = mDrawingState.buffer->getId();
     const uint64_t frameNumber = mDrawingState.frameNumber;
     const auto acquireFence = std::make_shared<FenceTime>(mDrawingState.acquireFence);
     mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence);
@@ -749,7 +717,7 @@
         return BAD_VALUE;
     }
 
-    if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) {
+    if (!mBufferInfo.mBuffer || !s.buffer->hasSameBuffer(*mBufferInfo.mBuffer)) {
         decrementPendingBufferCount();
     }
 
@@ -874,10 +842,10 @@
 Rect BufferStateLayer::computeBufferCrop(const State& s) {
     if (s.buffer && !s.bufferCrop.isEmpty()) {
         Rect bufferCrop;
-        s.buffer->getBuffer()->getBounds().intersect(s.bufferCrop, &bufferCrop);
+        s.buffer->getBounds().intersect(s.bufferCrop, &bufferCrop);
         return bufferCrop;
     } else if (s.buffer) {
-        return s.buffer->getBuffer()->getBounds();
+        return s.buffer->getBounds();
     } else {
         return s.bufferCrop;
     }
@@ -898,8 +866,8 @@
         return false;
     }
 
-    int32_t bufferWidth = s.buffer->getBuffer()->width;
-    int32_t bufferHeight = s.buffer->getBuffer()->height;
+    int32_t bufferWidth = static_cast<int32_t>(s.buffer->getWidth());
+    int32_t bufferHeight = static_cast<int32_t>(s.buffer->getHeight());
 
     // Undo any transformations on the buffer and return the result.
     if (s.bufferTransform & ui::Transform::ROT_90) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index eea700c..2f613d7 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -57,7 +57,8 @@
     bool setTransform(uint32_t transform) override;
     bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
     bool setCrop(const Rect& crop) override;
-    bool setBuffer(const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
+    bool setBuffer(std::shared_ptr<renderengine::ExternalTexture>& /* buffer */,
+                   const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
                    bool isAutoTimestamp, std::optional<nsecs_t> dequeueTime,
                    const FrameTimelineInfo& info) override;
     bool setDataspace(ui::Dataspace dataspace) override;
@@ -136,9 +137,6 @@
 
     bool bufferNeedsFiltering() const override;
 
-    std::shared_ptr<renderengine::ExternalTexture> getBufferFromBufferData(
-            const BufferData& bufferData);
-
     ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
     uint64_t mPreviousReleasedFrameNumber = 0;
 
diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp
index e7b8995..3c7b9d9 100644
--- a/services/surfaceflinger/ClientCache.cpp
+++ b/services/surfaceflinger/ClientCache.cpp
@@ -22,6 +22,7 @@
 #include <cinttypes>
 
 #include <android-base/stringprintf.h>
+#include <renderengine/impl/ExternalTexture.h>
 
 #include "ClientCache.h"
 
@@ -109,8 +110,9 @@
                         "Attempted to build the ClientCache before a RenderEngine instance was "
                         "ready!");
     processBuffers[id].buffer = std::make_shared<
-            renderengine::ExternalTexture>(buffer, *mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE);
+            renderengine::impl::ExternalTexture>(buffer, *mRenderEngine,
+                                                 renderengine::impl::ExternalTexture::Usage::
+                                                         READABLE);
     return true;
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index a19d23f..12c2c8e 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -28,6 +28,7 @@
 #include <log/log.h>
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <system/window.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
@@ -182,9 +183,10 @@
         mTexture = texture;
     } else {
         mTexture = std::make_shared<
-                renderengine::ExternalTexture>(GraphicBuffer::from(buffer),
-                                               mCompositionEngine.getRenderEngine(),
-                                               renderengine::ExternalTexture::Usage::WRITEABLE);
+                renderengine::impl::ExternalTexture>(GraphicBuffer::from(buffer),
+                                                     mCompositionEngine.getRenderEngine(),
+                                                     renderengine::impl::ExternalTexture::Usage::
+                                                             WRITEABLE);
     }
     mTextureCache.push_back(mTexture);
     if (mTextureCache.size() > mMaxTextureCacheSize) {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
index 497c433..54ecb56 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
@@ -20,6 +20,7 @@
 #define LOG_TAG "Planner"
 
 #include <compositionengine/impl/planner/TexturePool.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <utils/Log.h>
 
 namespace android::compositionengine::impl::planner {
@@ -82,16 +83,19 @@
 std::shared_ptr<renderengine::ExternalTexture> TexturePool::genTexture() {
     LOG_ALWAYS_FATAL_IF(!mSize.isValid(), "Attempted to generate texture with invalid size");
     return std::make_shared<
-            renderengine::ExternalTexture>(sp<GraphicBuffer>::
-                                                   make(mSize.getWidth(), mSize.getHeight(),
-                                                        HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                                        GraphicBuffer::USAGE_HW_RENDER |
-                                                                GraphicBuffer::USAGE_HW_COMPOSER |
-                                                                GraphicBuffer::USAGE_HW_TEXTURE,
-                                                        "Planner"),
-                                           mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(sp<GraphicBuffer>::
+                                             make(static_cast<uint32_t>(mSize.getWidth()),
+                                                  static_cast<uint32_t>(mSize.getHeight()),
+                                                  HAL_PIXEL_FORMAT_RGBA_8888, 1U,
+                                                  static_cast<uint64_t>(
+                                                          GraphicBuffer::USAGE_HW_RENDER |
+                                                          GraphicBuffer::USAGE_HW_COMPOSER |
+                                                          GraphicBuffer::USAGE_HW_TEXTURE),
+                                                  "Planner"),
+                                     mRenderEngine,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
 }
 
 void TexturePool::setEnabled(bool enabled) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index ad7976f..37f17f5 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -24,6 +24,7 @@
 #include <gtest/gtest.h>
 #include <log/log.h>
 
+#include <renderengine/impl/ExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <ui/PixelFormat.h>
 #include "MockHWC2.h"
@@ -815,10 +816,11 @@
         auto& overrideInfo = mOutputLayer.editState().overrideInfo;
 
         overrideInfo.buffer = std::make_shared<
-                renderengine::ExternalTexture>(kOverrideBuffer, mRenderEngine,
-                                               renderengine::ExternalTexture::Usage::READABLE |
-                                                       renderengine::ExternalTexture::Usage::
-                                                               WRITEABLE);
+                renderengine::impl::ExternalTexture>(kOverrideBuffer, mRenderEngine,
+                                                     renderengine::impl::ExternalTexture::Usage::
+                                                                     READABLE |
+                                                             renderengine::impl::ExternalTexture::
+                                                                     Usage::WRITEABLE);
         overrideInfo.acquireFence = kOverrideFence;
         overrideInfo.displayFrame = kOverrideDisplayFrame;
         overrideInfo.dataspace = kOverrideDataspace;
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 6d96260..5fcb52d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -26,6 +26,8 @@
 #include <compositionengine/mock/RenderSurface.h>
 #include <ftl/future.h>
 #include <gtest/gtest.h>
+#include <renderengine/ExternalTexture.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -37,7 +39,6 @@
 #include "MockHWC2.h"
 #include "RegionMatcher.h"
 #include "TestUtils.h"
-#include "renderengine/ExternalTexture.h"
 
 namespace android::compositionengine {
 namespace {
@@ -273,9 +274,10 @@
     // Inject some layers
     InjectedLayer layer;
     layer.outputLayerState.overrideInfo.buffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(), renderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(), renderEngine,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     injectOutputLayer(layer);
     // inject a null layer to check for null exceptions
     injectNullOutputLayer();
@@ -956,9 +958,10 @@
     mOutput->planComposition();
 
     std::shared_ptr<renderengine::ExternalTexture> buffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(), renderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(), renderEngine,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     layer1.outputLayerState.overrideInfo.buffer = buffer;
     layer2.outputLayerState.overrideInfo.buffer = buffer;
     layer1.outputLayerState.overrideInfo.peekThroughLayer = layer3.outputLayer;
@@ -3077,9 +3080,10 @@
     mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
     StrictMock<OutputPartialMock> mOutput;
     std::shared_ptr<renderengine::ExternalTexture> mOutputBuffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(), mRenderEngine,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
 
     std::optional<base::unique_fd> mReadyFence;
 };
@@ -3313,9 +3317,10 @@
             .WillRepeatedly(Return());
 
     const auto otherOutputBuffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(), mRenderEngine,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_))
             .WillOnce(Return(mOutputBuffer))
             .WillOnce(Return(otherOutputBuffer));
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index 7c8e41b..e5f9ebf 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -27,6 +27,7 @@
 #include <compositionengine/mock/OutputLayer.h>
 #include <gtest/gtest.h>
 #include <renderengine/ExternalTexture.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <ui/GraphicBuffer.h>
 
@@ -251,9 +252,10 @@
 
 TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) {
     const auto buffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE |
-                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+            renderengine::impl::
+                    ExternalTexture>(new GraphicBuffer(), mRenderEngine,
+                                     renderengine::impl::ExternalTexture::Usage::READABLE |
+                                             renderengine::impl::ExternalTexture::Usage::WRITEABLE);
     mSurface.mutableTextureForTest() = buffer;
 
     impl::OutputCompositionState state;
@@ -269,8 +271,8 @@
 }
 
 TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) {
-    const auto buffer = std::make_shared<renderengine::ExternalTexture>(new GraphicBuffer(),
-                                                                        mRenderEngine, false);
+    const auto buffer = std::make_shared<renderengine::impl::ExternalTexture>(new GraphicBuffer(),
+                                                                              mRenderEngine, false);
     mSurface.mutableTextureForTest() = buffer;
 
     impl::OutputCompositionState state;
@@ -288,8 +290,8 @@
 }
 
 TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) {
-    const auto buffer = std::make_shared<renderengine::ExternalTexture>(new GraphicBuffer(),
-                                                                        mRenderEngine, false);
+    const auto buffer = std::make_shared<renderengine::impl::ExternalTexture>(new GraphicBuffer(),
+                                                                              mRenderEngine, false);
     mSurface.mutableTextureForTest() = buffer;
 
     impl::OutputCompositionState state;
@@ -327,8 +329,8 @@
 }
 
 TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) {
-    const auto buffer = std::make_shared<renderengine::ExternalTexture>(new GraphicBuffer(),
-                                                                        mRenderEngine, false);
+    const auto buffer = std::make_shared<renderengine::impl::ExternalTexture>(new GraphicBuffer(),
+                                                                              mRenderEngine, false);
     mSurface.mutableTextureForTest() = buffer;
 
     impl::OutputCompositionState state;
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index d5a117a..4ae921d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -22,6 +22,7 @@
 #include <gmock/gmock-actions.h>
 #include <gtest/gtest.h>
 #include <renderengine/ExternalTexture.h>
+#include <renderengine/mock/FakeExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <ui/GraphicTypes.h>
 #include <utils/Errors.h>
@@ -702,9 +703,11 @@
     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
     clientCompList3.push_back({});
 
-    clientCompList3[0].source.buffer.buffer = std::make_shared<
-            renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
-                                           renderengine::ExternalTexture::READABLE);
+    clientCompList3[0].source.buffer.buffer =
+            std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                                      1ULL /* bufferId */,
+                                                                      HAL_PIXEL_FORMAT_RGBA_8888,
+                                                                      0ULL /*usage*/);
 
     EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
     EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
@@ -901,9 +904,11 @@
     std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
     clientCompList3.push_back({});
 
-    clientCompList3[0].source.buffer.buffer = std::make_shared<
-            renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
-                                           renderengine::ExternalTexture::READABLE);
+    clientCompList3[0].source.buffer.buffer =
+            std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                                      1ULL /* bufferId */,
+                                                                      HAL_PIXEL_FORMAT_RGBA_8888,
+                                                                      0ULL /*usage*/);
 
     EXPECT_CALL(*layerFE1,
                 prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 35d051e..58dc244 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -23,6 +23,7 @@
 #include <gtest/gtest.h>
 #include <renderengine/ExternalTexture.h>
 #include <renderengine/LayerSettings.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <chrono>
 
@@ -639,9 +640,10 @@
             LayerFE::LayerSettings{},
     };
     clientCompositionList[0].source.buffer.buffer = std::make_shared<
-            renderengine::ExternalTexture>(mTestLayers[2]->layerFECompositionState.buffer,
-                                           mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE);
+            renderengine::impl::ExternalTexture>(mTestLayers[2]->layerFECompositionState.buffer,
+                                                 mRenderEngine,
+                                                 renderengine::impl::ExternalTexture::Usage::
+                                                         READABLE);
     EXPECT_CALL(*mTestLayers[2]->layerFE, prepareClientCompositionList(_))
             .WillOnce(Return(clientCompositionList));
 
@@ -711,9 +713,10 @@
             LayerFE::LayerSettings{},
     };
     clientCompositionList[0].source.buffer.buffer = std::make_shared<
-            renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
-                                           mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE);
+            renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
+                                                 mRenderEngine,
+                                                 renderengine::impl::ExternalTexture::Usage::
+                                                         READABLE);
     EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_))
             .WillOnce(Return(clientCompositionList));
 
@@ -781,9 +784,10 @@
             LayerFE::LayerSettings{},
     };
     clientCompositionList[0].source.buffer.buffer = std::make_shared<
-            renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
-                                           mRenderEngine,
-                                           renderengine::ExternalTexture::Usage::READABLE);
+            renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
+                                                 mRenderEngine,
+                                                 renderengine::impl::ExternalTexture::Usage::
+                                                         READABLE);
     EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_))
             .WillOnce(Return(clientCompositionList));
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 31cdf0b..0d2618a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -416,8 +416,10 @@
     // Used only to set BufferStateLayer state
     virtual bool setTransform(uint32_t /*transform*/) { return false; };
     virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
-    virtual bool setBuffer(const BufferData&, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
-                           bool /*isAutoTimestamp*/, std::optional<nsecs_t> /* dequeueTime */,
+    virtual bool setBuffer(std::shared_ptr<renderengine::ExternalTexture>& /* buffer */,
+                           const BufferData& /* bufferData */, nsecs_t /* postTime */,
+                           nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
+                           std::optional<nsecs_t> /* dequeueTime */,
                            const FrameTimelineInfo& /*info*/) {
         return false;
     };
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index da8c3e0..ff30348 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -31,6 +31,7 @@
 #include <cutils/properties.h>
 #include <ftl/future.h>
 #include <gui/SyncScreenCaptureListener.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <ui/DisplayStatInfo.h>
 #include <utils/Trace.h>
 
@@ -351,8 +352,9 @@
         LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d",
                             bufferStatus);
         buffer = std::make_shared<
-                renderengine::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(),
-                                               renderengine::ExternalTexture::Usage::WRITEABLE);
+                renderengine::impl::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(),
+                                                     renderengine::impl::ExternalTexture::Usage::
+                                                             WRITEABLE);
     }
 
     auto captureScreenResultFuture =
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bd13c41..1dc75c8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -65,6 +65,7 @@
 #include <private/gui/SyncFeatures.h>
 #include <processgroup/processgroup.h>
 #include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
 #include <sys/types.h>
 #include <ui/ColorSpace.h>
 #include <ui/DataspaceUtils.h>
@@ -4419,10 +4420,13 @@
         }
     }
 
-    if (what & layer_state_t::eBufferChanged &&
-        layer->setBuffer(*s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
-                         dequeueBufferTimestamp, frameTimelineInfo)) {
-        flags |= eTraversalNeeded;
+    if (what & layer_state_t::eBufferChanged) {
+        std::shared_ptr<renderengine::ExternalTexture> buffer =
+                getExternalTextureFromBufferData(*s.bufferData, layer->getDebugName());
+        if (layer->setBuffer(buffer, *s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
+                             dequeueBufferTimestamp, frameTimelineInfo)) {
+            flags |= eTraversalNeeded;
+        }
     } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
         layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime);
     }
@@ -6384,9 +6388,10 @@
     const status_t bufferStatus = buffer->initCheck();
     LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d",
                         bufferStatus);
-    const auto texture = std::make_shared<
-            renderengine::ExternalTexture>(buffer, getRenderEngine(),
-                                           renderengine::ExternalTexture::Usage::WRITEABLE);
+    const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
+            renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
+                                                 renderengine::impl::ExternalTexture::Usage::
+                                                         WRITEABLE);
     return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture,
                                false /* regionSampling */, grayscale, captureListener);
 }
@@ -6463,7 +6468,7 @@
                 captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure());
     });
 
-    const bool useProtected = buffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED;
+    const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED;
 
     // We allow the system server to take screenshots of secure layers for
     // use in situations like the Screen-rotation animation and place
@@ -7074,6 +7079,36 @@
     return NO_ERROR;
 }
 
+std::shared_ptr<renderengine::ExternalTexture> SurfaceFlinger::getExternalTextureFromBufferData(
+        const BufferData& bufferData, const char* layerName) const {
+    bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged);
+    bool bufferSizeExceedsLimit = false;
+    std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
+    if (cacheIdChanged && bufferData.buffer != nullptr) {
+        bufferSizeExceedsLimit = exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
+                                                            bufferData.buffer->getHeight());
+        if (!bufferSizeExceedsLimit) {
+            ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer);
+            buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
+        }
+    } else if (cacheIdChanged) {
+        buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
+    } else if (bufferData.buffer != nullptr) {
+        bufferSizeExceedsLimit = exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
+                                                            bufferData.buffer->getHeight());
+        if (!bufferSizeExceedsLimit) {
+            buffer = std::make_shared<
+                    renderengine::impl::ExternalTexture>(bufferData.buffer, getRenderEngine(),
+                                                         renderengine::impl::ExternalTexture::
+                                                                 Usage::READABLE);
+        }
+    }
+    ALOGE_IF(bufferSizeExceedsLimit,
+             "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
+             "limit.",
+             layerName);
+    return buffer;
+}
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0c4236f..338b357 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -330,6 +330,9 @@
     virtual void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&)
             REQUIRES(mStateLock);
 
+    virtual std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
+            const BufferData& bufferData, const char* layerName) const;
+
     // Returns true if any display matches a `bool(const DisplayDevice&)` predicate.
     template <typename Predicate>
     bool hasDisplay(Predicate p) const REQUIRES(mStateLock) {
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f1e9b31..427159f 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -30,6 +30,7 @@
 #include <gui/IProducerListener.h>
 #include <gui/LayerMetadata.h>
 #include <log/log.h>
+#include <renderengine/mock/FakeExternalTexture.h>
 #include <renderengine/mock/Framebuffer.h>
 #include <renderengine/mock/Image.h>
 #include <renderengine/mock/RenderEngine.h>
@@ -234,15 +235,13 @@
                                                    CaptureArgs::UNSET_UID, visitor);
     };
 
-    // TODO: Eliminate expensive/real allocation if possible.
     const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
             GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
-    mCaptureScreenBuffer = std::make_shared<
-            renderengine::ExternalTexture>(new GraphicBuffer(renderArea->getReqWidth(),
-                                                             renderArea->getReqHeight(),
-                                                             HAL_PIXEL_FORMAT_RGBA_8888, 1, usage,
-                                                             "screenshot"),
-                                           *mRenderEngine, true);
+    mCaptureScreenBuffer =
+            std::make_shared<renderengine::mock::FakeExternalTexture>(renderArea->getReqWidth(),
+                                                                      renderArea->getReqHeight(),
+                                                                      HAL_PIXEL_FORMAT_RGBA_8888, 1,
+                                                                      usage);
 
     auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer,
                                                   forSystem, regionSampling);
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index deeb785..5364630 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -22,6 +22,7 @@
 #include <gui/SurfaceComposerClient.h>
 #include <log/log.h>
 #include <renderengine/ExternalTexture.h>
+#include <renderengine/mock/FakeExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <utils/String8.h>
 
@@ -101,9 +102,8 @@
         sp<BufferStateLayer> layer = createBufferStateLayer();
 
         sp<Fence> fence(new Fence());
-        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         int32_t layerId = layer->getSequence();
-        uint64_t bufferId = buffer->getId();
+        uint64_t bufferId = 42;
         uint64_t frameNumber = 5;
         nsecs_t dequeueTime = 10;
         nsecs_t postTime = 20;
@@ -115,13 +115,16 @@
                     traceTimestamp(layerId, bufferId, frameNumber, postTime,
                                    FrameTracer::FrameEvent::QUEUE, /*duration*/ 0));
         BufferData bufferData;
-        bufferData.buffer = buffer;
         bufferData.acquireFence = fence;
         bufferData.frameNumber = frameNumber;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, postTime, /*desiredPresentTime*/ 30, false, dequeueTime,
-                         FrameTimelineInfo{});
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, bufferId,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture, bufferData, postTime, /*desiredPresentTime*/ 30, false,
+                         dequeueTime, FrameTimelineInfo{});
 
         commitTransaction(layer.get());
         bool computeVisisbleRegions;
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index 704340d..5bb4c92 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -22,6 +22,7 @@
 #include <gui/SurfaceComposerClient.h>
 #include <log/log.h>
 #include <renderengine/ExternalTexture.h>
+#include <renderengine/mock/FakeExternalTexture.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <utils/String8.h>
 
@@ -114,14 +115,17 @@
         sp<BufferStateLayer> layer = createBufferStateLayer();
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         BufferData bufferData;
-        bufferData.buffer = buffer;
         bufferData.acquireFence = fence;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         acquireFence->signalForTest(12);
 
@@ -145,14 +149,17 @@
 
         sp<Fence> fence1(new Fence());
         auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
-        const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         BufferData bufferData;
-        bufferData.buffer = buffer1;
         bufferData.acquireFence = fence1;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture1 = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -160,14 +167,17 @@
 
         sp<Fence> fence2(new Fence());
         auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
-        const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         nsecs_t start = systemTime();
-        bufferData.buffer = buffer2;
         bufferData.acquireFence = fence2;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture2 = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         2ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         nsecs_t end = systemTime();
         acquireFence2->signalForTest(12);
@@ -203,14 +213,17 @@
 
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         BufferData bufferData;
-        bufferData.buffer = buffer;
         bufferData.acquireFence = fence;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         acquireFence->signalForTest(12);
 
@@ -234,14 +247,17 @@
         sp<BufferStateLayer> layer = createBufferStateLayer();
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         BufferData bufferData;
-        bufferData.buffer = buffer;
         bufferData.acquireFence = fence;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -269,14 +285,17 @@
 
         sp<Fence> fence(new Fence());
         auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
-        const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         BufferData bufferData;
-        bufferData.buffer = buffer;
         bufferData.acquireFence = fence;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 3, /*inputEventId*/ 0});
         EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -310,27 +329,33 @@
 
         sp<Fence> fence1(new Fence());
         auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
-        const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         BufferData bufferData;
-        bufferData.buffer = buffer1;
         bufferData.acquireFence = fence1;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture1 = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
         sp<Fence> fence2(new Fence());
         auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
-        const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
-        bufferData.buffer = buffer2;
         bufferData.acquireFence = fence2;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture2 = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         acquireFence2->signalForTest(12);
 
@@ -356,14 +381,17 @@
 
         sp<Fence> fence1(new Fence());
         auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
-        const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         BufferData bufferData;
-        bufferData.buffer = buffer1;
         bufferData.acquireFence = fence1;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture1 = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 1, /*inputEventId*/ 0});
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -371,14 +399,17 @@
 
         sp<Fence> fence2(new Fence());
         auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
-        const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         auto dropStartTime1 = systemTime();
-        bufferData.buffer = buffer2;
         bufferData.acquireFence = fence2;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture2 = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0});
         auto dropEndTime1 = systemTime();
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
@@ -387,14 +418,17 @@
 
         sp<Fence> fence3(new Fence());
         auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3);
-        const auto buffer3 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
         auto dropStartTime2 = systemTime();
-        bufferData.buffer = buffer3;
         bufferData.acquireFence = fence3;
         bufferData.frameNumber = 1;
         bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
         bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-        layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+        std::shared_ptr<renderengine::ExternalTexture> externalTexture3 = std::make_shared<
+                renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                         1ULL /* bufferId */,
+                                                         HAL_PIXEL_FORMAT_RGBA_8888,
+                                                         0ULL /*usage*/);
+        layer->setBuffer(externalTexture3, bufferData, 10, 20, false, std::nullopt,
                          {/*vsyncId*/ 2, /*inputEventId*/ 0});
         auto dropEndTime2 = systemTime();
         acquireFence3->signalForTest(12);
@@ -432,14 +466,17 @@
         std::vector<std::shared_ptr<frametimeline::SurfaceFrame>> bufferlessSurfaceFrames;
         for (int i = 0; i < 10; i += 2) {
             sp<Fence> fence(new Fence());
-            const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
             BufferData bufferData;
-            bufferData.buffer = buffer;
             bufferData.acquireFence = fence;
             bufferData.frameNumber = 1;
             bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
             bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
-            layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+            std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+                    renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+                                                             1ULL /* bufferId */,
+                                                             HAL_PIXEL_FORMAT_RGBA_8888,
+                                                             0ULL /*usage*/);
+            layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
                              {/*vsyncId*/ 1, /*inputEventId*/ 0});
             layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
                                                                   /*inputEventId*/ 0},