diff --git a/apps/hosted/android/keyboard.c b/apps/hosted/android/keyboard.c index 9407d970fd..7c16cff079 100644 --- a/apps/hosted/android/keyboard.c +++ b/apps/hosted/android/keyboard.c @@ -59,14 +59,17 @@ static void kdb_init(void) { semaphore_init(&kbd_wakeup, 1, 0); /* get the class and its constructor */ - RockboxKeyboardInput_class = e->FindClass(env_ptr, + jclass kbInput_class = e->FindClass(env_ptr, "org/rockbox/RockboxKeyboardInput"); + RockboxKeyboardInput_class = e->NewGlobalRef(env_ptr, kbInput_class); jmethodID constructor = e->GetMethodID(env_ptr, RockboxKeyboardInput_class, "", "()V"); - RockboxKeyboardInput_instance = e->NewObject(env_ptr, - RockboxKeyboardInput_class, - constructor); + jobject kbInput_instance = e->NewObject(env_ptr, + RockboxKeyboardInput_class, + constructor); + RockboxKeyboardInput_instance = e->NewGlobalRef(env_ptr, + kbInput_instance); kbd_inputfunc = e->GetMethodID(env_ptr, RockboxKeyboardInput_class, "kbd_input", "(Ljava/lang/String;" diff --git a/apps/hosted/android/notification.c b/apps/hosted/android/notification.c index 443200698c..33a7717012 100644 --- a/apps/hosted/android/notification.c +++ b/apps/hosted/android/notification.c @@ -125,13 +125,14 @@ void notification_init(void) JNIEnv e = *env_ptr; jfieldID nNM = e->GetFieldID(env_ptr, RockboxService_class, "fg_runner", "Lorg/rockbox/Helper/RunForegroundManager;"); - NotificationManager_instance = e->GetObjectField(env_ptr, - RockboxService_instance, nNM); - if (NotificationManager_instance == NULL) + jobject nMN_instance = e->GetObjectField(env_ptr, + RockboxService_instance, nNM); + if (nMN_instance == NULL) { DEBUGF("Failed to get RunForegroundManager instance. Performance will be bad"); return; } + NotificationManager_instance = e->NewGlobalRef(env_ptr, nMN_instance); jclass class = e->GetObjectClass(env_ptr, NotificationManager_instance); updateNotification = e->GetMethodID(env_ptr, class, "updateNotification", diff --git a/apps/hosted/android/yesno.c b/apps/hosted/android/yesno.c index a1de64e3f9..7aca3f7f79 100644 --- a/apps/hosted/android/yesno.c +++ b/apps/hosted/android/yesno.c @@ -30,7 +30,6 @@ #include "kernel.h" extern JNIEnv *env_ptr; -static jclass RockboxYesno_class = NULL; static jobject RockboxYesno_instance = NULL; static jmethodID yesno_func; static struct semaphore yesno_done; @@ -49,24 +48,25 @@ static void yesno_init(void) { JNIEnv e = *env_ptr; static jmethodID yesno_is_usable; - if (RockboxYesno_class == NULL) + if (RockboxYesno_instance == NULL) { semaphore_init(&yesno_done, 1, 0); /* get the class and its constructor */ - RockboxYesno_class = e->FindClass(env_ptr, - "org/rockbox/RockboxYesno"); + jclass yesno_class = e->FindClass(env_ptr, + "org/rockbox/RockboxYesno"); jmethodID constructor = e->GetMethodID(env_ptr, - RockboxYesno_class, + yesno_class, "", "()V"); - RockboxYesno_instance = e->NewObject(env_ptr, - RockboxYesno_class, - constructor); - yesno_func = e->GetMethodID(env_ptr, RockboxYesno_class, + jobject yesno_instance = e->NewObject(env_ptr, + yesno_class, + constructor); + RockboxYesno_instance = e->NewGlobalRef(env_ptr, yesno_instance); + yesno_func = e->GetMethodID(env_ptr, yesno_class, "yesno_display", "(Ljava/lang/String;" "Ljava/lang/String;" "Ljava/lang/String;)V"); - yesno_is_usable = e->GetMethodID(env_ptr, RockboxYesno_class, + yesno_is_usable = e->GetMethodID(env_ptr, yesno_class, "is_usable", "()Z"); } /* need to get it every time incase the activity died/restarted */ diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c index 0cde160e65..08a4075795 100644 --- a/firmware/target/hosted/android/lcd-android.c +++ b/firmware/target/hosted/android/lcd-android.c @@ -47,8 +47,16 @@ static bool display_on; void connect_with_java(JNIEnv* env, jobject fb_instance) { JNIEnv e = *env; - static bool have_class; - RockboxFramebuffer_instance = fb_instance; + + /* Update RockboxFramebuffer_instance */ + if (!e->IsSameObject(env, RockboxFramebuffer_instance, fb_instance)) { + if (RockboxFramebuffer_instance != NULL) + e->DeleteGlobalRef(env, RockboxFramebuffer_instance); + + RockboxFramebuffer_instance = e->NewGlobalRef(env, fb_instance); + } + + static bool have_class = false; if (!have_class) { jclass fb_class = e->GetObjectClass(env, fb_instance); @@ -70,10 +78,13 @@ void connect_with_java(JNIEnv* env, jobject fb_instance) java_lcd_init = e->GetMethodID(env, fb_class, "java_lcd_init", "(IILjava/nio/ByteBuffer;)V"); - - native_buffer = e->NewDirectByteBuffer(env, + + jobject buffer = e->NewDirectByteBuffer(env, lcd_framebuffer, (jlong)sizeof(lcd_framebuffer)); + + native_buffer = e->NewGlobalRef(env, buffer); + have_class = true; } /* we need to setup parts for the java object every time */ @@ -81,6 +92,12 @@ void connect_with_java(JNIEnv* env, jobject fb_instance) (jint)LCD_WIDTH, (jint)LCD_HEIGHT, native_buffer); } +void lcd_deinit(void) +{ + (*env_ptr)->DeleteGlobalRef(env_ptr, RockboxFramebuffer_instance); + (*env_ptr)->DeleteGlobalRef(env_ptr, native_buffer); +} + /* * Do nothing here and connect with the java object later (if it isn't already) */ diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c index c8bc410a54..f4ed4b1b33 100644 --- a/firmware/target/hosted/android/pcm-android.c +++ b/firmware/target/hosted/android/pcm-android.c @@ -35,7 +35,6 @@ static char *pcm_data_start; static jmethodID play_pause_method; static jmethodID stop_method; static jmethodID set_volume_method; -static jclass RockboxPCM_class; static jobject RockboxPCM_instance; @@ -155,10 +154,11 @@ void pcm_play_dma_init(void) **/ JNIEnv e = *env_ptr; /* get the class and its constructor */ - RockboxPCM_class = e->FindClass(env_ptr, "org/rockbox/RockboxPCM"); + jclass RockboxPCM_class = e->FindClass(env_ptr, "org/rockbox/RockboxPCM"); jmethodID constructor = e->GetMethodID(env_ptr, RockboxPCM_class, "", "()V"); /* instance = new RockboxPCM() */ - RockboxPCM_instance = e->NewObject(env_ptr, RockboxPCM_class, constructor); + jobject PCM_instance = e->NewObject(env_ptr, RockboxPCM_class, constructor); + RockboxPCM_instance = e->NewGlobalRef(env_ptr, PCM_instance); /* cache needed methods */ play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V"); set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V"); @@ -167,6 +167,11 @@ void pcm_play_dma_init(void) pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size); } +void pcm_deinit(void) +{ + (*env_ptr)->DeleteGlobalRef(env_ptr, RockboxPCM_instance); +} + void pcm_postinit(void) { } diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c index 92c2d7cf5d..66de4e0ebb 100644 --- a/firmware/target/hosted/android/system-android.c +++ b/firmware/target/hosted/android/system-android.c @@ -36,10 +36,18 @@ uintptr_t *stackend; extern int main(void); extern void telephony_init_device(void); +extern void lcd_deinit(void); +extern void pcm_deinit(void); void system_exception_wait(void) { } void system_reboot(void) { } -void power_off(void) { } + +void power_off(void) +{ + lcd_deinit(); + pcm_deinit(); + (*env_ptr)->DeleteGlobalRef(env_ptr, RockboxService_class); +} void system_init(void) { @@ -51,18 +59,19 @@ void system_init(void) JNIEXPORT void JNICALL Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this) { + jclass class = (*env)->GetObjectClass(env, this); + /* hack!!! we can't have a valid stack pointer otherwise. * but we don't really need it anyway, thread.c only needs it * for overflow detection which doesn't apply for the main thread * (it's managed by the OS) */ - (void)env; - (void)this; volatile uintptr_t stack = 0; stackbegin = stackend = (uintptr_t*) &stack; env_ptr = env; - RockboxService_instance = this; - RockboxService_class = (*env)->GetObjectClass(env, this); + + RockboxService_instance = (*env)->NewGlobalRef(env, this); + RockboxService_class = (*env)->NewGlobalRef(env, class); main(); }