summaryrefslogtreecommitdiff
path: root/android/src/org
diff options
context:
space:
mode:
Diffstat (limited to 'android/src/org')
-rw-r--r--android/src/org/rockbox/Helper/MediaButtonReceiver.java17
-rw-r--r--android/src/org/rockbox/RockboxActivity.java31
-rw-r--r--android/src/org/rockbox/RockboxFramebuffer.java2
-rw-r--r--android/src/org/rockbox/RockboxService.java113
4 files changed, 69 insertions, 94 deletions
diff --git a/android/src/org/rockbox/Helper/MediaButtonReceiver.java b/android/src/org/rockbox/Helper/MediaButtonReceiver.java
index 3749cec32a..a57bdd4831 100644
--- a/android/src/org/rockbox/Helper/MediaButtonReceiver.java
+++ b/android/src/org/rockbox/Helper/MediaButtonReceiver.java
@@ -22,9 +22,8 @@
22package org.rockbox.Helper; 22package org.rockbox.Helper;
23 23
24import java.lang.reflect.Method; 24import java.lang.reflect.Method;
25 25import org.rockbox.RockboxFramebuffer;
26import org.rockbox.RockboxService; 26import org.rockbox.RockboxService;
27
28import android.content.BroadcastReceiver; 27import android.content.BroadcastReceiver;
29import android.content.ComponentName; 28import android.content.ComponentName;
30import android.content.Context; 29import android.content.Context;
@@ -73,7 +72,12 @@ public class MediaButtonReceiver
73 72
74 /* helper class for the manifest */ 73 /* helper class for the manifest */
75 public static class MediaReceiver extends BroadcastReceiver 74 public static class MediaReceiver extends BroadcastReceiver
76 { 75 {
76 private void startService(Context c, Intent baseIntent)
77 {
78 baseIntent.setClass(c, RockboxService.class);
79 c.startService(baseIntent);
80 }
77 @Override 81 @Override
78 public void onReceive(Context context, Intent intent) 82 public void onReceive(Context context, Intent intent)
79 { 83 {
@@ -81,8 +85,11 @@ public class MediaButtonReceiver
81 { 85 {
82 KeyEvent key = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); 86 KeyEvent key = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
83 if (key.getAction() == KeyEvent.ACTION_UP) 87 if (key.getAction() == KeyEvent.ACTION_UP)
84 { /* pass the pressed key to Rockbox */ 88 { /* pass the pressed key to Rockbox, starting it if needed */
85 if (RockboxService.get_instance().get_fb().dispatchKeyEvent(key)) 89 RockboxService s = RockboxService.get_instance();
90 if (s == null || !s.isRockboxRunning())
91 startService(context, intent);
92 else if (RockboxFramebuffer.buttonHandler(key.getKeyCode(), false))
86 abortBroadcast(); 93 abortBroadcast();
87 } 94 }
88 } 95 }
diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java
index 90c687f35a..65c7f92bbe 100644
--- a/android/src/org/rockbox/RockboxActivity.java
+++ b/android/src/org/rockbox/RockboxActivity.java
@@ -29,16 +29,12 @@ import android.os.Bundle;
29import android.os.Handler; 29import android.os.Handler;
30import android.os.ResultReceiver; 30import android.os.ResultReceiver;
31import android.util.Log; 31import android.util.Log;
32import android.view.View;
33import android.view.ViewGroup;
34import android.view.Window; 32import android.view.Window;
35import android.view.WindowManager; 33import android.view.WindowManager;
36import android.widget.Toast; 34import android.widget.Toast;
37 35
38public class RockboxActivity extends Activity 36public class RockboxActivity extends Activity
39{ 37{
40 private RockboxService rbservice;
41
42 /** Called when the activity is first created. */ 38 /** Called when the activity is first created. */
43 @Override 39 @Override
44 public void onCreate(Bundle savedInstanceState) 40 public void onCreate(Bundle savedInstanceState)
@@ -79,9 +75,7 @@ public class RockboxActivity extends Activity
79 loadingdialog.setProgress(resultData.getInt("value", 0)); 75 loadingdialog.setProgress(resultData.getInt("value", 0));
80 break; 76 break;
81 case RockboxService.RESULT_SERVICE_RUNNING: 77 case RockboxService.RESULT_SERVICE_RUNNING:
82 rbservice = RockboxService.get_instance();
83 setServiceActivity(true); 78 setServiceActivity(true);
84 attachFramebuffer();
85 break; 79 break;
86 case RockboxService.RESULT_ERROR_OCCURED: 80 case RockboxService.RESULT_ERROR_OCCURED:
87 Toast.makeText(RockboxActivity.this, resultData.getString("error"), Toast.LENGTH_LONG); 81 Toast.makeText(RockboxActivity.this, resultData.getString("error"), Toast.LENGTH_LONG);
@@ -89,38 +83,21 @@ public class RockboxActivity extends Activity
89 } 83 }
90 } 84 }
91 }); 85 });
86 setContentView(new RockboxFramebuffer(this));
92 startService(intent); 87 startService(intent);
93 } 88 }
94 89
95 private void setServiceActivity(boolean set) 90 private void setServiceActivity(boolean set)
96 { 91 {
97 if (rbservice != null) 92 RockboxService s = RockboxService.get_instance();
98 rbservice.set_activity(set ? this : null); 93 if (s != null)
99 } 94 s.set_activity(set ? this : null);
100
101 private void attachFramebuffer()
102 {
103 View rbFramebuffer = null;
104 try {
105 rbFramebuffer = rbservice.get_fb();
106 setContentView(rbFramebuffer);
107 } catch (IllegalStateException e) {
108 /* we are already using the View,
109 * need to remove it and re-attach it */
110 ViewGroup g = (ViewGroup) rbFramebuffer.getParent();
111 g.removeView(rbFramebuffer);
112 setContentView(rbFramebuffer);
113 } catch (NullPointerException e) {
114 return;
115 }
116 rbFramebuffer.requestFocus();
117 } 95 }
118 96
119 public void onResume() 97 public void onResume()
120 { 98 {
121 super.onResume(); 99 super.onResume();
122 setVisible(true); 100 setVisible(true);
123 attachFramebuffer();
124 } 101 }
125 102
126 /* this is also called when the backlight goes off, 103 /* this is also called when the backlight goes off,
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java
index 037fd2db85..a17bc90ab6 100644
--- a/android/src/org/rockbox/RockboxFramebuffer.java
+++ b/android/src/org/rockbox/RockboxFramebuffer.java
@@ -148,7 +148,7 @@ public class RockboxFramebuffer extends SurfaceView
148 } 148 }
149 149
150 private native void touchHandler(boolean down, int x, int y); 150 private native void touchHandler(boolean down, int x, int y);
151 private native static boolean buttonHandler(int keycode, boolean state); 151 public native static boolean buttonHandler(int keycode, boolean state);
152 152
153 public native void surfaceCreated(SurfaceHolder holder); 153 public native void surfaceCreated(SurfaceHolder holder);
154 public native void surfaceDestroyed(SurfaceHolder holder); 154 public native void surfaceDestroyed(SurfaceHolder holder);
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}