SDL: Removed the ancient Android audio driver

From 691cf15e752fb46c8e9f0588621ad0af1e4009f4 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 29 Jul 2024 08:05:36 -0700
Subject: [PATCH] Removed the ancient Android audio driver

OpenSLES is well supported on Android 4.0 and later.
---
 CMakeLists.txt                                |   3 -
 .../java/org/libsdl/app/SDLAudioManager.java  | 374 ------------------
 include/build_config/SDL_build_config.h.cmake |   1 -
 .../build_config/SDL_build_config_android.h   |   1 -
 src/audio/SDL_audio.c                         |   3 -
 src/audio/SDL_sysaudio.h                      |   1 -
 src/audio/android/SDL_androidaudio.c          | 191 ---------
 src/audio/android/SDL_androidaudio.h          |  38 --
 src/core/android/SDL_android.c                | 328 +--------------
 src/core/android/SDL_android.h                |   6 -
 10 files changed, 11 insertions(+), 935 deletions(-)
 delete mode 100644 src/audio/android/SDL_androidaudio.c
 delete mode 100644 src/audio/android/SDL_androidaudio.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 89c0e8991687f..688e25fe10a5f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1246,9 +1246,6 @@ if(ANDROID)
   endif()
 
   if(SDL_AUDIO)
-    set(SDL_AUDIO_DRIVER_ANDROID 1)
-    sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/android/*.c")
-
     set(SDL_AUDIO_DRIVER_OPENSLES 1)
     sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/openslES/*.c")
 
diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLAudioManager.java b/android-project/app/src/main/java/org/libsdl/app/SDLAudioManager.java
index ed9c959d45a52..6ad2f543bbb1d 100644
--- a/android-project/app/src/main/java/org/libsdl/app/SDLAudioManager.java
+++ b/android-project/app/src/main/java/org/libsdl/app/SDLAudioManager.java
@@ -3,11 +3,7 @@
 import android.content.Context;
 import android.media.AudioDeviceCallback;
 import android.media.AudioDeviceInfo;
-import android.media.AudioFormat;
 import android.media.AudioManager;
-import android.media.AudioRecord;
-import android.media.AudioTrack;
-import android.media.MediaRecorder;
 import android.os.Build;
 import android.util.Log;
 
@@ -17,15 +13,11 @@
 public class SDLAudioManager {
     protected static final String TAG = "SDLAudio";
 
-    protected static AudioTrack mAudioTrack;
-    protected static AudioRecord mAudioRecord;
     protected static Context mContext;
 
     private static AudioDeviceCallback mAudioDeviceCallback;
 
     public static void initialize() {
-        mAudioTrack = null;
-        mAudioRecord = null;
         mAudioDeviceCallback = null;
 
         if(Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */)
@@ -58,230 +50,6 @@ public static void release(Context context) {
 
     // Audio
 
-    protected static String getAudioFormatString(int audioFormat) {
-        switch (audioFormat) {
-            case AudioFormat.ENCODING_PCM_8BIT:
-                return "8-bit";
-            case AudioFormat.ENCODING_PCM_16BIT:
-                return "16-bit";
-            case AudioFormat.ENCODING_PCM_FLOAT:
-                return "float";
-            default:
-                return Integer.toString(audioFormat);
-        }
-    }
-
-    protected static int[] open(boolean recording, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
-        int channelConfig;
-        int sampleSize;
-        int frameSize;
-
-        Log.v(TAG, "Opening " + (recording ? "recording" : "playback") + ", requested " + desiredFrames + " frames of " + desiredChannels + " channel " + getAudioFormatString(audioFormat) + " audio at " + sampleRate + " Hz");
-
-        /* On older devices let's use known good settings */
-        if (Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {
-            if (desiredChannels > 2) {
-                desiredChannels = 2;
-            }
-        }
-
-        /* AudioTrack has sample rate limitation of 48000 (fixed in 5.0.2) */
-        if (Build.VERSION.SDK_INT < 22 /* Android 5.1 (LOLLIPOP_MR1) */) {
-            if (sampleRate < 8000) {
-                sampleRate = 8000;
-            } else if (sampleRate > 48000) {
-                sampleRate = 48000;
-            }
-        }
-
-        if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
-            int minSDKVersion = (recording ? 23 /* Android 6.0 (M) */ : 21 /* Android 5.0 (LOLLIPOP) */);
-            if (Build.VERSION.SDK_INT < minSDKVersion) {
-                audioFormat = AudioFormat.ENCODING_PCM_16BIT;
-            }
-        }
-        switch (audioFormat)
-        {
-        case AudioFormat.ENCODING_PCM_8BIT:
-            sampleSize = 1;
-            break;
-        case AudioFormat.ENCODING_PCM_16BIT:
-            sampleSize = 2;
-            break;
-        case AudioFormat.ENCODING_PCM_FLOAT:
-            sampleSize = 4;
-            break;
-        default:
-            Log.v(TAG, "Requested format " + audioFormat + ", getting ENCODING_PCM_16BIT");
-            audioFormat = AudioFormat.ENCODING_PCM_16BIT;
-            sampleSize = 2;
-            break;
-        }
-
-        if (recording) {
-            switch (desiredChannels) {
-            case 1:
-                channelConfig = AudioFormat.CHANNEL_IN_MONO;
-                break;
-            case 2:
-                channelConfig = AudioFormat.CHANNEL_IN_STEREO;
-                break;
-            default:
-                Log.v(TAG, "Requested " + desiredChannels + " channels, getting stereo");
-                desiredChannels = 2;
-                channelConfig = AudioFormat.CHANNEL_IN_STEREO;
-                break;
-            }
-        } else {
-            switch (desiredChannels) {
-            case 1:
-                channelConfig = AudioFormat.CHANNEL_OUT_MONO;
-                break;
-            case 2:
-                channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
-                break;
-            case 3:
-                channelConfig = AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
-                break;
-            case 4:
-                channelConfig = AudioFormat.CHANNEL_OUT_QUAD;
-                break;
-            case 5:
-                channelConfig = AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
-                break;
-            case 6:
-                channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
-                break;
-            case 7:
-                channelConfig = AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
-                break;
-            case 8:
-                if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) {
-                    channelConfig = AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
-                } else {
-                    Log.v(TAG, "Requested " + desiredChannels + " channels, getting 5.1 surround");
-                    desiredChannels = 6;
-                    channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
-                }
-                break;
-            default:
-                Log.v(TAG, "Requested " + desiredChannels + " channels, getting stereo");
-                desiredChannels = 2;
-                channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
-                break;
-            }
-
-/*
-            Log.v(TAG, "Speaker configuration (and order of channels):");
-
-            if ((channelConfig & 0x00000004) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_FRONT_LEFT");
-            }
-            if ((channelConfig & 0x00000008) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_FRONT_RIGHT");
-            }
-            if ((channelConfig & 0x00000010) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_FRONT_CENTER");
-            }
-            if ((channelConfig & 0x00000020) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_LOW_FREQUENCY");
-            }
-            if ((channelConfig & 0x00000040) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_BACK_LEFT");
-            }
-            if ((channelConfig & 0x00000080) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_BACK_RIGHT");
-            }
-            if ((channelConfig & 0x00000100) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_FRONT_LEFT_OF_CENTER");
-            }
-            if ((channelConfig & 0x00000200) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_FRONT_RIGHT_OF_CENTER");
-            }
-            if ((channelConfig & 0x00000400) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_BACK_CENTER");
-            }
-            if ((channelConfig & 0x00000800) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_SIDE_LEFT");
-            }
-            if ((channelConfig & 0x00001000) != 0) {
-                Log.v(TAG, "   CHANNEL_OUT_SIDE_RIGHT");
-            }
-*/
-        }
-        frameSize = (sampleSize * desiredChannels);
-
-        // Let the user pick a larger buffer if they really want -- but ye
-        // gods they probably shouldn't, the minimums are horrifyingly high
-        // latency already
-        int minBufferSize;
-        if (recording) {
-            minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
-        } else {
-            minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);
-        }
-        desiredFrames = Math.max(desiredFrames, (minBufferSize + frameSize - 1) / frameSize);
-
-        int[] results = new int[4];
-
-        if (recording) {
-            if (mAudioRecord == null) {
-                mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate,
-                        channelConfig, audioFormat, desiredFrames * frameSize);
-
-                // see notes about AudioTrack state in audioOpen(), above. Probably also applies here.
-                if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
-                    Log.e(TAG, "Failed during initialization of AudioRecord");
-                    mAudioRecord.release();
-                    mAudioRecord = null;
-                    return null;
-                }
-
-                if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {
-                    mAudioRecord.setPreferredDevice(getPlaybackAudioDeviceInfo(deviceId));
-                }
-
-                mAudioRecord.startRecording();
-            }
-
-            results[0] = mAudioRecord.getSampleRate();
-            results[1] = mAudioRecord.getAudioFormat();
-            results[2] = mAudioRecord.getChannelCount();
-
-        } else {
-            if (mAudioTrack == null) {
-                mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
-
-                // Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
-                // Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
-                // Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
-                if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
-                    /* Try again, with safer values */
-
-                    Log.e(TAG, "Failed during initialization of Audio Track");
-                    mAudioTrack.release();
-                    mAudioTrack = null;
-                    return null;
-                }
-
-                if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */ && deviceId != 0) {
-                    mAudioTrack.setPreferredDevice(getInputAudioDeviceInfo(deviceId));
-                }
-
-                mAudioTrack.play();
-            }
-
-            results[0] = mAudioTrack.getSampleRate();
-            results[1] = mAudioTrack.getAudioFormat();
-            results[2] = mAudioTrack.getChannelCount();
-        }
-        results[3] = desiredFrames;
-
-        Log.v(TAG, "Opening " + (recording ? "recording" : "playback") + ", got " + results[3] + " frames of " + results[2] + " channel " + getAudioFormatString(results[1]) + " audio at " + results[0] + " Hz");
-
-        return results;
-    }
-
     private static AudioDeviceInfo getInputAudioDeviceInfo(int deviceId) {
         if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
             AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
@@ -330,148 +98,6 @@ public static void unregisterAudioDeviceCallback() {
         }
     }
 
-    /**
-     * This method is called by SDL using JNI.
-     */
-    public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
-        return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);
-    }
-
-    /**
-     * This method is called by SDL using JNI.
-     */
-    public static void audioWriteFloatBuffer(float[] buffer) {
-        if (mAudioTrack == null) {
-            Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
-            return;
-        }
-
-        if (android.os.Build.VERSION.SDK_INT < 21 /* Android 5.0 (LOLLIPOP) */) {
-            Log.e(TAG, "Attempted to make an incompatible audio call with uninitialized audio! (floating-point output is supported since Android 5.0 Lollipop)");
-            return;
-        }
-
-        for (int i = 0; i < buffer.length;) {
-            int result = mAudioTrack.write(buffer, i, buffer.length - i, AudioTrack.WRITE_BLOCKING);
-            if (result > 0) {
-                i += result;
-            } else if (result == 0) {
-                try {
-                    Thread.sleep(1);
-                } catch(InterruptedException e) {
-                    // Nom nom
-                }
-            } else {
-                Log.w(TAG, "SDL audio: error return from write(float)");
-                return;
-            }
-        }
-    }
-
-    /**
-     * This method is called by SDL using JNI.
-     */
-    public static void audioWriteShortBuffer(short[] buffer) {
-        if (mAudioTrack == null) {
-            Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
-            return;
-        }
-
-        for (int i = 0; i < buffer.length;) {
-            int result = mAudioTrack.write(buffer, i, buffer.length - i);
-            if (result > 0) {
-                i += result;
-            } else if (result == 0) {
-                try {
-                    Thread.sleep(1);
-                } catch(InterruptedException e) {
-                    // Nom nom
-                }
-            } else {
-                Log.w(TAG, "SDL audio: error return from write(short)");
-                return;
-            }
-        }
-    }
-
-    /**
-     * This method is called by SDL using JNI.
-     */
-    public static void audioWriteByteBuffer(byte[] buffer) {
-        if (mAudioTrack == null) {
-            Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
-            return;
-        }
-
-        for (int i = 0; i < buffer.length; ) {
-            int result = mAudioTrack.write(buffer, i, buffer.length - i);
-            if (result > 0) {
-                i += result;
-            } else if (result == 0) {
-                try {
-                    Thread.sleep(1);
-                } catch(InterruptedException e) {
-                    // Nom nom
-                }
-            } else {
-                Log.w(TAG, "SDL audio: error return from write(byte)");
-                return;
-            }
-        }
-    }
-
-    /**
-     * This method is called by SDL using JNI.
-     */
-    public static int[] recordingOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames, int deviceId) {
-        return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames, deviceId);
-    }
-
-    /** This method is called by SDL using JNI. */
-    public static int recordingReadFloatBuffer(float[] buffer, boolean blocking) {
-        if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
-            return 0;
-        } else {
-            return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
-        }
-    }
-
-    /** This method is called by SDL using JNI. */
-    public static int recordingReadShortBuffer(short[] buffer, boolean blocking) {
-        if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
-            return mAudioRecord.read(buffer, 0, buffer.length);
-        } else {
-            return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
-        }
-    }
-
-    /** This method is called by SDL using JNI. */
-    public static int recordingReadByteBuffer(byte[] buffer, boolean blocking) {
-        if (Build.VERSION.SDK_INT < 23 /* Android 6.0 (M) */) {
-            return mAudioRecord.read(buffer, 0, buffer.length);
-        } else {
-            return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
-        }
-    }
-
-    /** This method is called by SDL using JNI. */
-    public static void audioClose() {
-        if (mAudioTrack != null) {
-            mAudioTrack.stop();
-            mAudioTrack.release();
-            mAudioTrack = null;
-        }
-    }
-
-    /** This method is called by SDL using JNI. */
-    public static void recordingClose() {
-        if (mAudioRecord != null) {
-            mAudioRecord.stop();
-            mAudioRecord.release();
-            mAudioRecord = null;
-        }
-    }
-
     /** This method is called by SDL using JNI. */
     public static void audioSetThreadPriority(boolean recording, int device_id) {
         try {
diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake
index 3f01525e9aa51..0e3645e293809 100644
--- a/include/build_config/SDL_build_config.h.cmake
+++ b/include/build_config/SDL_build_config.h.cmake
@@ -266,7 +266,6 @@
 /* Enable various audio drivers */
 #cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@
 #cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@
-#cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@
 #cmakedefine SDL_AUDIO_DRIVER_OPENSLES @SDL_AUDIO_DRIVER_OPENSLES@
 #cmakedefine SDL_AUDIO_DRIVER_AAUDIO @SDL_AUDIO_DRIVER_AAUDIO@
 #cmakedefine SDL_AUDIO_DRIVER_COREAUDIO @SDL_AUDIO_DRIVER_COREAUDIO@
diff --git a/include/build_config/SDL_build_config_android.h b/include/build_config/SDL_build_config_android.h
index 3716c1550f788..926cff8df2b0f 100644
--- a/include/build_config/SDL_build_config_android.h
+++ b/include/build_config/SDL_build_config_android.h
@@ -144,7 +144,6 @@
 
 /* Enable various audio drivers */
 #ifndef SDL_AUDIO_DISABLED
-#define SDL_AUDIO_DRIVER_ANDROID    1
 #define SDL_AUDIO_DRIVER_OPENSLES   1
 #define SDL_AUDIO_DRIVER_AAUDIO     1
 #endif /* SDL_AUDIO_DISABLED */
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 2394865f2f241..d97c9d0e77b81 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -62,9 +62,6 @@ static const AudioBootStrap *const bootstrap[] = {
 #ifdef SDL_AUDIO_DRIVER_OPENSLES
     &OPENSLES_bootstrap,
 #endif
-#ifdef SDL_AUDIO_DRIVER_ANDROID
-    &ANDROIDAUDIO_bootstrap,
-#endif
 #ifdef SDL_AUDIO_DRIVER_PS2
     &PS2AUDIO_bootstrap,
 #endif
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
index d21a6e3c6a8f4..4f6c189178f84 100644
--- a/src/audio/SDL_sysaudio.h
+++ b/src/audio/SDL_sysaudio.h
@@ -372,7 +372,6 @@ extern AudioBootStrap DISKAUDIO_bootstrap;
 extern AudioBootStrap DUMMYAUDIO_bootstrap;
 extern AudioBootStrap AAUDIO_bootstrap;
 extern AudioBootStrap OPENSLES_bootstrap;
-extern AudioBootStrap ANDROIDAUDIO_bootstrap;
 extern AudioBootStrap PS2AUDIO_bootstrap;
 extern AudioBootStrap PSPAUDIO_bootstrap;
 extern AudioBootStrap VITAAUD_bootstrap;
diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c
deleted file mode 100644
index e15cd4ccfb72b..0000000000000
--- a/src/audio/android/SDL_androidaudio.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2024 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_internal.h"
-
-#ifdef SDL_AUDIO_DRIVER_ANDROID
-
-// Output audio to Android (legacy interface)
-
-#include "../SDL_sysaudio.h"
-#include "SDL_androidaudio.h"
-
-#include "../../core/android/SDL_android.h"
-#include <android/log.h>
-
-
-struct SDL_PrivateAudioData
-{
-    int resume;  // Resume device if it was paused automatically
-};
-
-static SDL_AudioDevice *playbackDevice = NULL;
-static SDL_AudioDevice *recordingDevice = NULL;
-
-static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device)
-{
-    device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
-    if (!device->hidden) {
-        return -1;
-    }
-
-    const SDL_bool recording = device->recording;
-
-    if (recording) {
-        if (recordingDevice) {
-            return SDL_SetError("An audio recording device is already opened");
-        }
-        recordingDevice = device;
-    } else {
-        if (playbackDevice) {
-            return SDL_SetError("An audio playback device is already opened");
-        }
-        playbackDevice = device;
-    }
-
-    SDL_AudioFormat test_format;
-    const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format);
-    while ((test_format = *(closefmts++)) != 0) {
-        if ((test_format == SDL_AUDIO_U8) ||
-            (test_format == SDL_AUDIO_S16) ||
-            (test_format == SDL_AUDIO_F32)) {
-            device->spec.format = test_format;
-            break;
-        }
-    }
-
-    if (!test_format) {
-        return SDL_SetError("android: Unsupported audio format");
-    }
-
-    if (Android_JNI_OpenAudioDevice(device) < 0) {
-        return -1;
-    }
-
-    SDL_UpdatedAudioDeviceFormat(device);
-
-    return 0;
-}
-
-// !!! FIXME: this needs a WaitDevice implementation.
-
-static int ANDROIDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
-{
-    Android_JNI_WriteAudioBuffer();
-    return 0;
-}
-
-static Uint8 *ANDROIDAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
-{
-    return Android_JNI_GetAudioBuffer();
-}
-
-static int ANDROIDAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
-{
-    return Android_JNI_RecordAudioBuffer(buffer, buflen);
-}
-
-static void ANDROIDAUDIO_FlushRecording(SDL_AudioDevice *device)
-{
-    Android_JNI_FlushRecordedAudio();
-}
-
-static void ANDROIDAUDIO_CloseDevice(SDL_AudioDevice *device)
-{
-    /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
-       so it's safe to terminate the Java side buffer and AudioTrack
-     */
-    if (device->hidden) {
-        Android_JNI_CloseAudioDevice(device->recording);
-        if (device->recording) {
-            SDL_assert(recordingDevice == device);
-            recordingDevice = NULL;
-        } else {
-            SDL_assert(playbackDevice == device);
-            playbackDevice = NULL;
-        }
-        SDL_free(device->hidden);
-        device->hidden = NULL;
-    }
-}
-
-// Pause (block) all non already paused audio devices by taking their mixer lock
-void ANDROIDAUDIO_PauseDevices(void)
-{
-    // TODO: Handle multiple devices?
-    struct SDL_PrivateAudioData *hidden;
-    if (playbackDevice && playbackDevice->hidden) {
-        hidden = (struct SDL_PrivateAudioData *)playbackDevice->hidden;
-        SDL_LockMutex(playbackDevice->lock);
-        hidden->resume = SDL_TRUE;
-    }
-
-    if (recordingDevice && recordingDevice->hidden) {
-        hidden = (struct SDL_PrivateAudioData *)recordingDevice->hidden;
-        SDL_LockMutex(recordingDevice->lock);
-        hidden->resume = SDL_TRUE;
-    }
-}
-
-// Resume (unblock) all non already paused audio devices by releasing their mixer lock
-void ANDROIDAUDIO_ResumeDevices(void)
-{
-    // TODO: Handle multiple devices?
-    struct SDL_PrivateAudioData *hidden;
-    if (playbackDevice && playbackDevice->hidden) {
-        hidden = (struct SDL_PrivateAudioData *)playbackDevice->hidden;
-        if (hidden->resume) {
-            hidden->resume = SDL_FALSE;
-            SDL_UnlockMutex(playbackDevice->lock);
-        }
-    }
-
-    if (recordingDevice && recordingDevice->hidden) {
-        hidden = (struct SDL_PrivateAudioData *)recordingDevice->hidden;
-        if (hidden->resume) {
-            hidden->resume = SDL_FALSE;
-            SDL_UnlockMutex(recordingDevice->lock);
-        }
-    }
-}
-
-static SDL_bool ANDROIDAUDIO_Init(SDL_AudioDriverImpl *impl)
-{
-    // !!! FIXME: if on Android API < 24, DetectDevices and Deinitialize should be NULL and OnlyHasDefaultPlaybackDevice and OnlyHasDefaultRecordingDevice should be SDL_TRUE, since audio device enum and hotplug appears to require Android 7.0+.
-    impl->ThreadInit = Android_AudioThreadInit;
-    impl->DetectDevices = Android_StartAudioHotplug;
-    impl->DeinitializeStart = Android_StopAudioHotplug;
-    impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
-    impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
-    impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
-    impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
-    impl->RecordDevice = ANDROIDAUDIO_RecordDevice;
-    impl->FlushRecording = ANDROIDAUDIO_FlushRecording;
-
-    impl->HasRecordingSupport = SDL_TRUE;
-
-    return SDL_TRUE;
-}
-
-AudioBootStrap ANDROIDAUDIO_bootstrap = {
-    "android", "SDL Android audio driver", ANDROIDAUDIO_Init, SDL_FALSE
-};
-
-#endif // SDL_AUDIO_DRIVER_ANDROID
diff --git a/src/audio/android/SDL_androidaudio.h b/src/audio/android/SDL_androidaudio.h
deleted file mode 100644
index ba00e61510f04..0000000000000
--- a/src/audio/android/SDL_androidaudio.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2024 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_internal.h"
-
-#ifndef SDL_androidaudio_h_
-#define SDL_androidaudio_h_
-
-#ifdef SDL_AUDIO_DRIVER_ANDROID
-
-void ANDROIDAUDIO_ResumeDevices(void);
-void ANDROIDAUDIO_PauseDevices(void);
-
-#else
-
-static void ANDROIDAUDIO_ResumeDevices(void) {}
-static void ANDROIDAUDIO_PauseDevices(void) {}
-
-#endif
-
-#endif // SDL_androidaudio_h_
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index 6824289351bb6..6c38308daaead 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -364,16 +364,6 @@ static jclass mAudioManagerClass;
 /* method signatures */
 static jmethodID midRegisterAudioDeviceCallback;
 static jmethodID midUnregisterAudioDeviceCallback;
-static jmethodID midAudioOpen;
-static jmethodID midAudioWriteByteBuffer;
-static jmethodID midAudioWriteShortBuffer;
-static jmethodID midAudioWriteFloatBuffer;
-static jmethodID midAudioClose;
-static jmethodID midRecordingOpen;
-static jmethodID midRecordingReadByteBuffer;
-static jmethodID midRecordingReadShortBuffer;
-static jmethodID midRecordingReadFloatBuffer;
-static jmethodID midRecordingClose;
 static jmethodID midAudioSetThreadPriority;
 
 /* controller manager */
@@ -710,34 +700,10 @@ JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv *env, jcl
     midUnregisterAudioDeviceCallback = (*env)->GetStaticMethodID(env, mAudioManagerClass,
                                                          "unregisterAudioDeviceCallback",
                                                          "()V");
-    midAudioOpen = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                             "audioOpen", "(IIIII)[I");
-    midAudioWriteByteBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                                        "audioWriteByteBuffer", "([B)V");
-    midAudioWriteShortBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                                         "audioWriteShortBuffer", "([S)V");
-    midAudioWriteFloatBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                                         "audioWriteFloatBuffer", "([F)V");
-    midAudioClose = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                              "audioClose", "()V");
-    midRecordingOpen = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                               "recordingOpen", "(IIIII)[I");
-    midRecordingReadByteBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                                         "recordingReadByteBuffer", "([BZ)I");
-    midRecordingReadShortBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                                          "recordingReadShortBuffer", "([SZ)I");
-    midRecordingReadFloatBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                                          "recordingReadFloatBuffer", "([FZ)I");
-    midRecordingClose = (*env)->GetStaticMethodID(env, mAudioManagerClass,
-                                                "recordingClose", "()V");
     midAudioSetThreadPriority = (*env)->GetStaticMethodID(env, mAudioManagerClass,
                                                           "audioSetThreadPriority", "(ZI)V");
 
-    if (!midRegisterAudioDeviceCallback || !midUnregisterAudioDeviceCallback || !midAudioOpen ||
-        !midAudioWriteByteBuffer || !midAudioWriteShortBuffer || !midAudioWriteFloatBuffer ||
-        !midAudioClose ||
-        !midRecordingOpen || !midRecordingReadByteBuffer || !midRecordingReadShortBuffer ||
-        !midRecordingReadFloatBuffer || !midRecordingClose || !midAudioSetThreadPriority) {
+    if (!midRegisterAudioDeviceCallback || !midUnregisterAudioDeviceCallback || !midAudioSetThreadPriority) {
         __android_log_p

(Patch may be truncated, please check the link at the top of this post.)