diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-08-07 21:30:22 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-08-07 21:30:22 +0000 |
commit | ca4439ff65bdc93fc44f4cc1be52aab50217ce78 (patch) | |
tree | 06578c5243a9c7b0c4c5dcb322ffb9a4609b5e7a | |
parent | f1184f963aea4cb16a5886c71cc662a0503e1cd5 (diff) | |
download | rockbox-ca4439ff65bdc93fc44f4cc1be52aab50217ce78.tar.gz rockbox-ca4439ff65bdc93fc44f4cc1be52aab50217ce78.zip |
Android port: handle incoming calls.
Stop explicitely if a call comes in, and resume playback (if it was playing before the call) upon hang up.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27746 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | android/src/org/rockbox/RockboxTimer.java | 28 | ||||
-rw-r--r-- | apps/menu.c | 13 | ||||
-rw-r--r-- | apps/misc.c | 19 | ||||
-rw-r--r-- | firmware/export/kernel.h | 2 | ||||
-rw-r--r-- | firmware/target/hosted/android/kernel-android.c | 24 |
5 files changed, 79 insertions, 7 deletions
diff --git a/android/src/org/rockbox/RockboxTimer.java b/android/src/org/rockbox/RockboxTimer.java index 6491e4ffe9..68a0e866fb 100644 --- a/android/src/org/rockbox/RockboxTimer.java +++ b/android/src/org/rockbox/RockboxTimer.java | |||
@@ -24,6 +24,8 @@ package org.rockbox; | |||
24 | import java.util.Timer; | 24 | import java.util.Timer; |
25 | import java.util.TimerTask; | 25 | import java.util.TimerTask; |
26 | 26 | ||
27 | import android.content.Context; | ||
28 | import android.telephony.TelephonyManager; | ||
27 | import android.util.Log; | 29 | import android.util.Log; |
28 | 30 | ||
29 | public class RockboxTimer extends Timer | 31 | public class RockboxTimer extends Timer |
@@ -33,24 +35,42 @@ public class RockboxTimer extends Timer | |||
33 | 35 | ||
34 | private class RockboxTimerTask extends TimerTask { | 36 | private class RockboxTimerTask extends TimerTask { |
35 | private RockboxTimer t; | 37 | private RockboxTimer t; |
36 | public RockboxTimerTask(RockboxTimer parent) { | 38 | private TelephonyManager tm; |
39 | private int last_state; | ||
40 | public RockboxTimerTask(RockboxService s, RockboxTimer parent) { | ||
37 | super(); | 41 | super(); |
38 | t = parent; | 42 | t = parent; |
43 | tm = (TelephonyManager)s.getSystemService(Context.TELEPHONY_SERVICE); | ||
44 | last_state = tm.getCallState(); | ||
39 | } | 45 | } |
40 | 46 | ||
41 | @Override | 47 | @Override |
42 | public void run() { | 48 | public void run() { |
43 | timerTask(); | 49 | timerTask(); |
50 | int state = tm.getCallState(); | ||
51 | if (state != last_state) | ||
52 | { | ||
53 | switch (state) { | ||
54 | case TelephonyManager.CALL_STATE_IDLE: | ||
55 | postCallHungUp(); | ||
56 | break; | ||
57 | case TelephonyManager.CALL_STATE_RINGING: | ||
58 | postCallIncoming(); | ||
59 | default: | ||
60 | break; | ||
61 | } | ||
62 | last_state = state; | ||
63 | } | ||
44 | synchronized(t) { | 64 | synchronized(t) { |
45 | t.notify(); | 65 | t.notify(); |
46 | } | 66 | } |
47 | } | 67 | } |
48 | } | 68 | } |
49 | 69 | ||
50 | public RockboxTimer(long period_inverval_in_ms) | 70 | public RockboxTimer(RockboxService instance, long period_inverval_in_ms) |
51 | { | 71 | { |
52 | super("tick timer", false); | 72 | super("tick timer", false); |
53 | task = new RockboxTimerTask(this); | 73 | task = new RockboxTimerTask(instance, this); |
54 | schedule(task, 0, period_inverval_in_ms); | 74 | schedule(task, 0, period_inverval_in_ms); |
55 | interval = period_inverval_in_ms; | 75 | interval = period_inverval_in_ms; |
56 | } | 76 | } |
@@ -75,4 +95,6 @@ public class RockboxTimer extends Timer | |||
75 | } | 95 | } |
76 | } | 96 | } |
77 | public native void timerTask(); | 97 | public native void timerTask(); |
98 | private native void postCallIncoming(); | ||
99 | private native void postCallHungUp(); | ||
78 | } | 100 | } |
diff --git a/apps/menu.c b/apps/menu.c index a88d725774..e6afec2d14 100644 --- a/apps/menu.c +++ b/apps/menu.c | |||
@@ -341,6 +341,7 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, | |||
341 | const struct menu_item_ex *temp, *menu; | 341 | const struct menu_item_ex *temp, *menu; |
342 | int ret = 0, i; | 342 | int ret = 0, i; |
343 | bool redraw_lists; | 343 | bool redraw_lists; |
344 | int old_audio_status = audio_status(); | ||
344 | FOR_NB_SCREENS(i) | 345 | FOR_NB_SCREENS(i) |
345 | viewportmanager_theme_enable(i, !hide_theme, NULL); | 346 | viewportmanager_theme_enable(i, !hide_theme, NULL); |
346 | 347 | ||
@@ -380,6 +381,7 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, | |||
380 | #endif | 381 | #endif |
381 | while (!done) | 382 | while (!done) |
382 | { | 383 | { |
384 | int new_old_audio_statusus; | ||
383 | redraw_lists = false; | 385 | redraw_lists = false; |
384 | if (!hide_theme) | 386 | if (!hide_theme) |
385 | { | 387 | { |
@@ -389,6 +391,15 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, | |||
389 | } | 391 | } |
390 | action = get_action(CONTEXT_MAINMENU, | 392 | action = get_action(CONTEXT_MAINMENU, |
391 | list_do_action_timeout(&lists, HZ)); | 393 | list_do_action_timeout(&lists, HZ)); |
394 | |||
395 | /* query audio status to see if it changed */ | ||
396 | new_old_audio_statusus = audio_status(); | ||
397 | if (old_audio_status != new_old_audio_statusus) | ||
398 | { /* force a redraw if anything changed the audio status | ||
399 | * from outside */ | ||
400 | redraw_lists = true; | ||
401 | old_audio_status = new_old_audio_statusus; | ||
402 | } | ||
392 | /* HZ so the status bar redraws corectly */ | 403 | /* HZ so the status bar redraws corectly */ |
393 | 404 | ||
394 | if (menu_callback) | 405 | if (menu_callback) |
@@ -410,8 +421,6 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, | |||
410 | 421 | ||
411 | if (gui_synclist_do_button(&lists, &action, LIST_WRAP_UNLESS_HELD)) | 422 | if (gui_synclist_do_button(&lists, &action, LIST_WRAP_UNLESS_HELD)) |
412 | continue; | 423 | continue; |
413 | if (action == ACTION_NONE) | ||
414 | continue; | ||
415 | #ifdef HAVE_QUICKSCREEN | 424 | #ifdef HAVE_QUICKSCREEN |
416 | else if (action == ACTION_STD_QUICKSCREEN) | 425 | else if (action == ACTION_STD_QUICKSCREEN) |
417 | { | 426 | { |
diff --git a/apps/misc.c b/apps/misc.c index ed6986180a..9fbdd433ef 100644 --- a/apps/misc.c +++ b/apps/misc.c | |||
@@ -517,6 +517,9 @@ static void unplug_change(bool inserted) | |||
517 | 517 | ||
518 | long default_event_handler_ex(long event, void (*callback)(void *), void *parameter) | 518 | long default_event_handler_ex(long event, void (*callback)(void *), void *parameter) |
519 | { | 519 | { |
520 | #if CONFIG_PLATFORM & PLATFORM_ANDROID | ||
521 | static bool resume = false; | ||
522 | #endif | ||
520 | switch(event) | 523 | switch(event) |
521 | { | 524 | { |
522 | case SYS_BATTERY_UPDATE: | 525 | case SYS_BATTERY_UPDATE: |
@@ -606,6 +609,22 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame | |||
606 | iap_handlepkt(); | 609 | iap_handlepkt(); |
607 | return SYS_IAP_HANDLEPKT; | 610 | return SYS_IAP_HANDLEPKT; |
608 | #endif | 611 | #endif |
612 | #if CONFIG_PLATFORM & PLATFORM_ANDROID | ||
613 | /* stop playback if we receive a call */ | ||
614 | case SYS_CALL_INCOMING: | ||
615 | resume = (audio_status() & AUDIO_STATUS_PLAY) != 0; | ||
616 | list_stop_handler(); | ||
617 | return SYS_CALL_INCOMING; | ||
618 | /* resume playback if needed */ | ||
619 | case SYS_CALL_HUNG_UP: | ||
620 | if (resume && playlist_resume() != -1) | ||
621 | { | ||
622 | playlist_start(global_status.resume_index, | ||
623 | global_status.resume_offset); | ||
624 | } | ||
625 | resume = false; | ||
626 | return SYS_CALL_HUNG_UP; | ||
627 | #endif | ||
609 | } | 628 | } |
610 | return 0; | 629 | return 0; |
611 | } | 630 | } |
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index 9ef5af8c0c..d256f31ab5 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h | |||
@@ -82,6 +82,8 @@ | |||
82 | #define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0) | 82 | #define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0) |
83 | #define SYS_IAP_PERIODIC MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 1) | 83 | #define SYS_IAP_PERIODIC MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 1) |
84 | #define SYS_IAP_HANDLEPKT MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 2) | 84 | #define SYS_IAP_HANDLEPKT MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 2) |
85 | #define SYS_CALL_INCOMING MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3) | ||
86 | #define SYS_CALL_HUNG_UP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 4) | ||
85 | 87 | ||
86 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) | 88 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) |
87 | 89 | ||
diff --git a/firmware/target/hosted/android/kernel-android.c b/firmware/target/hosted/android/kernel-android.c index 1a9b97b419..636c849c24 100644 --- a/firmware/target/hosted/android/kernel-android.c +++ b/firmware/target/hosted/android/kernel-android.c | |||
@@ -23,14 +23,17 @@ | |||
23 | #include <jni.h> | 23 | #include <jni.h> |
24 | #include "config.h" | 24 | #include "config.h" |
25 | #include "system.h" | 25 | #include "system.h" |
26 | #include "button.h" | ||
27 | #include "audio.h" | ||
26 | 28 | ||
27 | extern JNIEnv *env_ptr; | 29 | extern JNIEnv *env_ptr; |
28 | 30 | ||
31 | extern jobject RockboxService_instance; | ||
32 | |||
29 | static jclass RockboxTimer_class; | 33 | static jclass RockboxTimer_class; |
30 | static jobject RockboxTimer_instance; | 34 | static jobject RockboxTimer_instance; |
31 | static jmethodID java_wait_for_interrupt; | 35 | static jmethodID java_wait_for_interrupt; |
32 | static bool initialized = false; | 36 | static bool initialized = false; |
33 | |||
34 | /* | 37 | /* |
35 | * This is called from the separate Timer java thread. I have not added any | 38 | * This is called from the separate Timer java thread. I have not added any |
36 | * interrupt simulation to it (like the sdl counterpart does), | 39 | * interrupt simulation to it (like the sdl counterpart does), |
@@ -49,6 +52,22 @@ Java_org_rockbox_RockboxTimer_timerTask(JNIEnv *env, jobject this) | |||
49 | call_tick_tasks(); | 52 | call_tick_tasks(); |
50 | } | 53 | } |
51 | 54 | ||
55 | JNIEXPORT void JNICALL | ||
56 | Java_org_rockbox_RockboxTimer_postCallIncoming(JNIEnv *env, jobject this) | ||
57 | { | ||
58 | (void)env; | ||
59 | (void)this; | ||
60 | queue_broadcast(SYS_CALL_INCOMING, 0); | ||
61 | } | ||
62 | |||
63 | JNIEXPORT void JNICALL | ||
64 | Java_org_rockbox_RockboxTimer_postCallHungUp(JNIEnv *env, jobject this) | ||
65 | { | ||
66 | (void)env; | ||
67 | (void)this; | ||
68 | queue_broadcast(SYS_CALL_HUNG_UP, 0); | ||
69 | } | ||
70 | |||
52 | void tick_start(unsigned int interval_in_ms) | 71 | void tick_start(unsigned int interval_in_ms) |
53 | { | 72 | { |
54 | JNIEnv e = *env_ptr; | 73 | JNIEnv e = *env_ptr; |
@@ -57,11 +76,12 @@ void tick_start(unsigned int interval_in_ms) | |||
57 | jmethodID constructor = e->GetMethodID(env_ptr, | 76 | jmethodID constructor = e->GetMethodID(env_ptr, |
58 | RockboxTimer_class, | 77 | RockboxTimer_class, |
59 | "<init>", | 78 | "<init>", |
60 | "(J)V"); | 79 | "(Lorg/rockbox/RockboxService;J)V"); |
61 | /* the constructor will do the tick_start */ | 80 | /* the constructor will do the tick_start */ |
62 | RockboxTimer_instance = e->NewObject(env_ptr, | 81 | RockboxTimer_instance = e->NewObject(env_ptr, |
63 | RockboxTimer_class, | 82 | RockboxTimer_class, |
64 | constructor, | 83 | constructor, |
84 | RockboxService_instance, | ||
65 | (jlong)interval_in_ms); | 85 | (jlong)interval_in_ms); |
66 | 86 | ||
67 | /* get our wfi func also */ | 87 | /* get our wfi func also */ |