Revert "Revert "Created HardwareBufferRenderer to support rendering into...""

This reverts commit cca989f2b52725468464534f337ee55d01644fb3.

Test: atest CtsUiRenderingTestCases --iterations 10 --armeabi-v7a
Change-Id: Iee19edeb489ed54b421ac8de37ee5a70b8f9756a
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c0f3086..ee1c2ec 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -153,6 +153,7 @@
 
 void CanvasContext::destroy() {
     stopDrawing();
+    setHardwareBuffer(nullptr);
     setSurface(nullptr);
     setSurfaceControl(nullptr);
     freePrefetchedLayers();
@@ -176,6 +177,19 @@
     native_window_set_buffer_count(window, bufferCount);
 }
 
+void CanvasContext::setHardwareBuffer(AHardwareBuffer* buffer) {
+    if (mHardwareBuffer) {
+        AHardwareBuffer_release(mHardwareBuffer);
+        mHardwareBuffer = nullptr;
+    }
+
+    if (buffer) {
+        AHardwareBuffer_acquire(buffer);
+        mHardwareBuffer = buffer;
+    }
+    mRenderPipeline->setHardwareBuffer(mHardwareBuffer);
+}
+
 void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
     ATRACE_CALL();
 
@@ -261,7 +275,7 @@
             mRenderThread.removeFrameCallback(this);
             mRenderPipeline->onStop();
             mRenderThread.cacheManager().onContextStopped(this);
-        } else if (mIsDirty && hasSurface()) {
+        } else if (mIsDirty && hasOutputTarget()) {
             mRenderThread.postFrameCallback(this);
         }
     }
@@ -425,7 +439,7 @@
 
     mIsDirty = true;
 
-    if (CC_UNLIKELY(!hasSurface())) {
+    if (CC_UNLIKELY(!hasOutputTarget())) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         info.out.canDrawThisFrame = false;
         return;
@@ -570,7 +584,7 @@
         std::scoped_lock lock(mFrameMetricsReporterMutex);
         drawResult = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry,
                                            &mLayerUpdateQueue, mContentDrawBounds, mOpaque,
-                                           mLightInfo, mRenderNodes, &(profiler()));
+                                           mLightInfo, mRenderNodes, &(profiler()), mBufferParams);
     }
 
     uint64_t frameCompleteNr = getFrameNumber();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0f6b736..a811670 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -125,12 +125,13 @@
     // Won't take effect until next EGLSurface creation
     void setSwapBehavior(SwapBehavior swapBehavior);
 
+    void setHardwareBuffer(AHardwareBuffer* buffer);
     void setSurface(ANativeWindow* window, bool enableTimeout = true);
     void setSurfaceControl(ASurfaceControl* surfaceControl);
     bool pauseSurface();
     void setStopped(bool stopped);
-    bool isStopped() { return mStopped || !hasSurface(); }
-    bool hasSurface() const { return mNativeSurface.get(); }
+    bool isStopped() { return mStopped || !hasOutputTarget(); }
+    bool hasOutputTarget() const { return mNativeSurface.get() || mHardwareBuffer; }
     void allocateBuffers();
 
     void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
@@ -208,6 +209,10 @@
         mASurfaceTransactionCallback = callback;
     }
 
+    void setHardwareBufferRenderParams(const HardwareBufferRenderParams& params) {
+        mBufferParams = params;
+    }
+
     bool mergeTransaction(ASurfaceTransaction* transaction, ASurfaceControl* control);
 
     void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback) {
@@ -262,6 +267,9 @@
     int32_t mLastFrameHeight = 0;
 
     RenderThread& mRenderThread;
+
+    AHardwareBuffer* mHardwareBuffer = nullptr;
+    HardwareBufferRenderParams mBufferParams;
     std::unique_ptr<ReliableSurface> mNativeSurface;
     // The SurfaceControl reference is passed from ViewRootImpl, can be set to
     // NULL to remove the reference
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ccdf715..fab2f46 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -26,6 +26,7 @@
 #include "../Properties.h"
 #include "../RenderNode.h"
 #include "CanvasContext.h"
+#include "HardwareBufferRenderParams.h"
 #include "RenderThread.h"
 
 namespace android {
@@ -92,6 +93,9 @@
     mContext->setSyncDelayDuration(systemTime(SYSTEM_TIME_MONOTONIC) - mSyncQueued);
     mContext->setTargetSdrHdrRatio(mRenderSdrHdrRatio);
 
+    auto hardwareBufferParams = mHardwareBufferParams;
+    mContext->setHardwareBufferRenderParams(hardwareBufferParams);
+    IRenderPipeline* pipeline = mContext->getRenderPipeline();
     bool canUnblockUiThread;
     bool canDrawThisFrame;
     {
@@ -151,6 +155,11 @@
     if (!canUnblockUiThread) {
         unblockUiThread();
     }
+
+    if (pipeline->hasHardwareBuffer()) {
+        auto fence = pipeline->flush();
+        hardwareBufferParams.invokeRenderCallback(std::move(fence), 0);
+    }
 }
 
 bool DrawFrameTask::syncFrameState(TreeInfo& info) {
@@ -176,8 +185,9 @@
 
     // This is after the prepareTree so that any pending operations
     // (RenderNode tree state, prefetched layers, etc...) will be flushed.
-    if (CC_UNLIKELY(!mContext->hasSurface() || !canDraw)) {
-        if (!mContext->hasSurface()) {
+    bool hasTarget = mContext->hasOutputTarget();
+    if (CC_UNLIKELY(!hasTarget || !canDraw)) {
+        if (!hasTarget) {
             mSyncResult |= SyncResult::LostSurfaceRewardIfFound;
         } else {
             // If we have a surface but can't draw we must be stopped
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 4be8f6b..4130d4a 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -27,8 +27,16 @@
 #include "../Rect.h"
 #include "../TreeInfo.h"
 #include "RenderTask.h"
+#include "SkColorSpace.h"
+#include "SwapBehavior.h"
+#include "utils/TimeUtils.h"
+#ifdef __ANDROID__  // Layoutlib does not support hardware acceleration
+#include <android/hardware_buffer.h>
+#endif
+#include "HardwareBufferRenderParams.h"
 
 namespace android {
+
 namespace uirenderer {
 
 class DeferredLayerUpdater;
@@ -88,6 +96,10 @@
 
     void forceDrawNextFrame() { mForceDrawFrame = true; }
 
+    void setHardwareBufferRenderParams(const HardwareBufferRenderParams& params) {
+        mHardwareBufferParams = params;
+    }
+
     void setRenderSdrHdrRatio(float ratio) { mRenderSdrHdrRatio = ratio; }
 
 private:
@@ -114,6 +126,7 @@
 
     int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
 
+    HardwareBufferRenderParams mHardwareBufferParams;
     std::function<std::function<void(bool)>(int32_t, int64_t)> mFrameCallback;
     std::function<void(bool)> mFrameCommitCallback;
     std::function<void()> mFrameCompleteCallback;
diff --git a/libs/hwui/renderthread/HardwareBufferRenderParams.h b/libs/hwui/renderthread/HardwareBufferRenderParams.h
new file mode 100644
index 0000000..91fe3f6
--- /dev/null
+++ b/libs/hwui/renderthread/HardwareBufferRenderParams.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+#ifndef HARDWAREBUFFERRENDERER_H_
+#define HARDWAREBUFFERRENDERER_H_
+
+#include <android-base/unique_fd.h>
+#include <android/hardware_buffer.h>
+
+#include "SkColorSpace.h"
+#include "SkMatrix.h"
+#include "SkSurface.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+using namespace android::uirenderer::renderthread;
+
+using RenderCallback = std::function<void(android::base::unique_fd&&, int)>;
+
+class RenderProxy;
+
+class HardwareBufferRenderParams {
+public:
+    HardwareBufferRenderParams() = default;
+    HardwareBufferRenderParams(const SkMatrix& transform, const sk_sp<SkColorSpace>& colorSpace,
+                               RenderCallback&& callback)
+            : mTransform(transform)
+            , mColorSpace(colorSpace)
+            , mRenderCallback(std::move(callback)) {}
+    const SkMatrix& getTransform() const { return mTransform; }
+    sk_sp<SkColorSpace> getColorSpace() const { return mColorSpace; }
+
+    void invokeRenderCallback(android::base::unique_fd&& fenceFd, int status) {
+        if (mRenderCallback) {
+            std::invoke(mRenderCallback, std::move(fenceFd), status);
+        }
+    }
+
+private:
+    SkMatrix mTransform = SkMatrix::I();
+    sk_sp<SkColorSpace> mColorSpace = SkColorSpace::MakeSRGB();
+    RenderCallback mRenderCallback = nullptr;
+};
+
+}  // namespace renderthread
+}  // namespace uirenderer
+}  // namespace android
+#endif  // HARDWAREBUFFERRENDERER_H_
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 18cad31..c68fcdf 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -16,17 +16,19 @@
 
 #pragma once
 
+#include <SkColorSpace.h>
+#include <SkRect.h>
+#include <android-base/unique_fd.h>
+#include <utils/RefBase.h>
+
+#include "ColorMode.h"
 #include "DamageAccumulator.h"
 #include "FrameInfoVisualizer.h"
+#include "HardwareBufferRenderParams.h"
 #include "LayerUpdateQueue.h"
 #include "Lighting.h"
 #include "SwapBehavior.h"
 #include "hwui/Bitmap.h"
-#include "ColorMode.h"
-
-#include <SkColorSpace.h>
-#include <SkRect.h>
-#include <utils/RefBase.h>
 
 class GrDirectContext;
 
@@ -64,10 +66,14 @@
                             const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
                             const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
                             const std::vector<sp<RenderNode>>& renderNodes,
-                            FrameInfoVisualizer* profiler) = 0;
+                            FrameInfoVisualizer* profiler,
+                            const HardwareBufferRenderParams& bufferParams) = 0;
     virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
                              FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
     virtual DeferredLayerUpdater* createTextureLayer() = 0;
+    [[nodiscard]] virtual android::base::unique_fd flush() = 0;
+    virtual void setHardwareBuffer(AHardwareBuffer* hardwareBuffer) = 0;
+    virtual bool hasHardwareBuffer() = 0;
     virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior) = 0;
     virtual void onStop() = 0;
     virtual bool isSurfaceReady() = 0;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index f8e2dee..1e011c2 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -85,6 +85,18 @@
     mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
 }
 
+void RenderProxy::setHardwareBuffer(AHardwareBuffer* buffer) {
+    if (buffer) {
+        AHardwareBuffer_acquire(buffer);
+    }
+    mRenderThread.queue().post([this, hardwareBuffer = buffer]() mutable {
+        mContext->setHardwareBuffer(hardwareBuffer);
+        if (hardwareBuffer) {
+            AHardwareBuffer_release(hardwareBuffer);
+        }
+    });
+}
+
 void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
     if (window) { ANativeWindow_acquire(window); }
     mRenderThread.queue().post([this, win = window, enableTimeout]() mutable {
@@ -340,6 +352,10 @@
     mDrawFrameTask.setContentDrawBounds(left, top, right, bottom);
 }
 
+void RenderProxy::setHardwareBufferRenderParams(const HardwareBufferRenderParams& params) {
+    mDrawFrameTask.setHardwareBufferRenderParams(params);
+}
+
 void RenderProxy::setPictureCapturedCallback(
         const std::function<void(sk_sp<SkPicture>&&)>& callback) {
     mRenderThread.queue().post(
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 5dd65a0..82072a6 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -18,6 +18,7 @@
 #define RENDERPROXY_H_
 
 #include <SkRefCnt.h>
+#include <android/hardware_buffer.h>
 #include <android/native_window.h>
 #include <android/surface_control.h>
 #include <cutils/compiler.h>
@@ -76,7 +77,7 @@
     void setSwapBehavior(SwapBehavior swapBehavior);
     bool loadSystemProperties();
     void setName(const char* name);
-
+    void setHardwareBuffer(AHardwareBuffer* buffer);
     void setSurface(ANativeWindow* window, bool enableTimeout = true);
     void setSurfaceControl(ASurfaceControl* surfaceControl);
     void allocateBuffers();
@@ -84,6 +85,7 @@
     void setStopped(bool stopped);
     void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     void setLightGeometry(const Vector3& lightCenter, float lightRadius);
+    void setHardwareBufferRenderParams(const HardwareBufferRenderParams& params);
     void setOpaque(bool opaque);
     float setColorMode(ColorMode mode);
     void setRenderSdrHdrRatio(float ratio);