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:
parent
b0df323391
commit
58e097d4a6
5 changed files with 62 additions and 2 deletions
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue