diff --git a/app/Go.java b/app/Go.java index dcdd775..e0c1830 100644 --- a/app/Go.java +++ b/app/Go.java @@ -25,15 +25,7 @@ public final class Go { // TODO(crawshaw): context.registerComponentCallbacks for runtime.GC System.loadLibrary("gojni"); - - new Thread("GoMain") { - public void run() { - Go.run(ctx); - } - }.start(); - - Go.waitForRun(); - + Go.run(ctx); new Thread("GoReceive") { public void run() { Seq.receive(); } }.start(); diff --git a/app/android.c b/app/android.c index dca0aaa..9683e6c 100644 --- a/app/android.c +++ b/app/android.c @@ -29,11 +29,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { return -1; } - pthread_mutex_lock(&go_started_mu); - go_started = 0; - pthread_mutex_unlock(&go_started_mu); - pthread_cond_init(&go_started_cond, NULL); - return JNI_VERSION_1_6; } @@ -117,7 +112,7 @@ static const char* getenv_raw(const char *name) { return name; } -static void* init_go_runtime(void* unused) { +static void* call_main_and_wait() { init_from_context(); uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main"); if (!mainPC) { @@ -126,31 +121,6 @@ static void* init_go_runtime(void* unused) { callMain(mainPC); } -static void wait_go_runtime() { - pthread_mutex_lock(&go_started_mu); - while (go_started == 0) { - pthread_cond_wait(&go_started_cond, &go_started_mu); - } - pthread_mutex_unlock(&go_started_mu); - LOG_INFO("runtime started"); -} - -pthread_t nativeactivity_t; - -// Runtime entry point when embedding Go in other libraries. -void InitGoRuntime() { - pthread_mutex_lock(&go_started_mu); - go_started = 0; - pthread_mutex_unlock(&go_started_mu); - pthread_cond_init(&go_started_cond, NULL); - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&nativeactivity_t, NULL, init_go_runtime, NULL); - wait_go_runtime(); -} - // Runtime entry point when using NativeActivity. void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) { // Note that activity->clazz is mis-named. @@ -158,7 +128,7 @@ void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_ current_ctx = (*activity->env)->NewGlobalRef(activity->env, activity->clazz); current_native_activity = activity; - InitGoRuntime(); + call_main_and_wait(); // These functions match the methods on Activity, described at // http://developer.android.com/reference/android/app/Activity.html @@ -199,11 +169,5 @@ Java_go_Go_run(JNIEnv* env, jclass clazz, jobject ctx) { asset_manager = AAssetManager_fromJava(env, asset_manager_ref); } - init_go_runtime(NULL); -} - -// Used by Java initialization code to know when it can use cgocall. -JNIEXPORT void JNICALL -Java_go_Go_waitForRun(JNIEnv* env, jclass clazz) { - wait_go_runtime(); + call_main_and_wait(); } diff --git a/app/android.go b/app/android.go index 30a5a90..fc8a156 100644 --- a/app/android.go +++ b/app/android.go @@ -4,9 +4,22 @@ // +build android -// Go runtime entry point for apps running on android. -// Sets up everything the runtime needs and exposes -// the entry point to JNI. +/* +Android Apps are built with -buildmode=c-shared. They are loaded by a +running Java process. + +Before any entry point is reached, a global constructor initializes the +Go runtime, calling all Go init functions. All cgo calls will block +until this is complete. Next JNI_OnLoad is called. When that is +complete, one of two entry points is called. + +All-Go apps built using NativeActivity enter at ANativeActivity_onCreate. +Go libraries, such as those built with gomobild bind, enter from Java at +Java_go_Go_run. + +Both entry points make a cgo call that calls the Go main and blocks +until app.Run is called. +*/ package app @@ -22,10 +35,6 @@ package app #include #include -pthread_cond_t go_started_cond; -pthread_mutex_t go_started_mu; -int go_started; - // current_vm is stored to initialize other cgo packages. // // As all the Go packages in a program form a single shared library, @@ -44,21 +53,6 @@ ANativeActivity* current_native_activity; // For all-Go app, this is initialized in onCreate. // For go library app, this is set from the context passed to Go.run. AAssetManager* asset_manager; - -// build_auxv builds an ELF auxiliary vector for initializing the Go -// runtime. While there does not appear to be any spec for this -// format, there are some notes in -// -// Phrack, V. 0x0b, Issue 0x3a, P. 0x05. -// http://phrack.org/issues/58/5.html -// -// Much of the time on linux the real auxv can be read from the file -// /proc/self/auxv, however there are several conditions under which -// Android apps cannot read this file (see a note to this effect in -// sources/android/cpufeatures/cpu-features.c). So we construct a -// fake one, working backwards from what the Go runtime wants to see -// as defined by the code in src/runtime/os_linux_GOARCH.c. -void build_auxv(uint32_t *auxv, size_t len); */ import "C" import ( @@ -73,6 +67,8 @@ import ( "golang.org/x/mobile/geom" ) +var running = make(chan struct{}) // closed after app.Run is called + //export callMain func callMain(mainPC uintptr) { for _, name := range []string{"TMPDIR", "PATH", "LD_LIBRARY_PATH"} { @@ -80,7 +76,9 @@ func callMain(mainPC uintptr) { os.Setenv(name, C.GoString(C.getenv(n))) C.free(unsafe.Pointer(n)) } - callfn.CallFn(mainPC) + go callfn.CallFn(mainPC) + <-running + log.Print("app.Run called") } //export onCreate @@ -265,13 +263,6 @@ func runStart(cb Callbacks) { // notifyInitDone informs Java that the program is initialized. // A NativeActivity will not create a window until this is called. -func notifyInitDone() { - C.pthread_mutex_lock(&C.go_started_mu) - C.go_started = 1 - C.pthread_cond_signal(&C.go_started_cond) - C.pthread_mutex_unlock(&C.go_started_mu) -} - func run(cb Callbacks) { // We want to keep the event loop on a consistent OS thread. runtime.LockOSThread() @@ -284,10 +275,10 @@ func run(cb Callbacks) { if C.current_native_activity == nil { runStart(cb) - notifyInitDone() + close(running) select {} } else { - notifyInitDone() + close(running) windowDrawLoop(cb, <-windowCreated, queue) } } diff --git a/app/android_arm.c b/app/android_arm.c deleted file mode 100644 index e9b9b21..0000000 --- a/app/android_arm.c +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build android,arm - -#include -#include -#include -#include "_cgo_export.h" - -#define AT_PLATFORM 15 -#define AT_HWCAP 16 -#define HWCAP_VFP (1 << 6) -#define HWCAP_VFPv3 (1 << 13) - -void build_auxv(uint32_t *auxv, size_t len) { - // Minimum auxv required by runtime/os_linux_arm.go. - int i; - if (len < 5) { - __android_log_print(ANDROID_LOG_FATAL, "Go", "auxv len %d too small", len); - } - auxv[0] = AT_PLATFORM; - *(char**)&auxv[1] = strdup("v7l"); - - auxv[2] = AT_HWCAP; - auxv[3] = HWCAP_VFP | HWCAP_VFPv3; - for (i = 4; i < len; i++) { - auxv[i] = 0; - } -} diff --git a/app/android_x86.c b/app/android_x86.c deleted file mode 100644 index 6393422..0000000 --- a/app/android_x86.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build android,x86 - -#include -#include -#include -#include -#include -#include -#include -#include "_cgo_export.h" - -void build_auxv(uint32_t *xauxv, size_t xauxv_len) { - char* auxv = (char*)xauxv; - size_t auxv_len = xauxv_len*sizeof(uint32_t); - - // TODO(crawshaw): determine if we can read /proc/self/auxv on - // x86 android release builds. - int fd = open("/proc/self/auxv", O_RDONLY, 0); - if (fd == -1) { - __android_log_print(ANDROID_LOG_FATAL, "Go", "cannot open /proc/self/auxv: %s", strerror(errno)); - } - int n = read(fd, &auxv, auxv_len); - if (n < 0) { - __android_log_print(ANDROID_LOG_FATAL, "Go", "error reading /proc/self/auxv: %s", strerror(errno)); - } - if (n == auxv_len) { // auxv should be more than plenty. - __android_log_print(ANDROID_LOG_FATAL, "Go", "/proc/self/auxv too big"); - } - close(fd); - - for (; n < auxv_len; n++) { - auxv[n] = 0; - } -} diff --git a/bind/java/seq_android.c b/bind/java/seq_android.c index 168f8f5..3bb45aa 100644 --- a/bind/java/seq_android.c +++ b/bind/java/seq_android.c @@ -188,9 +188,7 @@ void init_seq(void *javavm) { JNIEnv *env; int res = (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6); if (res == JNI_EDETACHED) { - JavaVMAttachArgs args; - args.version = JNI_VERSION_1_6; - if ((*vm)->AttachCurrentThread(vm, &env, &args) != 0) { + if ((*vm)->AttachCurrentThread(vm, &env, NULL) != 0) { LOG_FATAL("cannot attach to current_vm"); } } else if (res != 0) {