diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java
index 3be9e3e..c30e302 100644
--- a/android/src/org/rockbox/RockboxActivity.java
+++ b/android/src/org/rockbox/RockboxActivity.java
@@ -113,6 +113,11 @@ public class RockboxActivity extends Activity {
     	super.onDestroy();
     	RockboxService.fb.suspend();
     }
+    
+    @Override
+    public boolean onTrackballEvent(android.view.MotionEvent event) {
+    	return RockboxService.fb.onTrackballEvent(event);
+    };

 	private void LOG(CharSequence text)
 	{
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java
index ca11de0..606ba55 100644
--- a/android/src/org/rockbox/RockboxFramebuffer.java
+++ b/android/src/org/rockbox/RockboxFramebuffer.java
@@ -70,9 +70,27 @@ public class RockboxFramebuffer extends View

 	private void LOG(CharSequence text)
 	{
-		Log.d("RockboxBootloader", (String) text);
+		Log.d("Rockbox", (String) text);
 	}

+	public boolean onTrackballEvent(MotionEvent me)
+	{
+		switch (me.getAction())
+		{
+		case MotionEvent.ACTION_MOVE:
+			buttonHandler(0, (int)(2*me.getX()), (int)(2*me.getY()));
+			break;
+		case MotionEvent.ACTION_DOWN:
+			buttonHandler(1, 0, 0);
+			break;
+		case MotionEvent.ACTION_UP:
+		case MotionEvent.ACTION_CANCEL:
+			buttonHandler(-1, 0, 0);
+			break;
+		}
+		return true;
+	}
+	
 	public boolean onTouchEvent(MotionEvent me)
 	{
 		LOG("onTouchEvent");
@@ -106,4 +124,5 @@ public class RockboxFramebuffer extends View
 	public native void set_lcd_active(int active);
 	public native void pixelHandler(int x, int y);
 	public native void touchHandler(int down);
+	public native void buttonHandler(int press, int relative_x, int relative_y);
 }
diff --git a/firmware/target/hosted/android/app/button-target.h b/firmware/target/hosted/android/app/button-target.h
index 329ed65..3ecb00e 100644
--- a/firmware/target/hosted/android/app/button-target.h
+++ b/firmware/target/hosted/android/app/button-target.h
@@ -40,6 +40,7 @@ int button_read_device(int *data);
 #define BUTTON_RIGHT BUTTON_MIDRIGHT
 #define BUTTON_UP    BUTTON_TOPMIDDLE
 #define BUTTON_DOWN  BUTTON_BOTTOMMIDDLE
+#define BUTTON_SELECT BUTTON_CENTER

 /* Touch Screen Area Buttons */
 #define BUTTON_TOPLEFT      0x00000010
diff --git a/firmware/target/hosted/android/button-android.c b/firmware/target/hosted/android/button-android.c
index 1172880..4f93d12 100644
--- a/firmware/target/hosted/android/button-android.c
+++ b/firmware/target/hosted/android/button-android.c
@@ -26,9 +26,11 @@
 #include "kernel.h"
 #include "system.h"
 #include "touchscreen.h"
+#include "button.h"

 static int last_y, last_x;
-
+static int last_button;
+static int last_button_tick;
 static enum {
     STATE_UNKNOWN,
     STATE_UP,
@@ -64,13 +66,55 @@ Java_org_rockbox_RockboxFramebuffer_touchHandler(JNIEnv*env, jobject this,
         last_state = STATE_UP;
 }

+/*
+ * this notifies us in an interrupt-like fashion when a hardware button is pressed */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jobject this,
+                                                   jint press, jint relative_x, jint relative_y)
+{
+    (void)env;
+    (void)this;
+    int btn = last_button&BUTTON_SELECT;
+
+    LOG("%s(): %d:%d:%d\n", __func__, press, relative_x, relative_y);
+    if (press > 0)
+        btn |= BUTTON_SELECT;
+    else if (press < 0)
+        btn &= ~BUTTON_SELECT;
+
+    if (relative_y < 0)
+        btn |= BUTTON_UP;
+    else if (relative_y > 0)
+        btn |= BUTTON_DOWN;
+
+    if (relative_x > 0)
+        btn |= BUTTON_RIGHT;
+    else if (relative_x < 0)
+        btn |= BUTTON_LEFT;
+
+    last_button = btn;
+    last_button_tick = current_tick;
+}
+
 void button_init_device(void)
 {
+    last_button = BUTTON_NONE;
+    last_button_tick = current_tick;
 }

 int button_read_device(int *data)
 {
-    /* get grid button/coordinates based on the current touchscreen mode */
-    int btn = touchscreen_to_pixels(last_x, last_y, data);
-    return (last_state == STATE_DOWN ? btn : 0);
+    int btn;
+    if (last_button == BUTTON_NONE)
+    {
+        /* get grid button/coordinates based on the current touchscreen mode */
+        btn = touchscreen_to_pixels(last_x, last_y, data);
+        return (last_state == STATE_DOWN ? btn : 0);
+    }
+    else
+    {
+        if (TIME_AFTER(current_tick, last_button_tick+5))
+            last_button &= BUTTON_SELECT;
+        return last_button;
+    }
 }