New WebViewFunctor API

Should function alongside existing functor API.

Bug: 120997728
Test: hwuiunit passes
Change-Id: I8f6143d0be1111431b55016f34de319f6b8c8910
diff --git a/libs/hwui/pipeline/skia/FunctorDrawable.h b/libs/hwui/pipeline/skia/FunctorDrawable.h
index af3a056..cf2f93b 100644
--- a/libs/hwui/pipeline/skia/FunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/FunctorDrawable.h
@@ -21,7 +21,9 @@
 #include <SkCanvas.h>
 #include <SkDrawable.h>
 
+#include <WebViewFunctorManager.h>
 #include <utils/Functor.h>
+#include <variant>
 
 namespace android {
 namespace uirenderer {
@@ -35,17 +37,43 @@
 class FunctorDrawable : public SkDrawable {
 public:
     FunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener, SkCanvas* canvas)
-            : mFunctor(functor), mListener(listener), mBounds(canvas->getLocalClipBounds()) {}
+            : mBounds(canvas->getLocalClipBounds())
+            , mAnyFunctor(std::in_place_type<LegacyFunctor>, functor, listener) {}
+
+    FunctorDrawable(int functor, SkCanvas* canvas)
+            : mBounds(canvas->getLocalClipBounds())
+            , mAnyFunctor(std::in_place_type<NewFunctor>, functor) {}
+
     virtual ~FunctorDrawable() {}
 
-    virtual void syncFunctor() const = 0;
+    virtual void syncFunctor(const WebViewSyncData& data) const {
+        if (mAnyFunctor.index() == 0) {
+            std::get<0>(mAnyFunctor).handle->sync(data);
+        } else {
+            (*(std::get<1>(mAnyFunctor).functor))(DrawGlInfo::kModeSync, nullptr);
+        }
+    }
 
 protected:
     virtual SkRect onGetBounds() override { return mBounds; }
 
-    Functor* mFunctor;
-    sp<GlFunctorLifecycleListener> mListener;
     const SkRect mBounds;
+
+    struct LegacyFunctor {
+        explicit LegacyFunctor(Functor* functor, GlFunctorLifecycleListener* listener)
+                : functor(functor), listener(listener) {}
+        Functor* functor;
+        sp<GlFunctorLifecycleListener> listener;
+    };
+
+    struct NewFunctor {
+        explicit NewFunctor(int functor) {
+            handle = WebViewFunctorManager::instance().handleFor(functor);
+        }
+        sp<WebViewFunctor::Handle> handle;
+    };
+
+    std::variant<NewFunctor, LegacyFunctor> mAnyFunctor;
 };
 
 }  // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index 4a87e75..240efb4 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -17,29 +17,28 @@
 #include "GLFunctorDrawable.h"
 #include <GrContext.h>
 #include <private/hwui/DrawGlInfo.h>
+#include "FunctorDrawable.h"
 #include "GlFunctorLifecycleListener.h"
+#include "GrBackendSurface.h"
+#include "GrRenderTarget.h"
+#include "GrRenderTargetContext.h"
 #include "RenderNode.h"
 #include "SkAndroidFrameworkUtils.h"
 #include "SkClipStack.h"
 #include "SkRect.h"
-#include "GrBackendSurface.h"
-#include "GrRenderTarget.h"
-#include "GrRenderTargetContext.h"
 
 namespace android {
 namespace uirenderer {
 namespace skiapipeline {
 
 GLFunctorDrawable::~GLFunctorDrawable() {
-    if (mListener.get() != nullptr) {
-        mListener->onGlFunctorReleased(mFunctor);
+    if (auto lp = std::get_if<LegacyFunctor>(&mAnyFunctor)) {
+        if (lp->listener) {
+            lp->listener->onGlFunctorReleased(lp->functor);
+        }
     }
 }
 
-void GLFunctorDrawable::syncFunctor() const {
-    (*mFunctor)(DrawGlInfo::kModeSync, nullptr);
-}
-
 static void setScissor(int viewportHeight, const SkIRect& clip) {
     SkASSERT(!clip.isEmpty());
     // transform to Y-flipped GL space, and prevent negatives
@@ -49,14 +48,14 @@
 }
 
 static bool GetFboDetails(SkCanvas* canvas, GLuint* outFboID, SkISize* outFboSize) {
-    GrRenderTargetContext *renderTargetContext =
+    GrRenderTargetContext* renderTargetContext =
             canvas->internal_private_accessTopLayerRenderTargetContext();
     if (!renderTargetContext) {
         ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
         return false;
     }
 
-    GrRenderTarget *renderTarget = renderTargetContext->accessRenderTarget();
+    GrRenderTarget* renderTarget = renderTargetContext->accessRenderTarget();
     if (!renderTarget) {
         ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
         return false;
@@ -94,16 +93,16 @@
     sk_sp<SkSurface> tmpSurface;
     // we are in a state where there is an unclipped saveLayer
     if (fboID != 0 && !surfaceBounds.contains(clipBounds)) {
-
         // create an offscreen layer and clear it
-        SkImageInfo surfaceInfo = canvas->imageInfo().makeWH(clipBounds.width(), clipBounds.height());
-        tmpSurface = SkSurface::MakeRenderTarget(canvas->getGrContext(), SkBudgeted::kYes,
-                                                 surfaceInfo);
+        SkImageInfo surfaceInfo =
+                canvas->imageInfo().makeWH(clipBounds.width(), clipBounds.height());
+        tmpSurface =
+                SkSurface::MakeRenderTarget(canvas->getGrContext(), SkBudgeted::kYes, surfaceInfo);
         tmpSurface->getCanvas()->clear(SK_ColorTRANSPARENT);
 
         GrGLFramebufferInfo fboInfo;
         if (!tmpSurface->getBackendRenderTarget(SkSurface::kFlushWrite_BackendHandleAccess)
-                .getGLFramebufferInfo(&fboInfo)) {
+                     .getGLFramebufferInfo(&fboInfo)) {
             ALOGW("Unable to extract renderTarget info from offscreen canvas; aborting GLFunctor");
             return;
         }
@@ -144,7 +143,7 @@
     bool clearStencilAfterFunctor = false;
     if (CC_UNLIKELY(clipRegion.isComplex())) {
         // clear the stencil
-        //TODO: move stencil clear and canvas flush to SkAndroidFrameworkUtils::clipWithStencil
+        // TODO: move stencil clear and canvas flush to SkAndroidFrameworkUtils::clipWithStencil
         glDisable(GL_SCISSOR_TEST);
         glStencilMask(0x1);
         glClearStencil(0);
@@ -163,7 +162,7 @@
 
         // GL ops get inserted here if previous flush is missing, which could dirty the stencil
         bool stencilWritten = SkAndroidFrameworkUtils::clipWithStencil(tmpCanvas);
-        tmpCanvas->flush(); //need this flush for the single op that draws into the stencil
+        tmpCanvas->flush();  // need this flush for the single op that draws into the stencil
 
         // ensure that the framebuffer that the webview will render into is bound before after we
         // draw into the stencil
@@ -188,7 +187,11 @@
         setScissor(info.height, clipRegion.getBounds());
     }
 
-    (*mFunctor)(DrawGlInfo::kModeDraw, &info);
+    if (mAnyFunctor.index() == 0) {
+        std::get<0>(mAnyFunctor).handle->drawGl(info);
+    } else {
+        (*(std::get<1>(mAnyFunctor).functor))(DrawGlInfo::kModeDraw, &info);
+    }
 
     if (clearStencilAfterFunctor) {
         // clear stencil buffer as it may be used by Skia
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.h b/libs/hwui/pipeline/skia/GLFunctorDrawable.h
index 215979c..2ea4f67 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.h
@@ -31,11 +31,9 @@
  */
 class GLFunctorDrawable : public FunctorDrawable {
 public:
-    GLFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener, SkCanvas* canvas)
-            : FunctorDrawable(functor, listener, canvas) {}
-    virtual ~GLFunctorDrawable();
+    using FunctorDrawable::FunctorDrawable;
 
-    void syncFunctor() const override;
+    virtual ~GLFunctorDrawable();
 
 protected:
     void onDraw(SkCanvas* canvas) override;
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index f08ac17..eed1942 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include <utils/MathUtils.h>
 #include "LayerDrawable.h"
+#include <utils/MathUtils.h>
 
 #include "GrBackendSurface.h"
 #include "SkColorFilter.h"
@@ -44,10 +44,9 @@
     if (!matrix.isScaleTranslate()) return true;
 
     // We only care about meaningful scale here
-    bool noScale = MathUtils::isOne(matrix.getScaleX())
-            && MathUtils::isOne(matrix.getScaleY());
-    bool pixelAligned = SkScalarIsInt(matrix.getTranslateX())
-            && SkScalarIsInt(matrix.getTranslateY());
+    bool noScale = MathUtils::isOne(matrix.getScaleX()) && MathUtils::isOne(matrix.getScaleY());
+    bool pixelAligned =
+            SkScalarIsInt(matrix.getTranslateX()) && SkScalarIsInt(matrix.getTranslateY());
     return !(noScale && pixelAligned);
 }
 
@@ -120,11 +119,12 @@
             // Integer translation is defined as when src rect and dst rect align fractionally.
             // Skia TextureOp has the above logic build-in, but not NonAAFillRectOp. TextureOp works
             // only for SrcOver blending and without color filter (readback uses Src blending).
-            bool isIntegerTranslate = isBasicallyTranslate(totalMatrix)
-                    && SkScalarFraction(skiaDestRect.fLeft + totalMatrix[SkMatrix::kMTransX])
-                    == SkScalarFraction(skiaSrcRect.fLeft)
-                    && SkScalarFraction(skiaDestRect.fTop + totalMatrix[SkMatrix::kMTransY])
-                    == SkScalarFraction(skiaSrcRect.fTop);
+            bool isIntegerTranslate =
+                    isBasicallyTranslate(totalMatrix) &&
+                    SkScalarFraction(skiaDestRect.fLeft + totalMatrix[SkMatrix::kMTransX]) ==
+                            SkScalarFraction(skiaSrcRect.fLeft) &&
+                    SkScalarFraction(skiaDestRect.fTop + totalMatrix[SkMatrix::kMTransY]) ==
+                            SkScalarFraction(skiaSrcRect.fTop);
             if (layer->getForceFilter() || !isIntegerTranslate) {
                 paint.setFilterQuality(kLow_SkFilterQuality);
             }
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.h b/libs/hwui/pipeline/skia/LayerDrawable.h
index 95dc6d0..7cd515a 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.h
+++ b/libs/hwui/pipeline/skia/LayerDrawable.h
@@ -32,8 +32,8 @@
 public:
     explicit LayerDrawable(DeferredLayerUpdater* layerUpdater) : mLayerUpdater(layerUpdater) {}
 
-    static bool DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
-                          const SkRect* srcRect, const SkRect* dstRect, bool useLayerTransform);
+    static bool DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer, const SkRect* srcRect,
+                          const SkRect* dstRect, bool useLayerTransform);
 
 protected:
     virtual SkRect onGetBounds() override {
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 4494cb0..df1537e 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -127,6 +127,7 @@
             mNode.markDrawEnd(mCanvas);
         }
     }
+
 private:
     SkCanvas& mCanvas;
     RenderNode& mNode;
@@ -140,7 +141,7 @@
     // ensures that we paint the layer even if it is not currently visible in the
     // event that the properties change and it becomes visible.
     if ((mProjectedDisplayList == nullptr && !renderNode->isRenderable()) ||
-            (renderNode->nothingToDraw() && mComposeLayer)) {
+        (renderNode->nothingToDraw() && mComposeLayer)) {
         return;
     }
 
@@ -234,8 +235,8 @@
             // we need to restrict the portion of the surface drawn to the size of the renderNode.
             SkASSERT(renderNode->getLayerSurface()->width() >= bounds.width());
             SkASSERT(renderNode->getLayerSurface()->height() >= bounds.height());
-            canvas->drawImageRect(renderNode->getLayerSurface()->makeImageSnapshot().get(),
-                    bounds, bounds, &paint);
+            canvas->drawImageRect(renderNode->getLayerSurface()->makeImageSnapshot().get(), bounds,
+                                  bounds, &paint);
 
             if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) {
                 renderNode->getSkiaLayer()->hasRenderedSinceRepaint = true;
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 073b481..562a3b2 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -15,11 +15,11 @@
  */
 
 #include "ShaderCache.h"
-#include <algorithm>
 #include <log/log.h>
-#include <thread>
-#include <array>
 #include <openssl/sha.h>
+#include <algorithm>
+#include <array>
+#include <thread>
 #include "FileBlobCache.h"
 #include "Properties.h"
 #include "utils/TraceUtils.h"
@@ -44,8 +44,7 @@
 }
 
 bool ShaderCache::validateCache(const void* identity, ssize_t size) {
-    if (nullptr == identity && size == 0)
-        return true;
+    if (nullptr == identity && size == 0) return true;
 
     if (nullptr == identity || size < 0) {
         if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) {
@@ -66,8 +65,7 @@
     auto key = sIDKey;
     auto loaded = mBlobCache->get(&key, sizeof(key), hash.data(), hash.size());
 
-    if (loaded && std::equal(hash.begin(), hash.end(), mIDHash.begin()))
-        return true;
+    if (loaded && std::equal(hash.begin(), hash.end(), mIDHash.begin())) return true;
 
     if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) {
         ALOGW("ShaderCache::validateCache cache validation fails");
@@ -119,7 +117,7 @@
     int maxTries = 3;
     while (valueSize > mObservedBlobValueSize && maxTries > 0) {
         mObservedBlobValueSize = std::min(valueSize, maxValueSize);
-        void *newValueBuffer = realloc(valueBuffer, mObservedBlobValueSize);
+        void* newValueBuffer = realloc(valueBuffer, mObservedBlobValueSize);
         if (!newValueBuffer) {
             free(valueBuffer);
             return nullptr;
@@ -133,7 +131,7 @@
         return nullptr;
     }
     if (valueSize > mObservedBlobValueSize) {
-        ALOGE("ShaderCache::load value size is too big %d", (int) valueSize);
+        ALOGE("ShaderCache::load value size is too big %d", (int)valueSize);
         free(valueBuffer);
         return nullptr;
     }
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index 82804cf..d41aadb 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -16,12 +16,12 @@
 
 #pragma once
 
+#include <GrContextOptions.h>
 #include <cutils/compiler.h>
 #include <memory>
 #include <mutex>
 #include <string>
 #include <vector>
-#include <GrContextOptions.h>
 
 namespace android {
 
@@ -52,7 +52,7 @@
      * the initialized state the load and store methods will return without
      * performing any cache operations.
      */
-    virtual void initShaderDiskCache(const void *identity, ssize_t size);
+    virtual void initShaderDiskCache(const void* identity, ssize_t size);
 
     virtual void initShaderDiskCache() { initShaderDiskCache(nullptr, 0); }
 
@@ -153,7 +153,7 @@
     /**
      *  "mObservedBlobValueSize" is the maximum value size observed by the cache reading function.
      */
-    size_t mObservedBlobValueSize = 20*1024;
+    size_t mObservedBlobValueSize = 20 * 1024;
 
     /**
      *  The time in seconds to wait before saving newly inserted cache entries.
@@ -176,7 +176,7 @@
      */
     static constexpr uint8_t sIDKey = 0;
 
-    friend class ShaderCacheTestUtils; //used for unit testing
+    friend class ShaderCacheTestUtils;  // used for unit testing
 };
 
 } /* namespace skiapipeline */
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index ac6f6a3..230065c 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -27,9 +27,9 @@
 namespace uirenderer {
 namespace skiapipeline {
 
-void SkiaDisplayList::syncContents() {
+void SkiaDisplayList::syncContents(const WebViewSyncData& data) {
     for (auto& functor : mChildFunctors) {
-        functor->syncFunctor();
+        functor->syncFunctor(data);
     }
     for (auto& animatedImage : mAnimatedImages) {
         animatedImage->syncProperties();
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index d7879e7..309ec02 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -16,11 +16,11 @@
 
 #pragma once
 
-#include "hwui/AnimatedImageDrawable.h"
 #include "FunctorDrawable.h"
 #include "RecordingCanvas.h"
 #include "RenderNodeDrawable.h"
 #include "TreeInfo.h"
+#include "hwui/AnimatedImageDrawable.h"
 #include "utils/LinearAllocator.h"
 
 #include <deque>
@@ -109,7 +109,7 @@
      * NOTE: This function can be folded into RenderNode when we no longer need
      *       to subclass from DisplayList
      */
-    void syncContents();
+    void syncContents(const WebViewSyncData& data);
 
     /**
      * ONLY to be called by RenderNode::prepareTree in order to prepare this
diff --git a/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp b/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
index ea578cb..e48ecf4 100644
--- a/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
+++ b/libs/hwui/pipeline/skia/SkiaMemoryTracer.cpp
@@ -21,16 +21,16 @@
 namespace skiapipeline {
 
 SkiaMemoryTracer::SkiaMemoryTracer(std::vector<ResourcePair> resourceMap, bool itemizeType)
-            : mResourceMap(resourceMap)
-            , mItemizeType(itemizeType)
-            , mTotalSize("bytes", 0)
-            , mPurgeableSize("bytes", 0) {}
+        : mResourceMap(resourceMap)
+        , mItemizeType(itemizeType)
+        , mTotalSize("bytes", 0)
+        , mPurgeableSize("bytes", 0) {}
 
 SkiaMemoryTracer::SkiaMemoryTracer(const char* categoryKey, bool itemizeType)
-            : mCategoryKey(categoryKey)
-            , mItemizeType(itemizeType)
-            , mTotalSize("bytes", 0)
-            , mPurgeableSize("bytes", 0) {}
+        : mCategoryKey(categoryKey)
+        , mItemizeType(itemizeType)
+        , mTotalSize("bytes", 0)
+        , mPurgeableSize("bytes", 0) {}
 
 const char* SkiaMemoryTracer::mapName(const char* resourceName) {
     for (auto& resource : mResourceMap) {
@@ -42,7 +42,7 @@
 }
 
 void SkiaMemoryTracer::processElement() {
-    if(!mCurrentElement.empty()) {
+    if (!mCurrentElement.empty()) {
         // Only count elements that contain "size", other values just provide metadata.
         auto sizeResult = mCurrentValues.find("size");
         if (sizeResult != mCurrentValues.end()) {
@@ -136,8 +136,8 @@
             for (const auto& typedValue : namedItem.second) {
                 TraceValue traceValue = convertUnits(typedValue.second);
                 const char* entry = (traceValue.count > 1) ? "entries" : "entry";
-                log.appendFormat("    %s: %.2f %s (%d %s)\n", typedValue.first,
-                                 traceValue.value, traceValue.units, traceValue.count, entry);
+                log.appendFormat("    %s: %.2f %s (%d %s)\n", typedValue.first, traceValue.value,
+                                 traceValue.units, traceValue.count, entry);
             }
         } else {
             auto result = namedItem.second.find("size");
diff --git a/libs/hwui/pipeline/skia/SkiaMemoryTracer.h b/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
index abf1f4b..e9a7981 100644
--- a/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
+++ b/libs/hwui/pipeline/skia/SkiaMemoryTracer.h
@@ -50,8 +50,8 @@
     }
 
     bool shouldDumpWrappedObjects() const override { return true; }
-    void setMemoryBacking(const char*, const char*, const char*) override { }
-    void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override { }
+    void setMemoryBacking(const char*, const char*, const char*) override {}
+    void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override {}
 
 private:
     struct TraceValue {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 7a255c1..bbc827d 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -183,15 +183,15 @@
         } else {
             String8 cachesOutput;
             mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
-                    &mRenderThread.renderState());
+                                                         &mRenderThread.renderState());
             ALOGE("%s", cachesOutput.string());
             if (errorHandler) {
                 std::ostringstream err;
                 err << "Unable to create layer for " << node->getName();
                 const int maxTextureSize = DeviceInfo::get()->maxTextureSize();
                 err << ", size " << info.width() << "x" << info.height() << " max size "
-                    << maxTextureSize << " color type " << (int)info.colorType()
-                    << " has context " << (int)(mRenderThread.getGrContext() != nullptr);
+                    << maxTextureSize << " color type " << (int)info.colorType() << " has context "
+                    << (int)(mRenderThread.getGrContext() != nullptr);
                 errorHandler->onError(err.str());
             }
         }
@@ -300,8 +300,7 @@
                 mSavePictureProcessor->savePicture(data, mCapturedFile);
             } else {
                 mSavePictureProcessor->savePicture(
-                        data,
-                        mCapturedFile + "_" + std::to_string(mCaptureSequence));
+                        data, mCapturedFile + "_" + std::to_string(mCaptureSequence));
             }
             mCaptureSequence--;
         }
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 42a411a..c94b24a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -97,8 +97,7 @@
         return mLightCenter;
     }
 
-    static void updateLighting(const LightGeometry& lightGeometry,
-                               const LightInfo& lightInfo) {
+    static void updateLighting(const LightGeometry& lightGeometry, const LightInfo& lightInfo) {
         mLightRadius = lightGeometry.radius;
         mAmbientShadowAlpha = lightInfo.ambientShadowAlpha;
         mSpotShadowAlpha = lightInfo.spotShadowAlpha;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index b56c3ef..6eefed9 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -24,8 +24,8 @@
 #include "RenderNode.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 #include "pipeline/skia/GLFunctorDrawable.h"
-#include "pipeline/skia/VkInteropFunctorDrawable.h"
 #include "pipeline/skia/VkFunctorDrawable.h"
+#include "pipeline/skia/VkInteropFunctorDrawable.h"
 
 namespace android {
 namespace uirenderer {
@@ -95,8 +95,8 @@
         drawDrawable(drawable);
     }
     if (enableReorder) {
-        mCurrentBarrier = mDisplayList->allocateDrawable<StartReorderBarrierDrawable>(
-                mDisplayList.get());
+        mCurrentBarrier =
+                mDisplayList->allocateDrawable<StartReorderBarrierDrawable>(mDisplayList.get());
         drawDrawable(mCurrentBarrier);
     }
 }
@@ -127,11 +127,25 @@
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
         // TODO(cblume) use VkFunctorDrawable instead of VkInteropFunctorDrawable here when the
         // interop is disabled/moved.
-        functorDrawable = mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(functor,
-                listener, asSkCanvas());
+        functorDrawable = mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(
+                functor, listener, asSkCanvas());
     } else {
-        functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, listener,
-                asSkCanvas());
+        functorDrawable =
+                mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, listener, asSkCanvas());
+    }
+    mDisplayList->mChildFunctors.push_back(functorDrawable);
+    drawDrawable(functorDrawable);
+}
+
+void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
+    FunctorDrawable* functorDrawable;
+    if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
+        // TODO(cblume) use VkFunctorDrawable instead of VkInteropFunctorDrawable here when the
+        // interop is disabled.
+        functorDrawable =
+                mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(functor, asSkCanvas());
+    } else {
+        functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, asSkCanvas());
     }
     mDisplayList->mChildFunctors.push_back(functorDrawable);
     drawDrawable(functorDrawable);
@@ -167,7 +181,7 @@
         if (colorSpaceFilter) {
             if (tmpPaint.getColorFilter()) {
                 tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(
-                       tmpPaint.refColorFilter(), std::move(colorSpaceFilter)));
+                        tmpPaint.refColorFilter(), std::move(colorSpaceFilter)));
             } else {
                 tmpPaint.setColorFilter(std::move(colorSpaceFilter));
             }
@@ -248,8 +262,7 @@
         filteredPaint.writeable().setFilterQuality(kLow_SkFilterQuality);
     }
     sk_sp<SkImage> image = bitmap.makeImage();
-    mRecorder.drawImageLattice(image, lattice, dst,
-                               filterPaint(std::move(filteredPaint)),
+    mRecorder.drawImageLattice(image, lattice, dst, filterPaint(std::move(filteredPaint)),
                                bitmap.palette());
     if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
         mDisplayList->mMutableImages.push_back(image.get());
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index d6107a9..afeccea 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -74,6 +74,7 @@
     virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
     virtual void callDrawGLFunction(Functor* functor,
                                     uirenderer::GlFunctorLifecycleListener* listener) override;
+    void drawWebViewFunctor(int functor) override;
 
 private:
     RecordingCanvas mRecorder;
diff --git a/libs/hwui/pipeline/skia/SkiaUtils.h b/libs/hwui/pipeline/skia/SkiaUtils.h
index 8344469..fa7f1fe 100644
--- a/libs/hwui/pipeline/skia/SkiaUtils.h
+++ b/libs/hwui/pipeline/skia/SkiaUtils.h
@@ -22,7 +22,7 @@
 
 static inline SkRect SkRectMakeLargest() {
     const SkScalar v = SK_ScalarMax;
-    return { -v, -v, v, v };
+    return {-v, -v, v, v};
 };
 
 } /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 437b5dc..b64eb24 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -20,9 +20,9 @@
 #include "Readback.h"
 #include "SkiaPipeline.h"
 #include "SkiaProfileRenderer.h"
+#include "VkInteropFunctorDrawable.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/Frame.h"
-#include "VkInteropFunctorDrawable.h"
 
 #include <SkSurface.h>
 #include <SkTypes.h>
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 71ad5e1..156f74a 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -17,23 +17,21 @@
 #include "VkFunctorDrawable.h"
 #include <private/hwui/DrawVkInfo.h>
 
-#include "thread/ThreadBase.h"
-#include "utils/TimeUtils.h"
 #include <GrBackendDrawableInfo.h>
-#include <thread>
+#include <SkImage.h>
 #include <utils/Color.h>
 #include <utils/Trace.h>
 #include <utils/TraceUtils.h>
-#include <SkImage.h>
 #include <vk/GrVkTypes.h>
+#include <thread>
+#include "thread/ThreadBase.h"
+#include "utils/TimeUtils.h"
 
 namespace android {
 namespace uirenderer {
 namespace skiapipeline {
 
-VkFunctorDrawHandler::VkFunctorDrawHandler(Functor *functor)
-    : INHERITED()
-    , mFunctor(functor) {}
+VkFunctorDrawHandler::VkFunctorDrawHandler(Functor* functor) : INHERITED(), mFunctor(functor) {}
 
 VkFunctorDrawHandler::~VkFunctorDrawHandler() {
     // TODO(cblume) Fill in the DrawVkInfo parameters.
@@ -55,14 +53,12 @@
     (*mFunctor)(DrawVkInfo::kModeComposite, &draw_vk_info);
 }
 
-VkFunctorDrawable::VkFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener,
-                                     SkCanvas* canvas)
-    : FunctorDrawable(functor, listener, canvas) {}
-
-VkFunctorDrawable::~VkFunctorDrawable() = default;
-
-void VkFunctorDrawable::syncFunctor() const {
-    (*mFunctor)(DrawVkInfo::kModeSync, nullptr);
+VkFunctorDrawable::~VkFunctorDrawable() {
+    if (auto lp = std::get_if<LegacyFunctor>(&mAnyFunctor)) {
+        if (lp->listener) {
+            lp->listener->onGlFunctorReleased(lp->functor);
+        }
+    }
 }
 
 void VkFunctorDrawable::onDraw(SkCanvas* /*canvas*/) {
@@ -71,12 +67,17 @@
 }
 
 std::unique_ptr<FunctorDrawable::GpuDrawHandler> VkFunctorDrawable::onSnapGpuDrawHandler(
-    GrBackendApi backendApi, const SkMatrix& matrix) {
+        GrBackendApi backendApi, const SkMatrix& matrix) {
     if (backendApi != GrBackendApi::kVulkan) {
         return nullptr;
     }
-    std::unique_ptr<VkFunctorDrawHandler> draw(new VkFunctorDrawHandler(mFunctor));
-    return std::move(draw);
+    std::unique_ptr<VkFunctorDrawHandler> draw;
+    if (mAnyFunctor.index() == 0) {
+        LOG_ALWAYS_FATAL("Not implemented");
+        return nullptr;
+    } else {
+        return std::make_unique<VkFunctorDrawHandler>(std::get<1>(mAnyFunctor).functor);
+    }
 }
 
 }  // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.h b/libs/hwui/pipeline/skia/VkFunctorDrawable.h
index 5cd1314..d6fefc1 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.h
@@ -18,9 +18,9 @@
 
 #include "FunctorDrawable.h"
 
-#include <utils/RefBase.h>
-#include <ui/GraphicBuffer.h>
 #include <SkImageInfo.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/RefBase.h>
 
 namespace android {
 namespace uirenderer {
@@ -36,6 +36,7 @@
     ~VkFunctorDrawHandler() override;
 
     void draw(const GrBackendDrawableInfo& info) override;
+
 private:
     typedef GpuDrawHandler INHERITED;
 
@@ -48,17 +49,15 @@
  */
 class VkFunctorDrawable : public FunctorDrawable {
 public:
-    VkFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener,
-            SkCanvas* canvas);
-    ~VkFunctorDrawable() override;
+    using FunctorDrawable::FunctorDrawable;
 
-    void syncFunctor() const override;
+    ~VkFunctorDrawable() override;
 
 protected:
     // SkDrawable functions:
     void onDraw(SkCanvas* canvas) override;
-    std::unique_ptr<FunctorDrawable::GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi backendApi,
-            const SkMatrix& matrix) override;
+    std::unique_ptr<FunctorDrawable::GpuDrawHandler> onSnapGpuDrawHandler(
+            GrBackendApi backendApi, const SkMatrix& matrix) override;
 };
 
 }  // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index 8228550..a5faae7 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -17,13 +17,13 @@
 #include "VkInteropFunctorDrawable.h"
 #include <private/hwui/DrawGlInfo.h>
 
-#include "renderthread/EglManager.h"
-#include "thread/ThreadBase.h"
-#include "utils/TimeUtils.h"
-#include <thread>
 #include <utils/Color.h>
 #include <utils/Trace.h>
 #include <utils/TraceUtils.h>
+#include <thread>
+#include "renderthread/EglManager.h"
+#include "thread/ThreadBase.h"
+#include "utils/TimeUtils.h"
 
 #include <EGL/eglext.h>
 #include <GLES2/gl2.h>
@@ -44,6 +44,7 @@
 class ScopedDrawRequest {
 public:
     ScopedDrawRequest() { beginDraw(); }
+
 private:
     void beginDraw() {
         std::lock_guard _lock{sLock};
@@ -57,9 +58,7 @@
         }
 
         if (!sEglManager.hasEglContext()) {
-            sGLDrawThread->queue().runSync([]() {
-                sEglManager.initialize();
-            });
+            sGLDrawThread->queue().runSync([]() { sEglManager.initialize(); });
         }
     }
 };
@@ -93,14 +92,14 @@
     if (!mFrameBuffer.get() || mFBInfo != surfaceInfo) {
         // Buffer will be used as an OpenGL ES render target.
         mFrameBuffer = new GraphicBuffer(
-                 //TODO: try to reduce the size of the buffer: possibly by using clip bounds.
-                 static_cast<uint32_t>(surfaceInfo.width()),
-                 static_cast<uint32_t>(surfaceInfo.height()),
-                 ColorTypeToPixelFormat(surfaceInfo.colorType()),
-                 GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
-                         GraphicBuffer::USAGE_SW_READ_NEVER | GraphicBuffer::USAGE_HW_RENDER,
-                 std::string("VkInteropFunctorDrawable::onDraw pid [") + std::to_string(getpid()) +
-                         "]");
+                // TODO: try to reduce the size of the buffer: possibly by using clip bounds.
+                static_cast<uint32_t>(surfaceInfo.width()),
+                static_cast<uint32_t>(surfaceInfo.height()),
+                ColorTypeToPixelFormat(surfaceInfo.colorType()),
+                GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
+                        GraphicBuffer::USAGE_SW_READ_NEVER | GraphicBuffer::USAGE_HW_RENDER,
+                std::string("VkInteropFunctorDrawable::onDraw pid [") + std::to_string(getpid()) +
+                        "]");
         status_t error = mFrameBuffer->initCheck();
         if (error < 0) {
             ALOGW("VkInteropFunctorDrawable::onDraw() failed in GraphicBuffer.create()");
@@ -110,16 +109,15 @@
         mFBInfo = surfaceInfo;
     }
 
-    //TODO: Synchronization is needed on mFrameBuffer to guarantee that the previous Vulkan
-    //TODO: draw command has completed.
-    //TODO: A simple but inefficient way is to flush and issue a QueueWaitIdle call. See
-    //TODO: GrVkGpu::destroyResources() for example.
+    // TODO: Synchronization is needed on mFrameBuffer to guarantee that the previous Vulkan
+    // TODO: draw command has completed.
+    // TODO: A simple but inefficient way is to flush and issue a QueueWaitIdle call. See
+    // TODO: GrVkGpu::destroyResources() for example.
     bool success = sGLDrawThread->queue().runSync([&]() -> bool {
         ATRACE_FORMAT("WebViewDraw_%dx%d", mFBInfo.width(), mFBInfo.height());
         EGLDisplay display = sEglManager.eglDisplay();
-        LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
-                "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
-                uirenderer::renderthread::EglManager::eglErrorString());
+        LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+                            uirenderer::renderthread::EglManager::eglErrorString());
         // We use an EGLImage to access the content of the GraphicBuffer
         // The EGL image is later bound to a 2D texture
         EGLClientBuffer clientBuffer = (EGLClientBuffer)mFrameBuffer->getNativeBuffer();
@@ -154,10 +152,10 @@
         AutoGLFramebuffer glFb;
         // Bind texture to the frame buffer.
         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                             glTexture.mTexture, 0);
+                               glTexture.mTexture, 0);
         if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
             ALOGE("Failed framebuffer check for created target buffer: %s",
-                    GLUtils::getGLFramebufferError());
+                  GLUtils::getGLFramebufferError());
             return false;
         }
 
@@ -166,19 +164,22 @@
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT);
 
-        (*mFunctor)(DrawGlInfo::kModeDraw, &info);
+        if (mAnyFunctor.index() == 0) {
+            std::get<0>(mAnyFunctor).handle->drawGl(info);
+        } else {
+            (*(std::get<1>(mAnyFunctor).functor))(DrawGlInfo::kModeDraw, &info);
+        }
 
         EGLSyncKHR glDrawFinishedFence =
                 eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_FENCE_KHR, NULL);
         LOG_ALWAYS_FATAL_IF(glDrawFinishedFence == EGL_NO_SYNC_KHR,
-                "Could not create sync fence %#x", eglGetError());
+                            "Could not create sync fence %#x", eglGetError());
         glFlush();
         // TODO: export EGLSyncKHR in file descr
         // TODO: import file desc in Vulkan Semaphore
         // TODO: instead block the GPU: probably by using external Vulkan semaphore.
         // Block the CPU until the glFlush finish.
-        EGLint waitStatus = eglClientWaitSyncKHR(display, glDrawFinishedFence, 0,
-                FENCE_TIMEOUT);
+        EGLint waitStatus = eglClientWaitSyncKHR(display, glDrawFinishedFence, 0, FENCE_TIMEOUT);
         LOG_ALWAYS_FATAL_IF(waitStatus != EGL_CONDITION_SATISFIED_KHR,
                             "Failed to wait for the fence %#x", eglGetError());
         eglDestroySyncKHR(display, glDrawFinishedFence);
@@ -197,26 +198,25 @@
     canvas->resetMatrix();
 
     auto functorImage = SkImage::MakeFromAHardwareBuffer(
-        reinterpret_cast<AHardwareBuffer*>(mFrameBuffer.get()), kPremul_SkAlphaType,
-        nullptr, kBottomLeft_GrSurfaceOrigin);
+            reinterpret_cast<AHardwareBuffer*>(mFrameBuffer.get()), kPremul_SkAlphaType, nullptr,
+            kBottomLeft_GrSurfaceOrigin);
     canvas->drawImage(functorImage, 0, 0, &paint);
     canvas->restore();
 }
 
 VkInteropFunctorDrawable::~VkInteropFunctorDrawable() {
-    if (mListener.get() != nullptr) {
-        ScopedDrawRequest _drawRequest{};
-        sGLDrawThread->queue().runSync([&]() {
-             mListener->onGlFunctorReleased(mFunctor);
-        });
+    if (auto lp = std::get_if<LegacyFunctor>(&mAnyFunctor)) {
+        if (lp->listener) {
+            ScopedDrawRequest _drawRequest{};
+            sGLDrawThread->queue().runSync(
+                    [&]() { lp->listener->onGlFunctorReleased(lp->functor); });
+        }
     }
 }
 
-void VkInteropFunctorDrawable::syncFunctor() const {
+void VkInteropFunctorDrawable::syncFunctor(const WebViewSyncData& data) const {
     ScopedDrawRequest _drawRequest{};
-    sGLDrawThread->queue().runSync([&]() {
-         (*mFunctor)(DrawGlInfo::kModeSync, nullptr);
-    });
+    sGLDrawThread->queue().runSync([&]() { FunctorDrawable::syncFunctor(data); });
 }
 
 }  // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
index 8fe52c5..c47ee11 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
@@ -18,8 +18,8 @@
 
 #include "FunctorDrawable.h"
 
-#include <utils/RefBase.h>
 #include <ui/GraphicBuffer.h>
+#include <utils/RefBase.h>
 
 namespace android {
 namespace uirenderer {
@@ -32,20 +32,18 @@
  */
 class VkInteropFunctorDrawable : public FunctorDrawable {
 public:
-    VkInteropFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener,
-            SkCanvas* canvas)
-            : FunctorDrawable(functor, listener, canvas) {}
+    using FunctorDrawable::FunctorDrawable;
+
     virtual ~VkInteropFunctorDrawable();
 
-    void syncFunctor() const override;
-
     static void vkInvokeFunctor(Functor* functor);
 
+    void syncFunctor(const WebViewSyncData& data) const override;
+
 protected:
     virtual void onDraw(SkCanvas* canvas) override;
 
 private:
-
     // Variables below describe/store temporary offscreen buffer used for Vulkan pipeline.
     sp<GraphicBuffer> mFrameBuffer;
     SkImageInfo mFBInfo;