diff options
Diffstat (limited to 'android/src/org/rockbox')
-rw-r--r-- | android/src/org/rockbox/RockboxActivity.java | 45 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxFramebuffer.java | 101 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxService.java | 45 |
3 files changed, 94 insertions, 97 deletions
diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java index 76535687f9..f3f0d2151c 100644 --- a/android/src/org/rockbox/RockboxActivity.java +++ b/android/src/org/rockbox/RockboxActivity.java @@ -66,10 +66,9 @@ public class RockboxActivity extends Activity protected void onReceiveResult(final int resultCode, final Bundle resultData) { switch (resultCode) { - case RockboxService.RESULT_LIB_LOADED: - rbservice = RockboxService.get_instance(); + case RockboxService.RESULT_INVOKING_MAIN: if (loadingdialog != null) - loadingdialog.setIndeterminate(true); + loadingdialog.dismiss(); break; case RockboxService.RESULT_LIB_LOAD_PROGRESS: if (loadingdialog == null) @@ -79,10 +78,10 @@ public class RockboxActivity extends Activity loadingdialog.setMax(resultData.getInt("max", 100)); loadingdialog.setProgress(resultData.getInt("value", 0)); break; - case RockboxService.RESULT_FB_INITIALIZED: + case RockboxService.RESULT_SERVICE_RUNNING: + rbservice = RockboxService.get_instance(); + setServiceActivity(true); attachFramebuffer(); - if (loadingdialog != null) - loadingdialog.dismiss(); break; case RockboxService.RESULT_ERROR_OCCURED: Toast.makeText(RockboxActivity.this, resultData.getString("error"), Toast.LENGTH_LONG); @@ -93,17 +92,17 @@ public class RockboxActivity extends Activity startService(intent); } - private boolean isRockboxRunning() + private void setServiceActivity(boolean set) { - if (rbservice == null) - rbservice = RockboxService.get_instance(); - return (rbservice!= null && rbservice.isRockboxRunning() == true); + if (rbservice != null) + rbservice.set_activity(this); } private void attachFramebuffer() { - View rbFramebuffer = rbservice.get_fb(); + View rbFramebuffer = null; try { + rbFramebuffer = rbservice.get_fb(); setContentView(rbFramebuffer); } catch (IllegalStateException e) { /* we are already using the View, @@ -111,17 +110,17 @@ public class RockboxActivity extends Activity ViewGroup g = (ViewGroup) rbFramebuffer.getParent(); g.removeView(rbFramebuffer); setContentView(rbFramebuffer); - } finally { - rbFramebuffer.requestFocus(); - rbservice.set_activity(this); + } catch (NullPointerException e) { + return; } + rbFramebuffer.requestFocus(); } public void onResume() { super.onResume(); - if (isRockboxRunning()) - attachFramebuffer(); + setVisible(true); + attachFramebuffer(); } /* this is also called when the backlight goes off, @@ -131,27 +130,23 @@ public class RockboxActivity extends Activity protected void onPause() { super.onPause(); - if (rbservice != null) - { - rbservice.set_activity(null); - rbservice.get_fb().dispatchWindowVisibilityChanged(View.INVISIBLE); - } + /* this will cause the framebuffer's Surface to be destroyed, enabling + * us to disable drawing */ + setVisible(false); } @Override protected void onStop() { super.onStop(); - if (rbservice != null) - rbservice.set_activity(null); + setServiceActivity(false); } @Override protected void onDestroy() { super.onDestroy(); - if (rbservice != null) - rbservice.set_activity(null); + setServiceActivity(false); } private void LOG(CharSequence text) diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java index 05d2b11184..037fd2db85 100644 --- a/android/src/org/rockbox/RockboxFramebuffer.java +++ b/android/src/org/rockbox/RockboxFramebuffer.java @@ -23,8 +23,6 @@ package org.rockbox; import java.nio.ByteBuffer; -import org.rockbox.Helper.MediaButtonReceiver; - import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -33,45 +31,72 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.View; +import android.view.SurfaceHolder; +import android.view.SurfaceView; import android.view.ViewConfiguration; -public class RockboxFramebuffer extends View +public class RockboxFramebuffer extends SurfaceView + implements SurfaceHolder.Callback { - private Bitmap btm; - private Rect rect; - private ByteBuffer native_buf; - private MediaButtonReceiver media_monitor; private final DisplayMetrics metrics; private final ViewConfiguration view_config; + private ByteBuffer native_buf; + private Bitmap btm; - public RockboxFramebuffer(Context c, int lcd_width, - int lcd_height, ByteBuffer native_fb) + /* first stage init; needs to run from a thread that has a Looper + * setup stuff that needs a Context */ + public RockboxFramebuffer(Context c) { super(c); + + metrics = c.getResources().getDisplayMetrics(); + view_config = ViewConfiguration.get(c); + getHolder().addCallback(this); /* Needed so we can catch KeyEvents */ setFocusable(true); setFocusableInTouchMode(true); setClickable(true); + /* don't draw until native is ready (2nd stage) */ + setEnabled(false); + } + + /* second stage init; called from Rockbox with information about the + * display framebuffer */ + @SuppressWarnings("unused") + private void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb) + { btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565); - rect = new Rect(); native_buf = native_fb; - media_monitor = new MediaButtonReceiver(c); - media_monitor.register(); - /* the service needs to know the about us */ - ((RockboxService)c).set_fb(this); - - metrics = c.getResources().getDisplayMetrics(); - view_config = ViewConfiguration.get(c); + setEnabled(true); } - public void onDraw(Canvas c) + @SuppressWarnings("unused") + private void java_lcd_update() + { + SurfaceHolder holder = getHolder(); + Canvas c = holder.lockCanvas(null); + btm.copyPixelsFromBuffer(native_buf); + synchronized (holder) + { /* draw */ + c.drawBitmap(btm, 0.0f, 0.0f, null); + } + holder.unlockCanvasAndPost(c); + } + + @SuppressWarnings("unused") + private void java_lcd_update_rect(int x, int y, int width, int height) { - /* can't copy a partial buffer :( */ + SurfaceHolder holder = getHolder(); + Rect dirty = new Rect(x, y, x+width, y+height); + Canvas c = holder.lockCanvas(dirty); + /* can't copy a partial buffer, + * but it doesn't make a noticeable difference anyway */ btm.copyPixelsFromBuffer(native_buf); - c.getClipBounds(rect); - c.drawBitmap(btm, rect, rect, null); - post_update_done(); + synchronized (holder) + { /* draw */ + c.drawBitmap(btm, dirty, dirty, null); + } + holder.unlockCanvasAndPost(c); } @SuppressWarnings("unused") @@ -109,28 +134,6 @@ public class RockboxFramebuffer extends View { return buttonHandler(keyCode, false); } - - public void destroy() - { - set_lcd_active(0); - media_monitor.unregister(); - } - - @Override - protected void onWindowVisibilityChanged(int visibility) - { - super.onWindowVisibilityChanged(visibility); - - switch (visibility) { - case VISIBLE: - set_lcd_active(1); - break; - case GONE: - case INVISIBLE: - set_lcd_active(0); - break; - } - } @SuppressWarnings("unused") private int getDpi() @@ -144,8 +147,12 @@ public class RockboxFramebuffer extends View return view_config.getScaledTouchSlop(); } - private native void post_update_done(); - private native void set_lcd_active(int active); private native void touchHandler(boolean down, int x, int y); private native static boolean buttonHandler(int keycode, boolean state); + + public native void surfaceCreated(SurfaceHolder holder); + public native void surfaceDestroyed(SurfaceHolder holder); + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) + { + } } diff --git a/android/src/org/rockbox/RockboxService.java b/android/src/org/rockbox/RockboxService.java index de90999783..4f5df62280 100644 --- a/android/src/org/rockbox/RockboxService.java +++ b/android/src/org/rockbox/RockboxService.java @@ -31,6 +31,7 @@ import java.util.TimerTask; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.rockbox.Helper.MediaButtonReceiver; import org.rockbox.Helper.RunForegroundManager; import android.app.Activity; @@ -59,20 +60,21 @@ public class RockboxService extends Service /* locals needed for the c code and rockbox state */ private RockboxFramebuffer fb = null; - private boolean mRockboxRunning = false; - private volatile boolean rbLibLoaded; + private volatile boolean rockbox_running; private Activity current_activity = null; private IntentFilter itf; private BroadcastReceiver batt_monitor; private RunForegroundManager fg_runner; + private MediaButtonReceiver mMediaButtonReceiver; @SuppressWarnings("unused") private int battery_level; private ResultReceiver resultReceiver; - public static final int RESULT_LIB_LOADED = 0; + public static final int RESULT_INVOKING_MAIN = 0; public static final int RESULT_LIB_LOAD_PROGRESS = 1; public static final int RESULT_FB_INITIALIZED = 2; - public static final int RESULT_ERROR_OCCURED = 3; + public static final int RESULT_SERVICE_RUNNING = 3; + public static final int RESULT_ERROR_OCCURED = 4; @Override public void onCreate() @@ -89,14 +91,6 @@ public class RockboxService extends Service { return fb; } - /* framebuffer is initialised by the native code(!) so this is needed */ - public void set_fb(RockboxFramebuffer newfb) - { - fb = newfb; - mRockboxRunning = true; - if (resultReceiver != null) - resultReceiver.send(RESULT_FB_INITIALIZED, null); - } public Activity get_activity() { @@ -113,7 +107,7 @@ public class RockboxService extends Service if (intent != null && intent.hasExtra("callback")) resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback"); - if (!rbLibLoaded) + if (!rockbox_running) startservice(); if (intent != null && intent.getAction() != null) @@ -151,6 +145,8 @@ public class RockboxService extends Service e.printStackTrace(); } } + if (resultReceiver != null) + resultReceiver.send(RESULT_SERVICE_RUNNING, null); } private void LOG(CharSequence text) @@ -176,6 +172,11 @@ public class RockboxService extends Service private void startservice() { final int BUFFER = 8*1024; + fb = new RockboxFramebuffer(this); + if (resultReceiver != null) + resultReceiver.send(RESULT_FB_INITIALIZED, null); + mMediaButtonReceiver = new MediaButtonReceiver(this); + mMediaButtonReceiver.register(); Thread rb = new Thread(new Runnable() { public void run() @@ -247,10 +248,11 @@ public class RockboxService extends Service } } - System.loadLibrary("rockbox"); - rbLibLoaded = true; + System.loadLibrary("rockbox"); + + rockbox_running = true; if (resultReceiver != null) - resultReceiver.send(RESULT_LIB_LOADED, null); + resultReceiver.send(RESULT_INVOKING_MAIN, null); main(); throw new IllegalStateException("native main() returned!"); @@ -259,15 +261,8 @@ public class RockboxService extends Service rb.setDaemon(false); rb.start(); } + private native void main(); - - /* returns true once rockbox is up and running. - * This is considered done once the framebuffer is initialised - */ - public boolean isRockboxRunning() - { - return mRockboxRunning; - } @Override public IBinder onBind(Intent intent) @@ -329,7 +324,7 @@ public class RockboxService extends Service public void onDestroy() { super.onDestroy(); - fb.destroy(); + mMediaButtonReceiver.unregister(); /* Make sure our notification is gone. */ stopForeground(); } |