diff options
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 121 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 59 | ||||
-rw-r--r-- | graphics/java/android/graphics/HardwareRenderer.java | 14 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_HardwareRenderer.cpp | 44 |
4 files changed, 138 insertions, 100 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index d839e3532b64..bee0709556e7 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.BLASTBufferQueue; import android.graphics.FrameInfo; import android.graphics.HardwareRenderer; import android.graphics.Picture; @@ -257,6 +258,76 @@ public final class ThreadedRenderer extends HardwareRenderer { private boolean mEnabled; private boolean mRequested = true; + /** + * This child class exists to break ownership cycles. ViewRootImpl owns a ThreadedRenderer + * which owns a WebViewOverlayProvider. WebViewOverlayProvider will in turn be set as + * the listener for HardwareRenderer callbacks. By keeping this a child class, there are + * no cycles in the chain. The ThreadedRenderer will remain GC-able if any callbacks are + * still outstanding, which will in turn release any JNI references to WebViewOverlayProvider. + */ + private static final class WebViewOverlayProvider implements + PrepareSurfaceControlForWebviewCallback, ASurfaceTransactionCallback { + private static final boolean sOverlaysAreEnabled = + HardwareRenderer.isWebViewOverlaysEnabled(); + private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); + private boolean mHasWebViewOverlays = false; + private BLASTBufferQueue mBLASTBufferQueue; + private SurfaceControl mSurfaceControl; + + public boolean setSurfaceControlOpaque(boolean opaque) { + synchronized (this) { + if (mHasWebViewOverlays) return false; + mTransaction.setOpaque(mSurfaceControl, opaque).apply(); + } + return opaque; + } + + public boolean shouldEnableOverlaySupport() { + return sOverlaysAreEnabled && mSurfaceControl != null && mBLASTBufferQueue != null; + } + + public void setSurfaceControl(SurfaceControl surfaceControl) { + synchronized (this) { + mSurfaceControl = surfaceControl; + if (mSurfaceControl != null && mHasWebViewOverlays) { + mTransaction.setOpaque(surfaceControl, false).apply(); + } + } + } + + public void setBLASTBufferQueue(BLASTBufferQueue bufferQueue) { + synchronized (this) { + mBLASTBufferQueue = bufferQueue; + } + } + + @Override + public void prepare() { + synchronized (this) { + mHasWebViewOverlays = true; + if (mSurfaceControl != null) { + mTransaction.setOpaque(mSurfaceControl, false).apply(); + } + } + } + + @Override + public boolean onMergeTransaction(long nativeTransactionObj, + long aSurfaceControlNativeObj, long frameNr) { + synchronized (this) { + if (mBLASTBufferQueue == null) { + return false; + } else { + mBLASTBufferQueue.mergeWithNextTransaction(nativeTransactionObj, frameNr); + return true; + } + } + } + } + + private final WebViewOverlayProvider mWebViewOverlayProvider = new WebViewOverlayProvider(); + private boolean mWebViewOverlaysEnabled = false; + @Nullable private ArrayList<FrameDrawingCallback> mNextRtFrameCallbacks; @@ -455,6 +526,56 @@ public final class ThreadedRenderer extends HardwareRenderer { } /** + * Whether or not the renderer owns the SurfaceControl's opacity. If true, use + * {@link #setSurfaceControlOpaque(boolean)} to update the opacity + */ + public boolean rendererOwnsSurfaceControlOpacity() { + return mWebViewOverlayProvider.mSurfaceControl != null; + } + + /** + * Sets the SurfaceControl's opacity that this HardwareRenderer is rendering onto. The renderer + * may opt to override the opacity, and will return the value that is ultimately set + * + * @return true if the surface is opaque, false otherwise + * + * @hide + */ + public boolean setSurfaceControlOpaque(boolean opaque) { + return mWebViewOverlayProvider.setSurfaceControlOpaque(opaque); + } + + private void updateWebViewOverlayCallbacks() { + boolean shouldEnable = mWebViewOverlayProvider.shouldEnableOverlaySupport(); + if (shouldEnable != mWebViewOverlaysEnabled) { + mWebViewOverlaysEnabled = shouldEnable; + if (shouldEnable) { + setASurfaceTransactionCallback(mWebViewOverlayProvider); + setPrepareSurfaceControlForWebviewCallback(mWebViewOverlayProvider); + } else { + setASurfaceTransactionCallback(null); + setPrepareSurfaceControlForWebviewCallback(null); + } + } + } + + @Override + public void setSurfaceControl(@Nullable SurfaceControl surfaceControl) { + super.setSurfaceControl(surfaceControl); + mWebViewOverlayProvider.setSurfaceControl(surfaceControl); + updateWebViewOverlayCallbacks(); + } + + /** + * Sets the BLASTBufferQueue being used for rendering. This is required to be specified + * for WebView overlay support + */ + public void setBlastBufferQueue(@Nullable BLASTBufferQueue blastBufferQueue) { + mWebViewOverlayProvider.setBLASTBufferQueue(blastBufferQueue); + updateWebViewOverlayCallbacks(); + } + + /** * Updates the light position based on the position of the window. * * @param attachInfo Information about the window. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 501d2512dd2b..0280be4f720b 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -485,9 +485,6 @@ public final class ViewRootImpl implements ViewParent, 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 @@ -1386,42 +1383,6 @@ public final class ViewRootImpl implements ViewParent, } } - /** - * Register a callback to be executed when Webview overlay needs to merge a transaction. - * This callback will be executed on RenderThread worker thread, and released inside native code - * when CanvasContext is destroyed. - */ - private void addASurfaceTransactionCallback() { - HardwareRenderer.ASurfaceTransactionCallback callback = (nativeTransactionObj, - nativeSurfaceControlObj, - frameNr) -> { - if (mBlastBufferQueue == null) { - return false; - } else { - mBlastBufferQueue.mergeWithNextTransaction(nativeTransactionObj, frameNr); - return true; - } - }; - 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; @@ -1466,11 +1427,8 @@ public final class ViewRootImpl implements ViewParent, if (mHardwareRendererObserver != null) { mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver); } - if (HardwareRenderer.isWebViewOverlaysEnabled()) { - addPrepareSurfaceControlForWebviewCallback(); - addASurfaceTransactionCallback(); - } mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); + mAttachInfo.mThreadedRenderer.setBlastBufferQueue(mBlastBufferQueue); } } } @@ -2041,6 +1999,7 @@ public final class ViewRootImpl implements ViewParent, if (mAttachInfo.mThreadedRenderer != null) { mAttachInfo.mThreadedRenderer.setSurfaceControl(null); + mAttachInfo.mThreadedRenderer.setBlastBufferQueue(null); } } @@ -7823,11 +7782,8 @@ public final class ViewRootImpl implements ViewParent, } } if (mAttachInfo.mThreadedRenderer != null) { - if (HardwareRenderer.isWebViewOverlaysEnabled()) { - addPrepareSurfaceControlForWebviewCallback(); - addASurfaceTransactionCallback(); - } mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); + mAttachInfo.mThreadedRenderer.setBlastBufferQueue(mBlastBufferQueue); } } else { destroySurface(); @@ -7873,11 +7829,10 @@ public final class ViewRootImpl implements ViewParent, return; } - synchronized (this) { - if (mIsForWebviewOverlay) { - mIsSurfaceOpaque = false; - return; - } + final ThreadedRenderer renderer = mAttachInfo.mThreadedRenderer; + if (renderer != null && renderer.rendererOwnsSurfaceControlOpacity()) { + opaque = renderer.setSurfaceControlOpaque(opaque); + } else { mTransaction.setOpaque(mSurfaceControl, opaque).apply(); } diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index ac2d0c45cc60..8894fa32b480 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -752,22 +752,14 @@ public class HardwareRenderer { nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); } - private ASurfaceTransactionCallback mASurfaceTransactionCallback; - /** @hide */ - public void setASurfaceTransactionCallback(ASurfaceTransactionCallback callback) { - // ensure callback is kept alive on the java side since weak ref is used in native code - mASurfaceTransactionCallback = callback; + protected void setASurfaceTransactionCallback(ASurfaceTransactionCallback callback) { nSetASurfaceTransactionCallback(mNativeProxy, callback); } - private PrepareSurfaceControlForWebviewCallback mAPrepareSurfaceControlForWebviewCallback; - /** @hide */ - public void setPrepareSurfaceControlForWebviewCallback( + protected 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); } @@ -1299,7 +1291,7 @@ public class HardwareRenderer { /** * @hide */ - public static native boolean isWebViewOverlaysEnabled(); + protected static native boolean isWebViewOverlaysEnabled(); /** @hide */ protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile); diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index db5915447d39..1ca4ce9dc3d8 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -423,28 +423,6 @@ private: jobject mObject; }; -class JWeakGlobalRefHolder { -public: - JWeakGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm) { - mWeakRef = getenv(vm)->NewWeakGlobalRef(object); - } - - virtual ~JWeakGlobalRefHolder() { - if (mWeakRef != nullptr) getenv(mVm)->DeleteWeakGlobalRef(mWeakRef); - mWeakRef = nullptr; - } - - jobject ref() { return mWeakRef; } - JavaVM* vm() { return mVm; } - -private: - JWeakGlobalRefHolder(const JWeakGlobalRefHolder&) = delete; - void operator=(const JWeakGlobalRefHolder&) = delete; - - JavaVM* mVm; - jobject mWeakRef; -}; - using TextureMap = std::unordered_map<uint32_t, sk_sp<SkImage>>; struct PictureCaptureState { @@ -578,20 +556,16 @@ static void android_view_ThreadedRenderer_setASurfaceTransactionCallback( } 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, aSurfaceTransactionCallback); + auto globalCallbackRef = std::make_shared<JGlobalRefHolder>( + vm, env->NewGlobalRef(aSurfaceTransactionCallback)); proxy->setASurfaceTransactionCallback( [globalCallbackRef](int64_t transObj, int64_t scObj, int64_t frameNr) -> bool { JNIEnv* env = getenv(globalCallbackRef->vm()); - jobject localref = env->NewLocalRef(globalCallbackRef->ref()); - if (CC_UNLIKELY(!localref)) { - return false; - } jboolean ret = env->CallBooleanMethod( - localref, gASurfaceTransactionCallback.onMergeTransaction, + globalCallbackRef->object(), + gASurfaceTransactionCallback.onMergeTransaction, static_cast<jlong>(transObj), static_cast<jlong>(scObj), static_cast<jlong>(frameNr)); - env->DeleteLocalRef(localref); return ret; }); } @@ -606,15 +580,11 @@ static void android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCall 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); + std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(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); + env->CallVoidMethod(globalCallbackRef->object(), + gPrepareSurfaceControlForWebviewCallback.prepare); }); } } |