android: Add facility for java code to wait native code to be ready.

Especially when unzipping rockbox.zip, the native code can be initialized
a lot later than the java code. The java code needs to be prevented from
accessing rockbox structures (e.g. current_tick, event queues) before they're
ready.

This commit adds wait_rockbox_ready() and fixes dodgy behavior of starting
rockbox via widget play button, headset remote buttons or multimedia keys.
Also fixes wrong small list items before first redraw.

Change-Id: I1caf925e829a9c1c6bb6e0016d5c80574574c91e
This commit is contained in:
Thomas Martitz 2012-03-22 20:35:57 +01:00
parent b0df323391
commit 58e097d4a6
5 changed files with 62 additions and 2 deletions

View file

@ -81,6 +81,8 @@ Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jclass class,
button = dpad_to_button((int)keycode);
if (button)
{
/* ensure button_queue can be safely posted to */
wait_rockbox_ready();
reset_poweroff_timer();
queue_post(&button_queue, button, 0);
return true;
@ -121,6 +123,10 @@ void button_init_device(void)
e->NewObject(env_ptr, class,
constructor,
RockboxService_instance);
/* when reaching this point, rockbox can be considered ready because the
* input system (button.c) is initialized. This implies the kernel and threading
* is up and running */
set_rockbox_ready();
}
int button_read_device(int *data)

View file

@ -122,6 +122,9 @@ Java_org_rockbox_RockboxFramebuffer_surfaceCreated(JNIEnv *env, jobject this,
connect_with_java(env, this);
display_on = true;
/* need to wait for button_queue to be valid to post to */
wait_rockbox_ready();
send_event(LCD_EVENT_ACTIVATION, NULL);
/* Force an update, since the newly created surface is initially black
* waiting for the next normal update results in a longish black screen */

View file

@ -22,6 +22,7 @@
#include <setjmp.h>
#include <jni.h>
#include <pthread.h>
#include "config.h"
#include "system.h"
@ -95,3 +96,40 @@ Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this)
/* simply return here. this will allow the VM to clean up objects and do
* garbage collection */
}
/* below is the facility for external (from other java threads) to safely call
* into our snative code. When extracting rockbox.zip the main function is
* called only after extraction. This delay can be accounted for by calling
* wait_rockbox_ready(). This does not return until the critical parts of Rockbox
* can be considered up and running. */
static pthread_cond_t btn_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t btn_mtx = PTHREAD_MUTEX_INITIALIZER;
static bool initialized;
bool is_rockbox_ready(void)
{
/* don't bother with mutexes for this */
return initialized;
}
void wait_rockbox_ready(void)
{
pthread_mutex_lock(&btn_mtx);
if (!initialized)
pthread_cond_wait(&btn_cond, &btn_mtx);
pthread_mutex_unlock(&btn_mtx);
}
void set_rockbox_ready(void)
{
pthread_mutex_lock(&btn_mtx);
initialized = true;
/* now ready. signal all waiters */
pthread_cond_broadcast(&btn_cond);
pthread_mutex_unlock(&btn_mtx);
}

View file

@ -37,4 +37,11 @@ extern JNIEnv* getJavaEnvironment(void);
#endif /* __SYSTEM_TARGET_H__ */
/* facility function to check/wait for rockbox being ready, to be used
* by java calls into native that depend on Rockbox structures such as
* initialized kernel. */
bool is_rockbox_ready(void);
void wait_rockbox_ready(void);
void set_rockbox_ready(void);
#define NEED_GENERIC_BYTESWAPS

View file

@ -21,11 +21,15 @@
#include <jni.h>
#include "system.h"
#include "kernel.h"
extern JNIEnv *env_ptr;
extern jobject RockboxService_instance;
/* telephony_init_device() is currently called in system_init(). Thus, there is
* a small chance of the callbacks (and queue_broadcast) being called before
* the kernel is initialized (this happens after system_init(). */
void telephony_init_device(void)
{
@ -44,7 +48,8 @@ Java_org_rockbox_monitors_TelephonyMonitor_postCallIncoming(JNIEnv *env, jobject
{
(void)env;
(void)this;
queue_broadcast(SYS_CALL_INCOMING, 0);
if (is_rockbox_ready())
queue_broadcast(SYS_CALL_INCOMING, 0);
}
JNIEXPORT void JNICALL
@ -52,5 +57,6 @@ Java_org_rockbox_monitors_TelephonyMonitor_postCallHungUp(JNIEnv *env, jobject t
{
(void)env;
(void)this;
queue_broadcast(SYS_CALL_HUNG_UP, 0);
if (is_rockbox_ready())
queue_broadcast(SYS_CALL_HUNG_UP, 0);
}