summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/src/org/rockbox/RockboxActivity.java45
-rw-r--r--android/src/org/rockbox/RockboxFramebuffer.java101
-rw-r--r--android/src/org/rockbox/RockboxService.java45
-rw-r--r--apps/keymaps/keymap-android.c3
-rw-r--r--firmware/target/hosted/android/app/button-target.h2
-rw-r--r--firmware/target/hosted/android/lcd-android.c140
6 files changed, 158 insertions, 178 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
66 protected void onReceiveResult(final int resultCode, final Bundle resultData) 66 protected void onReceiveResult(final int resultCode, final Bundle resultData)
67 { 67 {
68 switch (resultCode) { 68 switch (resultCode) {
69 case RockboxService.RESULT_LIB_LOADED: 69 case RockboxService.RESULT_INVOKING_MAIN:
70 rbservice = RockboxService.get_instance();
71 if (loadingdialog != null) 70 if (loadingdialog != null)
72 loadingdialog.setIndeterminate(true); 71 loadingdialog.dismiss();
73 break; 72 break;
74 case RockboxService.RESULT_LIB_LOAD_PROGRESS: 73 case RockboxService.RESULT_LIB_LOAD_PROGRESS:
75 if (loadingdialog == null) 74 if (loadingdialog == null)
@@ -79,10 +78,10 @@ public class RockboxActivity extends Activity
79 loadingdialog.setMax(resultData.getInt("max", 100)); 78 loadingdialog.setMax(resultData.getInt("max", 100));
80 loadingdialog.setProgress(resultData.getInt("value", 0)); 79 loadingdialog.setProgress(resultData.getInt("value", 0));
81 break; 80 break;
82 case RockboxService.RESULT_FB_INITIALIZED: 81 case RockboxService.RESULT_SERVICE_RUNNING:
82 rbservice = RockboxService.get_instance();
83 setServiceActivity(true);
83 attachFramebuffer(); 84 attachFramebuffer();
84 if (loadingdialog != null)
85 loadingdialog.dismiss();
86 break; 85 break;
87 case RockboxService.RESULT_ERROR_OCCURED: 86 case RockboxService.RESULT_ERROR_OCCURED:
88 Toast.makeText(RockboxActivity.this, resultData.getString("error"), Toast.LENGTH_LONG); 87 Toast.makeText(RockboxActivity.this, resultData.getString("error"), Toast.LENGTH_LONG);
@@ -93,17 +92,17 @@ public class RockboxActivity extends Activity
93 startService(intent); 92 startService(intent);
94 } 93 }
95 94
96 private boolean isRockboxRunning() 95 private void setServiceActivity(boolean set)
97 { 96 {
98 if (rbservice == null) 97 if (rbservice != null)
99 rbservice = RockboxService.get_instance(); 98 rbservice.set_activity(this);
100 return (rbservice!= null && rbservice.isRockboxRunning() == true);
101 } 99 }
102 100
103 private void attachFramebuffer() 101 private void attachFramebuffer()
104 { 102 {
105 View rbFramebuffer = rbservice.get_fb(); 103 View rbFramebuffer = null;
106 try { 104 try {
105 rbFramebuffer = rbservice.get_fb();
107 setContentView(rbFramebuffer); 106 setContentView(rbFramebuffer);
108 } catch (IllegalStateException e) { 107 } catch (IllegalStateException e) {
109 /* we are already using the View, 108 /* we are already using the View,
@@ -111,17 +110,17 @@ public class RockboxActivity extends Activity
111 ViewGroup g = (ViewGroup) rbFramebuffer.getParent(); 110 ViewGroup g = (ViewGroup) rbFramebuffer.getParent();
112 g.removeView(rbFramebuffer); 111 g.removeView(rbFramebuffer);
113 setContentView(rbFramebuffer); 112 setContentView(rbFramebuffer);
114 } finally { 113 } catch (NullPointerException e) {
115 rbFramebuffer.requestFocus(); 114 return;
116 rbservice.set_activity(this);
117 } 115 }
116 rbFramebuffer.requestFocus();
118 } 117 }
119 118
120 public void onResume() 119 public void onResume()
121 { 120 {
122 super.onResume(); 121 super.onResume();
123 if (isRockboxRunning()) 122 setVisible(true);
124 attachFramebuffer(); 123 attachFramebuffer();
125 } 124 }
126 125
127 /* this is also called when the backlight goes off, 126 /* this is also called when the backlight goes off,
@@ -131,27 +130,23 @@ public class RockboxActivity extends Activity
131 protected void onPause() 130 protected void onPause()
132 { 131 {
133 super.onPause(); 132 super.onPause();
134 if (rbservice != null) 133 /* this will cause the framebuffer's Surface to be destroyed, enabling
135 { 134 * us to disable drawing */
136 rbservice.set_activity(null); 135 setVisible(false);
137 rbservice.get_fb().dispatchWindowVisibilityChanged(View.INVISIBLE);
138 }
139 } 136 }
140 137
141 @Override 138 @Override
142 protected void onStop() 139 protected void onStop()
143 { 140 {
144 super.onStop(); 141 super.onStop();
145 if (rbservice != null) 142 setServiceActivity(false);
146 rbservice.set_activity(null);
147 } 143 }
148 144
149 @Override 145 @Override
150 protected void onDestroy() 146 protected void onDestroy()
151 { 147 {
152 super.onDestroy(); 148 super.onDestroy();
153 if (rbservice != null) 149 setServiceActivity(false);
154 rbservice.set_activity(null);
155 } 150 }
156 151
157 private void LOG(CharSequence text) 152 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;
23 23
24import java.nio.ByteBuffer; 24import java.nio.ByteBuffer;
25 25
26import org.rockbox.Helper.MediaButtonReceiver;
27
28import android.content.Context; 26import android.content.Context;
29import android.graphics.Bitmap; 27import android.graphics.Bitmap;
30import android.graphics.Canvas; 28import android.graphics.Canvas;
@@ -33,45 +31,72 @@ import android.util.DisplayMetrics;
33import android.util.Log; 31import android.util.Log;
34import android.view.KeyEvent; 32import android.view.KeyEvent;
35import android.view.MotionEvent; 33import android.view.MotionEvent;
36import android.view.View; 34import android.view.SurfaceHolder;
35import android.view.SurfaceView;
37import android.view.ViewConfiguration; 36import android.view.ViewConfiguration;
38 37
39public class RockboxFramebuffer extends View 38public class RockboxFramebuffer extends SurfaceView
39 implements SurfaceHolder.Callback
40{ 40{
41 private Bitmap btm;
42 private Rect rect;
43 private ByteBuffer native_buf;
44 private MediaButtonReceiver media_monitor;
45 private final DisplayMetrics metrics; 41 private final DisplayMetrics metrics;
46 private final ViewConfiguration view_config; 42 private final ViewConfiguration view_config;
43 private ByteBuffer native_buf;
44 private Bitmap btm;
47 45
48 public RockboxFramebuffer(Context c, int lcd_width, 46 /* first stage init; needs to run from a thread that has a Looper
49 int lcd_height, ByteBuffer native_fb) 47 * setup stuff that needs a Context */
48 public RockboxFramebuffer(Context c)
50 { 49 {
51 super(c); 50 super(c);
51
52 metrics = c.getResources().getDisplayMetrics();
53 view_config = ViewConfiguration.get(c);
54 getHolder().addCallback(this);
52 /* Needed so we can catch KeyEvents */ 55 /* Needed so we can catch KeyEvents */
53 setFocusable(true); 56 setFocusable(true);
54 setFocusableInTouchMode(true); 57 setFocusableInTouchMode(true);
55 setClickable(true); 58 setClickable(true);
59 /* don't draw until native is ready (2nd stage) */
60 setEnabled(false);
61 }
62
63 /* second stage init; called from Rockbox with information about the
64 * display framebuffer */
65 @SuppressWarnings("unused")
66 private void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb)
67 {
56 btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565); 68 btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
57 rect = new Rect();
58 native_buf = native_fb; 69 native_buf = native_fb;
59 media_monitor = new MediaButtonReceiver(c); 70 setEnabled(true);
60 media_monitor.register();
61 /* the service needs to know the about us */
62 ((RockboxService)c).set_fb(this);
63
64 metrics = c.getResources().getDisplayMetrics();
65 view_config = ViewConfiguration.get(c);
66 } 71 }
67 72
68 public void onDraw(Canvas c) 73 @SuppressWarnings("unused")
74 private void java_lcd_update()
75 {
76 SurfaceHolder holder = getHolder();
77 Canvas c = holder.lockCanvas(null);
78 btm.copyPixelsFromBuffer(native_buf);
79 synchronized (holder)
80 { /* draw */
81 c.drawBitmap(btm, 0.0f, 0.0f, null);
82 }
83 holder.unlockCanvasAndPost(c);
84 }
85
86 @SuppressWarnings("unused")
87 private void java_lcd_update_rect(int x, int y, int width, int height)
69 { 88 {
70 /* can't copy a partial buffer :( */ 89 SurfaceHolder holder = getHolder();
90 Rect dirty = new Rect(x, y, x+width, y+height);
91 Canvas c = holder.lockCanvas(dirty);
92 /* can't copy a partial buffer,
93 * but it doesn't make a noticeable difference anyway */
71 btm.copyPixelsFromBuffer(native_buf); 94 btm.copyPixelsFromBuffer(native_buf);
72 c.getClipBounds(rect); 95 synchronized (holder)
73 c.drawBitmap(btm, rect, rect, null); 96 { /* draw */
74 post_update_done(); 97 c.drawBitmap(btm, dirty, dirty, null);
98 }
99 holder.unlockCanvasAndPost(c);
75 } 100 }
76 101
77 @SuppressWarnings("unused") 102 @SuppressWarnings("unused")
@@ -109,28 +134,6 @@ public class RockboxFramebuffer extends View
109 { 134 {
110 return buttonHandler(keyCode, false); 135 return buttonHandler(keyCode, false);
111 } 136 }
112
113 public void destroy()
114 {
115 set_lcd_active(0);
116 media_monitor.unregister();
117 }
118
119 @Override
120 protected void onWindowVisibilityChanged(int visibility)
121 {
122 super.onWindowVisibilityChanged(visibility);
123
124 switch (visibility) {
125 case VISIBLE:
126 set_lcd_active(1);
127 break;
128 case GONE:
129 case INVISIBLE:
130 set_lcd_active(0);
131 break;
132 }
133 }
134 137
135 @SuppressWarnings("unused") 138 @SuppressWarnings("unused")
136 private int getDpi() 139 private int getDpi()
@@ -144,8 +147,12 @@ public class RockboxFramebuffer extends View
144 return view_config.getScaledTouchSlop(); 147 return view_config.getScaledTouchSlop();
145 } 148 }
146 149
147 private native void post_update_done();
148 private native void set_lcd_active(int active);
149 private native void touchHandler(boolean down, int x, int y); 150 private native void touchHandler(boolean down, int x, int y);
150 private native static boolean buttonHandler(int keycode, boolean state); 151 private native static boolean buttonHandler(int keycode, boolean state);
152
153 public native void surfaceCreated(SurfaceHolder holder);
154 public native void surfaceDestroyed(SurfaceHolder holder);
155 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
156 {
157 }
151} 158}
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;
31import java.util.zip.ZipEntry; 31import java.util.zip.ZipEntry;
32import java.util.zip.ZipFile; 32import java.util.zip.ZipFile;
33 33
34import org.rockbox.Helper.MediaButtonReceiver;
34import org.rockbox.Helper.RunForegroundManager; 35import org.rockbox.Helper.RunForegroundManager;
35 36
36import android.app.Activity; 37import android.app.Activity;
@@ -59,20 +60,21 @@ public class RockboxService extends Service
59 60
60 /* locals needed for the c code and rockbox state */ 61 /* locals needed for the c code and rockbox state */
61 private RockboxFramebuffer fb = null; 62 private RockboxFramebuffer fb = null;
62 private boolean mRockboxRunning = false; 63 private volatile boolean rockbox_running;
63 private volatile boolean rbLibLoaded;
64 private Activity current_activity = null; 64 private Activity current_activity = null;
65 private IntentFilter itf; 65 private IntentFilter itf;
66 private BroadcastReceiver batt_monitor; 66 private BroadcastReceiver batt_monitor;
67 private RunForegroundManager fg_runner; 67 private RunForegroundManager fg_runner;
68 private MediaButtonReceiver mMediaButtonReceiver;
68 @SuppressWarnings("unused") 69 @SuppressWarnings("unused")
69 private int battery_level; 70 private int battery_level;
70 private ResultReceiver resultReceiver; 71 private ResultReceiver resultReceiver;
71 72
72 public static final int RESULT_LIB_LOADED = 0; 73 public static final int RESULT_INVOKING_MAIN = 0;
73 public static final int RESULT_LIB_LOAD_PROGRESS = 1; 74 public static final int RESULT_LIB_LOAD_PROGRESS = 1;
74 public static final int RESULT_FB_INITIALIZED = 2; 75 public static final int RESULT_FB_INITIALIZED = 2;
75 public static final int RESULT_ERROR_OCCURED = 3; 76 public static final int RESULT_SERVICE_RUNNING = 3;
77 public static final int RESULT_ERROR_OCCURED = 4;
76 78
77 @Override 79 @Override
78 public void onCreate() 80 public void onCreate()
@@ -89,14 +91,6 @@ public class RockboxService extends Service
89 { 91 {
90 return fb; 92 return fb;
91 } 93 }
92 /* framebuffer is initialised by the native code(!) so this is needed */
93 public void set_fb(RockboxFramebuffer newfb)
94 {
95 fb = newfb;
96 mRockboxRunning = true;
97 if (resultReceiver != null)
98 resultReceiver.send(RESULT_FB_INITIALIZED, null);
99 }
100 94
101 public Activity get_activity() 95 public Activity get_activity()
102 { 96 {
@@ -113,7 +107,7 @@ public class RockboxService extends Service
113 107
114 if (intent != null && intent.hasExtra("callback")) 108 if (intent != null && intent.hasExtra("callback"))
115 resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback"); 109 resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback");
116 if (!rbLibLoaded) 110 if (!rockbox_running)
117 startservice(); 111 startservice();
118 112
119 if (intent != null && intent.getAction() != null) 113 if (intent != null && intent.getAction() != null)
@@ -151,6 +145,8 @@ public class RockboxService extends Service
151 e.printStackTrace(); 145 e.printStackTrace();
152 } 146 }
153 } 147 }
148 if (resultReceiver != null)
149 resultReceiver.send(RESULT_SERVICE_RUNNING, null);
154 } 150 }
155 151
156 private void LOG(CharSequence text) 152 private void LOG(CharSequence text)
@@ -176,6 +172,11 @@ public class RockboxService extends Service
176 private void startservice() 172 private void startservice()
177 { 173 {
178 final int BUFFER = 8*1024; 174 final int BUFFER = 8*1024;
175 fb = new RockboxFramebuffer(this);
176 if (resultReceiver != null)
177 resultReceiver.send(RESULT_FB_INITIALIZED, null);
178 mMediaButtonReceiver = new MediaButtonReceiver(this);
179 mMediaButtonReceiver.register();
179 Thread rb = new Thread(new Runnable() 180 Thread rb = new Thread(new Runnable()
180 { 181 {
181 public void run() 182 public void run()
@@ -247,10 +248,11 @@ public class RockboxService extends Service
247 } 248 }
248 } 249 }
249 250
250 System.loadLibrary("rockbox"); 251 System.loadLibrary("rockbox");
251 rbLibLoaded = true; 252
253 rockbox_running = true;
252 if (resultReceiver != null) 254 if (resultReceiver != null)
253 resultReceiver.send(RESULT_LIB_LOADED, null); 255 resultReceiver.send(RESULT_INVOKING_MAIN, null);
254 256
255 main(); 257 main();
256 throw new IllegalStateException("native main() returned!"); 258 throw new IllegalStateException("native main() returned!");
@@ -259,15 +261,8 @@ public class RockboxService extends Service
259 rb.setDaemon(false); 261 rb.setDaemon(false);
260 rb.start(); 262 rb.start();
261 } 263 }
264
262 private native void main(); 265 private native void main();
263
264 /* returns true once rockbox is up and running.
265 * This is considered done once the framebuffer is initialised
266 */
267 public boolean isRockboxRunning()
268 {
269 return mRockboxRunning;
270 }
271 266
272 @Override 267 @Override
273 public IBinder onBind(Intent intent) 268 public IBinder onBind(Intent intent)
@@ -329,7 +324,7 @@ public class RockboxService extends Service
329 public void onDestroy() 324 public void onDestroy()
330 { 325 {
331 super.onDestroy(); 326 super.onDestroy();
332 fb.destroy(); 327 mMediaButtonReceiver.unregister();
333 /* Make sure our notification is gone. */ 328 /* Make sure our notification is gone. */
334 stopForeground(); 329 stopForeground();
335 } 330 }
diff --git a/apps/keymaps/keymap-android.c b/apps/keymaps/keymap-android.c
index df187e7ac8..c822a64fc2 100644
--- a/apps/keymaps/keymap-android.c
+++ b/apps/keymaps/keymap-android.c
@@ -50,6 +50,9 @@ static const struct button_mapping button_context_standard[] = {
50 { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, 50 { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU },
51 { ACTION_STD_CONTEXT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, 51 { ACTION_STD_CONTEXT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU },
52 52
53 /* special hack to get a redraw on activity resume, see lcd-android.c */
54 { ACTION_REDRAW, BUTTON_FORCE_REDRAW, BUTTON_NONE },
55
53 LAST_ITEM_IN_LIST 56 LAST_ITEM_IN_LIST
54}; /* button_context_standard */ 57}; /* button_context_standard */
55 58
diff --git a/firmware/target/hosted/android/app/button-target.h b/firmware/target/hosted/android/app/button-target.h
index 6106b612f9..3b6028739c 100644
--- a/firmware/target/hosted/android/app/button-target.h
+++ b/firmware/target/hosted/android/app/button-target.h
@@ -58,6 +58,8 @@ void android_ignore_back_button(bool yes);
58#define BUTTON_BOTTOMMIDDLE 0x00080000 58#define BUTTON_BOTTOMMIDDLE 0x00080000
59#define BUTTON_BOTTOMRIGHT 0x00100000 59#define BUTTON_BOTTOMRIGHT 0x00100000
60 60
61#define BUTTON_FORCE_REDRAW 0x00200000
62
61/* No remote */ 63/* No remote */
62#define BUTTON_REMOTE 0 64#define BUTTON_REMOTE 0
63 65
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c
index 92e8f5b96f..f719329819 100644
--- a/firmware/target/hosted/android/lcd-android.c
+++ b/firmware/target/hosted/android/lcd-android.c
@@ -21,10 +21,12 @@
21 21
22 22
23#include <jni.h> 23#include <jni.h>
24#include <string.h>
24#include "config.h" 25#include "config.h"
25#include "system.h" 26#include "system.h"
26#include "kernel.h" 27#include "kernel.h"
27#include "lcd.h" 28#include "lcd.h"
29#include "button.h"
28 30
29extern JNIEnv *env_ptr; 31extern JNIEnv *env_ptr;
30extern jclass RockboxService_class; 32extern jclass RockboxService_class;
@@ -32,57 +34,48 @@ extern jobject RockboxService_instance;
32 34
33static jclass RockboxFramebuffer_class; 35static jclass RockboxFramebuffer_class;
34static jobject RockboxFramebuffer_instance; 36static jobject RockboxFramebuffer_instance;
35static jmethodID postInvalidate1; 37static jmethodID java_lcd_update;
36static jmethodID postInvalidate2; 38static jmethodID java_lcd_update_rect;
37 39
38static bool display_on;
39static int dpi; 40static int dpi;
40static int scroll_threshold; 41static int scroll_threshold;
41static struct wakeup lcd_wakeup; 42static bool display_on;
42static struct mutex lcd_mtx;
43 43
44void lcd_init_device(void) 44void lcd_init_device(void)
45{ 45{
46 JNIEnv e = *env_ptr; 46 JNIEnv e = *env_ptr;
47 wakeup_init(&lcd_wakeup); 47 /* get existing instance from the Service */
48 mutex_init(&lcd_mtx); 48 jmethodID get_fb = e->GetMethodID(env_ptr, RockboxService_class, "get_fb",
49 RockboxFramebuffer_class = e->FindClass(env_ptr, 49 "()Lorg/rockbox/RockboxFramebuffer;");
50 "org/rockbox/RockboxFramebuffer"); 50 RockboxFramebuffer_instance = e->CallObjectMethod(env_ptr,
51 /* instantiate a RockboxFramebuffer instance 51 RockboxService_instance,
52 * 52 get_fb);
53 * Pass lcd width and height and our framebuffer so the java layer 53 RockboxFramebuffer_class = (*env_ptr)->GetObjectClass(env_ptr,
54 * can create a Bitmap which directly maps to it 54 RockboxFramebuffer_instance);
55 **/ 55
56 56 /* Get init function and set up what's left from the constructor */
57 /* map the framebuffer to a ByteBuffer, this way lcd updates will 57 jmethodID java_lcd_init = (*env_ptr)->GetMethodID(env_ptr,
58 * be directly feched from the framebuffer */ 58 RockboxFramebuffer_class,
59 "java_lcd_init",
60 "(IILjava/nio/ByteBuffer;)V");
61
59 jobject buf = e->NewDirectByteBuffer(env_ptr, 62 jobject buf = e->NewDirectByteBuffer(env_ptr,
60 lcd_framebuffer, 63 lcd_framebuffer,
61 (jlong)sizeof(lcd_framebuffer)); 64 (jlong)sizeof(lcd_framebuffer));
62 65
63 jmethodID constructor = e->GetMethodID(env_ptr, 66 e->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, java_lcd_init,
64 RockboxFramebuffer_class,
65 "<init>",
66 "(Landroid/content/Context;" /* Service */
67 "II" /* lcd width/height */
68 "Ljava/nio/ByteBuffer;)V"); /* ByteBuffer */
69
70 RockboxFramebuffer_instance = e->NewObject(env_ptr,
71 RockboxFramebuffer_class,
72 constructor,
73 RockboxService_instance,
74 (jint)LCD_WIDTH, 67 (jint)LCD_WIDTH,
75 (jint)LCD_HEIGHT, 68 (jint)LCD_HEIGHT,
76 buf); 69 buf);
77 70
78 /* cache update functions */ 71 /* cache update functions */
79 postInvalidate1 = (*env_ptr)->GetMethodID(env_ptr, 72 java_lcd_update = (*env_ptr)->GetMethodID(env_ptr,
80 RockboxFramebuffer_class, 73 RockboxFramebuffer_class,
81 "postInvalidate", 74 "java_lcd_update",
82 "()V"); 75 "()V");
83 postInvalidate2 = (*env_ptr)->GetMethodID(env_ptr, 76 java_lcd_update_rect = (*env_ptr)->GetMethodID(env_ptr,
84 RockboxFramebuffer_class, 77 RockboxFramebuffer_class,
85 "postInvalidate", 78 "java_lcd_update_rect",
86 "(IIII)V"); 79 "(IIII)V");
87 80
88 jmethodID get_dpi = e->GetMethodID(env_ptr, 81 jmethodID get_dpi = e->GetMethodID(env_ptr,
@@ -98,49 +91,54 @@ void lcd_init_device(void)
98 get_dpi); 91 get_dpi);
99 scroll_threshold = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance, 92 scroll_threshold = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance,
100 get_scroll_threshold); 93 get_scroll_threshold);
101 display_on = true; 94 /* must not draw until surface is created */
95 display_on = false;
102} 96}
103 97
104/* the update mechanism is asynchronous since
105 * onDraw() must be called from the UI thread
106 *
107 * The Rockbox thread calling lcd_update() has to wait
108 * for the update to complete, so that it's synchronous,
109 * and we need to notify it (we could wait in the java layer, but
110 * that'd block the other Rockbox threads too)
111 *
112 * That should give more smoonth animations
113 */
114void lcd_update(void) 98void lcd_update(void)
115{ 99{
116 /* tell the system we're ready for drawing */
117 if (display_on) 100 if (display_on)
118 { 101 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance,
119 mutex_lock(&lcd_mtx); 102 java_lcd_update);
120 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, postInvalidate1);
121 wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
122 mutex_unlock(&lcd_mtx);
123 }
124} 103}
125 104
126void lcd_update_rect(int x, int y, int width, int height) 105void lcd_update_rect(int x, int y, int width, int height)
127{ 106{
128 if (display_on) 107 if (display_on)
129 { 108 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance,
130 mutex_lock(&lcd_mtx); 109 java_lcd_update_rect, x, y, width, height);
131 (*env_ptr)->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, postInvalidate2, 110}
132 (jint)x, (jint)y, (jint)x+width, (jint)y+height); 111
133 wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK); 112/*
134 mutex_unlock(&lcd_mtx); 113 * this is called when the surface is created, which called is everytime
135 } 114 * the activity is brought in front and the RockboxFramebuffer gains focus
115 *
116 * Note this is considered interrupt context
117 */
118JNIEXPORT void JNICALL
119Java_org_rockbox_RockboxFramebuffer_surfaceCreated(JNIEnv *e, jobject this,
120 jobject surfaceholder)
121{
122 (void)e; (void)this; (void)surfaceholder;
123
124 display_on = true;
125 send_event(LCD_EVENT_ACTIVATION, NULL);
126 /* Force an update, since the newly created surface is initially black
127 * waiting for the next normal update results in a longish black screen */
128 queue_post(&button_queue, BUTTON_FORCE_REDRAW, 0);
136} 129}
137 130
131/*
132 * the surface is destroyed everytime the RockboxFramebuffer loses focus and
133 * goes invisible
134 */
138JNIEXPORT void JNICALL 135JNIEXPORT void JNICALL
139Java_org_rockbox_RockboxFramebuffer_post_1update_1done(JNIEnv *e, jobject this) 136Java_org_rockbox_RockboxFramebuffer_surfaceDestroyed(JNIEnv *e, jobject this,
137 jobject surfaceholder)
140{ 138{
141 (void)e; 139 (void)e; (void)this; (void)surfaceholder;
142 (void)this; 140
143 wakeup_signal(&lcd_wakeup); 141 display_on = false;
144} 142}
145 143
146bool lcd_active(void) 144bool lcd_active(void)
@@ -158,26 +156,6 @@ int touchscreen_get_scroll_threshold(void)
158 return scroll_threshold; 156 return scroll_threshold;
159} 157}
160 158
161/*
162 * (un)block lcd updates.
163 *
164 * Notice: This is called from the activity thread, so take it
165 * as interrupt context and take care what the event callback does
166 * (it shouldn't block in particular
167 *
168 * the 1s are needed due to strange naming conventions...
169 **/
170JNIEXPORT void JNICALL
171Java_org_rockbox_RockboxFramebuffer_set_1lcd_1active(JNIEnv *e,
172 jobject this,
173 jint active)
174{
175 (void)e;
176 (void)this;
177 display_on = active != 0;
178 if (active)
179 send_event(LCD_EVENT_ACTIVATION, NULL);
180}
181/* below is a plain copy from lcd-sdl.c */ 159/* below is a plain copy from lcd-sdl.c */
182 160
183/** 161/**