summaryrefslogtreecommitdiff
path: root/android/src/org/rockbox/RockboxService.java
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-02-23 01:10:54 +0000
committerThomas Martitz <kugel@rockbox.org>2011-02-23 01:10:54 +0000
commit95e24dd7a54256e8df56e347c0f43133087a1df2 (patch)
tree677d66d4e72fedfe134bca103ed98b5792da1440 /android/src/org/rockbox/RockboxService.java
parentda3417706d927c7da0b59351fa8cc010d63d7928 (diff)
downloadrockbox-95e24dd7a54256e8df56e347c0f43133087a1df2.tar.gz
rockbox-95e24dd7a54256e8df56e347c0f43133087a1df2.zip
Android:
* Re-create RockboxFramebuffer instance with every time there's a new Activity. * Also, allow Rockbox to be started via multimedia buttons, immediately starting playback if wanted. We don't need to keep the fb instance around when it backround, and it makes us less depending on it and the activity (less race conditions). And this is how you usually do it in Android apps. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29384 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'android/src/org/rockbox/RockboxService.java')
-rw-r--r--android/src/org/rockbox/RockboxService.java113
1 files changed, 52 insertions, 61 deletions
diff --git a/android/src/org/rockbox/RockboxService.java b/android/src/org/rockbox/RockboxService.java
index 43d122a8cc..4f0caa7704 100644
--- a/android/src/org/rockbox/RockboxService.java
+++ b/android/src/org/rockbox/RockboxService.java
@@ -59,8 +59,7 @@ public class RockboxService extends Service
59 private static RockboxService instance = null; 59 private static RockboxService instance = null;
60 60
61 /* locals needed for the c code and rockbox state */ 61 /* locals needed for the c code and rockbox state */
62 private RockboxFramebuffer fb = null; 62 private static volatile boolean rockbox_running;
63 private volatile boolean rockbox_running;
64 private Activity current_activity = null; 63 private Activity current_activity = null;
65 private IntentFilter itf; 64 private IntentFilter itf;
66 private BroadcastReceiver batt_monitor; 65 private BroadcastReceiver batt_monitor;
@@ -69,11 +68,9 @@ public class RockboxService extends Service
69 @SuppressWarnings("unused") 68 @SuppressWarnings("unused")
70 private int battery_level; 69 private int battery_level;
71 private ResultReceiver resultReceiver; 70 private ResultReceiver resultReceiver;
72 final private Object lock = new Object();
73 71
74 public static final int RESULT_INVOKING_MAIN = 0; 72 public static final int RESULT_INVOKING_MAIN = 0;
75 public static final int RESULT_LIB_LOAD_PROGRESS = 1; 73 public static final int RESULT_LIB_LOAD_PROGRESS = 1;
76 public static final int RESULT_FB_INITIALIZED = 2;
77 public static final int RESULT_SERVICE_RUNNING = 3; 74 public static final int RESULT_SERVICE_RUNNING = 3;
78 public static final int RESULT_ERROR_OCCURED = 4; 75 public static final int RESULT_ERROR_OCCURED = 4;
79 public static final int RESULT_LIB_LOADED = 5; 76 public static final int RESULT_LIB_LOADED = 5;
@@ -88,14 +85,15 @@ public class RockboxService extends Service
88 85
89 public static RockboxService get_instance() 86 public static RockboxService get_instance()
90 { 87 {
88 /* don't call the construtor here, the instances are managed by
89 * android, so we can't just create a new one */
91 return instance; 90 return instance;
92 } 91 }
93 92
94 public RockboxFramebuffer get_fb() 93 public boolean isRockboxRunning()
95 { 94 {
96 return fb; 95 return rockbox_running;
97 } 96 }
98
99 public Activity get_activity() 97 public Activity get_activity()
100 { 98 {
101 return current_activity; 99 return current_activity;
@@ -108,71 +106,48 @@ public class RockboxService extends Service
108 private void do_start(Intent intent) 106 private void do_start(Intent intent)
109 { 107 {
110 LOG("Start Service"); 108 LOG("Start Service");
111
112 if (intent != null && intent.hasExtra("callback")) 109 if (intent != null && intent.hasExtra("callback"))
113 resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback"); 110 resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback");
114 111
115 /* Display a notification about us starting.
116 * We put an icon in the status bar. */
117 if (fg_runner == null)
118 { /* needs to be initialized before main() runs */
119 try {
120 } catch (Exception e) {
121 e.printStackTrace();
122 }
123 }
124
125 if (!rockbox_running) 112 if (!rockbox_running)
126 { 113 startservice();
127 synchronized(lock)
128 {
129 startservice();
130 while(true) {
131 try {
132 lock.wait();
133 } catch (InterruptedException e) {
134 continue;
135 }
136 break;
137 }
138 fb = new RockboxFramebuffer(this);
139 if (resultReceiver != null)
140 resultReceiver.send(RESULT_FB_INITIALIZED, null);
141 }
142 }
143 if (resultReceiver != null) 114 if (resultReceiver != null)
144 resultReceiver.send(RESULT_LIB_LOADED, null); 115 resultReceiver.send(RESULT_LIB_LOADED, null);
145 116
117
146 if (intent != null && intent.getAction() != null) 118 if (intent != null && intent.getAction() != null)
147 { 119 {
148 Log.d("RockboxService", intent.getAction()); 120 if (!rockbox_running)
149 if (intent.getAction().equals("org.rockbox.PlayPause")) 121 { /* give it a bit of time so we can register button presses
150 { 122 * sleeping longer doesn't work here, apparently Android
151 if (fb != null) 123 * surpresses long sleeps during intent handling */
152 fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, null); 124 try {
125 Thread.sleep(50);
126 }
127 catch (InterruptedException e) { }
153 } 128 }
154 else if (intent.getAction().equals("org.rockbox.Prev")) 129
130 if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON))
155 { 131 {
156 if (fb != null) 132 KeyEvent kev = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
157 fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_PREVIOUS, null); 133 RockboxFramebuffer.buttonHandler(kev.getKeyCode(), kev.getAction() == KeyEvent.ACTION_DOWN);
158 } 134 }
135 else if (intent.getAction().equals("org.rockbox.PlayPause"))
136 RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, false);
137 else if (intent.getAction().equals("org.rockbox.Prev"))
138 RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_PREVIOUS, false);
159 else if (intent.getAction().equals("org.rockbox.Next")) 139 else if (intent.getAction().equals("org.rockbox.Next"))
160 { 140 RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_NEXT, false);
161 if (fb != null)
162 fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_NEXT, null);
163 }
164 else if (intent.getAction().equals("org.rockbox.Stop")) 141 else if (intent.getAction().equals("org.rockbox.Stop"))
165 { 142 RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_STOP, false);
166 if (fb != null)
167 fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_STOP, null);
168 }
169 } 143 }
170 144
171 /* (Re-)attach the media button receiver, in case it has been lost */ 145 /* (Re-)attach the media button receiver, in case it has been lost */
172 mMediaButtonReceiver.register(); 146 mMediaButtonReceiver.register();
173
174 if (resultReceiver != null) 147 if (resultReceiver != null)
175 resultReceiver.send(RESULT_SERVICE_RUNNING, null); 148 resultReceiver.send(RESULT_SERVICE_RUNNING, null);
149
150 rockbox_running = true;
176 } 151 }
177 152
178 private void LOG(CharSequence text) 153 private void LOG(CharSequence text)
@@ -195,16 +170,23 @@ public class RockboxService extends Service
195 return 1; /* old API compatibility: 1 == START_STICKY */ 170 return 1; /* old API compatibility: 1 == START_STICKY */
196 } 171 }
197 172
198 private void startservice() 173 private void startservice()
199 { 174 {
200 final int BUFFER = 8*1024; 175 final Object lock = new Object();
201 Thread rb = new Thread(new Runnable() 176 Thread rb = new Thread(new Runnable()
202 { 177 {
203 public void run() 178 public void run()
204 { 179 {
180 final int BUFFER = 8*1024;
205 String rockboxDirPath = "/data/data/org.rockbox/app_rockbox/rockbox"; 181 String rockboxDirPath = "/data/data/org.rockbox/app_rockbox/rockbox";
206 File rockboxDir = new File(rockboxDirPath); 182 File rockboxDir = new File(rockboxDirPath);
207 183
184 /* load library before unzipping which may take a while */
185 synchronized (lock) {
186 System.loadLibrary("rockbox");
187 lock.notify();
188 }
189
208 /* the following block unzips libmisc.so, which contains the files 190 /* the following block unzips libmisc.so, which contains the files
209 * we ship, such as themes. It's needed to put it into a .so file 191 * we ship, such as themes. It's needed to put it into a .so file
210 * because there's no other way to ship files and have access 192 * because there's no other way to ship files and have access
@@ -268,13 +250,7 @@ public class RockboxService extends Service
268 } 250 }
269 } 251 }
270 } 252 }
271
272 synchronized (lock) {
273 System.loadLibrary("rockbox");
274 lock.notify();
275 }
276 253
277 rockbox_running = true;
278 if (resultReceiver != null) 254 if (resultReceiver != null)
279 resultReceiver.send(RESULT_INVOKING_MAIN, null); 255 resultReceiver.send(RESULT_INVOKING_MAIN, null);
280 256
@@ -283,7 +259,20 @@ public class RockboxService extends Service
283 } 259 }
284 }, "Rockbox thread"); 260 }, "Rockbox thread");
285 rb.setDaemon(false); 261 rb.setDaemon(false);
286 rb.start(); 262 /* wait at least until the library is loaded */
263 synchronized (lock)
264 {
265 rb.start();
266 while(true)
267 {
268 try {
269 lock.wait();
270 } catch (InterruptedException e) {
271 continue;
272 }
273 break;
274 }
275 }
287 } 276 }
288 277
289 private native void main(); 278 private native void main();
@@ -352,5 +341,7 @@ public class RockboxService extends Service
352 mMediaButtonReceiver = null; 341 mMediaButtonReceiver = null;
353 /* Make sure our notification is gone. */ 342 /* Make sure our notification is gone. */
354 stopForeground(); 343 stopForeground();
344 instance = null;
345 rockbox_running = false;
355 } 346 }
356} 347}