src/core/android/SDL_android.c
changeset 11531 84793b17a0d2
parent 11398 19590e8f2541
child 11653 4130b92b6be4
     1.1 --- a/src/core/android/SDL_android.c	Fri Sep 22 08:30:37 2017 -0700
     1.2 +++ b/src/core/android/SDL_android.c	Fri Sep 22 08:30:46 2017 -0700
     1.3 @@ -56,6 +56,8 @@
     1.4  #define CONCAT1(prefix, class, function)                CONCAT2(prefix, class, function)
     1.5  #define CONCAT2(prefix, class, function)                Java_ ## prefix ## _ ## class ## _ ## function
     1.6  #define SDL_JAVA_INTERFACE(function)                    CONCAT1(SDL_JAVA_PREFIX, SDLActivity, function)
     1.7 +#define SDL_JAVA_AUDIO_INTERFACE(function)              CONCAT1(SDL_JAVA_PREFIX, SDLAudioManager, function)
     1.8 +#define SDL_JAVA_CONTROLLER_INTERFACE(function)         CONCAT1(SDL_JAVA_PREFIX, SDLControllerManager, function)
     1.9  #define SDL_JAVA_INTERFACE_INPUT_CONNECTION(function)   CONCAT1(SDL_JAVA_PREFIX, SDLInputConnection, function)
    1.10  
    1.11  
    1.12 @@ -75,39 +77,6 @@
    1.13          JNIEnv* env, jclass jcls,
    1.14          jint width, jint height, jint format, jfloat rate);
    1.15  
    1.16 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadDown)(
    1.17 -        JNIEnv* env, jclass jcls,
    1.18 -        jint device_id, jint keycode);
    1.19 -
    1.20 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadUp)(
    1.21 -        JNIEnv* env, jclass jcls,
    1.22 -        jint device_id, jint keycode);
    1.23 -
    1.24 -JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeJoy)(
    1.25 -        JNIEnv* env, jclass jcls,
    1.26 -        jint device_id, jint axis, jfloat value);
    1.27 -
    1.28 -JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeHat)(
    1.29 -        JNIEnv* env, jclass jcls,
    1.30 -        jint device_id, jint hat_id, jint x, jint y);
    1.31 -
    1.32 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddJoystick)(
    1.33 -        JNIEnv* env, jclass jcls,
    1.34 -        jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
    1.35 -        jint nbuttons, jint naxes, jint nhats, jint nballs);
    1.36 -
    1.37 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveJoystick)(
    1.38 -        JNIEnv* env, jclass jcls,
    1.39 -        jint device_id);
    1.40 -
    1.41 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddHaptic)(
    1.42 -        JNIEnv* env, jclass jcls,
    1.43 -        jint device_id, jstring device_name);
    1.44 -
    1.45 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveHaptic)(
    1.46 -        JNIEnv* env, jclass jcls,
    1.47 -        jint device_id);
    1.48 -
    1.49  JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
    1.50          JNIEnv* env, jclass jcls);
    1.51  
    1.52 @@ -166,6 +135,48 @@
    1.53          JNIEnv* env, jclass cls,
    1.54          jstring text, jint newCursorPosition);
    1.55  
    1.56 +/* Java class SDLAudioManager */
    1.57 +JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(
    1.58 +        JNIEnv *env, jclass jcls);
    1.59 +
    1.60 +/* Java class SDLControllerManager */
    1.61 +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(
    1.62 +        JNIEnv *env, jclass jcls);
    1.63 +
    1.64 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
    1.65 +        JNIEnv* env, jclass jcls,
    1.66 +        jint device_id, jint keycode);
    1.67 +
    1.68 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
    1.69 +        JNIEnv* env, jclass jcls,
    1.70 +        jint device_id, jint keycode);
    1.71 +
    1.72 +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
    1.73 +        JNIEnv* env, jclass jcls,
    1.74 +        jint device_id, jint axis, jfloat value);
    1.75 +
    1.76 +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
    1.77 +        JNIEnv* env, jclass jcls,
    1.78 +        jint device_id, jint hat_id, jint x, jint y);
    1.79 +
    1.80 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
    1.81 +        JNIEnv* env, jclass jcls,
    1.82 +        jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
    1.83 +        jint nbuttons, jint naxes, jint nhats, jint nballs);
    1.84 +
    1.85 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
    1.86 +        JNIEnv* env, jclass jcls,
    1.87 +        jint device_id);
    1.88 +
    1.89 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
    1.90 +        JNIEnv* env, jclass jcls,
    1.91 +        jint device_id, jstring device_name);
    1.92 +
    1.93 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
    1.94 +        JNIEnv* env, jclass jcls,
    1.95 +        jint device_id);
    1.96 +
    1.97 +
    1.98  
    1.99  /* Uncomment this to log messages entering and exiting methods in this file */
   1.100  /* #define DEBUG_JNI */
   1.101 @@ -189,17 +200,6 @@
   1.102  
   1.103  /* method signatures */
   1.104  static jmethodID midGetNativeSurface;
   1.105 -static jmethodID midAudioOpen;
   1.106 -static jmethodID midAudioWriteShortBuffer;
   1.107 -static jmethodID midAudioWriteByteBuffer;
   1.108 -static jmethodID midAudioClose;
   1.109 -static jmethodID midCaptureOpen;
   1.110 -static jmethodID midCaptureReadShortBuffer;
   1.111 -static jmethodID midCaptureReadByteBuffer;
   1.112 -static jmethodID midCaptureClose;
   1.113 -static jmethodID midPollInputDevices;
   1.114 -static jmethodID midPollHapticDevices;
   1.115 -static jmethodID midHapticRun;
   1.116  static jmethodID midSetActivityTitle;
   1.117  static jmethodID midSetOrientation;
   1.118  static jmethodID midGetContext;
   1.119 @@ -210,7 +210,28 @@
   1.120  static jmethodID midClipboardSetText;
   1.121  static jmethodID midClipboardGetText;
   1.122  static jmethodID midClipboardHasText;
   1.123 +static jmethodID midOpenAPKExpansionInputStream;
   1.124  
   1.125 +/* audio manager */
   1.126 +static jclass mAudioManagerClass;
   1.127 +
   1.128 +/* method signatures */
   1.129 +static jmethodID midAudioOpen;
   1.130 +static jmethodID midAudioWriteShortBuffer;
   1.131 +static jmethodID midAudioWriteByteBuffer;
   1.132 +static jmethodID midAudioClose;
   1.133 +static jmethodID midCaptureOpen;
   1.134 +static jmethodID midCaptureReadShortBuffer;
   1.135 +static jmethodID midCaptureReadByteBuffer;
   1.136 +static jmethodID midCaptureClose;
   1.137 +
   1.138 +/* controller manager */
   1.139 +static jclass mControllerManagerClass;
   1.140 +
   1.141 +/* method signatures */
   1.142 +static jmethodID midPollInputDevices;
   1.143 +static jmethodID midPollHapticDevices;
   1.144 +static jmethodID midHapticRun;
   1.145  
   1.146  /* static fields */
   1.147  static jfieldID fidSeparateMouseAndTouch;
   1.148 @@ -245,7 +266,17 @@
   1.149      return JNI_VERSION_1_4;
   1.150  }
   1.151  
   1.152 -/* Called before SDL_main() to initialize JNI bindings */
   1.153 +void checkJNIReady()
   1.154 +{
   1.155 +    if (!mActivityClass || !mAudioManagerClass || !mControllerManagerClass) {
   1.156 +        // We aren't fully initialized, let's just return.
   1.157 +        return;
   1.158 +    }
   1.159 +
   1.160 +    SDL_SetMainReady();    
   1.161 +}
   1.162 +
   1.163 +/* Activity initialization -- called before SDL_main() to initialize JNI bindings */
   1.164  JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
   1.165  {
   1.166      __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeSetupJNI()");
   1.167 @@ -256,28 +287,6 @@
   1.168  
   1.169      midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.170                                  "getNativeSurface","()Landroid/view/Surface;");
   1.171 -    midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.172 -                                "audioOpen", "(IZZI)I");
   1.173 -    midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.174 -                                "audioWriteShortBuffer", "([S)V");
   1.175 -    midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.176 -                                "audioWriteByteBuffer", "([B)V");
   1.177 -    midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.178 -                                "audioClose", "()V");
   1.179 -    midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.180 -                                "captureOpen", "(IZZI)I");
   1.181 -    midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.182 -                                "captureReadShortBuffer", "([SZ)I");
   1.183 -    midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.184 -                                "captureReadByteBuffer", "([BZ)I");
   1.185 -    midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.186 -                                "captureClose", "()V");
   1.187 -    midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.188 -                                "pollInputDevices", "()V");
   1.189 -    midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.190 -                                "pollHapticDevices", "()V");
   1.191 -    midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.192 -                                "hapticRun", "(II)V");
   1.193      midSetActivityTitle = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.194                                  "setActivityTitle","(Ljava/lang/String;)Z");
   1.195      midSetOrientation = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.196 @@ -298,16 +307,14 @@
   1.197                                  "clipboardGetText", "()Ljava/lang/String;");
   1.198      midClipboardHasText = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.199                                  "clipboardHasText", "()Z");
   1.200 -
   1.201 -    bHasNewData = SDL_FALSE;
   1.202 +    midOpenAPKExpansionInputStream = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.203 +                                "openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
   1.204  
   1.205      if (!midGetNativeSurface ||
   1.206 -       !midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
   1.207 -       !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose ||
   1.208 -       !midPollInputDevices || !midPollHapticDevices || !midHapticRun ||
   1.209         !midSetActivityTitle || !midSetOrientation || !midGetContext || !midInputGetInputDeviceIds ||
   1.210         !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown || 
   1.211 -       !midClipboardSetText || !midClipboardGetText || !midClipboardHasText) {
   1.212 +       !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
   1.213 +       !midOpenAPKExpansionInputStream) {
   1.214          __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
   1.215      }
   1.216  
   1.217 @@ -317,7 +324,64 @@
   1.218          __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java static fields, do you have the latest version of SDLActivity.java?");
   1.219      }
   1.220  
   1.221 -    SDL_SetMainReady();
   1.222 +    checkJNIReady();
   1.223 +}
   1.224 +
   1.225 +/* Audio initialization -- called before SDL_main() to initialize JNI bindings */
   1.226 +JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
   1.227 +{
   1.228 +    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "AUDIO nativeSetupJNI()");
   1.229 +
   1.230 +    Android_JNI_SetupThread();
   1.231 +
   1.232 +    mAudioManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
   1.233 +
   1.234 +    midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.235 +                                "audioOpen", "(IZZI)I");
   1.236 +    midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.237 +                                "audioWriteShortBuffer", "([S)V");
   1.238 +    midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.239 +                                "audioWriteByteBuffer", "([B)V");
   1.240 +    midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.241 +                                "audioClose", "()V");
   1.242 +    midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.243 +                                "captureOpen", "(IZZI)I");
   1.244 +    midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.245 +                                "captureReadShortBuffer", "([SZ)I");
   1.246 +    midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.247 +                                "captureReadByteBuffer", "([BZ)I");
   1.248 +    midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
   1.249 +                                "captureClose", "()V");
   1.250 +
   1.251 +    if (!midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
   1.252 +       !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose) {
   1.253 +        __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?");
   1.254 +    }
   1.255 +
   1.256 +    checkJNIReady();
   1.257 +}
   1.258 +
   1.259 +/* Controller initialization -- called before SDL_main() to initialize JNI bindings */
   1.260 +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass cls)
   1.261 +{
   1.262 +    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "CONTROLLER nativeSetupJNI()");
   1.263 +
   1.264 +    Android_JNI_SetupThread();
   1.265 +
   1.266 +    mControllerManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
   1.267 +
   1.268 +    midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
   1.269 +                                "pollInputDevices", "()V");
   1.270 +    midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
   1.271 +                                "pollHapticDevices", "()V");
   1.272 +    midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
   1.273 +                                "hapticRun", "(II)V");
   1.274 +
   1.275 +    if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun) {
   1.276 +        __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
   1.277 +    }
   1.278 +
   1.279 +    checkJNIReady();
   1.280  }
   1.281  
   1.282  /* SDL main function prototype */
   1.283 @@ -421,7 +485,7 @@
   1.284  }
   1.285  
   1.286  /* Paddown */
   1.287 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadDown)(
   1.288 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
   1.289                                      JNIEnv* env, jclass jcls,
   1.290                                      jint device_id, jint keycode)
   1.291  {
   1.292 @@ -429,7 +493,7 @@
   1.293  }
   1.294  
   1.295  /* Padup */
   1.296 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(onNativePadUp)(
   1.297 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
   1.298                                      JNIEnv* env, jclass jcls,
   1.299                                      jint device_id, jint keycode)
   1.300  {
   1.301 @@ -437,7 +501,7 @@
   1.302  }
   1.303  
   1.304  /* Joy */
   1.305 -JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeJoy)(
   1.306 +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
   1.307                                      JNIEnv* env, jclass jcls,
   1.308                                      jint device_id, jint axis, jfloat value)
   1.309  {
   1.310 @@ -445,7 +509,7 @@
   1.311  }
   1.312  
   1.313  /* POV Hat */
   1.314 -JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeHat)(
   1.315 +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
   1.316                                      JNIEnv* env, jclass jcls,
   1.317                                      jint device_id, jint hat_id, jint x, jint y)
   1.318  {
   1.319 @@ -453,7 +517,7 @@
   1.320  }
   1.321  
   1.322  
   1.323 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddJoystick)(
   1.324 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
   1.325                                      JNIEnv* env, jclass jcls,
   1.326                                      jint device_id, jstring device_name, jstring device_desc, jint is_accelerometer,
   1.327                                      jint nbuttons, jint naxes, jint nhats, jint nballs)
   1.328 @@ -470,14 +534,14 @@
   1.329      return retval;
   1.330  }
   1.331  
   1.332 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveJoystick)(
   1.333 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
   1.334                                      JNIEnv* env, jclass jcls,
   1.335                                      jint device_id)
   1.336  {
   1.337      return Android_RemoveJoystick(device_id);
   1.338  }
   1.339  
   1.340 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeAddHaptic)(
   1.341 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)(
   1.342      JNIEnv* env, jclass jcls, jint device_id, jstring device_name)
   1.343  {
   1.344      int retval;
   1.345 @@ -490,7 +554,7 @@
   1.346      return retval;
   1.347  }
   1.348  
   1.349 -JNIEXPORT jint JNICALL SDL_JAVA_INTERFACE(nativeRemoveHaptic)(
   1.350 +JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
   1.351      JNIEnv* env, jclass jcls, jint device_id)
   1.352  {
   1.353      return Android_RemoveHaptic(device_id);
   1.354 @@ -882,7 +946,7 @@
   1.355      if (iscapture) {
   1.356          __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for capture");
   1.357          captureBuffer16Bit = is16Bit;
   1.358 -        if ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
   1.359 +        if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
   1.360              /* Error during audio initialization */
   1.361              __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioRecord initialization!");
   1.362              return 0;
   1.363 @@ -890,7 +954,7 @@
   1.364      } else {
   1.365          __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output");
   1.366          audioBuffer16Bit = is16Bit;
   1.367 -        if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
   1.368 +        if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
   1.369              /* Error during audio initialization */
   1.370              __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
   1.371              return 0;
   1.372 @@ -958,10 +1022,10 @@
   1.373  
   1.374      if (audioBuffer16Bit) {
   1.375          (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
   1.376 -        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
   1.377 +        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
   1.378      } else {
   1.379          (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
   1.380 -        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
   1.381 +        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
   1.382      }
   1.383  
   1.384      /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
   1.385 @@ -975,7 +1039,7 @@
   1.386  
   1.387      if (captureBuffer16Bit) {
   1.388          SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
   1.389 -        br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
   1.390 +        br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
   1.391          if (br > 0) {
   1.392              jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
   1.393              br *= 2;
   1.394 @@ -984,7 +1048,7 @@
   1.395          }
   1.396      } else {
   1.397          SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
   1.398 -        br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
   1.399 +        br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
   1.400          if (br > 0) {
   1.401              jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
   1.402              SDL_memcpy(buffer, ptr, br);
   1.403 @@ -1008,9 +1072,9 @@
   1.404      }
   1.405  #else
   1.406      if (captureBuffer16Bit) {
   1.407 -        (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
   1.408 +        (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
   1.409      } else {
   1.410 -        (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
   1.411 +        (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
   1.412      }
   1.413  #endif
   1.414  }
   1.415 @@ -1020,13 +1084,13 @@
   1.416      JNIEnv *env = Android_JNI_GetEnv();
   1.417  
   1.418      if (iscapture) {
   1.419 -        (*env)->CallStaticVoidMethod(env, mActivityClass, midCaptureClose);
   1.420 +        (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midCaptureClose);
   1.421          if (captureBuffer) {
   1.422              (*env)->DeleteGlobalRef(env, captureBuffer);
   1.423              captureBuffer = NULL;
   1.424          }
   1.425      } else {
   1.426 -        (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioClose);
   1.427 +        (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioClose);
   1.428          if (audioBuffer) {
   1.429              (*env)->DeleteGlobalRef(env, audioBuffer);
   1.430              audioBuffer = NULL;
   1.431 @@ -1160,13 +1224,7 @@
   1.432          inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /* ACCESS_RANDOM */);
   1.433          if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
   1.434              /* Try fallback to APK expansion files */
   1.435 -            mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
   1.436 -                "openAPKExpansionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
   1.437 -            if (!mid) {
   1.438 -                SDL_SetError("No openAPKExpansionInputStream() in Java class");
   1.439 -                goto failure; /* Java class is missing the required method */
   1.440 -            }
   1.441 -            inputStream = (*mEnv)->CallObjectMethod(mEnv, context, mid, fileNameJString);
   1.442 +            inputStream = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, midOpenAPKExpansionInputStream, fileNameJString);
   1.443  
   1.444              /* Exception is checked first because it always needs to be cleared.
   1.445               * If no exception occurred then the last SDL error message is kept.
   1.446 @@ -1673,19 +1731,19 @@
   1.447  void Android_JNI_PollInputDevices(void)
   1.448  {
   1.449      JNIEnv *env = Android_JNI_GetEnv();
   1.450 -    (*env)->CallStaticVoidMethod(env, mActivityClass, midPollInputDevices);
   1.451 +    (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollInputDevices);
   1.452  }
   1.453  
   1.454  void Android_JNI_PollHapticDevices(void)
   1.455  {
   1.456      JNIEnv *env = Android_JNI_GetEnv();
   1.457 -    (*env)->CallStaticVoidMethod(env, mActivityClass, midPollHapticDevices);
   1.458 +    (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollHapticDevices);
   1.459  }
   1.460  
   1.461  void Android_JNI_HapticRun(int device_id, int length)
   1.462  {
   1.463      JNIEnv *env = Android_JNI_GetEnv();
   1.464 -    (*env)->CallStaticVoidMethod(env, mActivityClass, midHapticRun, device_id, length);
   1.465 +    (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, length);
   1.466  }
   1.467  
   1.468  
   1.469 @@ -1862,6 +1920,11 @@
   1.470  
   1.471          /* context = SDLActivity.getContext(); */
   1.472          context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
   1.473 +        if (!context) {
   1.474 +            SDL_SetError("Couldn't get Android context!");
   1.475 +            LocalReferenceHolder_Cleanup(&refs);
   1.476 +            return NULL;
   1.477 +        }
   1.478  
   1.479          /* fileObj = context.getFilesDir(); */
   1.480          mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),