diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-11-12 21:04:13 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-11-12 21:04:13 +0000 |
commit | 0cf2cc1607a0844e906042173815451cd9c2ff58 (patch) | |
tree | 77c555919d5c08f9a54f2b28cababe1d2d207f7e | |
parent | bb56bc4ba08bf6c6458a289ef4918dfaea30b238 (diff) | |
download | rockbox-0cf2cc1607a0844e906042173815451cd9c2ff58.tar.gz rockbox-0cf2cc1607a0844e906042173815451cd9c2ff58.zip |
Android: Change how detecting call state (introduced in r27746) works, from polling to event based.
* For some reason, the polling methid is much more inefficient than I thought. According to htop it caused up to 15% CPU load on some phones (e.g. Galaxy S).
The event based causes no CPU load.
Rockbox' idle CPU load is now back to 0%, while it was previously dominated by polling the call state.
* Also stop on outgoing calls (no need to explicitely pause for making a call anymore).
* Factor out the detection mechanism to separate files.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28564 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | android/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxTelephony.java | 97 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxTimer.java | 35 | ||||
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/target/hosted/android/kernel-android.c | 18 | ||||
-rw-r--r-- | firmware/target/hosted/android/system-android.c | 22 | ||||
-rw-r--r-- | firmware/target/hosted/android/telephony-android.c | 54 |
7 files changed, 174 insertions, 56 deletions
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index e0fc106ca7..0eab90ff81 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml | |||
@@ -29,9 +29,10 @@ | |||
29 | </intent-filter> | 29 | </intent-filter> |
30 | </receiver> | 30 | </receiver> |
31 | 31 | ||
32 | |||
32 | </application> | 33 | </application> |
33 | 34 | ||
34 | <uses-sdk android:minSdkVersion="4" /> | 35 | <uses-sdk android:minSdkVersion="4" /> |
35 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> | 36 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> |
36 | 37 | <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> | |
37 | </manifest> | 38 | </manifest> |
diff --git a/android/src/org/rockbox/RockboxTelephony.java b/android/src/org/rockbox/RockboxTelephony.java new file mode 100644 index 0000000000..faaf0c36b7 --- /dev/null +++ b/android/src/org/rockbox/RockboxTelephony.java | |||
@@ -0,0 +1,97 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | package org.rockbox; | ||
23 | |||
24 | import android.content.Context; | ||
25 | import android.os.Handler; | ||
26 | import android.telephony.PhoneStateListener; | ||
27 | import android.telephony.TelephonyManager; | ||
28 | |||
29 | public class RockboxTelephony | ||
30 | { | ||
31 | public RockboxTelephony(Context c) | ||
32 | { | ||
33 | final Handler handler = new Handler(c.getMainLooper()); | ||
34 | final TelephonyManager tm = (TelephonyManager) | ||
35 | c.getSystemService(Context.TELEPHONY_SERVICE); | ||
36 | handler.post(new Runnable() | ||
37 | { | ||
38 | @Override | ||
39 | public void run() | ||
40 | { /* need to instantiate from a thread that has a Looper */ | ||
41 | tm.listen(new RockboxCallStateListener(), PhoneStateListener.LISTEN_CALL_STATE); | ||
42 | } | ||
43 | }); | ||
44 | } | ||
45 | |||
46 | private class RockboxCallStateListener extends PhoneStateListener | ||
47 | { | ||
48 | private int last_state; | ||
49 | |||
50 | public RockboxCallStateListener() | ||
51 | { | ||
52 | super(); | ||
53 | /* set artificial initial state, | ||
54 | * we will get an initial event shortly after this, | ||
55 | * so to handle it correctly we need an invalid state set */ | ||
56 | last_state = TelephonyManager.CALL_STATE_IDLE - 10; | ||
57 | } | ||
58 | |||
59 | private void handleState(int state) | ||
60 | { | ||
61 | if (state == last_state) | ||
62 | return; | ||
63 | switch (state) | ||
64 | { | ||
65 | case TelephonyManager.CALL_STATE_IDLE: | ||
66 | postCallHungUp(); | ||
67 | break; | ||
68 | case TelephonyManager.CALL_STATE_RINGING: | ||
69 | postCallIncoming(); | ||
70 | break; | ||
71 | case TelephonyManager.CALL_STATE_OFFHOOK: | ||
72 | /* for incoming calls we handled at RINGING already, | ||
73 | * if the previous state was IDLE then | ||
74 | * this is an outgoing call | ||
75 | */ | ||
76 | if (last_state == TelephonyManager.CALL_STATE_IDLE) | ||
77 | { /* currently handled the same as incoming calls */ | ||
78 | postCallIncoming(); | ||
79 | } | ||
80 | break; | ||
81 | default: | ||
82 | return; | ||
83 | } | ||
84 | last_state = state; | ||
85 | |||
86 | } | ||
87 | |||
88 | @Override | ||
89 | public void onCallStateChanged(int state, String number) | ||
90 | { | ||
91 | super.onCallStateChanged(state, number); | ||
92 | handleState(state); | ||
93 | } | ||
94 | } | ||
95 | private native void postCallIncoming(); | ||
96 | private native void postCallHungUp(); | ||
97 | } | ||
diff --git a/android/src/org/rockbox/RockboxTimer.java b/android/src/org/rockbox/RockboxTimer.java index 776902e45e..ff48b3f53a 100644 --- a/android/src/org/rockbox/RockboxTimer.java +++ b/android/src/org/rockbox/RockboxTimer.java | |||
@@ -25,57 +25,32 @@ import java.util.Timer; | |||
25 | import java.util.TimerTask; | 25 | import java.util.TimerTask; |
26 | 26 | ||
27 | import android.content.Context; | 27 | import android.content.Context; |
28 | import android.telephony.TelephonyManager; | ||
29 | import android.util.Log; | 28 | import android.util.Log; |
30 | 29 | ||
31 | public class RockboxTimer extends Timer | 30 | public class RockboxTimer extends Timer |
32 | { | 31 | { |
33 | RockboxTimerTask task; | ||
34 | long interval; | ||
35 | |||
36 | private class RockboxTimerTask extends TimerTask { | 32 | private class RockboxTimerTask extends TimerTask { |
37 | private RockboxTimer timer; | 33 | private RockboxTimer timer; |
38 | private TelephonyManager tm; | 34 | public RockboxTimerTask(RockboxTimer parent) |
39 | private int last_state; | ||
40 | public RockboxTimerTask(RockboxService s, RockboxTimer parent) | ||
41 | { | 35 | { |
42 | super(); | 36 | super(); |
43 | timer = parent; | 37 | timer = parent; |
44 | tm = (TelephonyManager)s.getSystemService(Context.TELEPHONY_SERVICE); | ||
45 | last_state = tm.getCallState(); | ||
46 | } | 38 | } |
47 | 39 | ||
48 | @Override | 40 | @Override |
49 | public void run() | 41 | public void run() |
50 | { | 42 | { |
51 | timerTask(); | 43 | timerTask(); |
52 | int state = tm.getCallState(); | ||
53 | if (state != last_state) | ||
54 | { | ||
55 | switch (state) | ||
56 | { | ||
57 | case TelephonyManager.CALL_STATE_IDLE: | ||
58 | postCallHungUp(); | ||
59 | break; | ||
60 | case TelephonyManager.CALL_STATE_RINGING: | ||
61 | postCallIncoming(); | ||
62 | default: | ||
63 | break; | ||
64 | } | ||
65 | last_state = state; | ||
66 | } | ||
67 | synchronized(timer) { | 44 | synchronized(timer) { |
68 | timer.notify(); | 45 | timer.notify(); |
69 | } | 46 | } |
70 | } | 47 | } |
71 | } | 48 | } |
72 | 49 | ||
73 | public RockboxTimer(RockboxService instance, long period_inverval_in_ms) | 50 | public RockboxTimer(Context c, long period_inverval_in_ms) |
74 | { | 51 | { |
75 | super("tick timer"); | 52 | super("tick timer"); |
76 | task = new RockboxTimerTask(instance, this); | 53 | schedule(new RockboxTimerTask(this), 0, period_inverval_in_ms); |
77 | schedule(task, 0, period_inverval_in_ms); | ||
78 | interval = period_inverval_in_ms; | ||
79 | } | 54 | } |
80 | 55 | ||
81 | @SuppressWarnings("unused") | 56 | @SuppressWarnings("unused") |
@@ -98,6 +73,4 @@ public class RockboxTimer extends Timer | |||
98 | } | 73 | } |
99 | } | 74 | } |
100 | public native void timerTask(); | 75 | public native void timerTask(); |
101 | private native void postCallIncoming(); | ||
102 | private native void postCallHungUp(); | ||
103 | } | 76 | } |
diff --git a/firmware/SOURCES b/firmware/SOURCES index c2df946394..29dc8644ee 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -1714,6 +1714,7 @@ target/hosted/android/kernel-android.c | |||
1714 | target/hosted/android/pcm-android.c | 1714 | target/hosted/android/pcm-android.c |
1715 | target/hosted/android/powermgmt-android.c | 1715 | target/hosted/android/powermgmt-android.c |
1716 | target/hosted/android/system-android.c | 1716 | target/hosted/android/system-android.c |
1717 | target/hosted/android/telephony-android.c | ||
1717 | #ifdef APPLICATION | 1718 | #ifdef APPLICATION |
1718 | target/hosted/android/app/button-application.c | 1719 | target/hosted/android/app/button-application.c |
1719 | #endif | 1720 | #endif |
diff --git a/firmware/target/hosted/android/kernel-android.c b/firmware/target/hosted/android/kernel-android.c index 636c849c24..c0d927d026 100644 --- a/firmware/target/hosted/android/kernel-android.c +++ b/firmware/target/hosted/android/kernel-android.c | |||
@@ -52,22 +52,6 @@ Java_org_rockbox_RockboxTimer_timerTask(JNIEnv *env, jobject this) | |||
52 | call_tick_tasks(); | 52 | call_tick_tasks(); |
53 | } | 53 | } |
54 | 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 | |||
71 | void tick_start(unsigned int interval_in_ms) | 55 | void tick_start(unsigned int interval_in_ms) |
72 | { | 56 | { |
73 | JNIEnv e = *env_ptr; | 57 | JNIEnv e = *env_ptr; |
@@ -76,7 +60,7 @@ void tick_start(unsigned int interval_in_ms) | |||
76 | jmethodID constructor = e->GetMethodID(env_ptr, | 60 | jmethodID constructor = e->GetMethodID(env_ptr, |
77 | RockboxTimer_class, | 61 | RockboxTimer_class, |
78 | "<init>", | 62 | "<init>", |
79 | "(Lorg/rockbox/RockboxService;J)V"); | 63 | "(Landroid/content/Context;J)V"); |
80 | /* the constructor will do the tick_start */ | 64 | /* the constructor will do the tick_start */ |
81 | RockboxTimer_instance = e->NewObject(env_ptr, | 65 | RockboxTimer_instance = e->NewObject(env_ptr, |
82 | RockboxTimer_class, | 66 | RockboxTimer_class, |
diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c index 7d1fe9d458..009630eeaa 100644 --- a/firmware/target/hosted/android/system-android.c +++ b/firmware/target/hosted/android/system-android.c | |||
@@ -24,10 +24,6 @@ | |||
24 | #include "config.h" | 24 | #include "config.h" |
25 | #include "system.h" | 25 | #include "system.h" |
26 | 26 | ||
27 | void system_exception_wait(void) { } | ||
28 | void system_reboot(void) { } | ||
29 | void power_off(void) { } | ||
30 | void system_init(void) { } | ||
31 | 27 | ||
32 | 28 | ||
33 | /* global fields for use with various JNI calls */ | 29 | /* global fields for use with various JNI calls */ |
@@ -40,6 +36,21 @@ uintptr_t *stackend; | |||
40 | 36 | ||
41 | extern int main(void); | 37 | extern int main(void); |
42 | extern void powermgmt_init_target(void); | 38 | extern void powermgmt_init_target(void); |
39 | extern void telephony_init_device(void); | ||
40 | |||
41 | void system_exception_wait(void) { } | ||
42 | void system_reboot(void) { } | ||
43 | void power_off(void) { } | ||
44 | |||
45 | void system_init(void) | ||
46 | { | ||
47 | /* no better place yet, most of powermgmt.c is #ifdef'd out for non-native | ||
48 | * builds */ | ||
49 | powermgmt_init_target(); | ||
50 | /* also no better place yet */ | ||
51 | telephony_init_device(); | ||
52 | } | ||
53 | |||
43 | /* this is the entry point of the android app initially called by jni */ | 54 | /* this is the entry point of the android app initially called by jni */ |
44 | JNIEXPORT void JNICALL | 55 | JNIEXPORT void JNICALL |
45 | Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this) | 56 | Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this) |
@@ -57,8 +68,5 @@ Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this) | |||
57 | RockboxService_instance = this; | 68 | RockboxService_instance = this; |
58 | RockboxService_class = (*env)->GetObjectClass(env, this); | 69 | RockboxService_class = (*env)->GetObjectClass(env, this); |
59 | 70 | ||
60 | /* no better place yet, most of powermgmt.c is #ifdef'd out for non-native | ||
61 | * builds */ | ||
62 | powermgmt_init_target(); | ||
63 | main(); | 71 | main(); |
64 | } | 72 | } |
diff --git a/firmware/target/hosted/android/telephony-android.c b/firmware/target/hosted/android/telephony-android.c new file mode 100644 index 0000000000..771b7a973a --- /dev/null +++ b/firmware/target/hosted/android/telephony-android.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 by Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #include <jni.h> | ||
24 | #include "kernel.h" | ||
25 | |||
26 | extern JNIEnv *env_ptr; | ||
27 | extern RockboxService_instance; | ||
28 | |||
29 | |||
30 | void telephony_init_device(void) | ||
31 | { | ||
32 | JNIEnv e = *env_ptr; | ||
33 | jclass class = e->FindClass(env_ptr, "org/rockbox/RockboxTelephony"); | ||
34 | jmethodID constructor = e->GetMethodID(env_ptr, class, "<init>", "(Landroid/content/Context;)V"); | ||
35 | |||
36 | e->NewObject(env_ptr, class, constructor, RockboxService_instance); | ||
37 | } | ||
38 | |||
39 | |||
40 | JNIEXPORT void JNICALL | ||
41 | Java_org_rockbox_RockboxTelephony_postCallIncoming(JNIEnv *env, jobject this) | ||
42 | { | ||
43 | (void)env; | ||
44 | (void)this; | ||
45 | queue_broadcast(SYS_CALL_INCOMING, 0); | ||
46 | } | ||
47 | |||
48 | JNIEXPORT void JNICALL | ||
49 | Java_org_rockbox_RockboxTelephony_postCallHungUp(JNIEnv *env, jobject this) | ||
50 | { | ||
51 | (void)env; | ||
52 | (void)this; | ||
53 | queue_broadcast(SYS_CALL_HUNG_UP, 0); | ||
54 | } | ||