android: Remove blocking permission request code. Async only in SDL3!

(this actually still blocks at our internal points of usage, though, for
replacement at a later time.)
main
Ryan C. Gordon 2024-02-12 19:46:03 -05:00
parent af61cfd5e0
commit bc984f78bf
12 changed files with 73 additions and 77 deletions

View File

@ -1424,6 +1424,8 @@ SDL_WindowsMessageHook has changed signatures so the message may be modified and
SDL_AndroidGetExternalStorageState() takes the state as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error.
SDL_AndroidRequestPermission is no longer a blocking call; the caller now provides a callback function that fires when a response is available.
The following functions have been removed:
* SDL_RenderGetD3D11Device() - replaced with the "SDL.renderer.d3d11.device" property
* SDL_RenderGetD3D12Device() - replaced with the "SDL.renderer.d3d12.device" property

View File

@ -399,29 +399,6 @@ extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state);
*/
extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void);
/**
* Request permissions at runtime.
*
* You do not need to call this for built-in functionality of SDL; recording
* from a microphone or reading images from a camera, using standard SDL
* APIs, will manage permission requests for you.
*
* This blocks the calling thread until the permission is granted or denied.
* if the app already has the requested permission, this returns immediately,
* but may block indefinitely until the user responds to the system's
* permission request dialog.
*
* If possible, you should _not_ use this function. You should use
* SDL_AndroidRequestPermissionAsync and deal with the response in a callback
* at a later time, and possibly in a different thread.
*
* \param permission The permission to request.
* \returns SDL_TRUE if the permission was granted, SDL_FALSE otherwise.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission);
typedef void (SDLCALL *SDL_AndroidRequestPermissionCallback)(void *userdata, const char *permission, SDL_bool granted);
@ -453,7 +430,7 @@ typedef void (SDLCALL *SDL_AndroidRequestPermissionCallback)(void *userdata, con
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC int SDLCALL SDL_AndroidRequestPermissionAsync(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata);
extern DECLSPEC int SDLCALL SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata);
/**
* Shows an Android toast notification.

View File

@ -381,6 +381,12 @@ static int BuildAAudioStream(SDL_AudioDevice *device)
return 0;
}
// !!! FIXME: make this non-blocking!
static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted)
{
SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1);
}
static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
{
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
@ -390,7 +396,18 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
LOGI(__func__);
if (device->iscapture) {
if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) {
// !!! FIXME: make this non-blocking!
SDL_AtomicInt permission_response;
SDL_AtomicSet(&permission_response, 0);
if (SDL_AndroidRequestPermission("android.permission.RECORD_AUDIO", AndroidRequestPermissionBlockingCallback, &permission_response) == -1) {
return -1;
}
while (SDL_AtomicGet(&permission_response) == 0) {
SDL_Delay(10);
}
if (SDL_AtomicGet(&permission_response) < 0) {
LOGI("This app doesn't have RECORD_AUDIO permission");
return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
}

View File

@ -228,6 +228,12 @@ static void OPENSLES_DestroyPCMRecorder(SDL_AudioDevice *device)
}
}
// !!! FIXME: make this non-blocking!
static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted)
{
SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1);
}
static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device)
{
struct SDL_PrivateAudioData *audiodata = device->hidden;
@ -241,9 +247,22 @@ static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device)
SLresult result;
int i;
if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) {
LOGE("This app doesn't have RECORD_AUDIO permission");
return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
// !!! FIXME: make this non-blocking!
{
SDL_AtomicInt permission_response;
SDL_AtomicSet(&permission_response, 0);
if (SDL_AndroidRequestPermission("android.permission.RECORD_AUDIO", AndroidRequestPermissionBlockingCallback, &permission_response) == -1) {
return -1;
}
while (SDL_AtomicGet(&permission_response) == 0) {
SDL_Delay(10);
}
if (SDL_AtomicGet(&permission_response) < 0) {
LOGE("This app doesn't have RECORD_AUDIO permission");
return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
}
}
// Just go with signed 16-bit audio as it's the most compatible

View File

@ -161,17 +161,9 @@ void *SDL_AndroidGetJNIEnv()
return NULL;
}
DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission);
SDL_bool SDL_AndroidRequestPermission(const char *permission)
{
(void)permission;
SDL_Unsupported();
return SDL_FALSE;
}
typedef void (SDLCALL *SDL_AndroidRequestPermissionCallback)(void *userdata, const char *permission, SDL_bool granted);
DECLSPEC int SDLCALL SDL_AndroidRequestPermissionAsync(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata);
int SDL_AndroidRequestPermissionAsync(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata)
DECLSPEC int SDLCALL SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata);
int SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata)
{
(void)permission;
(void)cb;

View File

@ -2557,11 +2557,6 @@ const char *SDL_AndroidGetExternalStoragePath(void)
return s_AndroidExternalFilesPath;
}
SDL_bool SDL_AndroidRequestPermission(const char *permission)
{
return Android_JNI_RequestPermission(permission);
}
int SDL_AndroidShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset)
{
return Android_JNI_ShowToast(message, duration, gravity, xOffset, yOffset);
@ -2662,7 +2657,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePermissionResult)(
SDL_assert(!"Shouldn't have hit this code"); // we had a permission response for a request we never made...?
}
int SDL_AndroidRequestPermissionAsync(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata)
int SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata)
{
if (!permission) {
return SDL_InvalidParamError("permission");
@ -2700,29 +2695,6 @@ int SDL_AndroidRequestPermissionAsync(const char *permission, SDL_AndroidRequest
return 0;
}
static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted)
{
SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1);
}
SDL_bool Android_JNI_RequestPermission(const char *permission)
{
SDL_AtomicInt response;
SDL_AtomicSet(&response, 0);
if (SDL_AndroidRequestPermissionAsync(permission, AndroidRequestPermissionBlockingCallback, &response) == -1) {
return SDL_FALSE;
}
/* Wait for the request to complete */
while (SDL_AtomicGet(&response) == 0) {
SDL_Delay(10);
}
return (SDL_AtomicGet(&response) < 0) ? SDL_FALSE : SDL_TRUE;
}
/* Show toast notification */
int Android_JNI_ShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset)
{

View File

@ -125,9 +125,6 @@ SDL_bool Android_JNI_SetSystemCursor(int cursorID);
SDL_bool Android_JNI_SupportsRelativeMouse(void);
SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled);
/* Request permission */
SDL_bool Android_JNI_RequestPermission(const char *permission);
/* Show toast notification */
int Android_JNI_ShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset);

View File

@ -972,7 +972,6 @@ SDL3_0.0.0 {
SDL_RenderGeometryRawFloat;
SDL_SetWindowShape;
SDL_RenderViewportSet;
SDL_AndroidRequestPermissionAsync;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@ -997,4 +997,3 @@
#define SDL_RenderGeometryRawFloat SDL_RenderGeometryRawFloat_REAL
#define SDL_SetWindowShape SDL_SetWindowShape_REAL
#define SDL_RenderViewportSet SDL_RenderViewportSet_REAL
#define SDL_AndroidRequestPermissionAsync SDL_AndroidRequestPermissionAsync_REAL

View File

@ -93,7 +93,7 @@ SDL_DYNAPI_PROC(const char*,SDL_AndroidGetExternalStoragePath,(void),(),return)
SDL_DYNAPI_PROC(int,SDL_AndroidGetExternalStorageState,(Uint32 *a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_AndroidGetInternalStoragePath,(void),(),return)
SDL_DYNAPI_PROC(void*,SDL_AndroidGetJNIEnv,(void),(),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_AndroidRequestPermission,(const char *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_AndroidRequestPermission,(const char *a, SDL_AndroidRequestPermissionCallback b, void *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_AndroidSendMessage,(Uint32 a, int b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_AndroidShowToast,(const char *a, int b, int c, int d, int e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return)
@ -1022,4 +1022,3 @@ SDL_DYNAPI_PROC(int,SDL_GetRenderColorScale,(SDL_Renderer *a, float *b),(a,b),re
SDL_DYNAPI_PROC(int,SDL_RenderGeometryRawFloat,(SDL_Renderer *a, SDL_Texture *b, const float *c, int d, const SDL_FColor *e, int f, const float *g, int h, int i, const void *j, int k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowShape,(SDL_Window *a, SDL_Surface *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_RenderViewportSet,(SDL_Renderer *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_AndroidRequestPermissionAsync,(const char *a, SDL_AndroidRequestPermissionCallback b, void *c),(a,b,c),return)

View File

@ -1029,6 +1029,29 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReportResponse
extern "C"
{
// !!! FIXME: make this non-blocking!
static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted)
{
SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1);
}
static SDL_bool RequestBluetoothPermissions(const char *permission)
{
// !!! FIXME: make this non-blocking!
SDL_AtomicInt permission_response;
SDL_AtomicSet(&permission_response, 0);
if (SDL_AndroidRequestPermission(permission, AndroidRequestPermissionBlockingCallback, &permission_response) == -1) {
return SDL_FALSE;
}
while (SDL_AtomicGet(&permission_response) == 0) {
SDL_Delay(10);
}
return SDL_AtomicGet(&permission_response) > 0;
}
int hid_init(void)
{
if ( !g_initialized && g_HIDDeviceManagerCallbackHandler )
@ -1046,7 +1069,7 @@ int hid_init(void)
bool init_bluetooth = false;
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAM, SDL_FALSE)) {
if (SDL_GetAndroidSDKVersion() < 31 ||
Android_JNI_RequestPermission("android.permission.BLUETOOTH_CONNECT")) {
RequestBluetoothPermissions("android.permission.BLUETOOTH_CONNECT")) {
init_bluetooth = true;
}
}

View File

@ -68,12 +68,12 @@ static void
create_cameraMgr(void)
{
if (cameraMgr == NULL) {
#if 0 // !!! FIXME: this is getting replaced in a different branch.
if (!Android_JNI_RequestPermission("android.permission.CAMERA")) {
SDL_SetError("This app doesn't have CAMERA permission");
return;
}
#endif
cameraMgr = ACameraManager_create();
if (cameraMgr == NULL) {
SDL_Log("Error creating ACameraManager");