Index: tools/viewer/sk_app/android/surface_glue_android.cpp |
diff --git a/tools/viewer/sk_app/android/surface_glue_android.cpp b/tools/viewer/sk_app/android/surface_glue_android.cpp |
index acee839a30edfca2318eb534a84c5a7ea46eacad..3d8617f0aa4ab8854991fbeb37151ff60894c840 100644 |
--- a/tools/viewer/sk_app/android/surface_glue_android.cpp |
+++ b/tools/viewer/sk_app/android/surface_glue_android.cpp |
@@ -31,14 +31,17 @@ static const std::unordered_map<int, Window::Key> ANDROID_TO_WINDOW_KEYMAP({ |
{AKEYCODE_SOFT_RIGHT, Window::Key::kRight} |
}); |
-void* pthread_main(void* arg); |
- |
-SkiaAndroidApp::SkiaAndroidApp() { |
+SkiaAndroidApp::SkiaAndroidApp(JNIEnv* env, jobject androidApp) { |
+ env->GetJavaVM(&fJavaVM); |
+ fAndroidApp = env->NewGlobalRef(androidApp); |
+ jclass cls = env->GetObjectClass(fAndroidApp); |
+ fSetTitleMethodID = env->GetMethodID(cls, "setTitle", "(Ljava/lang/String;)V"); |
fNativeWindow = nullptr; |
pthread_create(&fThread, nullptr, pthread_main, this); |
} |
SkiaAndroidApp::~SkiaAndroidApp() { |
+ fPThreadEnv->DeleteGlobalRef(fAndroidApp); |
if (fWindow) { |
fWindow->detach(); |
} |
@@ -51,23 +54,29 @@ SkiaAndroidApp::~SkiaAndroidApp() { |
} |
} |
+void SkiaAndroidApp::setTitle(const char* title) const { |
+ jstring titleString = fPThreadEnv->NewStringUTF(title); |
+ fPThreadEnv->CallVoidMethod(fAndroidApp, fSetTitleMethodID, titleString); |
+ fPThreadEnv->DeleteLocalRef(titleString); |
+} |
+ |
void SkiaAndroidApp::paintIfNeeded() { |
if (fNativeWindow && fWindow) { |
fWindow->onPaint(); |
} |
} |
-void SkiaAndroidApp::postMessage(const Message& message) { |
+void SkiaAndroidApp::postMessage(const Message& message) const { |
auto writeSize = write(fPipes[1], &message, sizeof(message)); |
SkASSERT(writeSize == sizeof(message)); |
} |
-void SkiaAndroidApp::readMessage(Message* message) { |
+void SkiaAndroidApp::readMessage(Message* message) const { |
auto readSize = read(fPipes[0], message, sizeof(Message)); |
SkASSERT(readSize == sizeof(Message)); |
} |
-static int message_callback(int fd, int events, void* data) { |
+int SkiaAndroidApp::message_callback(int fd, int events, void* data) { |
auto skiaAndroidApp = (SkiaAndroidApp*)data; |
Message message; |
skiaAndroidApp->readMessage(&message); |
@@ -127,11 +136,14 @@ static int message_callback(int fd, int events, void* data) { |
return 1; // continue receiving callbacks |
} |
-void* pthread_main(void* arg) { |
+void* SkiaAndroidApp::pthread_main(void* arg) { |
SkDebugf("pthread_main begins"); |
auto skiaAndroidApp = (SkiaAndroidApp*)arg; |
+ // Because JNIEnv is thread sensitive, we need AttachCurrentThread to set our fPThreadEnv |
+ skiaAndroidApp->fJavaVM->AttachCurrentThread(&(skiaAndroidApp->fPThreadEnv), nullptr); |
+ |
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); |
pipe(skiaAndroidApp->fPipes); |
ALooper_addFd(looper, skiaAndroidApp->fPipes[0], LOOPER_ID_MESSAGEPIPE, ALOOPER_EVENT_INPUT, |
@@ -152,13 +164,13 @@ void* pthread_main(void* arg) { |
extern "C" // extern "C" is needed for JNI (although the method itself is in C++) |
JNIEXPORT jlong JNICALL |
- Java_org_skia_viewer_ViewerApplication_createNativeApp(JNIEnv* env, jobject activity) { |
- SkiaAndroidApp* skiaAndroidApp = new SkiaAndroidApp; |
+ Java_org_skia_viewer_ViewerApplication_createNativeApp(JNIEnv* env, jobject application) { |
+ SkiaAndroidApp* skiaAndroidApp = new SkiaAndroidApp(env, application); |
return (jlong)((size_t)skiaAndroidApp); |
} |
extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerApplication_destroyNativeApp( |
- JNIEnv* env, jobject activity, jlong handle) { |
+ JNIEnv* env, jobject application, jlong handle) { |
auto skiaAndroidApp = (SkiaAndroidApp*)handle; |
skiaAndroidApp->postMessage(Message(kDestroyApp)); |
} |