1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 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 #include "SDL_config.h"
24 
25 #ifdef SDL_SENSOR_ANDROID
26 
27 /* This is the system specific header for the SDL sensor API */
28 #include <android/sensor.h>
29 
30 #include "SDL_error.h"
31 #include "SDL_sensor.h"
32 #include "SDL_androidsensor.h"
33 #include "../SDL_syssensor.h"
34 #include "../SDL_sensor_c.h"
35 //#include "../../core/android/SDL_android.h"
36 
37 #ifndef LOOPER_ID_USER
38 #define LOOPER_ID_USER  3
39 #endif
40 
41 typedef struct
42 {
43     ASensorRef asensor;
44     SDL_SensorID instance_id;
45 } SDL_AndroidSensor;
46 
47 static ASensorManager* SDL_sensor_manager;
48 static ALooper* SDL_sensor_looper;
49 static SDL_AndroidSensor *SDL_sensors;
50 static int SDL_sensors_count;
51 
52 static int
SDL_ANDROID_SensorInit(void)53 SDL_ANDROID_SensorInit(void)
54 {
55     int i, sensors_count;
56     ASensorList sensors;
57 
58     SDL_sensor_manager = ASensorManager_getInstance();
59     if (!SDL_sensor_manager) {
60         return SDL_SetError("Couldn't create sensor manager");
61     }
62 
63     SDL_sensor_looper = ALooper_forThread();
64     if (!SDL_sensor_looper) {
65         SDL_sensor_looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
66         if (!SDL_sensor_looper) {
67             return SDL_SetError("Couldn't create sensor event loop");
68         }
69     }
70 
71     /* FIXME: Is the sensor list dynamic? */
72     sensors_count = ASensorManager_getSensorList(SDL_sensor_manager, &sensors);
73     if (sensors_count > 0) {
74         SDL_sensors = (SDL_AndroidSensor *)SDL_calloc(sensors_count, sizeof(*SDL_sensors));
75         if (!SDL_sensors) {
76             return SDL_OutOfMemory();
77         }
78 
79         for (i = 0; i < sensors_count; ++i) {
80             SDL_sensors[i].asensor = sensors[i];
81             SDL_sensors[i].instance_id = SDL_GetNextSensorInstanceID();
82         }
83         SDL_sensors_count = sensors_count;
84     }
85     return 0;
86 }
87 
88 static int
SDL_ANDROID_SensorGetCount(void)89 SDL_ANDROID_SensorGetCount(void)
90 {
91     return SDL_sensors_count;
92 }
93 
94 static void
SDL_ANDROID_SensorDetect(void)95 SDL_ANDROID_SensorDetect(void)
96 {
97 }
98 
99 static const char *
SDL_ANDROID_SensorGetDeviceName(int device_index)100 SDL_ANDROID_SensorGetDeviceName(int device_index)
101 {
102     return ASensor_getName(SDL_sensors[device_index].asensor);
103 }
104 
105 static SDL_SensorType
SDL_ANDROID_SensorGetDeviceType(int device_index)106 SDL_ANDROID_SensorGetDeviceType(int device_index)
107 {
108     switch (ASensor_getType(SDL_sensors[device_index].asensor)) {
109     case 0x00000001:
110         return SDL_SENSOR_ACCEL;
111     case 0x00000004:
112         return SDL_SENSOR_GYRO;
113     default:
114         return SDL_SENSOR_UNKNOWN;
115     }
116 }
117 
118 static int
SDL_ANDROID_SensorGetDeviceNonPortableType(int device_index)119 SDL_ANDROID_SensorGetDeviceNonPortableType(int device_index)
120 {
121     return ASensor_getType(SDL_sensors[device_index].asensor);
122 }
123 
124 static SDL_SensorID
SDL_ANDROID_SensorGetDeviceInstanceID(int device_index)125 SDL_ANDROID_SensorGetDeviceInstanceID(int device_index)
126 {
127     return SDL_sensors[device_index].instance_id;
128 }
129 
130 static int
SDL_ANDROID_SensorOpen(SDL_Sensor * sensor,int device_index)131 SDL_ANDROID_SensorOpen(SDL_Sensor *sensor, int device_index)
132 {
133     struct sensor_hwdata *hwdata;
134     int delay_us, min_delay_us;
135 
136     hwdata = (struct sensor_hwdata *)SDL_calloc(1, sizeof(*hwdata));
137     if (hwdata == NULL) {
138         return SDL_OutOfMemory();
139     }
140 
141     hwdata->asensor = SDL_sensors[device_index].asensor;
142     hwdata->eventqueue = ASensorManager_createEventQueue(SDL_sensor_manager, SDL_sensor_looper, LOOPER_ID_USER, NULL, NULL);
143     if (!hwdata->eventqueue) {
144         SDL_free(hwdata);
145         return SDL_SetError("Couldn't create sensor event queue");
146     }
147 
148     if (ASensorEventQueue_enableSensor(hwdata->eventqueue, hwdata->asensor) < 0) {
149         ASensorManager_destroyEventQueue(SDL_sensor_manager, hwdata->eventqueue);
150         SDL_free(hwdata);
151         return SDL_SetError("Couldn't enable sensor");
152     }
153 
154     /* Use 60 Hz update rate if possible */
155     /* FIXME: Maybe add a hint for this? */
156     delay_us = 1000000 / 60;
157     min_delay_us = ASensor_getMinDelay(hwdata->asensor);
158     if (delay_us < min_delay_us) {
159         delay_us = min_delay_us;
160     }
161     ASensorEventQueue_setEventRate(hwdata->eventqueue, hwdata->asensor, delay_us);
162 
163     sensor->hwdata = hwdata;
164     return 0;
165 }
166 
167 static void
SDL_ANDROID_SensorUpdate(SDL_Sensor * sensor)168 SDL_ANDROID_SensorUpdate(SDL_Sensor *sensor)
169 {
170     int events;
171     ASensorEvent event;
172     struct android_poll_source* source;
173 
174     if (ALooper_pollAll(0, NULL, &events, (void**)&source) == LOOPER_ID_USER) {
175         SDL_zero(event);
176         while (ASensorEventQueue_getEvents(sensor->hwdata->eventqueue, &event, 1) > 0) {
177             SDL_PrivateSensorUpdate(sensor, event.data, SDL_arraysize(event.data));
178         }
179     }
180 }
181 
182 static void
SDL_ANDROID_SensorClose(SDL_Sensor * sensor)183 SDL_ANDROID_SensorClose(SDL_Sensor *sensor)
184 {
185     if (sensor->hwdata) {
186         ASensorEventQueue_disableSensor(sensor->hwdata->eventqueue, sensor->hwdata->asensor);
187         ASensorManager_destroyEventQueue(SDL_sensor_manager, sensor->hwdata->eventqueue);
188         SDL_free(sensor->hwdata);
189         sensor->hwdata = NULL;
190     }
191 }
192 
193 static void
SDL_ANDROID_SensorQuit(void)194 SDL_ANDROID_SensorQuit(void)
195 {
196     if (SDL_sensors) {
197         SDL_free(SDL_sensors);
198         SDL_sensors = NULL;
199         SDL_sensors_count = 0;
200     }
201 }
202 
203 SDL_SensorDriver SDL_ANDROID_SensorDriver =
204 {
205     SDL_ANDROID_SensorInit,
206     SDL_ANDROID_SensorGetCount,
207     SDL_ANDROID_SensorDetect,
208     SDL_ANDROID_SensorGetDeviceName,
209     SDL_ANDROID_SensorGetDeviceType,
210     SDL_ANDROID_SensorGetDeviceNonPortableType,
211     SDL_ANDROID_SensorGetDeviceInstanceID,
212     SDL_ANDROID_SensorOpen,
213     SDL_ANDROID_SensorUpdate,
214     SDL_ANDROID_SensorClose,
215     SDL_ANDROID_SensorQuit,
216 };
217 
218 #endif /* SDL_SENSOR_ANDROID */
219 
220 /* vi: set ts=4 sw=4 expandtab: */
221