diff options
5 files changed, 65 insertions, 18 deletions
diff --git a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java index e3260c25f7..d6fe710aeb 100644 --- a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java +++ b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java @@ -60,6 +60,7 @@ public class ViewerActivity setContentView(R.layout.activity_main); mApplication = (ViewerApplication) getApplication(); + mApplication.setViewerActivity(this); mView = (SurfaceView) findViewById(R.id.surfaceView); mView.getHolder().addCallback(this); @@ -67,6 +68,12 @@ public class ViewerActivity } @Override + protected void onDestroy() { + mApplication.setViewerActivity(null); + super.onDestroy(); + } + + @Override public void surfaceCreated(SurfaceHolder holder) { if (mApplication.getNativeHandle() != 0) { onSurfaceCreated(mApplication.getNativeHandle(), holder.getSurface()); diff --git a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerApplication.java b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerApplication.java index 9389f72208..4b890bd5e1 100644 --- a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerApplication.java +++ b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerApplication.java @@ -11,6 +11,7 @@ import android.app.Application; public class ViewerApplication extends Application { private long mNativeHandle = 0; + private ViewerActivity mViewerActivity; static { System.loadLibrary("skia_android"); @@ -38,4 +39,20 @@ public class ViewerApplication extends Application { public long getNativeHandle() { return mNativeHandle; } + + public void setViewerActivity(ViewerActivity viewerActivity) { + this.mViewerActivity = viewerActivity; + } + + public void setTitle(String title) { + final String finalTitle = title; + if (mViewerActivity != null) { + mViewerActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mViewerActivity.setTitle(finalTitle); + } + }); + } + } } diff --git a/tools/viewer/sk_app/android/Window_android.cpp b/tools/viewer/sk_app/android/Window_android.cpp index 0156ea123e..f16e56753f 100644 --- a/tools/viewer/sk_app/android/Window_android.cpp +++ b/tools/viewer/sk_app/android/Window_android.cpp @@ -38,8 +38,7 @@ const DisplayParams& Window_android::getDisplayParams() { } void Window_android::setTitle(const char* title) { - //todo - SkDebugf("Title: %s", title); + fSkiaAndroidApp->setTitle(title); } bool Window_android::attach(BackEndType attachType, const DisplayParams& params) { diff --git a/tools/viewer/sk_app/android/surface_glue_android.cpp b/tools/viewer/sk_app/android/surface_glue_android.cpp index acee839a30..3d8617f0aa 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)); } diff --git a/tools/viewer/sk_app/android/surface_glue_android.h b/tools/viewer/sk_app/android/surface_glue_android.h index 296112258e..1ce06674b9 100644 --- a/tools/viewer/sk_app/android/surface_glue_android.h +++ b/tools/viewer/sk_app/android/surface_glue_android.h @@ -37,19 +37,31 @@ struct Message { }; struct SkiaAndroidApp { - int fPipes[2]; // 0 is the read message pipe, 1 is the write message pipe Application* fApp; Window* fWindow; - ANativeWindow* fNativeWindow; + jobject fAndroidApp; - SkiaAndroidApp(); - ~SkiaAndroidApp(); - void postMessage(const Message& message); - void readMessage(Message* message); + SkiaAndroidApp(JNIEnv* env, jobject androidApp); + + void postMessage(const Message& message) const; + void readMessage(Message* message) const; void paintIfNeeded(); + // This must be called in SkiaAndroidApp's own pthread because the JNIEnv is thread sensitive + void setTitle(const char* title) const; private: pthread_t fThread; + ANativeWindow* fNativeWindow; + int fPipes[2]; // 0 is the read message pipe, 1 is the write message pipe + JavaVM* fJavaVM; + JNIEnv* fPThreadEnv; + jmethodID fSetTitleMethodID; + + // This must be called in SkiaAndroidApp's own pthread because the JNIEnv is thread sensitive + ~SkiaAndroidApp(); + + static int message_callback(int fd, int events, void* data); + static void* pthread_main(void*); }; } // namespace sk_app |