Fix z-order for webview surface control

Set the root surface control transparent, and set the z order of the newly created child surface control to -1.
A new callback is needed to update root surface control in sync from Java side.

Bug: 186750329
Test: use latest APKs from Webview team, play a video, mini toolbar should be visible
Change-Id: I0b37ee8f83fd2b41ff4f2856dbadd31ff6170baf
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d42e0c3..cf8c746 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -461,6 +461,9 @@
     protected final ViewFrameInfo mViewFrameInfo = new ViewFrameInfo();
     private final InputEventAssigner mInputEventAssigner = new InputEventAssigner();
 
+    // Set to true if mSurfaceControl is used for Webview Overlay
+    private boolean mIsForWebviewOverlay;
+
     /**
      * Update the Choreographer's FrameInfo object with the timing information for the current
      * ViewRootImpl instance. Erase the data in the current ViewFrameInfo to prepare for the next
@@ -1374,6 +1377,23 @@
         mAttachInfo.mThreadedRenderer.setASurfaceTransactionCallback(callback);
     }
 
+    /**
+     * Register a callback to be executed when Webview overlay needs a surface control.
+     * This callback will be executed on RenderThread worker thread, and released inside native code
+     * when CanvasContext is destroyed.
+     */
+    private void addPrepareSurfaceControlForWebviewCallback() {
+        HardwareRenderer.PrepareSurfaceControlForWebviewCallback callback = () -> {
+            // make mSurfaceControl transparent, so child surface controls are visible
+            if (mIsForWebviewOverlay) return;
+            synchronized (ViewRootImpl.this) {
+                mIsForWebviewOverlay = true;
+            }
+            mTransaction.setOpaque(mSurfaceControl, false).apply();
+        };
+        mAttachInfo.mThreadedRenderer.setPrepareSurfaceControlForWebviewCallback(callback);
+    }
+
     @UnsupportedAppUsage
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         mAttachInfo.mHardwareAccelerated = false;
@@ -1418,6 +1438,7 @@
                     if (mHardwareRendererObserver != null) {
                         mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
                     }
+                    addPrepareSurfaceControlForWebviewCallback();
                     addASurfaceTransactionCallback();
                     mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
                 }
@@ -7743,6 +7764,7 @@
                 }
             }
             if (mAttachInfo.mThreadedRenderer != null) {
+                addPrepareSurfaceControlForWebviewCallback();
                 addASurfaceTransactionCallback();
                 mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
             }
@@ -7790,7 +7812,14 @@
             return;
         }
 
-        mTransaction.setOpaque(mSurfaceControl, opaque).apply();
+        synchronized (this) {
+            if (mIsForWebviewOverlay) {
+                mIsSurfaceOpaque = false;
+                return;
+            }
+            mTransaction.setOpaque(mSurfaceControl, opaque).apply();
+        }
+
         mIsSurfaceOpaque = opaque;
     }
 
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 6aa74cb..e141d51 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -762,6 +762,16 @@
         nSetASurfaceTransactionCallback(mNativeProxy, callback);
     }
 
+    private PrepareSurfaceControlForWebviewCallback mAPrepareSurfaceControlForWebviewCallback;
+
+    /** @hide */
+    public void setPrepareSurfaceControlForWebviewCallback(
+            PrepareSurfaceControlForWebviewCallback callback) {
+        // ensure callback is kept alive on the java side since weak ref is used in native code
+        mAPrepareSurfaceControlForWebviewCallback = callback;
+        nSetPrepareSurfaceControlForWebviewCallback(mNativeProxy, callback);
+    }
+
     /** @hide */
     public void setFrameCallback(FrameDrawingCallback callback) {
         nSetFrameCallback(mNativeProxy, callback);
@@ -876,6 +886,19 @@
         session.close();
     }
 
+   /**
+     * Interface used to receive callbacks when Webview requests a surface control.
+     *
+     * @hide
+     */
+    public interface PrepareSurfaceControlForWebviewCallback {
+        /**
+         * Invoked when Webview calls to get a surface control.
+         *
+         */
+        void prepare();
+    }
+
     /**
      * Interface used to receive callbacks when a transaction needs to be merged.
      *
@@ -1374,6 +1397,9 @@
     private static native void nSetASurfaceTransactionCallback(long nativeProxy,
             ASurfaceTransactionCallback callback);
 
+    private static native void nSetPrepareSurfaceControlForWebviewCallback(long nativeProxy,
+            PrepareSurfaceControlForWebviewCallback callback);
+
     private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
 
     private static native void nSetFrameCompleteCallback(long nativeProxy,
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index d9b9e24..92e20c4 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -197,6 +197,8 @@
     auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
     mSurfaceControl = funcs.createFunc(rootSurfaceControl, "Webview Overlay SurfaceControl");
     ASurfaceTransaction* transaction = funcs.transactionCreateFunc();
+    activeContext->prepareSurfaceControlForWebview();
+    funcs.transactionSetZOrderFunc(transaction, mSurfaceControl, -1);
     funcs.transactionSetVisibilityFunc(transaction, mSurfaceControl,
                                        ASURFACE_TRANSACTION_VISIBILITY_SHOW);
     funcs.transactionApplyFunc(transaction);
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 819a34b..9ff2f46 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -71,6 +71,10 @@
 } gASurfaceTransactionCallback;
 
 struct {
+    jmethodID prepare;
+} gPrepareSurfaceControlForWebviewCallback;
+
+struct {
     jmethodID onFrameDraw;
 } gFrameDrawingCallback;
 
@@ -672,6 +676,28 @@
     }
 }
 
+static void android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(
+        JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    if (!callback) {
+        proxy->setPrepareSurfaceControlForWebviewCallback(nullptr);
+    } else {
+        JavaVM* vm = nullptr;
+        LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
+        auto globalCallbackRef =
+                std::make_shared<JWeakGlobalRefHolder>(vm, callback);
+        proxy->setPrepareSurfaceControlForWebviewCallback([globalCallbackRef]() {
+            JNIEnv* env = getenv(globalCallbackRef->vm());
+            jobject localref = env->NewLocalRef(globalCallbackRef->ref());
+            if (CC_UNLIKELY(!localref)) {
+                return;
+            }
+            env->CallVoidMethod(localref, gPrepareSurfaceControlForWebviewCallback.prepare);
+            env->DeleteLocalRef(localref);
+        });
+    }
+}
+
 static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
         jobject clazz, jlong proxyPtr, jobject frameCallback) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -970,6 +996,9 @@
         {"nSetASurfaceTransactionCallback",
          "(JLandroid/graphics/HardwareRenderer$ASurfaceTransactionCallback;)V",
          (void*)android_view_ThreadedRenderer_setASurfaceTransactionCallback},
+        {"nSetPrepareSurfaceControlForWebviewCallback",
+         "(JLandroid/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback;)V",
+         (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
         {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
          (void*)android_view_ThreadedRenderer_setFrameCallback},
         {"nSetFrameCompleteCallback",
@@ -1037,6 +1066,11 @@
     gASurfaceTransactionCallback.onMergeTransaction =
             GetMethodIDOrDie(env, aSurfaceTransactionCallbackClass, "onMergeTransaction", "(JJJ)V");
 
+    jclass prepareSurfaceControlForWebviewCallbackClass = FindClassOrDie(
+            env, "android/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback");
+    gPrepareSurfaceControlForWebviewCallback.prepare =
+            GetMethodIDOrDie(env, prepareSurfaceControlForWebviewCallbackClass, "prepare", "()V");
+
     jclass frameCallbackClass = FindClassOrDie(env,
             "android/graphics/HardwareRenderer$FrameDrawingCallback");
     gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8bfc2c1..77e64d5 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -197,6 +197,7 @@
 
     if (surfaceControl == nullptr) {
         setASurfaceTransactionCallback(nullptr);
+        setPrepareSurfaceControlForWebviewCallback(nullptr);
     }
 
     if (mSurfaceControl != nullptr) {
@@ -918,6 +919,12 @@
     return true;
 }
 
+void CanvasContext::prepareSurfaceControlForWebview() {
+    if (mPrepareSurfaceControlForWebviewCallback) {
+        std::invoke(mPrepareSurfaceControlForWebviewCallback);
+    }
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4bdc251..a61c2bf 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -212,6 +212,12 @@
 
     bool mergeTransaction(ASurfaceTransaction* transaction, ASurfaceControl* control);
 
+    void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback) {
+        mPrepareSurfaceControlForWebviewCallback = callback;
+    }
+
+    void prepareSurfaceControlForWebview();
+
     static CanvasContext* getActiveContext();
 
 private:
@@ -312,6 +318,8 @@
     bool mExpectSurfaceStats = false;
 
     std::function<void(int64_t, int64_t, int64_t)> mASurfaceTransactionCallback;
+    std::function<void()> mPrepareSurfaceControlForWebviewCallback;
+
     void cleanupResources();
 };
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 6fd644b..c47050c 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -319,6 +319,12 @@
             [this, cb = callback]() { mContext->setASurfaceTransactionCallback(cb); });
 }
 
+void RenderProxy::setPrepareSurfaceControlForWebviewCallback(
+        const std::function<void()>& callback) {
+    mRenderThread.queue().post(
+            [this, cb = callback]() { mContext->setPrepareSurfaceControlForWebviewCallback(cb); });
+}
+
 void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
     mDrawFrameTask.setFrameCallback(std::move(callback));
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 6d80949..d575aa7 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -124,6 +124,7 @@
     void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback);
     void setASurfaceTransactionCallback(
             const std::function<void(int64_t, int64_t, int64_t)>& callback);
+    void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback);
     void setFrameCallback(std::function<void(int64_t)>&& callback);
     void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 4ba7748..524407d 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -102,6 +102,10 @@
             (AST_setVisibility)dlsym(handle_, "ASurfaceTransaction_setVisibility");
     LOG_ALWAYS_FATAL_IF(transactionSetVisibilityFunc == nullptr,
                         "Failed to find required symbol ASurfaceTransaction_setVisibility!");
+
+    transactionSetZOrderFunc = (AST_setZOrder)dlsym(handle_, "ASurfaceTransaction_setZOrder");
+    LOG_ALWAYS_FATAL_IF(transactionSetZOrderFunc == nullptr,
+                        "Failed to find required symbol ASurfaceTransaction_setZOrder!");
 }
 
 void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index dd06009..c5e3746 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -96,6 +96,8 @@
 typedef void (*AST_apply)(ASurfaceTransaction* transaction);
 typedef void (*AST_setVisibility)(ASurfaceTransaction* transaction,
                                   ASurfaceControl* surface_control, int8_t visibility);
+typedef void (*AST_setZOrder)(ASurfaceTransaction* transaction, ASurfaceControl* surface_control,
+                              int32_t z_order);
 
 struct ASurfaceControlFunctions {
     ASurfaceControlFunctions();
@@ -112,6 +114,7 @@
     AST_delete transactionDeleteFunc;
     AST_apply transactionApplyFunc;
     AST_setVisibility transactionSetVisibilityFunc;
+    AST_setZOrder transactionSetZOrderFunc;
 };
 
 class ChoreographerSource;