Have HWUI validate the WebViewFunctors at registration
Also tweak how webview's plat_support creates the functor
sruct to be thread-safe, avoids any potential race conditions
even though WebView itself is stated to be thread-hostile in
general. It's too easy to have this just be defined-safe instead.
Bug: 186814981
Test: build & boot, no crashes in real-webview apps
Change-Id: I06f02a279e248fee375ce133c5ce9a2250665ad9
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index 979678d..d9b9e24 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -221,8 +221,30 @@
return sInstance;
}
+static void validateCallbacks(const WebViewFunctorCallbacks& callbacks) {
+ // TODO: Should we do a stack peek to see if this is really webview?
+ LOG_ALWAYS_FATAL_IF(callbacks.onSync == nullptr, "onSync is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.onContextDestroyed == nullptr, "onContextDestroyed is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.onDestroyed == nullptr, "onDestroyed is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.removeOverlays == nullptr, "removeOverlays is null");
+ switch (auto mode = WebViewFunctor_queryPlatformRenderMode()) {
+ case RenderMode::OpenGL_ES:
+ LOG_ALWAYS_FATAL_IF(callbacks.gles.draw == nullptr, "gles.draw is null");
+ break;
+ case RenderMode::Vulkan:
+ LOG_ALWAYS_FATAL_IF(callbacks.vk.initialize == nullptr, "vk.initialize is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.vk.draw == nullptr, "vk.draw is null");
+ LOG_ALWAYS_FATAL_IF(callbacks.vk.postDraw == nullptr, "vk.postDraw is null");
+ break;
+ default:
+ LOG_ALWAYS_FATAL("unknown platform mode? %d", (int)mode);
+ break;
+ }
+}
+
int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
RenderMode functorMode) {
+ validateCallbacks(callbacks);
auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode);
int id = object->id();
auto handle = object->createHandle();
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index cf8fc82..5092675 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -287,6 +287,7 @@
int sync = 0;
int contextDestroyed = 0;
int destroyed = 0;
+ int removeOverlays = 0;
int glesDraw = 0;
};
@@ -311,6 +312,12 @@
expectOnRenderThread("onDestroyed");
sMockFunctorCounts[functor].destroyed++;
},
+ .removeOverlays =
+ [](int functor, void* data,
+ void (*mergeTransaction)(ASurfaceTransaction*)) {
+ expectOnRenderThread("removeOverlays");
+ sMockFunctorCounts[functor].removeOverlays++;
+ },
};
switch (mode) {
case RenderMode::OpenGL_ES:
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 402cb58..10c874e 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -62,8 +62,10 @@
gSigChain.insert(pair<int, struct sigaction>(sig, old_sa));
}
- // Replace the default GLES driver
+ // Avoid talking to SF
Properties::isolatedProcess = true;
+ // Default to GLES (Vulkan-aware tests will override this)
+ Properties::overrideRenderPipelineType(RenderPipelineType::SkiaGL);
// Run the tests
testing::InitGoogleTest(&argc, argv);
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
index ea57ea0..472e0a4 100644
--- a/native/webview/plat_support/draw_functor.cpp
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -192,44 +192,43 @@
int CreateFunctor_v3(void* data, int version,
AwDrawFnFunctorCallbacks* functor_callbacks) {
- static bool callbacks_initialized = false;
- static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = {
- .onSync = &onSync,
- .onContextDestroyed = &onContextDestroyed,
- .onDestroyed = &onDestroyed,
- .removeOverlays = &removeOverlays,
- };
- if (!callbacks_initialized) {
- switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
- case uirenderer::RenderMode::OpenGL_ES:
- webview_functor_callbacks.gles.draw = &draw_gl;
- break;
- case uirenderer::RenderMode::Vulkan:
- webview_functor_callbacks.vk.initialize = &initializeVk;
- webview_functor_callbacks.vk.draw = &drawVk;
- webview_functor_callbacks.vk.postDraw = &postDrawVk;
- break;
+ static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = [] {
+ uirenderer::WebViewFunctorCallbacks ret = {
+ .onSync = &onSync,
+ .onContextDestroyed = &onContextDestroyed,
+ .onDestroyed = &onDestroyed,
+ .removeOverlays = &removeOverlays,
+ };
+ switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
+ case uirenderer::RenderMode::OpenGL_ES:
+ ret.gles.draw = &draw_gl;
+ break;
+ case uirenderer::RenderMode::Vulkan:
+ ret.vk.initialize = &initializeVk;
+ ret.vk.draw = &drawVk;
+ ret.vk.postDraw = &postDrawVk;
+ break;
+ }
+ return ret;
+ }();
+ SupportData* support = new SupportData{
+ .data = data,
+ };
+
+ // These callbacks are available on all versions.
+ support->callbacks = {
+ .on_sync = functor_callbacks->on_sync,
+ .on_context_destroyed = functor_callbacks->on_context_destroyed,
+ .on_destroyed = functor_callbacks->on_destroyed,
+ .draw_gl = functor_callbacks->draw_gl,
+ .init_vk = functor_callbacks->init_vk,
+ .draw_vk = functor_callbacks->draw_vk,
+ .post_draw_vk = functor_callbacks->post_draw_vk,
+ };
+
+ if (version >= 3) {
+ support->callbacks.remove_overlays = functor_callbacks->remove_overlays;
}
- callbacks_initialized = true;
- }
- SupportData* support = new SupportData{
- .data = data,
- };
-
- // These callbacks are available on all versions.
- support->callbacks = {
- .on_sync = functor_callbacks->on_sync,
- .on_context_destroyed = functor_callbacks->on_context_destroyed,
- .on_destroyed = functor_callbacks->on_destroyed,
- .draw_gl = functor_callbacks->draw_gl,
- .init_vk = functor_callbacks->init_vk,
- .draw_vk = functor_callbacks->draw_vk,
- .post_draw_vk = functor_callbacks->post_draw_vk,
- };
-
- if (version >= 3) {
- support->callbacks.remove_overlays = functor_callbacks->remove_overlays;
- }
int functor = uirenderer::WebViewFunctor_create(
support, webview_functor_callbacks,