summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2012-03-22 20:35:57 +0100
committerThomas Martitz <kugel@rockbox.org>2012-03-22 20:44:52 +0100
commit58e097d4a6c64bf762a8c30e24f16cc62c574519 (patch)
tree16f8135f9ced2e8cd815ff68024b6ef3f237e388
parentb0df3233917c51049a380f04b909f061de828972 (diff)
downloadrockbox-58e097d4a6c64bf762a8c30e24f16cc62c574519.tar.gz
rockbox-58e097d4a6c64bf762a8c30e24f16cc62c574519.tar.bz2
rockbox-58e097d4a6c64bf762a8c30e24f16cc62c574519.zip
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
-rw-r--r--firmware/target/hosted/android/button-android.c6
-rw-r--r--firmware/target/hosted/android/lcd-android.c3
-rw-r--r--firmware/target/hosted/android/system-android.c38
-rw-r--r--firmware/target/hosted/android/system-target.h7
-rw-r--r--firmware/target/hosted/android/telephony-android.c10
5 files changed, 62 insertions, 2 deletions
diff --git a/firmware/target/hosted/android/button-android.c b/firmware/target/hosted/android/button-android.c
index 406d37d25b..ee8b32d704 100644
--- a/firmware/target/hosted/android/button-android.c
+++ b/firmware/target/hosted/android/button-android.c
@@ -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)
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c
index 4e4ea66268..15c844bbd6 100644
--- a/firmware/target/hosted/android/lcd-android.c
+++ b/firmware/target/hosted/android/lcd-android.c
@@ -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 */
diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c
index b3c4cdccb5..614d89bfd1 100644
--- a/firmware/target/hosted/android/system-android.c
+++ b/firmware/target/hosted/android/system-android.c
@@ -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);
+}
diff --git a/firmware/target/hosted/android/system-target.h b/firmware/target/hosted/android/system-target.h
index fd81b6661e..455fcc95fa 100644
--- a/firmware/target/hosted/android/system-target.h
+++ b/firmware/target/hosted/android/system-target.h
@@ -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
diff --git a/firmware/target/hosted/android/telephony-android.c b/firmware/target/hosted/android/telephony-android.c
index df89a56e14..63f0f05e39 100644
--- a/firmware/target/hosted/android/telephony-android.c
+++ b/firmware/target/hosted/android/telephony-android.c
@@ -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);
}