Atlas - SDL_androidsensor.c

Home / ext / SDL / src / sensor / android Lines: 1 | Size: 8477 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#ifdef SDL_SENSOR_ANDROID 24 25// This is the system specific header for the SDL sensor API 26#include <android/sensor.h> 27 28#include "SDL_androidsensor.h" 29#include "../SDL_syssensor.h" 30#include "../SDL_sensor_c.h" 31#include "../../thread/SDL_systhread.h" 32 33#ifndef LOOPER_ID_USER 34#define LOOPER_ID_USER 3 35#endif 36 37typedef struct 38{ 39 ASensorRef asensor; 40 SDL_SensorID instance_id; 41 ASensorEventQueue *event_queue; 42 SDL_Sensor *sensor; 43} SDL_AndroidSensor; 44 45typedef struct 46{ 47 SDL_AtomicInt running; 48 SDL_Thread *thread; 49 SDL_Semaphore *sem; 50} SDL_AndroidSensorThreadContext; 51 52static ASensorManager *SDL_sensor_manager; 53static ALooper *SDL_sensor_looper; 54static SDL_AndroidSensorThreadContext SDL_sensor_thread_context; 55static SDL_AndroidSensor *SDL_sensors SDL_GUARDED_BY(SDL_sensors_lock); 56static int SDL_sensors_count; 57 58static int SDLCALL SDL_ANDROID_SensorThread(void *data) 59{ 60 SDL_AndroidSensorThreadContext *ctx = (SDL_AndroidSensorThreadContext *)data; 61 int i, events; 62 ASensorEvent event; 63 struct android_poll_source *source; 64 65 SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_HIGH); 66 67 SDL_sensor_looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 68 SDL_SignalSemaphore(ctx->sem); 69 70 while (SDL_GetAtomicInt(&ctx->running)) { 71 Uint64 timestamp = SDL_GetTicksNS(); 72 73 if (ALooper_pollOnce(-1, NULL, &events, (void **)&source) == LOOPER_ID_USER) { 74 SDL_LockSensors(); 75 for (i = 0; i < SDL_sensors_count; ++i) { 76 if (!SDL_sensors[i].event_queue) { 77 continue; 78 } 79 80 SDL_zero(event); 81 while (ASensorEventQueue_getEvents(SDL_sensors[i].event_queue, &event, 1) > 0) { 82 SDL_SendSensorUpdate(timestamp, SDL_sensors[i].sensor, timestamp, event.data, SDL_arraysize(event.data)); 83 } 84 } 85 SDL_UnlockSensors(); 86 } 87 } 88 89 SDL_sensor_looper = NULL; 90 91 return 0; 92} 93 94static void SDL_ANDROID_StopSensorThread(SDL_AndroidSensorThreadContext *ctx) 95{ 96 SDL_SetAtomicInt(&ctx->running, false); 97 98 if (ctx->thread) { 99 int result; 100 101 if (SDL_sensor_looper) { 102 ALooper_wake(SDL_sensor_looper); 103 } 104 SDL_WaitThread(ctx->thread, &result); 105 ctx->thread = NULL; 106 } 107 108 if (ctx->sem) { 109 SDL_DestroySemaphore(ctx->sem); 110 ctx->sem = NULL; 111 } 112} 113 114static bool SDL_ANDROID_StartSensorThread(SDL_AndroidSensorThreadContext *ctx) 115{ 116 ctx->sem = SDL_CreateSemaphore(0); 117 if (!ctx->sem) { 118 SDL_ANDROID_StopSensorThread(ctx); 119 return false; 120 } 121 122 SDL_SetAtomicInt(&ctx->running, true); 123 ctx->thread = SDL_CreateThread(SDL_ANDROID_SensorThread, "Sensors", ctx); 124 if (!ctx->thread) { 125 SDL_ANDROID_StopSensorThread(ctx); 126 return false; 127 } 128 129 // Wait for the sensor thread to start 130 SDL_WaitSemaphore(ctx->sem); 131 132 return true; 133} 134 135static bool SDL_ANDROID_SensorInit(void) 136{ 137 int i, sensors_count; 138 ASensorList sensors; 139 140 SDL_sensor_manager = ASensorManager_getInstance(); 141 if (!SDL_sensor_manager) { 142 return SDL_SetError("Couldn't create sensor manager"); 143 } 144 145 // FIXME: Is the sensor list dynamic? 146 sensors_count = ASensorManager_getSensorList(SDL_sensor_manager, &sensors); 147 if (sensors_count > 0) { 148 SDL_sensors = (SDL_AndroidSensor *)SDL_calloc(sensors_count, sizeof(*SDL_sensors)); 149 if (!SDL_sensors) { 150 return false; 151 } 152 153 for (i = 0; i < sensors_count; ++i) { 154 SDL_sensors[i].asensor = sensors[i]; 155 SDL_sensors[i].instance_id = SDL_GetNextObjectID(); 156 } 157 SDL_sensors_count = sensors_count; 158 } 159 160 if (!SDL_ANDROID_StartSensorThread(&SDL_sensor_thread_context)) { 161 return false; 162 } 163 return true; 164} 165 166static int SDL_ANDROID_SensorGetCount(void) 167{ 168 return SDL_sensors_count; 169} 170 171static void SDL_ANDROID_SensorDetect(void) 172{ 173} 174 175static const char *SDL_ANDROID_SensorGetDeviceName(int device_index) 176{ 177 return ASensor_getName(SDL_sensors[device_index].asensor); 178} 179 180static SDL_SensorType SDL_ANDROID_SensorGetDeviceType(int device_index) 181{ 182 switch (ASensor_getType(SDL_sensors[device_index].asensor)) { 183 case 0x00000001: 184 return SDL_SENSOR_ACCEL; 185 case 0x00000004: 186 return SDL_SENSOR_GYRO; 187 default: 188 return SDL_SENSOR_UNKNOWN; 189 } 190} 191 192static int SDL_ANDROID_SensorGetDeviceNonPortableType(int device_index) 193{ 194 return ASensor_getType(SDL_sensors[device_index].asensor); 195} 196 197static SDL_SensorID SDL_ANDROID_SensorGetDeviceInstanceID(int device_index) 198{ 199 return SDL_sensors[device_index].instance_id; 200} 201 202static bool SDL_ANDROID_SensorOpen(SDL_Sensor *sensor, int device_index) 203{ 204 int delay_us, min_delay_us; 205 206 SDL_LockSensors(); 207 { 208 SDL_sensors[device_index].sensor = sensor; 209 SDL_sensors[device_index].event_queue = ASensorManager_createEventQueue(SDL_sensor_manager, SDL_sensor_looper, LOOPER_ID_USER, NULL, NULL); 210 if (!SDL_sensors[device_index].event_queue) { 211 SDL_UnlockSensors(); 212 return SDL_SetError("Couldn't create sensor event queue"); 213 } 214 215 if (ASensorEventQueue_enableSensor(SDL_sensors[device_index].event_queue, SDL_sensors[device_index].asensor) < 0) { 216 ASensorManager_destroyEventQueue(SDL_sensor_manager, SDL_sensors[device_index].event_queue); 217 SDL_sensors[device_index].event_queue = NULL; 218 SDL_UnlockSensors(); 219 return SDL_SetError("Couldn't enable sensor"); 220 } 221 222 // Use 60 Hz update rate if possible 223 // FIXME: Maybe add a hint for this? 224 delay_us = 1000000 / 60; 225 min_delay_us = ASensor_getMinDelay(SDL_sensors[device_index].asensor); 226 if (delay_us < min_delay_us) { 227 delay_us = min_delay_us; 228 } 229 ASensorEventQueue_setEventRate(SDL_sensors[device_index].event_queue, SDL_sensors[device_index].asensor, delay_us); 230 } 231 SDL_UnlockSensors(); 232 233 return true; 234} 235 236static void SDL_ANDROID_SensorUpdate(SDL_Sensor *sensor) 237{ 238} 239 240static void SDL_ANDROID_SensorClose(SDL_Sensor *sensor) 241{ 242 int i; 243 244 for (i = 0; i < SDL_sensors_count; ++i) { 245 if (SDL_sensors[i].sensor == sensor) { 246 SDL_LockSensors(); 247 { 248 ASensorEventQueue_disableSensor(SDL_sensors[i].event_queue, SDL_sensors[i].asensor); 249 ASensorManager_destroyEventQueue(SDL_sensor_manager, SDL_sensors[i].event_queue); 250 SDL_sensors[i].event_queue = NULL; 251 SDL_sensors[i].sensor = NULL; 252 } 253 SDL_UnlockSensors(); 254 break; 255 } 256 } 257} 258 259static void SDL_ANDROID_SensorQuit(void) 260{ 261 // All sensors are closed, but we need to unblock the sensor thread 262 SDL_AssertSensorsLocked(); 263 SDL_UnlockSensors(); 264 SDL_ANDROID_StopSensorThread(&SDL_sensor_thread_context); 265 SDL_LockSensors(); 266 267 if (SDL_sensors) { 268 SDL_free(SDL_sensors); 269 SDL_sensors = NULL; 270 SDL_sensors_count = 0; 271 } 272} 273 274SDL_SensorDriver SDL_ANDROID_SensorDriver = { 275 SDL_ANDROID_SensorInit, 276 SDL_ANDROID_SensorGetCount, 277 SDL_ANDROID_SensorDetect, 278 SDL_ANDROID_SensorGetDeviceName, 279 SDL_ANDROID_SensorGetDeviceType, 280 SDL_ANDROID_SensorGetDeviceNonPortableType, 281 SDL_ANDROID_SensorGetDeviceInstanceID, 282 SDL_ANDROID_SensorOpen, 283 SDL_ANDROID_SensorUpdate, 284 SDL_ANDROID_SensorClose, 285 SDL_ANDROID_SensorQuit, 286}; 287 288#endif // SDL_SENSOR_ANDROID 289
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.