Move WebView overlay support off of NewWeakGlobalRef
Test: ? Bug: 194893628 Change-Id: Idab4dbdfa958b383754db703b76503a63a8b9d26
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -454,6 +525,56 @@ public final class ThreadedRenderer extends HardwareRenderer {
|
||||
setLightCenter(attachInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user