diff --git a/README-android.txt b/README-android.txt
index a161c8407..4a1cfc29f 100644
--- a/README-android.txt
+++ b/README-android.txt
@@ -4,13 +4,14 @@ Simple DirectMedia Layer for Android
 
 Requirements:
 
-Android SDK (version 10 or later)
+Android SDK (version 12 or later)
 http://developer.android.com/sdk/index.html
 
 Android NDK r7 or later
 http://developer.android.com/sdk/ndk/index.html
 
 Minimum API level supported by SDL: 10 (Android 2.3.3)
+Joystick support is available for API level >=12 devices.
 
 ================================================================================
  How the port works
@@ -396,8 +397,11 @@ When you're done instrumenting with valgrind, you can disable the wrapper:
  Why is API level 10 the minimum required?
 ================================================================================
 
-API level 10 is required because SDL requires some functionality for running not
-available on older devices and some for building which is not in older NDK/SDKs.
+API level 10 is the minimum required level at runtime (that is, on the device) 
+because SDL requires some functionality for running not
+available on older devices. Since the incorporation of joystick support into SDL,
+the minimum SDK required to *build* SDL is version 12. Devices running API levels
+10-11 are still supported, only with the joystick functionality disabled.
 
 Support for native OpenGL ES and ES2 applications was introduced in the NDK for
 API level 4 and 8. EGL was made a stable API in the NDK for API level 9, which
diff --git a/WhatsNew.txt b/WhatsNew.txt
index 5ac78c513..36afc564c 100644
--- a/WhatsNew.txt
+++ b/WhatsNew.txt
@@ -1,6 +1,16 @@
 
 This is a list of major changes in SDL's version history.
 
+---------------------------------------------------------------------------
+2.0.2:
+---------------------------------------------------------------------------
+
+Android:
+* Joystick support (minimum SDK version required to build SDL is now 12, 
+  the required runtime version remains at 10, but on such devices joystick 
+  support won't be available).
+
+
 ---------------------------------------------------------------------------
 2.0.1:
 ---------------------------------------------------------------------------
diff --git a/android-project/AndroidManifest.xml b/android-project/AndroidManifest.xml
index 27db41843..0e4ad4162 100644
--- a/android-project/AndroidManifest.xml
+++ b/android-project/AndroidManifest.xml
@@ -31,7 +31,7 @@
     </application>
 
     <!-- Android 2.3.3 -->
-    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10" />
+    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="12" />
 
     <!-- OpenGL ES 2.0 -->
     <uses-feature android:glEsVersion="0x00020000" /> 
diff --git a/android-project/default.properties b/android-project/default.properties
index 9d135cb85..0cdab9561 100644
--- a/android-project/default.properties
+++ b/android-project/default.properties
@@ -8,4 +8,4 @@
 # project structure.
 
 # Project target.
-target=android-7
+target=android-12
diff --git a/android-project/jni/Application.mk b/android-project/jni/Application.mk
index 05cf0c31c..e5b50793b 100644
--- a/android-project/jni/Application.mk
+++ b/android-project/jni/Application.mk
@@ -2,3 +2,5 @@
 # Uncomment this if you're using STL in your project
 # See CPLUSPLUS-SUPPORT.html in the NDK documentation for more information
 # APP_STL := stlport_static 
+
+APP_ABI := armeabi armeabi-v7a x86
diff --git a/android-project/project.properties b/android-project/project.properties
index b7c2081d5..0f507e530 100644
--- a/android-project/project.properties
+++ b/android-project/project.properties
@@ -11,4 +11,4 @@
 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
 
 # Project target.
-target=android-10
+target=android-12
diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java
index 49b014ce1..f7cb9abca 100644
--- a/android-project/src/org/libsdl/app/SDLActivity.java
+++ b/android-project/src/org/libsdl/app/SDLActivity.java
@@ -16,6 +16,10 @@ import android.graphics.*;
 import android.media.*;
 import android.hardware.*;
 
+import java.lang.*;
+import java.util.List;
+import java.util.ArrayList;
+
 
 /**
     SDL Activity
@@ -31,10 +35,11 @@ public class SDLActivity extends Activity {
     protected static SDLSurface mSurface;
     protected static View mTextEdit;
     protected static ViewGroup mLayout;
+    protected static SDLJoystickHandler mJoystickHandler;
 
     // This is what SDL runs in. It invokes SDL_main(), eventually
     protected static Thread mSDLThread;
-
+    
     // Audio
     protected static Thread mAudioThread;
     protected static AudioTrack mAudioTrack;
@@ -60,6 +65,13 @@ public class SDLActivity extends Activity {
 
         // Set up the surface
         mSurface = new SDLSurface(getApplication());
+        
+        if(Build.VERSION.SDK_INT >= 12) {
+            mJoystickHandler = new SDLJoystickHandler_API12();
+        }
+        else {
+            mJoystickHandler = new SDLJoystickHandler();
+        }
 
         mLayout = new AbsoluteLayout(this);
         mLayout.addView(mSurface);
@@ -236,6 +248,10 @@ public class SDLActivity extends Activity {
     public static native void nativePause();
     public static native void nativeResume();
     public static native void onNativeResize(int x, int y, int format);
+    public static native void onNativePadDown(int padId, int keycode);
+    public static native void onNativePadUp(int padId, int keycode);
+    public static native void onNativeJoy(int joyId, int axis,
+                                          float value);
     public static native void onNativeKeyDown(int keycode);
     public static native void onNativeKeyUp(int keycode);
     public static native void onNativeKeyboardFocusLost();
@@ -406,6 +422,23 @@ public class SDLActivity extends Activity {
         }
         return Arrays.copyOf(filtered, used);
     }
+            
+    // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
+    public static int getNumJoysticks() {
+        return mJoystickHandler.getNumJoysticks();
+    }
+    
+    public static String getJoystickName(int joy) {
+        return mJoystickHandler.getJoystickName(joy);
+    }
+    
+    public static int getJoystickAxes(int joy) {
+        return mJoystickHandler.getJoystickAxes(joy);
+    }
+    
+    public static int getJoyId(int devId) {
+        return mJoystickHandler.getJoyId(devId);
+    }
 }
 
 /**
@@ -451,6 +484,10 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
 
         mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
         mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+        
+        if(Build.VERSION.SDK_INT >= 12) {
+            setOnGenericMotionListener(new SDLGenericMotionHandler_API12());
+        }
 
         // Some arbitrary defaults to avoid a potential division by zero
         mWidth = 1.0f;
@@ -557,16 +594,26 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
     // Key events
     @Override
     public boolean onKey(View  v, int keyCode, KeyEvent event) {
-        
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            //Log.v("SDL", "key down: " + keyCode);
-            SDLActivity.onNativeKeyDown(keyCode);
-            return true;
-        }
-        else if (event.getAction() == KeyEvent.ACTION_UP) {
-            //Log.v("SDL", "key up: " + keyCode);
-            SDLActivity.onNativeKeyUp(keyCode);
-            return true;
+        // Dispatch the different events depending on where they come from
+        if(event.getSource() == InputDevice.SOURCE_KEYBOARD) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                //Log.v("SDL", "key down: " + keyCode);
+                SDLActivity.onNativeKeyDown(keyCode);
+                return true;
+            }
+            else if (event.getAction() == KeyEvent.ACTION_UP) {
+                //Log.v("SDL", "key up: " + keyCode);
+                SDLActivity.onNativeKeyUp(keyCode);
+                return true;
+            }
+        } else if ( (event.getSource() & 0x00000401) != 0 || /* API 12: SOURCE_GAMEPAD */
+                   (event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) {
+            int id = SDLActivity.getJoyId( event.getDeviceId() );
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                SDLActivity.onNativePadDown(id, keyCode);
+            } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                SDLActivity.onNativePadUp(id, keyCode);
+            }
         }
         
         return false;
@@ -646,8 +693,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
                                       y / SensorManager.GRAVITY_EARTH,
                                       event.values[2] / SensorManager.GRAVITY_EARTH - 1);
         }
-    }
-    
+    }    
 }
 
 /* This is a fake invisible editor view that receives the input and defines the
@@ -769,3 +815,95 @@ class SDLInputConnection extends BaseInputConnection {
 
 }
 
+/* A null joystick handler for API level < 12 devices (the accelerometer is handled separately) */
+class SDLJoystickHandler {
+    public int getNumJoysticks() {
+        return 0;
+    }
+    
+    public String getJoystickName(int joy) {
+        return "";
+    }
+    
+    public int getJoystickAxes(int joy) {
+        return 0;
+    }
+    
+    public int getJoyId(int devId) {
+        return 0;
+    }
+}
+
+/* Actual joystick functionality available for API >= 12 devices */
+class SDLJoystickHandler_API12 extends SDLJoystickHandler {
+    private List<Integer> mJoyIdList;
+    
+    // Create a list of valid ID's the first time this function is called
+    private void createJoystickList() {
+        if(mJoyIdList != null) {
+            return;
+        }
+        
+        mJoyIdList = new ArrayList<Integer>();
+        int[] deviceIds = InputDevice.getDeviceIds();
+        for(int i=0; i<deviceIds.length; i++) {
+            if( (InputDevice.getDevice(deviceIds[i]).getSources() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
+                mJoyIdList.add(deviceIds[i]);
+            }
+        }
+    }
+    
+    public int getNumJoysticks() {
+        createJoystickList();
+        
+        return mJoyIdList.size();
+    }
+    
+    public String getJoystickName(int joy) {
+        createJoystickList();
+        return InputDevice.getDevice(mJoyIdList.get(joy)).getName();
+    }
+    
+    public int getJoystickAxes(int joy) {
+        createJoystickList();
+        return InputDevice.getDevice(mJoyIdList.get(joy)).getMotionRanges().size();
+    }
+    
+    public int getJoyId(int devId) {
+        int i=0;
+        
+        createJoystickList();
+        
+        for(i=0; i<mJoyIdList.size(); i++) {
+            if(mJoyIdList.get(i) == devId) {
+                return i;
+            }
+        }
+        
+        return -1;
+    }
+    
+}
+
+class SDLGenericMotionHandler_API12 extends Activity implements View.OnGenericMotionListener {
+    // Generic Motion (mouse hover, joystick...) events go here
+    // We only have joysticks yet
+    @Override
+    public boolean onGenericMotion(View v, MotionEvent event) {
+        int actionPointerIndex = event.getActionIndex();
+        int action = event.getActionMasked();
+        
+        if ( (event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) {
+            switch(action) {
+                case MotionEvent.ACTION_MOVE:
+                    int id = SDLActivity.getJoyId( event.getDeviceId() );
+                    float x = event.getAxisValue(MotionEvent.AXIS_X, actionPointerIndex);
+                    float y = event.getAxisValue(MotionEvent.AXIS_Y, actionPointerIndex);
+                    SDLActivity.onNativeJoy(id, 0, x);
+                    SDLActivity.onNativeJoy(id, 1, y);
+                    break;
+            }
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/build-scripts/androidbuild.sh b/build-scripts/androidbuild.sh
index b4a83234c..eed062256 100755
--- a/build-scripts/androidbuild.sh
+++ b/build-scripts/androidbuild.sh
@@ -24,6 +24,7 @@ fi
 if [ -z "$1" ] || [ -z "$SOURCES" ]; then
     echo "Usage: androidbuild.sh com.yourcompany.yourapp < sources.list"
     echo "Usage: androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c"
+    echo "To copy SDL source instead of symlinking: COPYSOURCE=1 androidbuild.sh ... "
     exit 1
 fi
 
@@ -63,9 +64,15 @@ cp -r $SDLPATH/android-project/* $BUILDPATH
 
 # Copy SDL sources
 mkdir -p $BUILDPATH/jni/SDL
-cp -r $SDLPATH/src $BUILDPATH/jni/SDL
-cp -r $SDLPATH/include $BUILDPATH/jni/SDL
-cp $SDLPATH/Android.mk $BUILDPATH/jni/SDL
+if [ -z "$COPYSOURCE" ]; then
+    ln -s $SDLPATH/src $BUILDPATH/jni/SDL
+    ln -s $SDLPATH/include $BUILDPATH/jni/SDL
+else
+    cp -r $SDLPATH/src $BUILDPATH/jni/SDL
+    cp -r $SDLPATH/include $BUILDPATH/jni/SDL
+fi
+
+cp -r $SDLPATH/Android.mk $BUILDPATH/jni/SDL
 sed -i "s|YourSourceHere.c|$MKSOURCES|g" $BUILDPATH/jni/src/Android.mk
 sed -i "s|org\.libsdl\.app|$APP|g" $BUILDPATH/AndroidManifest.xml
 
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index dac928e07..01399b6d2 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -203,6 +203,16 @@ extern "C" {
  *    "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown"
  */
 #define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
+    
+/**
+ *  \brief  A variable controlling whether an Android built-in accelerometer should be
+ *  listed as a joystick device, rather than listing actual joysticks only.
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - List only real joysticks and accept input from them
+ *    "1"       - List real joysticks along with the accelerometer as if it were a 3 axis joystick (the default).
+ */
+#define SDL_HINT_ACCEL_AS_JOY "SDL_ACCEL_AS_JOY"
 
 
 /**
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index 763715e68..6fc6f0771 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -146,6 +146,30 @@ void Java_org_libsdl_app_SDLActivity_onNativeResize(
     Android_SetScreenResolution(width, height, format);
 }
 
+// Paddown
+void Java_org_libsdl_app_SDLActivity_onNativePadDown(
+                                    JNIEnv* env, jclass jcls,
+                                    jint padId, jint keycode)
+{
+    Android_OnPadDown(padId, keycode);
+}
+
+// Padup
+void Java_org_libsdl_app_SDLActivity_onNativePadUp(
+                                   JNIEnv* env, jclass jcls,
+                                   jint padId, jint keycode)
+{
+    Android_OnPadUp(padId, keycode);
+}
+
+// Padup
+void Java_org_libsdl_app_SDLActivity_onNativeJoy(
+                                    JNIEnv* env, jclass jcls,
+                                    jint joyId, jint axis, jfloat value)
+{
+    Android_OnJoy(joyId, axis, value);
+}
+
 
 /* Surface Created */
 void Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
@@ -1212,6 +1236,62 @@ int Android_JNI_GetTouchDeviceIds(int **ids) {
     return number;
 }
 
+/* return the total number of plugged in joysticks */
+int Android_JNI_GetNumJoysticks()
+{
+    JNIEnv* env = Android_JNI_GetEnv();
+    if (!env) {
+        return -1;
+    }
+    
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "getNumJoysticks", "()I");
+    if (!mid) {
+        return -1;
+    }
+    
+    return (int)(*env)->CallStaticIntMethod(env, mActivityClass, mid);
+}
+
+/* Return the name of joystick number "i" */
+char* Android_JNI_GetJoystickName(int i)
+{
+    JNIEnv* env = Android_JNI_GetEnv();
+    if (!env) {
+        return SDL_strdup("");
+    }
+    
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "getJoystickName", "(I)Ljava/lang/String;");
+    if (!mid) {
+        return SDL_strdup("");
+    }
+    jstring string = (jstring)((*env)->CallStaticObjectMethod(env, mActivityClass, mid, i));
+    const char* utf = (*env)->GetStringUTFChars(env, string, 0);
+    if (!utf) {
+        return SDL_strdup("");
+    }
+    
+    char* text = SDL_strdup(utf);
+    (*env)->ReleaseStringUTFChars(env, string, utf);
+    return text;
+}
+
+/* return the number of axes in the given joystick */
+int Android_JNI_GetJoystickAxes(int joy)
+{
+    JNIEnv* env = Android_JNI_GetEnv();
+    if (!env) {
+        return -1;
+    }
+    
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "getJoystickAxes", "(I)I");
+    if (!mid) {
+        return -1;
+    }
+    
+    return (int)(*env)->CallIntMethod(env, mActivityClass, mid, joy);
+}
+
+
 /* sends message to be handled on the UI event dispatch thread */
 int Android_JNI_SendMessage(int command, int param)
 {
diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h
index 6181a15db..805518a8f 100644
--- a/src/core/android/SDL_android.h
+++ b/src/core/android/SDL_android.h
@@ -64,6 +64,11 @@ SDL_bool Android_JNI_HasClipboardText();
 
 /* Power support */
 int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
+    
+/* Joystick support */
+int Android_JNI_GetNumJoysticks();
+char* Android_JNI_GetJoystickName(int i);
+int Android_JNI_GetJoystickAxes(int joy);
 
 /* Touch support */
 int Android_JNI_GetTouchDeviceIds(int **ids);
diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c
index adaca528e..0c7f81001 100644
--- a/src/joystick/android/SDL_sysjoystick.c
+++ b/src/joystick/android/SDL_sysjoystick.c
@@ -29,11 +29,48 @@
 #include "SDL_error.h"
 #include "SDL_events.h"
 #include "SDL_joystick.h"
+#include "SDL_hints.h"
 #include "../SDL_sysjoystick.h"
 #include "../SDL_joystick_c.h"
 #include "../../core/android/SDL_android.h"
 
-static const char *accelerometerName = "Android accelerometer";
+#define ANDROID_ACCELEROMETER_INDEX (SYS_numjoysticks - 1)
+#define ANDROID_ACCELEROMETER_NAME "Android Accelerometer"
+
+static SDL_Joystick **SYS_Joysticks;
+static char **SYS_JoystickNames;
+static int SYS_numjoysticks;
+static SDL_bool SYS_accelAsJoy;
+
+/* Function to convert Android keyCodes into SDL ones.
+ * This code manipulation is done to get a sequential list of codes.
+ */
+int
+keycode_to_SDL(int keycode)
+{
+    int final = 0;
+    /* D-Pad key codes (API 1):
+     * KEYCODE_DPAD_UP=19, KEYCODE_DPAD_DOWN
+     * KEYCODE_DPAD_LEFT, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_CENTER
+     */
+    if(keycode < 96)
+        return keycode-19;
+    /* Some gamepad buttons (API 9):
+     * KEYCODE_BUTTON_A=96, KEYCODE_BUTTON_B, KEYCODE_BUTTON_C,
+     * KEYCODE_BUTTON_X, KEYCODE_BUTTON_Y, KEYCODE_BUTTON_Z,
+     * KEYCODE_BUTTON_L1, KEYCODE_BUTTON_L2,
+     * KEYCODE_BUTTON_R1, KEYCODE_BUTTON_R2,
+     * KEYCODE_BUTTON_THUMBL, KEYCODE_BUTTON_THUMBR,
+     * KEYCODE_BUTTON_START, KEYCODE_BUTTON_SELECT, KEYCODE_BUTTON_MODE
+     */
+    else if(keycode < 188)
+        return keycode-91;
+    /* More gamepad buttons (API 12):
+     * KEYCODE_BUTTON_1=188 to KEYCODE_BUTTON_16
+     */
+    else
+        return keycode-168;
+}
 
 /* Function to scan the system for joysticks.
  * This function should set SDL_numjoysticks to the number of available
@@ -43,18 +80,56 @@ static const char *accelerometerName = "Android accelerometer";
 int
 SDL_SYS_JoystickInit(void)
 {
-    return (1);
+    int i = 0;
+    const char *env;
+    
+    env = SDL_GetHint(SDL_HINT_ACCEL_AS_JOY);
+    if (env && !SDL_atoi(env))
+        SYS_accelAsJoy = SDL_FALSE;
+    else
+        SYS_accelAsJoy = SDL_TRUE; /* Default behavior */
+    
+    SYS_numjoysticks = Android_JNI_GetNumJoysticks();
+    if (SYS_accelAsJoy) {
+        SYS_numjoysticks++;
+    }
+    SYS_Joysticks = (SDL_Joystick **)SDL_malloc(SYS_numjoysticks*sizeof(SDL_Joystick *));
+    if (SYS_Joysticks == NULL)
+    {
+        return SDL_OutOfMemory();
+    }
+    SYS_JoystickNames = (char **)SDL_malloc(SYS_numjoysticks*sizeof(char *));
+    if (SYS_JoystickNames == NULL)
+    {
+        SDL_free(SYS_Joysticks);
+        SYS_Joysticks = NULL;
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(SYS_JoystickNames, 0, (SYS_numjoysticks*sizeof(char *)));
+    SDL_memset(SYS_Joysticks, 0, (SYS_numjoysticks*sizeof(SDL_Joystick *)));
+    
+    for (i = 0; i < SYS_numjoysticks; i++)
+    {
+        if ( SYS_accelAsJoy && i == ANDROID_ACCELEROMETER_INDEX ) {
+            SYS_JoystickNames[i] = ANDROID_ACCELEROMETER_NAME;
+        } else {
+            SYS_JoystickNames[i] = Android_JNI_GetJoystickName(i);
+        }
+    }
+   
+    return (SYS_numjoysticks);
 }
 
 int SDL_SYS_NumJoysticks()
 {
-    return 1;
+    return SYS_numjoysticks;
 }
 
 void SDL_SYS_JoystickDetect()
 {
 }
 
+/* TODO: Hotplugging support */
 SDL_bool SDL_SYS_JoystickNeedsPolling()
 {
     return SDL_FALSE;
@@ -64,7 +139,7 @@ SDL_bool SDL_SYS_JoystickNeedsPolling()
 const char *
 SDL_SYS_JoystickNameForDeviceIndex(int device_index)
 {
-    return accelerometerName;
+    return SYS_JoystickNames[device_index];
 }
 
 /* Function to perform the mapping from device index to the instance id for this index */
@@ -81,11 +156,19 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
 int
 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
 {
-    if (device_index == 0) {
-        joystick->nbuttons = 0;
+    if (device_index < SYS_numjoysticks) {
         joystick->nhats = 0;
         joystick->nballs = 0;
-        joystick->naxes = 3;
+        if (SYS_accelAsJoy && device_index == ANDROID_ACCELEROMETER_INDEX) {
+            joystick->nbuttons = 0;
+            joystick->naxes = 3;
+        } else {
+            /* TODO: Get the real number of buttons in the device */
+            joystick->nbuttons = 36;
+            joystick->naxes = Android_JNI_GetJoystickAxes(device_index);
+        }
+        
+        SYS_Joysticks[device_index] = joystick;
         return 0;
     } else {
         SDL_SetError("No joystick available with that index");
@@ -111,7 +194,8 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
     Sint16 value;
     float values[3];
 
-    if (Android_JNI_GetAccelerometerValues(values)) {
+    if (SYS_accelAsJoy && Android_JNI_GetAccelerometerValues(values) &&
+        joystick->instance_id == ANDROID_ACCELEROMETER_INDEX) {
         for ( i = 0; i < 3; i++ ) {
             value = (Sint16)(values[i] * 32767.0f);
             SDL_PrivateJoystickAxis(joystick, i, value);
@@ -129,6 +213,10 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
 void
 SDL_SYS_JoystickQuit(void)
 {
+    SDL_free(SYS_JoystickNames);
+    SDL_free(SYS_Joysticks);
+    SYS_JoystickNames = NULL;
+    SYS_Joysticks = NULL;
 }
 
 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
@@ -151,6 +239,32 @@ SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
     return guid;
 }
 
+int
+Android_OnPadDown(int padId, int keycode)
+{
+    SDL_PrivateJoystickButton(SYS_Joysticks[padId], keycode_to_SDL(keycode), SDL_PRESSED);
+    
+    return 0;
+}
+
+int
+Android_OnPadUp(int padId, int keycode)
+{
+    SDL_PrivateJoystickButton(SYS_Joysticks[padId], keycode_to_SDL(keycode), SDL_RELEASED);
+    
+    return 0;
+}
+
+int
+Android_OnJoy(int joyId, int axis, float value)
+{
+    /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
+    /* TODO: Are the reported values right? */
+    SDL_PrivateJoystickAxis(SYS_Joysticks[joyId], axis, (Sint16) (32767.*value) );
+    
+    return 0;
+}
+
 #endif /* SDL_JOYSTICK_ANDROID */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/android/SDL_sysjoystick.h b/src/joystick/android/SDL_sysjoystick.h
new file mode 100644
index 000000000..f98c6a04b
--- /dev/null
+++ b/src/joystick/android/SDL_sysjoystick.h
@@ -0,0 +1,28 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+ 
+ This software is provided 'as-is', without any express or implied
+ warranty.  In no event will the authors be held liable for any damages
+ arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "SDL_config.h"
+
+extern int Android_OnPadDown(int padId, int keycode);
+extern int Android_OnPadUp(int padId, int keycode);
+extern int Android_OnJoy(int joyId, int axisnum, float value);
+
+/* vi: set ts=4 sw=4 expandtab: */