Rockbox as an application: Commit current Android port progress.

General state is: Rockbox is usable (plays music, saves configuration, touchscreen works too).
Problems:
 - Playing music in the background (i.e. when switching to another app) doesn't work reliably, but I'm working on that now.
 - no cabbiev2 (only some preliminary files for it), no other default theme.
 - screen flickers sometimes if the updates are too frequent
 - no multi screen apk/package
 - strange behavior when a phone call comes in

The java files (and the eclipse project) resides in android/, which is also supposed to be the build folder.
I've put a small README in there for instructions. There are some steps needed after the make part, which are described there,
and which eclipse mostly handles. But there ought to be some script/makefile rules which do that instead in the future.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27668 a1c6a512-1295-4272-9138-f99709370657
diff --git a/android/.classpath b/android/.classpath
new file mode 100644
index 0000000..6efcbb7
--- /dev/null
+++ b/android/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/android/.project b/android/.project
new file mode 100644
index 0000000..7e8d136
--- /dev/null
+++ b/android/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Rockbox</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
new file mode 100644
index 0000000..a22c393
--- /dev/null
+++ b/android/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="org.rockbox"
+      android:versionCode="1"
+      android:versionName="1.0">
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
+        <activity android:name=".RockboxActivity"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+<uses-sdk android:minSdkVersion="4" />
+<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+</manifest> 
\ No newline at end of file
diff --git a/android/README b/android/README
new file mode 100644
index 0000000..e41bfa6
--- /dev/null
+++ b/android/README
@@ -0,0 +1,34 @@
+This folder contains the java parts needed to build an Rockbox as an
+application for android.
+
+* Build instructions
+
+Until there's a script which does all the work the procedure is documented here.
+
+First, make sure you have the ANDROID_NDK_PATH environment variable set up,
+otherwise configure will fail to find the compiler.
+
+Use this as your build folder, using '../tools/configure' etc.
+    $ ../tools/configure
+    $ make
+
+After the build finished, you need to copy librockbox.so to libs/armeabi/.
+    $ cp librockbox.so libs/armeabi
+
+For the other files (codecs, themes), you execute 'make zip'. Then you copy the
+zip to libs/armeabi, using the name libmisc.so. This is needed, since there's no 
+way to bundle stuff into apk's and have access to them from native code other
+than pretending it was a library.
+    $ make zip
+    $ cp rockbox.zip lib/armeabi/libmisc.so
+
+rockbox.zip..err, libmisc.so will be unpacked at runtime.
+
+To finish, you can follow this guide [1], or use eclipse. Simply install eclipse
+and the android plugins, then import this folder as a new Android project and run it.
+See [2] for a guide on how to set up eclipse for android development.
+
+
+    
+[1]: http://asantoso.wordpress.com/2009/09/15/how-to-build-android-application-package-apk-from-the-command-line-using-the-sdk-tools-continuously-integrated-using-cruisecontrol/
+[2]: http://developer.android.com/sdk/installing.html
diff --git a/android/default.properties b/android/default.properties
new file mode 100644
index 0000000..9d79b12
--- /dev/null
+++ b/android/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-4
diff --git a/android/gen/org/rockbox/R.java b/android/gen/org/rockbox/R.java
new file mode 100644
index 0000000..38c177e
--- /dev/null
+++ b/android/gen/org/rockbox/R.java
@@ -0,0 +1,22 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package org.rockbox;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class drawable {
+        public static final int icon=0x7f020000;
+    }
+    public static final class layout {
+        public static final int main=0x7f030000;
+    }
+    public static final class string {
+        public static final int app_name=0x7f040000;
+    }
+}
diff --git a/android/res/drawable-hdpi/icon.png b/android/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/android/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/android/res/drawable-ldpi/icon.png b/android/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/android/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/android/res/drawable-mdpi/icon.png b/android/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/android/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml
new file mode 100644
index 0000000..4361cfe
--- /dev/null
+++ b/android/res/layout/main.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+</LinearLayout>
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
new file mode 100644
index 0000000..6c3c846
--- /dev/null
+++ b/android/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    
+    <string name="app_name">Rockbox</string>
+</resources>
diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java
new file mode 100644
index 0000000..791cad9
--- /dev/null
+++ b/android/src/org/rockbox/RockboxActivity.java
@@ -0,0 +1,148 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+package org.rockbox;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import android.app.Activity;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Window;
+import android.view.WindowManager;
+
+public class RockboxActivity extends Activity {
+    /** Called when the activity is first created. */
+    public RockboxFramebuffer fb;
+    private Thread rb;
+    static final int BUFFER = 2048;
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    	LOG("start rb");
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
+                       ,WindowManager.LayoutParams.FLAG_FULLSCREEN); 
+        fb = new RockboxFramebuffer(this);
+        if (true) {
+        try 
+        {
+           BufferedOutputStream dest = null;
+           BufferedInputStream is = null;
+           ZipEntry entry;
+           File file = new File("/data/data/org.rockbox/lib/libmisc.so");
+           /* use arbitary file to determine whether extracting is needed */
+           File file2 = new File("/data/data/org.rockbox/app_rockbox/rockbox/codecs/mpa.codec");
+           if (!file2.exists() || (file.lastModified() > file2.lastModified()))
+           {
+	           ZipFile zipfile = new ZipFile(file);
+	           Enumeration<? extends ZipEntry> e = zipfile.entries();
+	           File folder;
+	           while(e.hasMoreElements()) {
+	              entry = (ZipEntry) e.nextElement();
+	              LOG("Extracting: " +entry);
+	              if (entry.isDirectory())
+	              {
+	            	  folder = new File(entry.getName());
+	            	  LOG("mkdir "+ entry);
+	            	  try {
+	            		  folder.mkdirs();
+	            	  } catch (SecurityException ex){
+	            		  LOG(ex.getMessage());
+	            	  }
+	            	  continue;
+	              }
+	              is = new BufferedInputStream(zipfile.getInputStream(entry));
+	              int count;
+	              byte data[] = new byte[BUFFER];
+	              folder = new File(new File(entry.getName()).getParent());
+	              LOG("" + folder.getAbsolutePath());
+	              if (!folder.exists())
+	            	  folder.mkdirs();
+	              FileOutputStream fos = new FileOutputStream(entry.getName());
+	              dest = new BufferedOutputStream(fos, BUFFER);
+	              while ((count = is.read(data, 0, BUFFER)) != -1) {
+	                 dest.write(data, 0, count);
+	              }
+	              dest.flush();
+	              dest.close();
+	              is.close();
+	           }
+           }
+        } catch(Exception e) {
+           e.printStackTrace();
+        }}
+        Rect r = new Rect();
+        fb.getDrawingRect(r);
+        LOG(r.left + " " + r.top + " " + r.right + " " + r.bottom);
+    	rb = new Thread(new Runnable()
+    	{
+    		public void run()
+    		{
+    			main();
+    		}
+    	},"Rockbox thread");
+        System.loadLibrary("rockbox");
+        rb.setDaemon(false);
+        setContentView(fb);
+    }
+
+	private void LOG(CharSequence text)
+	{
+		Log.d("RockboxBootloader", (String) text);
+	}
+
+    public synchronized void onStart()
+    {
+    	super.onStart();
+    	if (!rb.isAlive())
+    		rb.start();
+    }
+    
+    public void onPause()
+    {
+    	super.onPause();
+    }
+    
+    public void onResume()
+    {
+    	super.onResume();
+    	switch (rb.getState()) {
+    	case BLOCKED: LOG("BLOCKED"); break;
+    	case RUNNABLE: LOG("RUNNABLE"); break;
+    	case NEW: LOG("NEW"); break;
+    	case TERMINATED: LOG("TERMINATED"); break;
+    	case TIMED_WAITING: LOG("TIMED_WAITING"); break;
+    	case WAITING: LOG("WAITING"); break;
+    	}
+    }
+
+
+    private native void main();
+}
\ No newline at end of file
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java
new file mode 100644
index 0000000..f947806
--- /dev/null
+++ b/android/src/org/rockbox/RockboxFramebuffer.java
@@ -0,0 +1,98 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+package org.rockbox;
+
+import java.nio.ByteBuffer;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.os.Handler;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class RockboxFramebuffer extends View 
+{
+	private Bitmap btm;
+    private ByteBuffer native_buf;
+    private Handler update_handler;
+    private Runnable cb;
+
+
+	public RockboxFramebuffer(Context c)
+	{
+		super(c);
+		update_handler = new Handler();
+		cb = new Runnable() {
+			public void run()
+			{
+				btm.copyPixelsFromBuffer(native_buf);
+				invalidate();
+			}
+		};
+		btm = null;
+	}
+
+	public void onDraw(Canvas c) 
+	{
+		if (btm != null)
+			c.drawBitmap(btm, 0.0f, 0.0f, null);
+	}
+	
+	public void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb)
+	{
+		btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
+		native_buf = native_fb;
+	}
+	
+	public void java_lcd_update()
+	{
+		update_handler.post(cb);
+	}
+
+	private void LOG(CharSequence text)
+	{
+		Log.d("RockboxBootloader", (String) text);	
+	}
+
+	public boolean onTouchEvent(MotionEvent me)
+	{
+		LOG("onTouchEvent");
+		switch (me.getAction())
+		{
+		case MotionEvent.ACTION_CANCEL:
+		case MotionEvent.ACTION_UP:
+			touchHandler(0);
+			break;
+		case MotionEvent.ACTION_MOVE:
+		case MotionEvent.ACTION_DOWN:
+			touchHandler(1);
+			break;
+		
+		}
+		pixelHandler((int)me.getX(), (int)me.getY());
+		return true;
+	}
+	
+	public native void pixelHandler(int x, int y);
+	public native void touchHandler(int down);
+}
diff --git a/android/src/org/rockbox/RockboxPCM.java b/android/src/org/rockbox/RockboxPCM.java
new file mode 100644
index 0000000..f098df6
--- /dev/null
+++ b/android/src/org/rockbox/RockboxPCM.java
@@ -0,0 +1,155 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+package org.rockbox;
+
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.util.Log;
+
+public class RockboxPCM extends AudioTrack 
+{
+	byte[] raw_data;
+
+	private void LOG(CharSequence text)
+	{
+		Log.d("RockboxBootloader", (String) text);
+	}
+
+	public RockboxPCM()
+	{
+		super(AudioManager.STREAM_MUSIC, 
+			    44100,
+			    /* should be CHANNEL_OUT_STEREO in 2.0 and above */
+			    AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+			    AudioFormat.ENCODING_PCM_16BIT,
+			    24<<10,
+			    AudioTrack.MODE_STREAM);
+		int buf_len = 24<<10;
+
+	    raw_data = new byte[buf_len*2];
+	    for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00;
+	    /* fill with silence */
+	    write(raw_data, 0, raw_data.length);
+	    if (getState() == AudioTrack.STATE_INITIALIZED)
+	    {
+	    	if (setNotificationMarkerPosition(bytes2frames(buf_len*2)/4) != AudioTrack.SUCCESS)
+	    		LOG("setNotificationMarkerPosition Error");
+	    	setPlaybackPositionUpdateListener(new PCMListener(buf_len*2));
+	    }
+	}
+
+    
+
+	int bytes2frames(int bytes) {
+		/* 1 sample is 2 bytes, 2 samples are 1 frame */
+		return (bytes/4);
+	}
+	
+	int frames2bytes(int frames) {
+		/* 1 frame is 2 samples, 1 sample is 2 bytes */
+		return (frames*4);
+	}
+
+    @SuppressWarnings("unused")
+	private void play_pause(boolean pause) {
+    	LOG("play_pause()");
+    	if (pause)
+    		pause();
+    	else
+    	{
+    		if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED)
+    		{
+    	        for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00;
+    	        LOG("Writing silence");
+    	        /* fill with silence */
+    	        write(raw_data, 0, raw_data.length);
+    		}
+    		play();
+    	}
+    	LOG("play_pause() return");
+    }
+
+    @SuppressWarnings("unused")
+    private void set_volume(int volume)
+    {
+    	/* volume comes from 0..-990 from Rockbox */
+    	/* TODO volume is in dB, but this code acts as if it were in %, convert? */
+    	float fvolume;
+    	/* special case min and max volume to not suffer from floating point accuracy */
+    	if (volume == 0)
+    		fvolume = 1.0f;
+    	else if (volume == -990)
+    		fvolume = 0.0f;
+    	else
+    		fvolume = (volume + 990)/990.0f;
+    	setStereoVolume(fvolume, fvolume);
+    }
+
+    public native void pcmSamplesToByteArray(byte[] dest);
+   
+    private class PCMListener implements OnPlaybackPositionUpdateListener {
+        int max_len;
+        byte[] buf;
+		public PCMListener(int len) {
+            max_len = len;
+            buf = new byte[len/2];
+		}
+		@Override
+		public void onMarkerReached(AudioTrack track) {
+			// push new data to the hardware
+			int result = 1;
+            pcmSamplesToByteArray(buf);
+			//LOG("Trying to write " + buf.length + " bytes");
+			result = track.write(buf, 0, buf.length);
+			if (result > 0)
+			{
+				//LOG(result + " bytes written");
+				track.setPlaybackPositionUpdateListener(this);
+				track.setNotificationMarkerPosition(bytes2frames(max_len)/4);
+				switch(track.getPlayState())
+				{
+				case AudioTrack.PLAYSTATE_PLAYING:
+					//LOG("State PLAYING");
+					break;
+				case AudioTrack.PLAYSTATE_PAUSED:
+					LOG("State PAUSED");
+					break;
+				case AudioTrack.PLAYSTATE_STOPPED:
+					LOG("State STOPPED");
+					break;
+				}
+			}
+			else
+			{
+				LOG("Error in onMarkerReached");
+				track.stop();
+			}
+		}
+
+		@Override
+		public void onPeriodicNotification(AudioTrack track) {
+			// TODO Auto-generated method stub
+			
+		}
+	}
+}
diff --git a/android/src/org/rockbox/RockboxTimer.java b/android/src/org/rockbox/RockboxTimer.java
new file mode 100644
index 0000000..c7239b4
--- /dev/null
+++ b/android/src/org/rockbox/RockboxTimer.java
@@ -0,0 +1,93 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+package org.rockbox;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import android.util.Log;
+
+public class RockboxTimer extends Timer 
+{
+	RockboxTimerTask task;
+	long interval;
+	
+	private class RockboxTimerTask extends TimerTask {
+		private RockboxTimer t;
+		public RockboxTimerTask(RockboxTimer parent) {
+			super();
+			t = parent;
+		}
+
+		@Override
+		public void run() {
+			timerTask();
+			synchronized(t) {
+				t.notify();
+			}
+		}
+	}
+	
+	public void pause()
+	{
+		cancel();
+	}
+	public void resume()
+	{
+		try {
+			schedule(task, 0, interval);
+		} catch (IllegalStateException e) {
+			/* not an error */
+		} catch (Exception e) {
+			LOG(e.toString());
+		}
+	}
+	
+	public RockboxTimer(long period_inverval_in_ms)
+	{
+		super("tick timer", false);
+		task = new RockboxTimerTask(this);
+		schedule(task, 0, period_inverval_in_ms);
+		interval = period_inverval_in_ms;
+	}
+
+	private void LOG(CharSequence text)
+	{
+		Log.d("RockboxBootloader", (String) text);	
+	}
+
+
+    /* methods called from native, keep them simple */    
+    public void java_wait_for_interrupt()
+    {
+    	synchronized(this) {
+	    	try {
+	    		this.wait();
+	    	} catch (InterruptedException e) {
+	    		/* wakeup and return */
+	    	} catch (Exception e) {
+	    		LOG(e.toString());
+	    	}
+    	}
+    }
+	public native void timerTask();
+}
diff --git a/apps/codecs/codec_crt0.c b/apps/codecs/codec_crt0.c
index dd0f99f..c680030 100644
--- a/apps/codecs/codec_crt0.c
+++ b/apps/codecs/codec_crt0.c
@@ -34,6 +34,10 @@
 
 extern enum codec_status codec_main(void);
 
+/* stub, the entry point is called via its reference in __header to
+ * avoid warning with certain compilers */
+int _start(void) {return 0;}
+
 enum codec_status codec_start(void)
 {
 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h
index 5b5385a..ee7c969 100644
--- a/apps/codecs/libwavpack/wavpack.h
+++ b/apps/codecs/libwavpack/wavpack.h
@@ -16,7 +16,9 @@
 
 typedef unsigned char   uchar;
 typedef unsigned short  ushort;
+#if 0 // unused and causing compiler errrors
 typedef unsigned int    uint;
+#endif
 
 #include <stdio.h>
 
diff --git a/backdrops/cabbiev2.320x480x16.bmp b/backdrops/cabbiev2.320x480x16.bmp
new file mode 100644
index 0000000..6933fd0
--- /dev/null
+++ b/backdrops/cabbiev2.320x480x16.bmp
Binary files differ
diff --git a/bootloader/common.c b/bootloader/common.c
index 362c3b4..1099b9f 100644
--- a/bootloader/common.c
+++ b/bootloader/common.c
@@ -68,7 +68,7 @@
 #endif
 }
 
-void printf(const char *format, ...)
+int printf(const char *format, ...)
 {
     int len;
     unsigned char *ptr;
@@ -91,6 +91,7 @@
     if(remote_line >= LCD_REMOTE_HEIGHT/SYSFONT_HEIGHT)
         remote_line = 0;
 #endif
+    return len;
 }
 
 char *strerror(int error)
diff --git a/bootloader/common.h b/bootloader/common.h
index 6713585..7d5425c 100644
--- a/bootloader/common.h
+++ b/bootloader/common.h
@@ -41,7 +41,7 @@
 
 /* Functions common to all bootloaders */
 void reset_screen(void);
-void printf(const char *format, ...);
+int printf(const char *format, ...);
 char *strerror(int error);
 void error(int errortype, int error, bool shutdown);
 int load_firmware(unsigned char* buf, char* firmware, int buffer_size);
diff --git a/firmware/SOURCES b/firmware/SOURCES
index d8cfade..4092f71 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1698,3 +1698,14 @@
 #endif /* BOOTLOADER */
 #endif /* SIMULATOR */
 #endif
+
+
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+target/hosted/android/lcd-android.c
+target/hosted/android/button-android.c
+target/hosted/android/kernel-android.c
+target/hosted/android/pcm-android.c
+target/hosted/android/system-android.c
+drivers/audio/android.c
+thread.c
+#endif
diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c
index 69bc138..b63586c 100644
--- a/firmware/common/rbpaths.c
+++ b/firmware/common/rbpaths.c
@@ -33,9 +33,13 @@
 void paths_init(void)
 {
     /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+    mkdir("/sdcard/rockbox");
+#else
     char home_path[MAX_PATH];
     snprintf(home_path, sizeof(home_path), "%s/.config/rockbox.org", getenv("HOME"));
     mkdir(home_path);
+#endif
 }
 
 const char* get_user_file_path(const char *path,
@@ -50,7 +54,11 @@
     pos += ROCKBOX_DIR_LEN;
     if (*pos == '/') pos += 1;
 
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+    if (snprintf(buf, bufsize, "/sdcard/rockbox/%s", pos)
+#else
     if (snprintf(buf, bufsize, "%s/.config/rockbox.org/%s", getenv("HOME"), pos)
+#endif
             >= (int)bufsize)
         return NULL;
 
diff --git a/firmware/drivers/audio/android.c b/firmware/drivers/audio/android.c
new file mode 100644
index 0000000..300bb08
--- /dev/null
+++ b/firmware/drivers/audio/android.c
@@ -0,0 +1,61 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright © 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#include "config.h"
+#include "audiohw.h"
+
+const struct sound_settings_info audiohw_settings[] = {
+    [SOUND_VOLUME]        = {"dB", 0,  1, VOLUME_MIN / 10, VOLUME_MAX / 10, -25},
+/* Bass and treble tone controls */
+#ifdef AUDIOHW_HAVE_BASS
+    [SOUND_BASS]          = {"dB", 0,  1, -24,  24,   0},
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE
+    [SOUND_TREBLE]        = {"dB", 0,  1, -24,  24,   0},
+#endif
+    [SOUND_BALANCE]       = {"%",  0,  1,-100, 100,   0},
+    [SOUND_CHANNELS]      = {"",   0,  1,   0,   5,   0},
+    [SOUND_STEREO_WIDTH]  = {"%",  0,  5,   0, 250, 100},
+#if defined(HAVE_RECORDING)
+    [SOUND_LEFT_GAIN]     = {"dB", 1,  1,-128,  96,   0},
+    [SOUND_RIGHT_GAIN]    = {"dB", 1,  1,-128,  96,   0},
+    [SOUND_MIC_GAIN]      = {"dB", 1,  1,-128, 108,  16},
+#endif
+#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
+    [SOUND_BASS_CUTOFF]   = {"",   0,  1,   1,   4,   1},
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
+    [SOUND_TREBLE_CUTOFF] = {"",   0,  1,   1,   4,   1},
+#endif
+};
+
+
+void audiohw_set_volume(int volume)
+{
+    extern void pcm_set_mixer_volume(int);
+    pcm_set_mixer_volume(volume);
+}
+
+void audiohw_set_balance(int balance)
+{
+    (void)balance;
+}
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index d4861aa..658dd13 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -66,7 +66,7 @@
 #elif defined(HAVE_AK4537)
 #include "ak4537.h"
 #endif
-#if defined(HAVE_SDL_AUDIO)
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
 /* #include <SDL_audio.h> gives errors in other code areas,
  * we don't really need it here, so don't. but it should maybe be fixed */
 #ifndef SIMULATOR /* simulator gets values from the target .h files */
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 1b8a782..3b59004 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -78,8 +78,10 @@
  * bit fields to allow PLATFORM_HOSTED to be OR'ed e.g. with a
  * possible future PLATFORM_ANDROID (some OSes might need totally different
  * handling to run on them than a stand-alone application) */
-#define PLATFORM_NATIVE (1<<0)
-#define PLATFORM_HOSTED (1<<1)
+#define PLATFORM_NATIVE  (1<<0)
+#define PLATFORM_HOSTED  (1<<1)
+#define PLATFORM_ANDROID (1<<2)
+#define PLATFORM_SDL     (1<<3)
 
 /* CONFIG_KEYPAD */
 #define PLAYER_PAD          1
@@ -427,6 +429,8 @@
 
 #elif defined(APPLICATION)
 #include "config/application.h"
+#define CONFIG_CPU 0
+#define CONFIG_STORAGE 0
 #else
 /* no known platform */
 #endif
@@ -689,11 +693,17 @@
 #define HAVE_EXTENDED_MESSAGING_AND_NAME
 #define HAVE_WAKEUP_EXT_CB
 
+
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+#define HAVE_PRIORITY_SCHEDULING
+#endif
+
 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
 #define HAVE_PRIORITY_SCHEDULING
 #define HAVE_SCHEDULER_BOOSTCTRL
 #endif /* PLATFORM_NATIVE */
 
+
 #define HAVE_SEMAPHORE_OBJECTS
 
 #if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC
diff --git a/firmware/export/config/application.h b/firmware/export/config/application.h
index a5583de..988f0d5 100644
--- a/firmware/export/config/application.h
+++ b/firmware/export/config/application.h
@@ -4,11 +4,13 @@
 #define TARGET_TREE /* this target is using the target tree system */
 
 /* We don't run on hardware directly */
-#define CONFIG_PLATFORM PLATFORM_HOSTED
+#ifdef ANDROID
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
+#else
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL)
+#endif
 /* For Rolo and boot loader */
-/*
-#define MODEL_NUMBER 24
-*/
+#define MODEL_NUMBER 100
 
 #define MODEL_NAME   "Rockbox"
 
@@ -37,9 +39,17 @@
 /* define this if you would like tagcache to build on this target */
 #define HAVE_TAGCACHE
 
-/* LCD dimensions */
+/* LCD dimensions
+ *
+ * overriden by configure for application builds */
+#ifndef LCD_WIDTH
 #define LCD_WIDTH  320
-#define LCD_HEIGHT 240
+#endif
+
+#ifndef LCD_HEIGHT
+#define LCD_HEIGHT 480
+#endif
+
 #define LCD_DEPTH  16
 #define LCD_PIXELFORMAT 565
 
@@ -62,10 +72,10 @@
 #define CONFIG_CODEC SWCODEC
 
 #define CONFIG_KEYPAD COWON_D2_PAD
+
+#if (CONFIG_PLATFORM & PLATFORM_SDL)
 /* Use SDL audio/pcm in a SDL app build */
 #define HAVE_SDL
-
-#ifdef HAVE_SDL
 #define HAVE_SDL_AUDIO
 #endif
 
@@ -92,3 +102,5 @@
 
 /* Define this if a programmable hotkey is mapped */
 //#define HAVE_HOTKEY
+
+#define BOOTDIR "/.rockbox"
diff --git a/firmware/export/config/sim.h b/firmware/export/config/sim.h
index 5dcb4f6..066201a 100644
--- a/firmware/export/config/sim.h
+++ b/firmware/export/config/sim.h
@@ -99,7 +99,8 @@
 #define DEFAULT_BRIGHTNESS_SETTING MAX_BRIGHTNESS_SETTING
 #endif
 
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL)
 #define HAVE_SDL
 #define HAVE_SDL_AUDIO
-#define CONFIG_PLATFORM PLATFORM_HOSTED
+
 #define _ISOC99_SOURCE 1
diff --git a/firmware/export/debug.h b/firmware/export/debug.h
index f7f0f32..f19a96c 100644
--- a/firmware/export/debug.h
+++ b/firmware/export/debug.h
@@ -21,6 +21,7 @@
 #ifndef DEBUG_H
 #define DEBUG_H
 
+#include "config.h"
 #include "gcc_extensions.h"
 
 extern void debug_init(void);
@@ -34,7 +35,11 @@
 /*  */
 #if defined(SIMULATOR) && !defined(__PCTOOL__)
 #define DEBUGF  debugf
-#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__)
+#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__) && defined(DEBUG)
+#elif (CONFIG_PLATFORM & PLATFORM_ANDROID)
+#include "system-target.h"
+#define DEBUGF LOG
+#define LDEBUGF(...)
 #else
 #if defined(DEBUG)
 
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index c4b7d1f..2853c0b 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -79,9 +79,19 @@
 
 #define MAXTHREADS (BASETHREADS+TARGET_EXTRA_THREADS)
 
+/*
+ * We need more stack when we run under a host
+ * maybe more expensive C lib functions?
+ *
+ * simulator doesn't simulate stack usage anyway but well ... */
+#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SIMULATOR))
 #define DEFAULT_STACK_SIZE 0x400 /* Bytes */
+#else
+#define DEFAULT_STACK_SIZE 0x1000 /* Bytes */
+#endif
 
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+
+#if (CONFIG_PLATFORM & (PLATFORM_NATIVE|PLATFORM_ANDROID))
 /* Need to keep structures inside the header file because debug_menu
  * needs them. */
 #ifdef CPU_COLDFIRE
@@ -101,7 +111,7 @@
     uint32_t pr;    /*    32 - Procedure register */
     uint32_t start; /*    36 - Thread start address, or NULL when started */
 };
-#elif defined(CPU_ARM)
+#elif defined(CPU_ARM) || (CONFIG_PLATFORM & PLATFORM_ANDROID)
 struct regs
 {
     uint32_t r[8];  /*  0-28 - Registers r4-r11 */
diff --git a/firmware/sound.c b/firmware/sound.c
index 76f1dd0..4cc63f4 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -273,7 +273,7 @@
 
 #elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985)
     audiohw_set_headphone_vol(tenthdb2master(l), tenthdb2master(r));
-#elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO)
+#elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO) || defined(ANDROID)
     audiohw_set_volume(current_volume);
 #endif
 #else /* HAVE_SDL_AUDIO */
diff --git a/firmware/target/hosted/android/app/adc-target.h b/firmware/target/hosted/android/app/adc-target.h
new file mode 100644
index 0000000..f8069be
--- /dev/null
+++ b/firmware/target/hosted/android/app/adc-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __ADC_TARGET_H__
+#define __ADC_TARGET_H__
+
+#endif /* __ADC_TARGET_H__ */
diff --git a/firmware/target/hosted/android/app/backlight-target.h b/firmware/target/hosted/android/app/backlight-target.h
new file mode 100644
index 0000000..f753e7c
--- /dev/null
+++ b/firmware/target/hosted/android/app/backlight-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __BACKLIGHT_TARGET_H__
+#define __BACKLIGHT_TARGET_H__
+
+#endif /* __BACKLIGHT_TARGET_H__ */
diff --git a/firmware/target/hosted/android/app/button-application.c b/firmware/target/hosted/android/app/button-application.c
new file mode 100644
index 0000000..a27f769
--- /dev/null
+++ b/firmware/target/hosted/android/app/button-application.c
@@ -0,0 +1,29 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************9*************************/
+
+
+#include "button.h"
+
+int key_to_button(int keyboard_key)
+{
+    (void)keyboard_key;
+    return BUTTON_NONE;
+}
diff --git a/firmware/target/hosted/android/app/button-target.h b/firmware/target/hosted/android/app/button-target.h
new file mode 100644
index 0000000..329ed65
--- /dev/null
+++ b/firmware/target/hosted/android/app/button-target.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Rob Purchase
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _BUTTON_TARGET_H_
+#define _BUTTON_TARGET_H_
+
+#include <stdbool.h>
+#include "config.h"
+
+#undef button_init_device
+void button_init_device(void);
+int button_read_device(int *data);
+
+/* Main unit's buttons */
+#define BUTTON_POWER      0x00000001
+#define BUTTON_PLUS       0x00000002
+#define BUTTON_MINUS      0x00000004
+#define BUTTON_MENU       0x00000008
+
+/* Compatibility hacks for flipping. Needs a somewhat better fix. */
+#define BUTTON_LEFT  BUTTON_MIDLEFT
+#define BUTTON_RIGHT BUTTON_MIDRIGHT
+#define BUTTON_UP    BUTTON_TOPMIDDLE
+#define BUTTON_DOWN  BUTTON_BOTTOMMIDDLE
+
+/* Touch Screen Area Buttons */
+#define BUTTON_TOPLEFT      0x00000010
+#define BUTTON_TOPMIDDLE    0x00000020
+#define BUTTON_TOPRIGHT     0x00000040
+#define BUTTON_MIDLEFT      0x00000080
+#define BUTTON_CENTER       0x00000100
+#define BUTTON_MIDRIGHT     0x00000200
+#define BUTTON_BOTTOMLEFT   0x00000400
+#define BUTTON_BOTTOMMIDDLE 0x00000800
+#define BUTTON_BOTTOMRIGHT  0x00001000
+
+#define BUTTON_MAIN 0x1FFF
+
+/* No remote */
+#define BUTTON_REMOTE 0
+
+/* Software power-off */
+#define POWEROFF_BUTTON BUTTON_POWER
+#define POWEROFF_COUNT 10
+                
+#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/hosted/android/app/i2c-target.h b/firmware/target/hosted/android/app/i2c-target.h
new file mode 100644
index 0000000..89f0436
--- /dev/null
+++ b/firmware/target/hosted/android/app/i2c-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __I2C_TARGET_H__
+#define __I2C_TARGET_H__
+
+#endif /* __I2C_TARGET_H__ */
diff --git a/firmware/target/hosted/android/app/usb-target.h b/firmware/target/hosted/android/app/usb-target.h
new file mode 100644
index 0000000..10e0467
--- /dev/null
+++ b/firmware/target/hosted/android/app/usb-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __USB_TARGET_H__
+#define __USB_TARGET_H__
+
+#endif /* __USB_TARGET_H__ */
diff --git a/firmware/target/hosted/android/button-android.c b/firmware/target/hosted/android/button-android.c
new file mode 100644
index 0000000..67e8ca1
--- /dev/null
+++ b/firmware/target/hosted/android/button-android.c
@@ -0,0 +1,87 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#include <jni.h>
+#include <stdbool.h>
+#include "config.h"
+#include "kernel.h"
+#include "system.h"
+#include "touchscreen.h"
+
+static long last_touch;
+static int last_y, last_x;
+
+static enum {
+    STATE_UNKNOWN,
+    STATE_UP,
+    STATE_DOWN,
+} last_state = STATE_UNKNOWN;
+
+
+/*
+ * this writes in an interrupt-like fashion the last pixel coordinates
+ * that the user pressed on the screen */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxFramebuffer_pixelHandler(JNIEnv*env, jobject this,
+                                                        int x, int y)
+{
+    (void)env;
+    (void)this;
+    last_x = x;
+    last_y = y;
+    last_touch = current_tick;
+}
+
+/*
+ * this notifies us in an interrupt-like fashion whether the user just
+ * began or stopped the touch action */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxFramebuffer_touchHandler(JNIEnv*env, jobject this,
+                                                        int down)
+{
+    (void)env;
+    (void)this;
+    if (down)
+        last_state = STATE_DOWN;
+    else
+        last_state = STATE_UP;
+}
+
+void button_init_device(void)
+{
+    last_touch = 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);
+    if (last_state == STATE_DOWN)
+    {
+        return btn;
+    }
+    else
+    {
+        *data = last_x = last_y = 0;
+        return 0;
+    }
+}
diff --git a/firmware/target/hosted/android/buttonmap.h b/firmware/target/hosted/android/buttonmap.h
new file mode 100644
index 0000000..e90b8a4
--- /dev/null
+++ b/firmware/target/hosted/android/buttonmap.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Fred Bauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __BUTTONMAP_H__
+#define __BUTTONMAP_H__
+/* Button maps: simulated key, x, y, radius, name */
+/* Run sim with --mapping to get coordinates      */
+/* or --debugbuttons to check                     */
+/* The First matching button is returned          */
+struct button_map {
+    int button, x, y, radius;
+    char *description;
+};
+
+extern struct button_map bm[];
+
+int xy2button( int x, int y);
+
+/* for the sim, these function is implemented in uisimulator/buttonmap/ *.c */
+int key_to_button(int keyboard_button);
+#ifdef HAVE_TOUCHSCREEN
+int key_to_touch(int keyboard_button, unsigned int mouse_coords);
+#endif
+
+#endif /* __BUTTONMAP_H__ */
diff --git a/firmware/target/hosted/android/kernel-android.c b/firmware/target/hosted/android/kernel-android.c
new file mode 100644
index 0000000..9594516
--- /dev/null
+++ b/firmware/target/hosted/android/kernel-android.c
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#include <jni.h>
+#include "config.h"
+#include "system.h"
+
+extern JNIEnv *env_ptr;
+extern jclass  RockboxActivity_class;
+extern jobject RockboxActivity_instance;
+
+static jclass  RockboxTimer_class;
+static jobject RockboxTimer_instance;
+static jmethodID java_wait_for_interrupt;
+static bool    initialized = false;
+
+/*
+ * This is called from the separate Timer java thread. I have not added any
+ * interrupt simulation to it (like the sdl counterpart does),
+ * I think this is probably not needed, unless code calls disable_interrupt()
+ * in order to be protected from tick tasks, but I can't remember a place right
+ * now.
+ *
+ * No synchronisation mechanism either. This could possibly be problematic,
+ * but we'll see :)
+ */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxTimer_timerTask(JNIEnv *env, jobject this)
+{
+    (void)env;
+    (void)this;
+    call_tick_tasks();
+}
+
+void tick_start(unsigned int interval_in_ms)
+{
+    JNIEnv e = *env_ptr;
+    /* first, create a new Timer instance */
+    RockboxTimer_class  = e->FindClass(env_ptr, "org/rockbox/RockboxTimer");
+    jmethodID constructor = e->GetMethodID(env_ptr,
+                                           RockboxTimer_class,
+                                           "<init>",
+                                           "(J)V");
+    /* the constructor will do the tick_start */
+    RockboxTimer_instance = e->NewObject(env_ptr,
+                                         RockboxTimer_class,
+                                         constructor,
+                                         (jlong)interval_in_ms);
+
+    /* get our wfi func also */
+    java_wait_for_interrupt = e->GetMethodID(env_ptr,
+                                             RockboxTimer_class,
+                                             "java_wait_for_interrupt",
+                                             "()V");
+    /* it's now safe to call java_wait_for_interrupt */
+    initialized = true;
+}
+
+void wait_for_interrupt(void)
+{
+    if (LIKELY(initialized))
+    {
+        (*env_ptr)->CallVoidMethod(env_ptr,
+                                   RockboxTimer_instance,
+                                   java_wait_for_interrupt);
+    }
+}
+ 
+bool timer_register(int reg_prio, void (*unregister_callback)(void),
+                    long cycles, void (*timer_callback)(void))
+{
+    (void)reg_prio;
+    (void)unregister_callback;
+    (void)cycles;
+    (void)timer_callback;
+    return false;
+}
+
+bool timer_set_period(long cycles)
+{
+    (void)cycles;
+    return false;
+}
+
+void timer_unregister(void)
+{
+}
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c
new file mode 100644
index 0000000..ef4004e
--- /dev/null
+++ b/firmware/target/hosted/android/lcd-android.c
@@ -0,0 +1,291 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#include <jni.h>
+#include "config.h"
+#include "system.h"
+#include "lcd.h"
+
+extern JNIEnv *env_ptr;
+extern jclass  RockboxActivity_class;
+extern jobject RockboxActivity_instance;
+
+static jobject Framebuffer_instance;
+static jmethodID java_lcd_update;
+
+void lcd_init_device(void)
+{
+    /* get the RockboxFramebuffer instance allocated by the activity */
+    jfieldID id = (*env_ptr)->GetFieldID(env_ptr,
+                                         RockboxActivity_class,
+                                         "fb",
+                                         "Lorg/rockbox/RockboxFramebuffer;");
+
+    Framebuffer_instance = (*env_ptr)->GetObjectField(env_ptr,
+                                                      RockboxActivity_instance,
+                                                      id);
+
+    jclass Framebuffer_class = (*env_ptr)->GetObjectClass(env_ptr,
+                                                          Framebuffer_instance);
+
+    /* get the java init function and call it. it'll set up a bitmap
+     * based on LCD_WIDTH, LCD_HEIGHT and the ByteBuffer which directly maps
+     * our framebuffer */
+
+    jmethodID java_init_lcd = (*env_ptr)->GetMethodID(env_ptr,
+                                                      Framebuffer_class,
+                                                      "java_lcd_init",
+                                                      "(IILjava/nio/ByteBuffer;)V");
+    java_lcd_update = (*env_ptr)->GetMethodID(env_ptr,
+                                              Framebuffer_class,
+                                              "java_lcd_update",
+                                              "()V");
+
+    /* map the framebuffer to a ByteBuffer, this way lcd updates will
+     * be directly feched from the framebuffer */
+    jobject buf = (*env_ptr)->NewDirectByteBuffer(env_ptr,
+                                                  lcd_framebuffer,
+                                                  sizeof(lcd_framebuffer));
+    
+    (*env_ptr)->CallVoidMethod(env_ptr,
+                               Framebuffer_instance,
+                               java_init_lcd,
+                               LCD_WIDTH, LCD_HEIGHT, buf);
+}
+
+void lcd_update()
+{
+    /* tell the system we're ready for drawing */
+    (*env_ptr)->CallVoidMethod(env_ptr, Framebuffer_instance, java_lcd_update);
+}
+
+void lcd_update_rect(int x, int y, int height, int width)
+{
+    /* can't do partial updates yet */
+    (void)x; (void)y; (void)height; (void)width;
+    lcd_update();
+}
+
+/* below is a plain copy from lcd-sdl.c */
+
+/**
+ * |R|   |1.000000 -0.000001  1.402000| |Y'|
+ * |G| = |1.000000 -0.334136 -0.714136| |Pb|
+ * |B|   |1.000000  1.772000  0.000000| |Pr|
+ * Scaled, normalized, rounded and tweaked to yield RGB 565:
+ * |R|   |74   0 101| |Y' -  16| >> 9
+ * |G| = |74 -24 -51| |Cb - 128| >> 8
+ * |B|   |74 128   0| |Cr - 128| >> 9
+ */
+#define YFAC    (74)
+#define RVFAC   (101)
+#define GUFAC   (-24)
+#define GVFAC   (-51)
+#define BUFAC   (128)
+
+static inline int clamp(int val, int min, int max)
+{
+    if (val < min)
+        val = min;
+    else if (val > max)
+        val = max;
+    return val;
+}
+
+void lcd_yuv_set_options(unsigned options)
+{
+    (void)options;
+}
+
+/* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
+   in the core */
+void lcd_blit_yuv(unsigned char * const src[3],
+                  int src_x, int src_y, int stride,
+                  int x, int y, int width, int height)
+{
+    const unsigned char *ysrc, *usrc, *vsrc;
+    int linecounter;
+    fb_data *dst, *row_end;
+    long z;
+
+    /* width and height must be >= 2 and an even number */
+    width &= ~1;
+    linecounter = height >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+    dst     = &lcd_framebuffer[y][x];
+    row_end = dst + width;
+#else
+    dst     = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
+    row_end = dst + LCD_WIDTH * width;
+#endif
+
+    z    = stride * src_y;
+    ysrc = src[0] + z + src_x;
+    usrc = src[1] + (z >> 2) + (src_x >> 1);
+    vsrc = src[2] + (usrc - src[1]);
+
+    /* stride => amount to jump from end of last row to start of next */
+    stride -= width;
+
+    /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
+
+    do
+    {
+        do
+        {
+            int y, cb, cr, rv, guv, bu, r, g, b;
+
+            y  = YFAC*(*ysrc++ - 16);
+            cb = *usrc++ - 128;
+            cr = *vsrc++ - 128;
+
+            rv  =            RVFAC*cr;
+            guv = GUFAC*cb + GVFAC*cr;
+            bu  = BUFAC*cb;
+
+            r = y + rv;
+            g = y + guv;
+            b = y + bu;
+
+            if ((unsigned)(r | g | b) > 64*256-1)
+            {
+                r = clamp(r, 0, 64*256-1);
+                g = clamp(g, 0, 64*256-1);
+                b = clamp(b, 0, 64*256-1);
+            }
+
+            *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+            dst++;
+#else
+            dst += LCD_WIDTH;
+#endif
+
+            y = YFAC*(*ysrc++ - 16);
+            r = y + rv;
+            g = y + guv;
+            b = y + bu;
+
+            if ((unsigned)(r | g | b) > 64*256-1)
+            {
+                r = clamp(r, 0, 64*256-1);
+                g = clamp(g, 0, 64*256-1);
+                b = clamp(b, 0, 64*256-1);
+            }
+
+            *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+            dst++;
+#else
+            dst += LCD_WIDTH;
+#endif
+        }
+        while (dst < row_end);
+
+        ysrc    += stride;
+        usrc    -= width >> 1;
+        vsrc    -= width >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+        row_end += LCD_WIDTH;
+        dst     += LCD_WIDTH - width;
+#else
+        row_end -= 1;
+        dst     -= LCD_WIDTH*width + 1;
+#endif
+
+        do
+        {
+            int y, cb, cr, rv, guv, bu, r, g, b;
+
+            y  = YFAC*(*ysrc++ - 16);
+            cb = *usrc++ - 128;
+            cr = *vsrc++ - 128;
+
+            rv  =            RVFAC*cr;
+            guv = GUFAC*cb + GVFAC*cr;
+            bu  = BUFAC*cb;
+
+            r = y + rv;
+            g = y + guv;
+            b = y + bu;
+
+            if ((unsigned)(r | g | b) > 64*256-1)
+            {
+                r = clamp(r, 0, 64*256-1);
+                g = clamp(g, 0, 64*256-1);
+                b = clamp(b, 0, 64*256-1);
+            }
+
+            *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+            dst++;
+#else
+            dst += LCD_WIDTH;
+#endif
+
+            y = YFAC*(*ysrc++ - 16);
+            r = y + rv;
+            g = y + guv;
+            b = y + bu;
+
+            if ((unsigned)(r | g | b) > 64*256-1)
+            {
+                r = clamp(r, 0, 64*256-1);
+                g = clamp(g, 0, 64*256-1);
+                b = clamp(b, 0, 64*256-1);
+            }
+
+            *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+            dst++;
+#else
+            dst += LCD_WIDTH;
+#endif
+        }
+        while (dst < row_end);
+
+        ysrc    += stride;
+        usrc    += stride >> 1;
+        vsrc    += stride >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+        row_end += LCD_WIDTH;
+        dst     += LCD_WIDTH - width;
+#else
+        row_end -= 1;
+        dst     -= LCD_WIDTH*width + 1;
+#endif
+    }
+    while (--linecounter > 0);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+    lcd_update_rect(x, y, width, height);
+#else
+    lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
+#endif
+}
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
new file mode 100644
index 0000000..91978f4
--- /dev/null
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -0,0 +1,174 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <jni.h>
+#include <stdbool.h>
+#include <system.h>
+#include "pcm.h"
+
+extern JNIEnv *env_ptr;
+extern jclass  RockboxActivity_class;
+extern jobject RockboxActivity_instance;
+
+/* infos about our pcm chunks */
+static size_t  pcm_data_size;
+static char   *pcm_data_start;
+
+/* cache frequently called methods */
+static jmethodID play_pause_method;
+static jmethodID stop_method;
+static jmethodID set_volume_method;
+static jclass    RockboxPCM_class;
+static jobject   RockboxPCM_instance;
+
+
+/*
+ * transfer our raw data into a java array
+ *
+ * a bit of a monster functions, but it should cover all cases to overcome
+ * the issue that the chunk size of the java layer and our pcm chunks are
+ * differently sized
+ *
+ * afterall, it only copies the raw pcm data from pcm_data_start to
+ * the passed byte[]-array
+ *
+ * it is called from the PositionMarker callback of AudioTrack
+ **/
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
+                                                  jobject this,
+                                                  jbyteArray arr)
+{
+    (void)this;
+    size_t len;
+	size_t array_size = (*env)->GetArrayLength(env, arr);
+    if (array_size > pcm_data_size)
+        len = pcm_data_size;
+    else
+        len = array_size;
+
+	(*env)->SetByteArrayRegion(env, arr, 0, len, pcm_data_start);
+
+    if (array_size > pcm_data_size)
+    {   /* didn't have enough data for the array ? */
+        size_t remaining = array_size - pcm_data_size;
+        size_t offset = len;
+    retry:
+        pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
+        if (pcm_data_size == 0)
+            return;
+        if (remaining > pcm_data_size)
+        {   /* got too little data, get more ... */
+            (*env)->SetByteArrayRegion(env, arr, offset, pcm_data_size, pcm_data_start);
+            /* advance in the java array by the amount we copied */
+            offset += pcm_data_size;
+            /* we copied at least a bit */
+            remaining -= pcm_data_size;
+            /* let's get another buch of data and try again */
+            goto retry;
+        }
+        else
+            (*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start);
+        len = remaining;
+    }
+    pcm_data_start += len;
+    pcm_data_size -= len;
+}
+
+void pcm_play_lock(void)
+{
+}
+
+void pcm_play_unlock(void)
+{
+}
+
+void pcm_dma_apply_settings(void)
+{
+}
+
+void pcm_play_dma_start(const void *addr, size_t size)
+{
+    pcm_data_start = (char*)addr;
+    pcm_data_size = size;
+    
+    pcm_play_dma_pause(false);
+}
+
+void pcm_play_dma_stop(void)
+{
+    (*env_ptr)->CallVoidMethod(env_ptr,
+                               RockboxPCM_instance,
+                               stop_method);
+}
+
+void pcm_play_dma_pause(bool pause)
+{
+    (*env_ptr)->CallVoidMethod(env_ptr,
+                               RockboxPCM_instance,
+                               play_pause_method,
+                               (int)pause);
+}
+
+size_t pcm_get_bytes_waiting(void)
+{
+    return pcm_data_size;
+}
+
+const void * pcm_play_dma_get_peak_buffer(int *count)
+{
+    uintptr_t addr = (uintptr_t)pcm_data_start;
+    *count = pcm_data_size / 4;
+    return (void *)((addr + 3) & ~3);
+}
+
+void pcm_play_dma_init(void)
+{
+    /* in order to have background music playing after leaving the activity,
+     * we need to allocate the PCM object from the Rockbox thread (the Activity
+     * runs in a separate thread because it would otherwise kill us when
+     * stopping it)
+     *
+     * Luckily we only reference the PCM object from here, so it's safe (and
+     * clean) to allocate it here
+     **/
+    JNIEnv e = *env_ptr;
+    /* get the class and its constructor */
+    RockboxPCM_class = e->FindClass(env_ptr, "org/rockbox/RockboxPCM");
+    jmethodID constructor = e->GetMethodID(env_ptr, RockboxPCM_class, "<init>", "()V");
+    /* instance = new RockboxPCM() */
+    RockboxPCM_instance = e->NewObject(env_ptr, RockboxPCM_class, constructor);
+    /* cache needed methods */
+    play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V");
+    set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
+    stop_method       = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
+    /* get initial pcm data, if any */
+    pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
+}
+
+void pcm_postinit(void)
+{
+}
+
+void pcm_set_mixer_volume(int volume)
+{
+    (*env_ptr)->CallVoidMethod(env_ptr, RockboxPCM_instance, set_volume_method, volume);
+}
diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c
new file mode 100644
index 0000000..07dff2e
--- /dev/null
+++ b/firmware/target/hosted/android/system-android.c
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#include <jni.h>
+#include "config.h"
+#include "system.h"
+
+void system_exception_wait(void) { }
+void system_reboot(void) { }
+void power_off(void) { }
+void system_init(void) { }
+
+
+/* global fields for use with various JNI calls */
+JNIEnv *env_ptr;
+jobject RockboxActivity_instance;
+jclass  RockboxActivity_class;
+
+uintptr_t *stackbegin;
+uintptr_t *stackend;
+
+extern int main(void);
+/* this is the entry point of the android app initially called by jni */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxActivity_main(JNIEnv *env, jobject this)
+{
+    /* hack!!! we can't have a valid stack pointer otherwise.
+     * but we don't really need it anyway, thread.c only needs it
+     * for overflow detection which doesn't apply for the main thread
+     * (it's managed by the OS) */
+
+    (void)env;
+    (void)this;
+    volatile uintptr_t stack = 0;
+    stackbegin = stackend = &stack;
+    env_ptr = env;
+    RockboxActivity_instance = this;
+    RockboxActivity_class = (*env)->GetObjectClass(env, this);
+    main();
+}
diff --git a/firmware/target/hosted/android/system-target.h b/firmware/target/hosted/android/system-target.h
new file mode 100644
index 0000000..210d191
--- /dev/null
+++ b/firmware/target/hosted/android/system-target.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ *             __________               __   ___.                  
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___  
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /  
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <   
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \  
+ *                     \/            \/     \/    \/            \/ 
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __SYSTEM_TARGET_H__
+#define __SYSTEM_TARGET_H__
+
+#define disable_irq()
+#define enable_irq()
+#define disable_irq_save() 0
+#define restore_irq(level) (void)level
+
+void power_off(void);
+
+#include <android/log.h>
+#define LOG_TAG "Rockbox"
+#define LOG(args...) \
+	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ##args);
+
+#endif /* __SYSTEM_TARGET_H__ */
+
+#define NEED_GENERIC_BYTESWAPS
+
diff --git a/firmware/target/hosted/android/thread-android-arm.c b/firmware/target/hosted/android/thread-android-arm.c
new file mode 100644
index 0000000..baf8b84
--- /dev/null
+++ b/firmware/target/hosted/android/thread-android-arm.c
@@ -0,0 +1,98 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Thom Johansen
+ * Copyright (C) 2010 by Thomas Martitz (Android-suitable core_sleep())
+ *
+ * Generic ARM threading support
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <jni.h>
+/*---------------------------------------------------------------------------
+ * Start the thread running and terminate it if it returns
+ *---------------------------------------------------------------------------
+ */
+static void __attribute__((naked,used)) start_thread(void)
+{
+    /* r0 = context */
+    asm volatile (
+        "ldr    sp, [r0, #32]            \n" /* Load initial sp */
+        "ldr    r4, [r0, #40]            \n" /* start in r4 since it's non-volatile */
+        "mov    r1, #0                   \n" /* Mark thread as running */
+        "str    r1, [r0, #40]            \n"
+        "mov    lr, pc                   \n" /* Call thread function */
+        "bx     r4                       \n"
+    ); /* No clobber list - new thread doesn't care */
+    thread_exit();
+}
+
+/* For startup, place context pointer in r4 slot, start_thread pointer in r5
+ * slot, and thread function pointer in context.start. See load_context for
+ * what happens when thread is initially going to run. */
+#define THREAD_STARTUP_INIT(core, thread, function) \
+    ({ (thread)->context.r[0] = (uint32_t)&(thread)->context,  \
+       (thread)->context.r[1] = (uint32_t)start_thread, \
+       (thread)->context.start = (uint32_t)function; })
+
+
+/*---------------------------------------------------------------------------
+ * Store non-volatile context.
+ *---------------------------------------------------------------------------
+ */
+static inline void store_context(void* addr)
+{
+    asm volatile(
+        "stmia  %0, { r4-r11, sp, lr } \n"
+        : : "r" (addr)
+    );
+}
+
+/*---------------------------------------------------------------------------
+ * Load non-volatile context.
+ *---------------------------------------------------------------------------
+ */
+static inline void load_context(const void* addr)
+{
+    asm volatile(
+        "ldr     r0, [%0, #40]          \n" /* Load start pointer */
+        "cmp     r0, #0                 \n" /* Check for NULL */
+
+        /* If not already running, jump to start */
+        "ldmneia %0, { r0, pc }         \n"
+        "ldmia   %0, { r4-r11, sp, lr } \n" /* Load regs r4 to r14 from context */
+        : : "r" (addr) : "r0" /* only! */
+    );
+}
+
+/*
+ * this core sleep suspends the OS thread rockbox runs under, which greatly
+ * reduces cpu usage (~100% to <10%)
+ *
+ * it returns when the RockboxTimer notified us, i.e. at each tick
+ * (after it called the tick tasks)
+ *
+ * wait_for_interrupt is implemented in kernel-android.c
+ **/
+
+extern void wait_for_interrupt(void);
+static inline void core_sleep(void)
+{
+    wait_for_interrupt();
+}
+
+
diff --git a/firmware/thread.c b/firmware/thread.c
index c00fc36..b3d8ec3 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -123,8 +123,13 @@
 struct thread_entry threads[MAXTHREADS] IBSS_ATTR;
 
 static const char main_thread_name[] = "main";
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
 extern uintptr_t stackbegin[];
 extern uintptr_t stackend[];
+#else
+extern uintptr_t *stackbegin;
+extern uintptr_t *stackend;
+#endif
 
 static inline void core_sleep(IF_COP_VOID(unsigned int core))
         __attribute__((always_inline));
@@ -170,7 +175,9 @@
 /****************************************************************************
  * Processor-specific section - include necessary core support
  */
-#if defined(CPU_ARM)
+#if defined(ANDROID)
+#include "thread-android-arm.c"
+#elif defined(CPU_ARM)
 #include "thread-arm.c"
 #if defined (CPU_PP)
 #include "thread-pp.c"
@@ -1150,7 +1157,7 @@
     store_context(&thread->context);
 
     /* Check if the current thread stack is overflown */
-    if (UNLIKELY(thread->stack[0] != DEADBEEF))
+    if (UNLIKELY(thread->stack[0] != DEADBEEF) && thread->stack_size > 0)
         thread_stkov(thread);
 
 #if NUM_CORES > 1
@@ -2319,7 +2326,9 @@
  */
 int thread_stack_usage(const struct thread_entry *thread)
 {
-    return stack_usage(thread->stack, thread->stack_size);
+    if (LIKELY(thread->stack_size > 0))
+        return stack_usage(thread->stack, thread->stack_size);
+    return 0;
 }
 
 #if NUM_CORES > 1
diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index 7a127de..094214d 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -631,6 +631,8 @@
     }
     else {
         unless (".rockbox" eq $rbdir) {
+            mkpath($rbdir);
+            rmtree($rbdir);
             move(".rockbox", $rbdir);
             print "mv .rockbox $rbdir\n" if $verbose;
         }
diff --git a/tools/configure b/tools/configure
index ce23c2a..7504d56 100755
--- a/tools/configure
+++ b/tools/configure
@@ -14,6 +14,7 @@
 # global LD options for all platforms
 GLOBAL_LDOPTS=""
 
+extradefines=""
 use_logf="#undef ROCKBOX_HAS_LOGF"
 use_bootchart="#undef DO_BOOTCHART"
 
@@ -25,7 +26,10 @@
 libdir=
 bindir_full=
 libdir_full=
-  
+
+app_platform=
+app_lcd_width=
+app_lcd_height=
 #
 # Begin Function Definitions
 #
@@ -47,6 +51,59 @@
  OC=${prefix}objcopy
 }
 
+app_get_platform() {
+    echo "Select your platform: (S)DL, (A)ndroid (default: Android)"
+    choice=`input`
+    case $choice in
+        s|S*)     app_platform="sdl" ;;
+        *|a|A*)   app_platform="android" ;;
+    esac
+
+    echo "Selected $app_platform platform"
+    echo "Select the LCD resolution seperated with enter: XxY (default: 320x480)"
+    app_lcd_width=`input`
+    if [ -z "$app_lcd_width" ]; then app_lcd_width="320"; fi
+    app_lcd_height=`input`
+    if [ -z "$app_lcd_height" ]; then app_lcd_height="480"; fi
+    echo "Selected $app_lcd_width x $app_lcd_height resolution"
+
+    app_lcd_width="#define LCD_WIDTH $app_lcd_width"
+    app_lcd_height="#define LCD_HEIGHT $app_lcd_height"
+    # setup files and paths depending on the platform
+    if [ "$app_platform" = "sdl" ]; then
+        if [ -z "$PREFIX" ]; then
+            rbdir="/usr/local/share/rockbox"
+            bindir="/usr/local/bin"
+            bindir_full=$bindir
+            libdir="/usr/local/lib"
+            libdir_full=$libdir
+        else
+            rbdir=`realpath $PREFIX/share/rockbox`
+            bindir="$PREFIX/bin"
+            libdir="$PREFIX/lib"
+            if [ -d bindir ]; then
+                bindir_full=`realpath $bindir`
+            fi
+            if [ -d libdir ]; then
+                libdir_full=`realpath $libdir`
+            fi
+        fi        
+        output="rockbox"
+        bootoutput="rockbox"
+    elif [ "$app_platform" = "android" ]; then
+        if [ -n "$PREFIX" ]; then
+            echo "WARNING: PREFIX not supported on Android. You can however use --rbdir"
+        fi
+        rbdir="/data/data/org.rockbox/app_rockbox/rockbox"
+        bindir="/data/data/org.rockbox/lib"
+        bindir_full=$bindir
+        libdir="/data/data/org.rockbox/app_rockbox"
+        libdir_full=$libdir
+        output="librockbox.so"
+        bootoutput="librockbox.so"
+    fi
+}
+
 findarmgcc() {
   if [ "$ARG_ARM_EABI" != "0" ]; then
     prefixtools arm-elf-eabi-
@@ -102,6 +159,15 @@
   done
 }
 
+appcc () {
+    if [ "$1" = "sdl" ]; then
+        simcc "sdl-app"
+    elif [ "$1" = "android" ]; then
+        app_type=$1
+        androidcc
+    fi
+}
+
 simcc () {
 
  # default tool setup for native building
@@ -114,15 +180,17 @@
  GCCOPTIMIZE=''
  LDOPTS='-lm' # button-sdl.c uses sqrt()
 
- # default output binary name
- output="rockboxui"
+ # default output binary name, don't override app_get_platform()
+ if [ "$app_type" != "sdl-app" ]; then
+    output="rockboxui"
+ fi
 
  # default share option, override below if needed
  SHARED_FLAG="-shared"
 
  if [ "$win32crosscompile" = "yes" ]; then
    LDOPTS="$LDOPTS -mconsole"
-   output="rockboxui.exe"
+   output="$output.exe"
    winbuild="yes"
  else
  case $uname in
@@ -130,7 +198,7 @@
    echo "Cygwin host detected"
 
    LDOPTS="$LDOPTS -mconsole"
-   output="rockboxui.exe"
+   output="$output.exe"
    winbuild="yes"
    ;;
 
@@ -138,7 +206,7 @@
    echo "MinGW host detected"
 
    LDOPTS="$LDOPTS -mconsole"
-   output="rockboxui.exe"
+   output="$output.exe"
    winbuild="yes"
    ;;
 
@@ -188,6 +256,7 @@
         LDOPTS="$LDOPTS `$sdl --libs`"
     fi
  fi
+ 
 
  GCCOPTS="$GCCOPTS -I\$(SIMDIR)"
 
@@ -379,6 +448,18 @@
  gccchoice="4.1.2"
 }
 
+androidcc () {
+    gccchoice="4.4.0"
+    prefixtools $ANDROID_NDK_PATH/build/prebuilt/linux-x86/arm-eabi-$gccchoice/bin/arm-eabi-
+    GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib// -e s/-Wundef//`
+    GCCOPTS="$GCCOPTS -std=gnu99 -ffunction-sections -fno-short-enums -march=armv5te -mtune=xscale -msoft-float -fomit-frame-pointer"
+    GLOBAL_LDOPTS="$GLOBAL_LDOPTS -nostdlib -lc -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -L$ANDROID_NDK_PATH/build/platforms/android-4/arch-arm/usr/lib/ -Wl,-rpath-link=$ANDROID_NKD_PATH/build/platforms/android-4/arch-arm/usr/lib"
+    LDOPTS="$LDOPTS -shared -nostdlib -lm -ldl -llog"
+    extradefines="$extradefines -DANDROID"
+    endian="little"
+    SHARED_FLAG="-shared"
+}
+
 whichadvanced () {
   atype=`echo "$1" | cut -c 2-`
   ##################################################################
@@ -975,7 +1056,7 @@
  143) YP-S3               160) Vibe 500          131) Mini2440
 
  ==MPIO==                                        == Application ==
- 170) HD200                                      200) SDL 320x240
+ 170) HD200                                      200) Application
 
 EOF
 
@@ -2609,40 +2690,23 @@
     modelname="application"
     target="-DAPPLICATION"
 
-    if [ -z "$PREFIX" ]; then
-        rbdir="/usr/local/share/rockbox"
-        bindir="/usr/local/bin"
-        bindir_full=$bindir
-        libdir="/usr/local/lib"
-        libdir_full=$libdir
-    else
-        rbdir=`realpath $PREFIX/share/rockbox`
-        bindir="$PREFIX/bin"
-        libdir="$PREFIX/lib"
-        if [ -d bindir ]; then
-            bindir_full=`realpath $bindir`
-        fi
-        if [ -d libdir ]; then
-            libdir_full=`realpath $libdir`
-        fi
-    fi
     need_full_path="yes"
+    app_get_platform
 
     memory=8
     uname=`uname`
-    simcc "sdl-app"
+
+    appcc "$app_platform"
     tool="cp "
     boottool="cp "
     bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
     bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
-    output="rockbox"
-    bootoutput="bootloader-cowond2.bin"
     appextra="recorder:gui:radio"
     plugins=""
     swcodec="yes"
     # architecture, manufacturer and model for the target-tree build
     t_cpu="hosted"
-    t_manufacturer="sdl"
+    t_manufacturer="$app_platform"
     t_model="app"
     ;;
 
@@ -2732,7 +2796,7 @@
     [Ii])
       appsdir='\$(ROOTDIR)/bootloader'
       apps="bootloader"
-      extradefines="-DBOOTLOADER -DE200R_INSTALLER -ffunction-sections -fdata-sections"
+      extradefines="$extradefines -DBOOTLOADER -DE200R_INSTALLER -ffunction-sections -fdata-sections"
       bootloader="1"
       echo "e200R-installer build selected"
       ;;
@@ -2743,11 +2807,11 @@
       variant=`input`
       case $variant in
         4)
-           extradefines="-DBOOTLOADER -DC200_ERASE -DC240_ERASE -ffunction-sections -fdata-sections"
+           extradefines="$extradefines -DBOOTLOADER -DC200_ERASE -DC240_ERASE -ffunction-sections -fdata-sections"
            echo "c240 eraser build selected"
         ;;
         5)
-           extradefines="-DBOOTLOADER -DC200_ERASE -DC250_ERASE -ffunction-sections -fdata-sections"
+           extradefines="$extradefines -DBOOTLOADER -DC200_ERASE -DC250_ERASE -ffunction-sections -fdata-sections"
            echo "c240 eraser build selected"
         ;;
       esac
@@ -2771,7 +2835,7 @@
               output=$bootoutput
           fi
       fi
-      extradefines="-DBOOTLOADER -ffunction-sections -fdata-sections"
+      extradefines="$extradefines -DBOOTLOADER -ffunction-sections -fdata-sections"
       bootloader="1"
       echo "Bootloader build selected"
       ;;
@@ -2782,7 +2846,7 @@
       fi
       debug="-DDEBUG"
       simulator="yes"
-      extradefines="-DSIMULATOR"
+      extradefines="$extradefines -DSIMULATOR"
       archosrom=""
       flash=""
       echo "Simulator build selected"
@@ -2792,7 +2856,7 @@
       whichadvanced $btype
       ;;
     [Gg])
-      extradefines="-DSTUB" # for target makefile symbol EXTRA_DEFINES
+      extradefines="$extradefines -DSTUB" # for target makefile symbol EXTRA_DEFINES
       appsdir='\$(ROOTDIR)/gdb'
       apps="stub"
       case $modelname in
@@ -2815,7 +2879,7 @@
       toolset='';
       t_cpu='';
       GCCOPTS='';
-      extradefines="-DDEBUG"
+      extradefines="$extradefines  -DDEBUG"
       appsdir='\$(ROOTDIR)/tools/checkwps';
       output='checkwps.'${modelname};
       archosrom='';
@@ -3048,6 +3112,8 @@
  -e "s<@have_backlight@<$have_backlight<g" \
  -e "s<@have_fmradio_in@<$have_fmradio_in<g" \
  -e "s<@have_ata_poweroff@<$have_ata_poweroff<g" \
+ -e "s<@lcd_width@<$app_lcd_width<g" \
+ -e "s<@lcd_height@<$app_lcd_height<g" \
 <<EOF
 /* This header was made by configure */
 #ifndef __BUILD_AUTOCONF_H
@@ -3075,6 +3141,10 @@
 @config_rtc@
 @have_rtc_alarm@
 
+/* lcd dimensions for application builds from configure */
+@lcd_width@
+@lcd_height@
+
 /* root of Rockbox */
 #define ROCKBOX_DIR "@RBDIR@"
 #define ROCKBOX_BINARY_PATH "@binpath@"
@@ -3089,6 +3159,10 @@
     TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/sdl/"
     TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/"
   fi
+  if [ -n "$app_platform" -a "$app_platform" = "android" ]; then
+    # android's gcc doesn't add this :/
+    TARGET_INC="$TARGET_INC -I$ANDROID_NDK_PATH/build/platforms/android-4/arch-arm/usr/include"
+  fi
   TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu/$t_manufacturer"
   TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu"
   GCCOPTS="$GCCOPTS"
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c
index 260e880..4c0fa33 100644
--- a/uisimulator/common/io.c
+++ b/uisimulator/common/io.c
@@ -25,7 +25,11 @@
 #include <stdarg.h>
 #include <sys/stat.h>
 #include <time.h>
-#ifndef WIN32
+#include "config.h"
+
+#define HAVE_STATVFS (0 == (CONFIG_PLATFORM & PLATFORM_ANDROID) && !defined(WIN32))
+
+#if HAVE_STATVFS
 #include <sys/statvfs.h>
 #endif
 
@@ -41,14 +45,18 @@
 #endif
 
 #include <fcntl.h>
+#if (CONFIG_PLATFORM & PLATFORM_SDL)
 #include <SDL.h>
 #include <SDL_thread.h>
+#include "thread-sdl.h"
+#else
+#define sim_thread_unlock() NULL
+#define sim_thread_lock(a)
+#endif
 #include "thread.h"
 #include "kernel.h"
 #include "debug.h"
-#include "config.h"
 #include "ata.h" /* for IF_MV2 et al. */
-#include "thread-sdl.h"
 #include "rbpaths.h"
 
 /* keep this in sync with file.h! */
@@ -193,7 +201,7 @@
 /** Simulator I/O engine routines **/
 #define IO_YIELD_THRESHOLD 512
 
-enum
+enum io_dir
 {
     IO_READ,
     IO_WRITE,
@@ -225,7 +233,7 @@
     return HZ;
 }
 
-static ssize_t io_trigger_and_wait(int cmd)
+static ssize_t io_trigger_and_wait(enum io_dir cmd)
 {
     void *mythread = NULL;
     ssize_t result;
@@ -246,6 +254,9 @@
     case IO_WRITE:
         result = write(io.fd, io.buf, io.count);
         break;
+        /* shut up gcc */
+    default:
+        result = -1;
     }
 
     /* Regain our status as current */
@@ -480,7 +491,7 @@
         if (free)
             *free = free_clusters * secperclus / 2 * (bytespersec / 512);
     }
-#else
+#elif HAVE_STATVFS
     struct statvfs vfs;
 
     if (!statvfs(".", &vfs)) {
@@ -490,9 +501,9 @@
             *size = vfs.f_blocks / 2 * (vfs.f_frsize / 512);
         if (free)
             *free = vfs.f_bfree / 2 * (vfs.f_frsize / 512);
-    }
+    } else
 #endif
-    else {
+    {
         if (size)
             *size = 0;
         if (free)
@@ -537,9 +548,19 @@
        to find an unused filename */
     for (codec_count = 0; codec_count < 10; codec_count++)
     {
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+        /* we need that path fixed, since get_user_file_path()
+         * gives us the folder on the sdcard where we cannot load libraries
+         * from (no exec permissions)
+         */
+        snprintf(path, sizeof(path),
+                 "/data/data/org.rockbox/app_rockbox/libtemp_codec_%d.so",
+                 codec_count);
+#else
         char name[MAX_PATH];
         const char *_name = get_user_file_path(ROCKBOX_DIR, 0, name, sizeof(name));
         snprintf(path, sizeof(path), "%s/_temp_codec%d.dll", get_sim_pathname(_name), codec_count);
+#endif
         fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU);
         if (fd >= 0)
             break;  /* Created a file ok */
diff --git a/uisimulator/common/stubs.c b/uisimulator/common/stubs.c
index 6d7d7de..a9011b9 100644
--- a/uisimulator/common/stubs.c
+++ b/uisimulator/common/stubs.c
@@ -21,8 +21,6 @@
 #include <stdio.h>
 #include <time.h>
 #include <stdbool.h>
-#include "thread-sdl.h"
-
 #include "debug.h"
 
 #include "screens.h"
@@ -35,7 +33,6 @@
 
 #include "ata.h" /* for volume definitions */
 
-extern char having_new_lcd;
 static bool storage_spinning = false;
 
 #if CONFIG_CODEC != SWCODEC
@@ -211,10 +208,13 @@
 }
 #endif
 
+#ifdef ARCHOS_PLAYER
 bool is_new_player(void)
 {
+    extern char having_new_lcd;
     return having_new_lcd;
 }
+#endif
 
 #ifdef HAVE_USB_POWER
 bool usb_powered(void)
diff --git a/uisimulator/uisimulator.make b/uisimulator/uisimulator.make
index b06b48c..dcbd799 100644
--- a/uisimulator/uisimulator.make
+++ b/uisimulator/uisimulator.make
@@ -30,7 +30,6 @@
 	$(SILENT)$(shell rm -f $@)
 	$(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
 
-# SIMLIB needs to be linked twice for some reason
 $(BUILDDIR)/$(BINARY): $$(OBJ) $(SIMLIB) $(VOICESPEEXLIB) $(FIRMLIB) $(SKINLIB)
 	$(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(SIMLIB) $(LDOPTS) $(GLOBAL_LDOPTS)
 
diff --git a/wps/WPSLIST b/wps/WPSLIST
index 3068f48..938caa1 100644
--- a/wps/WPSLIST
+++ b/wps/WPSLIST
@@ -292,6 +292,7 @@
 Author: Johannes Voggenthaler, Apoo Maha, Marc Guay, Alex Vanderpol, Jerry Lange, Keith Perri, Mark Fawcus, and Marianne Arnold with support from Rockbox developers and forums. Based on Cabbie by Yohann Misquitta.
 
 # Preferred font (including .fnt extension - leave blank for player):
+Font.320x480x16: 16-Adobe-Helvetica.fnt
 Font.320x240x16: 15-Adobe-Helvetica.fnt
 Font.240x400x16: 16-Adobe-Helvetica.fnt
 Font.240x320x16: 15-Adobe-Helvetica.fnt
@@ -320,6 +321,7 @@
 filetype colours:
 
 #backdrop - remember this is the source file name in your SVN folder, not dest name!
+backdrop.320x480x16: backdrops/cabbiev2.320x480x16.bmp
 backdrop.320x240x16: backdrops/cabbiev2.320x240x16.bmp
 backdrop.128x128x16: backdrops/cabbiev2.128x128x16.bmp
 backdrop.132x80x16: backdrops/cabbiev2.132x80x16.bmp 
@@ -333,6 +335,7 @@
 backdrop.240x400x16: backdrops/cabbiev2.240x400x16.bmp
 
 #selection bar settings for color targets
+selector type.320x480x16: bar (gradient)
 selector type.320x240x16: bar (gradient)
 selector type.128x128x16: bar (gradient)
 selector type.132x80x16:  bar (gradient)
@@ -346,6 +349,7 @@
 selector type.138x110x2: bar (inverse)
 
 #icons
+iconset.320x480x16: icons/tango_small.bmp 
 iconset.320x240x16: icons/tango_small.bmp 
 iconset.128x128x16: icons/tango_small.bmp 
 iconset.132x80x16: icons/tango_small.bmp 
@@ -359,6 +363,7 @@
 iconset.240x400x16: icons/tango_small.bmp 
 
 #viewer icons
+viewers iconset.320x480x16: icons/tango_small_viewers.bmp
 viewers iconset.320x240x16: icons/tango_small_viewers.bmp
 viewers iconset.128x128x16: icons/tango_small_viewers.bmp
 viewers iconset.132x80x16: icons/tango_small_viewers.bmp
diff --git a/wps/cabbiev2.320x480x16.wps b/wps/cabbiev2.320x480x16.wps
new file mode 100644
index 0000000..a64fa6f
--- /dev/null
+++ b/wps/cabbiev2.320x480x16.wps
@@ -0,0 +1,79 @@
+# cabbie 2.0
+# (C) 2007, Johannes Voggenthaler (Zinc Alloy)
+# (C) 2009, Maurus Cuelenaere (mcuelenaere) ported to Onda VX747
+# derived from "cabbie" (C) Yohann Misquitta
+
+%wd
+%X(wpsbackdrop-240x400x16.bmp)
+%Cl(55,50,130,130,c,c)
+%pb(22,284,199,13,pb-240x320x16.bmp)
+%T(22,284,199,13,progressbar)
+%T(90,238,60,20,playlist)
+%?Tl(2.5)<%Vd(t)|%Vd(u)>
+%V(0,0,240,330,1)
+
+
+%?C<|>
+%?C<|>
+%?C<|%s%ac%?it<%it|%fn>>
+%?C<|%s%ac%?ia<%ia|%?d(2)<%d(2)|%(root%)>>>
+%?C<|%s%ac%?id<%id|%?d(1)<%d(1)|%(root%)>>>
+%?C<|%ac%?iy<%iy|>>
+%?C<|>
+%?C<|%ac%?ig<%ig|>>
+%?C<|%ac%?fv<%(vbr%) |>%fb kbit/s %fc>
+%?C<|>
+%?C<%s%ac%?it<%it|%fn>|>
+%?C<%s%ac%?ia<%ia|%?d(2)<%d(2)|%(root%)>>|%ac%Sx(Next Track:)>
+%?C<%s%ac%?id<%id|%?d(1)<%d(1)|%(root%)>>|%ac%s%?It<%It|%Fn>>
+%?C<|%s%ac%?Ia<%Ia|%?D(2)<%D(2)|%(root%)>>>
+%?C<%s%ac%Sx(Next:) %?Ia<%Ia|%?D(2)<%D(2)|%(root%)>> - %?It<%It|%Fn>|%s%ac%?Id<%Id|%?D(1)<%D(1)|%(root%)>>>
+
+
+     %pc%ac%?Sr<%pe %Sx(of) %pp|%pp %Sx(of) %pe>%ar%pr     
+
+%?C<%Cd>
+
+%xl(A,lock-240x320x16.bmp,11,0,2)
+%xl(B,battery-240x320x16.bmp,46,0,10)
+%xl(C,volume-240x320x16.bmp,98,0,10)
+%xl(D,shuffle-240x320x16.bmp,139,0)
+%xl(E,repeat-240x320x16.bmp,182,0,4)
+%xl(F,playmode-240x320x16.bmp,206,0,5)
+
+%V(0,372,240,-,1)
+%?mh<%xd(Aa)|%xd(Ab)>
+%?bp<%?bc<%xd(Ba)|%xd(Bb)>|%?bl<|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)>>
+%?pv<%xd(Ca)|%xd(Cb)|%xd(Cc)|%xd(Cd)|%xd(Ce)|%xd(Cf)|%xd(Cg)|%xd(Ch)|%xd(Ci)|%xd(Cj)>
+%?ps<%xd(D)>
+%?mm<|%xd(Ea)|%xd(Eb)|%xd(Ec)|%xd(Ed)>
+%?mp<%xd(Fa)|%xd(Fb)|%xd(Fc)|%xd(Fd)|%xd(Fe)>
+
+%T(206,0,24,24,play)
+%T(206,0,24,24,&stop)
+%T(182,0,18,92,repmode)
+%T(139,0,37,23,shuffle)
+%T(98,0,33,23,volume)
+
+#viewport for the touch icons
+%xl(G,browser-320x240x16.bmp,0,0)
+%xl(I,pitch-320x240x16.bmp,39,0)
+%xl(H,context-320x240x16.bmp,58,0)
+%xl(J,quick-320x240x16.bmp,86,0)
+%xl(K,rew-320x240x16.bmp,115,0)
+%xl(L,ff-320x240x16.bmp,144,0)
+
+%Vl(t,70,335,-,30,1)
+%xd(G) %xd(H) %xd(I) %xd(J) %xd(K) %xd(L)
+%T(0,0,37,24,browse)
+%T(39,5,24,24,pitch)
+%T(58,0,24,24,contextmenu)
+%T(86,0,24,24,quickscreen)
+%T(115,0,24,23,&rwd)
+%T(144,0,24,23,&ffwd)
+%T(115,0,24,23,prev)
+%T(144,0,24,23,next)
+
+%Vl(u,70,335,-,30,1)
+#purposely left blank
+
diff --git a/wps/cabbiev2/wpsbackdrop-320x480x16.bmp b/wps/cabbiev2/wpsbackdrop-320x480x16.bmp
new file mode 100644
index 0000000..3278c0d
--- /dev/null
+++ b/wps/cabbiev2/wpsbackdrop-320x480x16.bmp
Binary files differ