Plumb new functor in native/webview
Add plumbing to native/webview for the new functor.
Add a void* data parameter to avoid having to use a thread safe
map for in both the plumbing and in webview.
Test: Compiles and webview runs
Bug: 120997728
Change-Id: I0f9f3acb05688a5afcf95974bc0b3b117f33a8e3
diff --git a/api/system-current.txt b/api/system-current.txt
index 751ef34..35d0f17 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7760,6 +7760,7 @@
method public void callDrawGlFunction(android.graphics.Canvas, long, java.lang.Runnable);
method public boolean canInvokeDrawGlFunctor(android.view.View);
method public void detachDrawGlFunctor(android.view.View, long);
+ method public void drawWebViewFunctor(android.graphics.Canvas, int);
method public android.app.Application getApplication();
method public java.lang.String getDataDirectorySuffix();
method public java.lang.String getErrorString(android.content.Context, int);
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 6ab7f66..ef69b63 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -138,6 +138,20 @@
}
/**
+ * Call webview draw functor. See API in draw_fn.h.
+ * @param canvas a hardware accelerated canvas (see {@link Canvas#isHardwareAccelerated()}).
+ * @param functor created by AwDrawFn_CreateFunctor in draw_fn.h.
+ */
+ public void drawWebViewFunctor(@NonNull Canvas canvas, int functor) {
+ if (!(canvas instanceof RecordingCanvas)) {
+ // Canvas#isHardwareAccelerated() is only true for subclasses of RecordingCanvas.
+ throw new IllegalArgumentException(canvas.getClass().getName()
+ + " is not a RecordingCanvas canvas");
+ }
+ ((RecordingCanvas) canvas).drawWebViewFunctor(functor);
+ }
+
+ /**
* Detaches the draw GL functor.
*
* @param nativeDrawGLFunctor the pointer to the native functor that implements
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index 20e77b4..5b7ae70 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -37,7 +37,8 @@
}
}
-int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode) {
+int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype,
+ RenderMode functorMode) {
if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) {
ALOGW("Unknown rendermode %d", (int)functorMode);
return -1;
@@ -47,7 +48,7 @@
ALOGW("Unable to map from GLES platform to a vulkan functor");
return -1;
}
- return WebViewFunctorManager::instance().createFunctor(prototype, functorMode);
+ return WebViewFunctorManager::instance().createFunctor(data, prototype, functorMode);
}
void WebViewFunctor_release(int functor) {
@@ -56,7 +57,9 @@
static std::atomic_int sNextId{1};
-WebViewFunctor::WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode) {
+WebViewFunctor::WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
+ RenderMode functorMode)
+ : mData(data) {
mFunctor = sNextId++;
mCallbacks = callbacks;
mMode = functorMode;
@@ -66,12 +69,12 @@
destroyContext();
ATRACE_NAME("WebViewFunctor::onDestroy");
- mCallbacks.onDestroyed(mFunctor);
+ mCallbacks.onDestroyed(mFunctor, mData);
}
void WebViewFunctor::sync(const WebViewSyncData& syncData) const {
ATRACE_NAME("WebViewFunctor::sync");
- mCallbacks.onSync(mFunctor, syncData);
+ mCallbacks.onSync(mFunctor, mData, syncData);
}
void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {
@@ -79,14 +82,14 @@
if (!mHasContext) {
mHasContext = true;
}
- mCallbacks.gles.draw(mFunctor, drawInfo);
+ mCallbacks.gles.draw(mFunctor, mData, drawInfo);
}
void WebViewFunctor::destroyContext() {
if (mHasContext) {
mHasContext = false;
ATRACE_NAME("WebViewFunctor::onContextDestroyed");
- mCallbacks.onContextDestroyed(mFunctor);
+ mCallbacks.onContextDestroyed(mFunctor, mData);
}
}
@@ -95,9 +98,9 @@
return sInstance;
}
-int WebViewFunctorManager::createFunctor(const WebViewFunctorCallbacks& callbacks,
+int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
RenderMode functorMode) {
- auto object = std::make_unique<WebViewFunctor>(callbacks, functorMode);
+ auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode);
int id = object->id();
auto handle = object->createHandle();
{
@@ -164,4 +167,4 @@
return nullptr;
}
-} // namespace android::uirenderer
\ No newline at end of file
+} // namespace android::uirenderer
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index 2a621dd..1719ce7 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -29,7 +29,7 @@
class WebViewFunctor {
public:
- WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
+ WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
~WebViewFunctor();
class Handle : public LightRefBase<Handle> {
@@ -63,6 +63,7 @@
private:
WebViewFunctorCallbacks mCallbacks;
+ void* const mData;
int mFunctor;
RenderMode mMode;
bool mHasContext = false;
@@ -73,7 +74,7 @@
public:
static WebViewFunctorManager& instance();
- int createFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
+ int createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
void releaseFunctor(int functor);
void onContextDestroyed();
void destroyFunctor(int functor);
diff --git a/libs/hwui/private/hwui/WebViewFunctor.h b/libs/hwui/private/hwui/WebViewFunctor.h
index e5346aa..da3d06a 100644
--- a/libs/hwui/private/hwui/WebViewFunctor.h
+++ b/libs/hwui/private/hwui/WebViewFunctor.h
@@ -17,6 +17,7 @@
#ifndef FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H
#define FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H
+#include <cutils/compiler.h>
#include <private/hwui/DrawGlInfo.h>
namespace android::uirenderer {
@@ -27,7 +28,7 @@
};
// Static for the lifetime of the process
-RenderMode WebViewFunctor_queryPlatformRenderMode();
+ANDROID_API RenderMode WebViewFunctor_queryPlatformRenderMode();
struct WebViewSyncData {
bool applyForceDark;
@@ -35,21 +36,21 @@
struct WebViewFunctorCallbacks {
// kModeSync, called on RenderThread
- void (*onSync)(int functor, const WebViewSyncData& syncData);
+ void (*onSync)(int functor, void* data, const WebViewSyncData& syncData);
// Called when either the context is destroyed _or_ when the functor's last reference goes
// away. Will always be called with an active context and always on renderthread.
- void (*onContextDestroyed)(int functor);
+ void (*onContextDestroyed)(int functor, void* data);
// Called when the last reference to the handle goes away and the handle is considered
// irrevocably destroyed. Will always be proceeded by a call to onContextDestroyed if
// this functor had ever been drawn.
- void (*onDestroyed)(int functor);
+ void (*onDestroyed)(int functor, void* data);
union {
struct {
// Called on RenderThread. initialize is guaranteed to happen before this call
- void (*draw)(int functor, const DrawGlInfo& params);
+ void (*draw)(int functor, void* data, const DrawGlInfo& params);
} gles;
// TODO: VK support. The current DrawVkInfo is monolithic and needs to be split up for
// what params are valid on what callbacks
@@ -70,12 +71,12 @@
// Creates a new WebViewFunctor from the given prototype. The prototype is copied after
// this function returns. Caller retains full ownership of it.
// Returns -1 if the creation fails (such as an unsupported functorMode + platform mode combination)
-int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode);
+ANDROID_API int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype, RenderMode functorMode);
// May be called on any thread to signal that the functor should be destroyed.
// The functor will receive an onDestroyed when the last usage of it is released,
// and it should be considered alive & active until that point.
-void WebViewFunctor_release(int functor);
+ANDROID_API void WebViewFunctor_release(int functor);
} // namespace android::uirenderer
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 5ff8993..6a1ca5a 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -315,24 +315,24 @@
static WebViewFunctorCallbacks createMockFunctor(RenderMode mode) {
auto callbacks = WebViewFunctorCallbacks{
.onSync =
- [](int functor, const WebViewSyncData& data) {
+ [](int functor, void* client_data, const WebViewSyncData& data) {
expectOnRenderThread();
sMockFunctorCounts[functor].sync++;
},
.onContextDestroyed =
- [](int functor) {
+ [](int functor, void* client_data) {
expectOnRenderThread();
sMockFunctorCounts[functor].contextDestroyed++;
},
.onDestroyed =
- [](int functor) {
+ [](int functor, void* client_data) {
expectOnRenderThread();
sMockFunctorCounts[functor].destroyed++;
},
};
switch (mode) {
case RenderMode::OpenGL_ES:
- callbacks.gles.draw = [](int functor, const DrawGlInfo& params) {
+ callbacks.gles.draw = [](int functor, void* client_data, const DrawGlInfo& params) {
expectOnRenderThread();
sMockFunctorCounts[functor].glesDraw++;
};
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 53bf84f..1b4cf7e 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -100,8 +100,8 @@
GLFunctorDrawable functorDrawable(&functor, nullptr, &dummyCanvas);
skiaDL.mChildFunctors.push_back(&functorDrawable);
- int functor2 = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor2 = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
auto& counts = TestUtils::countsForFunctor(functor2);
skiaDL.mChildFunctors.push_back(
skiaDL.allocateDrawable<GLFunctorDrawable>(functor2, &dummyCanvas));
diff --git a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
index c8169af..e1fb8b7 100644
--- a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
+++ b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
@@ -27,8 +27,8 @@
using namespace android::uirenderer;
TEST(WebViewFunctor, createDestroyGLES) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
WebViewFunctor_release(functor);
TestUtils::runOnRenderThreadUnmanaged([](renderthread::RenderThread&) {
@@ -41,8 +41,8 @@
}
TEST(WebViewFunctor, createSyncHandleGLES) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -82,8 +82,8 @@
}
TEST(WebViewFunctor, createSyncDrawGLES) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -109,8 +109,8 @@
}
TEST(WebViewFunctor, contextDestroyed) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -151,4 +151,4 @@
EXPECT_EQ(2, counts.glesDraw);
EXPECT_EQ(2, counts.contextDestroyed);
EXPECT_EQ(1, counts.destroyed);
-}
\ No newline at end of file
+}
diff --git a/native/webview/plat_support/Android.bp b/native/webview/plat_support/Android.bp
index 96c9c1c..0936256 100644
--- a/native/webview/plat_support/Android.bp
+++ b/native/webview/plat_support/Android.bp
@@ -22,6 +22,7 @@
name: "libwebviewchromium_plat_support",
srcs: [
+ "draw_functor.cpp",
"draw_gl_functor.cpp",
"draw_vk_functor.cpp",
"functor_utils.cpp",
diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h
index 8d48a58..6afd883 100644
--- a/native/webview/plat_support/draw_fn.h
+++ b/native/webview/plat_support/draw_fn.h
@@ -129,31 +129,31 @@
// Called on render thread while UI thread is blocked. Called for both GL and
// VK.
-typedef void AwDrawFn_OnSync(int functor, AwDrawFn_OnSyncParams* params);
+typedef void AwDrawFn_OnSync(int functor, void* data, AwDrawFn_OnSyncParams* params);
// Called on render thread when either the context is destroyed _or_ when the
// functor's last reference goes away. Will always be called with an active
// context. Called for both GL and VK.
-typedef void AwDrawFn_OnContextDestroyed(int functor);
+typedef void AwDrawFn_OnContextDestroyed(int functor, void* data);
// Called on render thread when the last reference to the handle goes away and
-// the handle is considered irrevocably destroyed. Will always be proceeded by
+// the handle is considered irrevocably destroyed. Will always be preceded by
// a call to OnContextDestroyed if this functor had ever been drawn. Called for
// both GL and VK.
-typedef void AwDrawFn_OnDestroyed(int functor);
+typedef void AwDrawFn_OnDestroyed(int functor, void* data);
// Only called for GL.
-typedef void AwDrawFn_DrawGL(int functor, AwDrawFn_DrawGLParams* params);
+typedef void AwDrawFn_DrawGL(int functor, void* data, AwDrawFn_DrawGLParams* params);
// Initialize vulkan state. Needs to be called again after any
// OnContextDestroyed. Only called for Vulkan.
-typedef void AwDrawFn_InitVk(int functor, AwDrawFn_InitVkParams* params);
+typedef void AwDrawFn_InitVk(int functor, void* data, AwDrawFn_InitVkParams* params);
// Only called for Vulkan.
-typedef void AwDrawFn_DrawVk(int functor, AwDrawFn_DrawVkParams* params);
+typedef void AwDrawFn_DrawVk(int functor, void* data, AwDrawFn_DrawVkParams* params);
// Only called for Vulkan.
-typedef void AwDrawFn_PostDrawVk(int functor,
+typedef void AwDrawFn_PostDrawVk(int functor, void* data,
AwDrawFn_PostDrawVkParams* params);
struct AwDrawFnFunctorCallbacks {
@@ -176,7 +176,7 @@
typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void);
// Create a functor. |functor_callbacks| should be valid until OnDestroyed.
-typedef int AwDrawFn_CreateFunctor(AwDrawFnFunctorCallbacks* functor_callbacks);
+typedef int AwDrawFn_CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks);
// May be called on any thread to signal that the functor should be destroyed.
// The functor will receive an onDestroyed when the last usage of it is
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
new file mode 100644
index 0000000..820bac5
--- /dev/null
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "draw_fn.h"
+
+#include <jni.h>
+#include <private/hwui/WebViewFunctor.h>
+#include <utils/Log.h>
+
+#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
+#define COMPILE_ASSERT(expr, err) \
+__unused static const char (err)[(expr) ? 1 : -1] = "";
+
+namespace android {
+namespace {
+
+struct SupportData {
+ void* const data;
+ AwDrawFnFunctorCallbacks callbacks;
+};
+
+void onSync(int functor, void* data,
+ const uirenderer::WebViewSyncData& syncData) {
+ AwDrawFn_OnSyncParams params = {
+ .version = kAwDrawFnVersion,
+ .apply_force_dark = syncData.applyForceDark,
+ };
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.on_sync(functor, support->data, ¶ms);
+}
+
+void onContextDestroyed(int functor, void* data) {
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.on_context_destroyed(functor, support->data);
+}
+
+void onDestroyed(int functor, void* data) {
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.on_destroyed(functor, support->data);
+ delete support;
+}
+
+void draw_gl(int functor, void* data,
+ const uirenderer::DrawGlInfo& draw_gl_params) {
+ AwDrawFn_DrawGLParams params = {
+ .version = kAwDrawFnVersion,
+ .clip_left = draw_gl_params.clipLeft,
+ .clip_top = draw_gl_params.clipTop,
+ .clip_right = draw_gl_params.clipRight,
+ .clip_bottom = draw_gl_params.clipBottom,
+ .width = draw_gl_params.width,
+ .height = draw_gl_params.height,
+ .is_layer = draw_gl_params.isLayer,
+ };
+ COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_gl_params.transform),
+ mismatched_transform_matrix_sizes);
+ for (int i = 0; i < NELEM(params.transform); ++i) {
+ params.transform[i] = draw_gl_params.transform[i];
+ }
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.draw_gl(functor, support->data, ¶ms);
+}
+
+int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
+ static bool callbacks_initialized = false;
+ static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = {
+ .onSync = &onSync,
+ .onContextDestroyed = &onContextDestroyed,
+ .onDestroyed = &onDestroyed,
+ };
+ if (!callbacks_initialized) {
+ switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
+ case uirenderer::RenderMode::OpenGL_ES:
+ webview_functor_callbacks.gles.draw = &draw_gl;
+ break;
+ case uirenderer::RenderMode::Vulkan:
+ break;
+ }
+ callbacks_initialized = true;
+ }
+ SupportData* support = new SupportData{
+ .data = data,
+ .callbacks = *functor_callbacks,
+ };
+ int functor = uirenderer::WebViewFunctor_create(
+ support, webview_functor_callbacks,
+ uirenderer::WebViewFunctor_queryPlatformRenderMode());
+ if (functor <= 0) delete support;
+ return functor;
+}
+
+void ReleaseFunctor(int functor) {
+ uirenderer::WebViewFunctor_release(functor);
+}
+
+AwDrawFnRenderMode QueryRenderMode(void) {
+ switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
+ case uirenderer::RenderMode::OpenGL_ES:
+ return AW_DRAW_FN_RENDER_MODE_OPENGL_ES;
+ case uirenderer::RenderMode::Vulkan:
+ return AW_DRAW_FN_RENDER_MODE_VULKAN;
+ }
+}
+
+jlong GetDrawFnFunctionTable() {
+ static AwDrawFnFunctionTable function_table = {
+ .version = kAwDrawFnVersion,
+ .query_render_mode = &QueryRenderMode,
+ .create_functor = &CreateFunctor,
+ .release_functor = &ReleaseFunctor,
+ };
+ return reinterpret_cast<intptr_t>(&function_table);
+}
+
+const char kClassName[] = "com/android/webview/chromium/DrawFunctor";
+const JNINativeMethod kJniMethods[] = {
+ {"nativeGetFunctionTable", "()J",
+ reinterpret_cast<void*>(GetDrawFnFunctionTable)},
+};
+
+} // namespace
+
+void RegisterDrawFunctor(JNIEnv* env) {
+ jclass clazz = env->FindClass(kClassName);
+ LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName);
+
+ int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods));
+ LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res);
+}
+
+} // namespace android
diff --git a/native/webview/plat_support/jni_entry_point.cpp b/native/webview/plat_support/jni_entry_point.cpp
index 4771be1..9599fa6 100644
--- a/native/webview/plat_support/jni_entry_point.cpp
+++ b/native/webview/plat_support/jni_entry_point.cpp
@@ -21,6 +21,7 @@
namespace android {
+void RegisterDrawFunctor(JNIEnv* env);
void RegisterDrawGLFunctor(JNIEnv* env);
void RegisterGraphicsUtils(JNIEnv* env);
@@ -30,6 +31,7 @@
JNIEnv* env = NULL;
jint ret = vm->AttachCurrentThread(&env, NULL);
LOG_ALWAYS_FATAL_IF(ret != JNI_OK, "AttachCurrentThread failed");
+ android::RegisterDrawFunctor(env);
android::RegisterDrawGLFunctor(env);
android::RegisterGraphicsUtils(env);