summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/sensor/android/SDL_androidsensor.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/sensor/android/SDL_androidsensor.c
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/sensor/android/SDL_androidsensor.c')
-rw-r--r--contrib/SDL-3.2.8/src/sensor/android/SDL_androidsensor.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/sensor/android/SDL_androidsensor.c b/contrib/SDL-3.2.8/src/sensor/android/SDL_androidsensor.c
new file mode 100644
index 0000000..87981a1
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/sensor/android/SDL_androidsensor.c
@@ -0,0 +1,288 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
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