1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3  *  Copyright (C) 2011-2017 - Daniel De Matteis
4  *  Copyright (C) 2012-2015 - Michael Lelli
5  *  Copyright (C) 2013-2014 - Steven Crowe
6  *
7  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
8  *  of the GNU General Public License as published by the Free Software Found-
9  *  ation, either version 3 of the License, or (at your option) any later version.
10  *
11  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  *  PURPOSE.  See the GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along with RetroArch.
16  *  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <unistd.h>
20 #include <dlfcn.h>
21 
22 #include <android/keycodes.h>
23 
24 #include <dynamic/dylib.h>
25 #include <retro_inline.h>
26 #include <string/stdstring.h>
27 
28 #ifdef HAVE_CONFIG_H
29 #include "../../config.h"
30 #endif
31 
32 #include "../../config.def.h"
33 
34 #ifdef HAVE_MENU
35 #include "../../menu/menu_driver.h"
36 #endif
37 
38 
39 #include "../../command.h"
40 #include "../../frontend/drivers/platform_unix.h"
41 #include "../drivers_keyboard/keyboard_event_android.h"
42 #include "../../tasks/tasks_internal.h"
43 #include "../../performance_counters.h"
44 
45 #include "../../configuration.h"
46 #include "../../retroarch.h"
47 
48 #define MAX_TOUCH 16
49 #define MAX_NUM_KEYBOARDS 3
50 #define DEFAULT_ASENSOR_EVENT_RATE 60
51 
52 /* If using an SDK lower than 14 then add missing mouse button codes */
53 #if __ANDROID_API__ < 14
54 enum {
55     AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
56     AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1,
57     AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
58     AMOTION_EVENT_BUTTON_BACK = 1 << 3,
59     AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
60     AMOTION_EVENT_AXIS_VSCROLL = 9,
61     AMOTION_EVENT_ACTION_HOVER_MOVE = 7,
62     AINPUT_SOURCE_STYLUS = 0x00004000
63 };
64 #endif
65 
66 /* If using an SDK lower than 24 then add missing relative axis codes */
67 #ifndef AMOTION_EVENT_AXIS_RELATIVE_X
68 #define AMOTION_EVENT_AXIS_RELATIVE_X 27
69 #endif
70 
71 #ifndef AMOTION_EVENT_AXIS_RELATIVE_Y
72 #define AMOTION_EVENT_AXIS_RELATIVE_Y 28
73 #endif
74 
75 /* Use this to enable/disable using the touch screen as mouse */
76 #define ENABLE_TOUCH_SCREEN_MOUSE 1
77 
78 #define AKEYCODE_ASSIST 219
79 
80 #define LAST_KEYCODE AKEYCODE_ASSIST
81 
82 #define MAX_KEYS ((LAST_KEYCODE + 7) / 8)
83 
84 /* First ports are used to keep track of gamepad states.
85  * Last port is used for keyboard state */
86 static uint8_t android_key_state[DEFAULT_MAX_PADS + 1][MAX_KEYS];
87 
88 #define ANDROID_KEYBOARD_PORT_INPUT_PRESSED(binds, id) (BIT_GET(android_key_state[ANDROID_KEYBOARD_PORT], rarch_keysym_lut[(binds)[(id)].key]))
89 
90 #define ANDROID_KEYBOARD_INPUT_PRESSED(key) (BIT_GET(android_key_state[0], (key)))
91 
android_keyboard_state_get(unsigned port)92 uint8_t *android_keyboard_state_get(unsigned port)
93 {
94    return android_key_state[port];
95 }
96 
android_keyboard_free(void)97 static void android_keyboard_free(void)
98 {
99    unsigned i, j;
100 
101    for (i = 0; i < DEFAULT_MAX_PADS; i++)
102       for (j = 0; j < MAX_KEYS; j++)
103          android_key_state[i][j] = 0;
104 }
105 
106 /* TODO/FIXME -
107  * fix game focus toggle */
108 
109 typedef struct
110 {
111    float x;
112    float y;
113    float z;
114 } sensor_t;
115 
116 struct input_pointer
117 {
118    int16_t x, y;
119    int16_t full_x, full_y;
120 };
121 
122 static int pad_id1 = -1;
123 static int pad_id2 = -1;
124 static int kbd_id[MAX_NUM_KEYBOARDS];
125 static int kbd_num = 0;
126 
127 enum
128 {
129    AXIS_X        = 0,
130    AXIS_Y        = 1,
131    AXIS_Z        = 11,
132    AXIS_RZ       = 14,
133    AXIS_HAT_X    = 15,
134    AXIS_HAT_Y    = 16,
135    AXIS_LTRIGGER = 17,
136    AXIS_RTRIGGER = 18,
137    AXIS_GAS      = 22,
138    AXIS_BRAKE    = 23
139 };
140 
141 typedef struct state_device
142 {
143    int id;
144    int port;
145    char name[256];
146 } state_device_t;
147 
148 typedef struct android_input
149 {
150    int64_t quick_tap_time;
151    state_device_t pad_states[MAX_USERS];        /* int alignment */
152    int mouse_x_delta, mouse_y_delta;
153    int mouse_l, mouse_r, mouse_m, mouse_wu, mouse_wd;
154    unsigned pads_connected;
155    unsigned pointer_count;
156    sensor_t accelerometer_state;                /* float alignment */
157    sensor_t gyroscope_state;                    /* float alignment */
158    float mouse_x_prev, mouse_y_prev;
159    struct input_pointer pointer[MAX_TOUCH];     /* int16_t alignment */
160    char device_model[256];
161 } android_input_t;
162 
163 static void frontend_android_get_version_sdk(int32_t *sdk);
164 static void frontend_android_get_name(char *s, size_t len);
165 
166 bool (*engine_lookup_name)(char *buf,
167       int *vendorId, int *productId, size_t size, int id);
168 void (*engine_handle_dpad)(struct android_app *, AInputEvent*, int, int);
169 
170 static bool android_input_set_sensor_state(void *data, unsigned port,
171       enum retro_sensor_action action, unsigned event_rate);
172 
173 extern float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
174       int32_t axis, size_t pointer_idx);
175 
176 static typeof(AMotionEvent_getAxisValue) *p_AMotionEvent_getAxisValue;
177 
178 #define AMotionEvent_getAxisValue (*p_AMotionEvent_getAxisValue)
179 
180 extern int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
181 
182 static typeof(AMotionEvent_getButtonState) *p_AMotionEvent_getButtonState;
183 
184 #define AMotionEvent_getButtonState (*p_AMotionEvent_getButtonState)
185 
186 #ifdef HAVE_DYNAMIC
187 static void *libandroid_handle;
188 #endif
189 
android_input_lookup_name_prekitkat(char * buf,int * vendorId,int * productId,size_t size,int id)190 static bool android_input_lookup_name_prekitkat(char *buf,
191       int *vendorId, int *productId, size_t size, int id)
192 {
193    jobject name      = NULL;
194    jmethodID getName = NULL;
195    jobject device    = NULL;
196    jmethodID method  = NULL;
197    jclass    class   = 0;
198    const char *str   = NULL;
199    JNIEnv     *env   = (JNIEnv*)jni_thread_getenv();
200 
201    if (!env)
202       return false;
203 
204    FIND_CLASS(env, class, "android/view/InputDevice");
205    if (!class)
206       return false;
207 
208    GET_STATIC_METHOD_ID(env, method, class, "getDevice",
209          "(I)Landroid/view/InputDevice;");
210    if (!method)
211       return false;
212 
213    CALL_OBJ_STATIC_METHOD_PARAM(env, device, class, method, (jint)id);
214    if (!device)
215       return false;
216 
217    GET_METHOD_ID(env, getName, class, "getName", "()Ljava/lang/String;");
218    if (!getName)
219       return false;
220 
221    CALL_OBJ_METHOD(env, name, device, getName);
222    if (!name)
223       return false;
224 
225    buf[0] = '\0';
226 
227    str = (*env)->GetStringUTFChars(env, name, 0);
228    if (str)
229       strlcpy(buf, str, size);
230    (*env)->ReleaseStringUTFChars(env, name, str);
231 
232    return true;
233 }
234 
android_input_lookup_name(char * buf,int * vendorId,int * productId,size_t size,int id)235 static bool android_input_lookup_name(char *buf,
236       int *vendorId, int *productId, size_t size, int id)
237 {
238    jmethodID getVendorId  = NULL;
239    jmethodID getProductId = NULL;
240    jmethodID getName      = NULL;
241    jobject device         = NULL;
242    jobject name           = NULL;
243    jmethodID method       = NULL;
244    jclass class           = NULL;
245    const char *str        = NULL;
246    JNIEnv     *env        = (JNIEnv*)jni_thread_getenv();
247 
248    if (!env)
249       return false;
250 
251    FIND_CLASS(env, class, "android/view/InputDevice");
252    if (!class)
253       return false;
254 
255    GET_STATIC_METHOD_ID(env, method, class, "getDevice",
256          "(I)Landroid/view/InputDevice;");
257    if (!method)
258       return false;
259 
260    CALL_OBJ_STATIC_METHOD_PARAM(env, device, class, method, (jint)id);
261    if (!device)
262       return false;
263 
264    GET_METHOD_ID(env, getName, class, "getName", "()Ljava/lang/String;");
265    if (!getName)
266       return false;
267 
268    CALL_OBJ_METHOD(env, name, device, getName);
269    if (!name)
270       return false;
271 
272    buf[0] = '\0';
273 
274    str = (*env)->GetStringUTFChars(env, name, 0);
275    if (str)
276       strlcpy(buf, str, size);
277    (*env)->ReleaseStringUTFChars(env, name, str);
278 
279    GET_METHOD_ID(env, getVendorId, class, "getVendorId", "()I");
280    if (!getVendorId)
281       return false;
282 
283    CALL_INT_METHOD(env, *vendorId, device, getVendorId);
284 
285    GET_METHOD_ID(env, getProductId, class, "getProductId", "()I");
286    if (!getProductId)
287       return false;
288 
289    *productId = 0;
290    CALL_INT_METHOD(env, *productId, device, getProductId);
291 
292    return true;
293 }
294 
android_input_poll_main_cmd(void)295 static void android_input_poll_main_cmd(void)
296 {
297    int8_t cmd;
298    struct android_app *android_app = (struct android_app*)g_android;
299 
300    if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd))
301       cmd = -1;
302 
303    switch (cmd)
304    {
305       case APP_CMD_REINIT_DONE:
306          slock_lock(android_app->mutex);
307 
308          android_app->reinitRequested = 0;
309 
310          scond_broadcast(android_app->cond);
311          slock_unlock(android_app->mutex);
312          break;
313 
314       case APP_CMD_INPUT_CHANGED:
315          slock_lock(android_app->mutex);
316 
317          if (android_app->inputQueue)
318             AInputQueue_detachLooper(android_app->inputQueue);
319 
320          android_app->inputQueue = android_app->pendingInputQueue;
321 
322          if (android_app->inputQueue)
323             AInputQueue_attachLooper(android_app->inputQueue,
324                   android_app->looper, LOOPER_ID_INPUT, NULL,
325                   NULL);
326 
327          scond_broadcast(android_app->cond);
328          slock_unlock(android_app->mutex);
329 
330          break;
331 
332       case APP_CMD_INIT_WINDOW:
333          slock_lock(android_app->mutex);
334          android_app->window = android_app->pendingWindow;
335          android_app->reinitRequested = 1;
336          scond_broadcast(android_app->cond);
337          slock_unlock(android_app->mutex);
338 
339          break;
340 
341       case APP_CMD_SAVE_STATE:
342          slock_lock(android_app->mutex);
343          android_app->stateSaved = 1;
344          scond_broadcast(android_app->cond);
345          slock_unlock(android_app->mutex);
346          break;
347 
348       case APP_CMD_RESUME:
349       case APP_CMD_START:
350       case APP_CMD_PAUSE:
351       case APP_CMD_STOP:
352          slock_lock(android_app->mutex);
353          android_app->activityState = cmd;
354          scond_broadcast(android_app->cond);
355          slock_unlock(android_app->mutex);
356          break;
357 
358       case APP_CMD_CONFIG_CHANGED:
359          AConfiguration_fromAssetManager(android_app->config,
360                android_app->activity->assetManager);
361          break;
362       case APP_CMD_TERM_WINDOW:
363          slock_lock(android_app->mutex);
364 
365          /* The window is being hidden or closed, clean it up. */
366          /* terminate display/EGL context here */
367 
368          android_app->window = NULL;
369          scond_broadcast(android_app->cond);
370          slock_unlock(android_app->mutex);
371          break;
372 
373       case APP_CMD_GAINED_FOCUS:
374          {
375             bool boolean              = false;
376             bool enable_accelerometer = (android_app->sensor_state_mask &
377                   (UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE)) &&
378                         !android_app->accelerometerSensor;
379             bool enable_gyroscope     = (android_app->sensor_state_mask &
380                   (UINT64_C(1) << RETRO_SENSOR_GYROSCOPE_ENABLE)) &&
381                         !android_app->gyroscopeSensor;
382 
383             rarch_ctl(RARCH_CTL_SET_PAUSED, &boolean);
384             rarch_ctl(RARCH_CTL_SET_IDLE,   &boolean);
385             video_driver_unset_stub_frame();
386 
387             if (enable_accelerometer)
388                input_sensor_set_state(0,
389                      RETRO_SENSOR_ACCELEROMETER_ENABLE,
390                      android_app->accelerometer_event_rate);
391 
392             if (enable_gyroscope)
393                input_sensor_set_state(0,
394                      RETRO_SENSOR_GYROSCOPE_ENABLE,
395                      android_app->gyroscope_event_rate);
396          }
397          slock_lock(android_app->mutex);
398          android_app->unfocused = false;
399          scond_broadcast(android_app->cond);
400          slock_unlock(android_app->mutex);
401          break;
402       case APP_CMD_LOST_FOCUS:
403          {
404             bool boolean               = true;
405             bool disable_accelerometer = (android_app->sensor_state_mask &
406                   (UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE)) &&
407                         android_app->accelerometerSensor;
408             bool disable_gyroscope     = (android_app->sensor_state_mask &
409                   (UINT64_C(1) << RETRO_SENSOR_GYROSCOPE_ENABLE)) &&
410                         android_app->gyroscopeSensor;
411 
412             rarch_ctl(RARCH_CTL_SET_PAUSED, &boolean);
413             rarch_ctl(RARCH_CTL_SET_IDLE,   &boolean);
414             video_driver_set_stub_frame();
415 
416             /* Avoid draining battery while app is not being used. */
417             if (disable_accelerometer)
418                input_sensor_set_state(0,
419                      RETRO_SENSOR_ACCELEROMETER_DISABLE,
420                      android_app->accelerometer_event_rate);
421 
422             if (disable_gyroscope)
423                input_sensor_set_state(0,
424                      RETRO_SENSOR_GYROSCOPE_DISABLE,
425                      android_app->gyroscope_event_rate);
426          }
427          slock_lock(android_app->mutex);
428          android_app->unfocused = true;
429          scond_broadcast(android_app->cond);
430          slock_unlock(android_app->mutex);
431          break;
432 
433       case APP_CMD_DESTROY:
434          android_app->destroyRequested = 1;
435          break;
436       case APP_CMD_VIBRATE_KEYPRESS:
437       {
438          JNIEnv *env = (JNIEnv*)jni_thread_getenv();
439 
440          if (env && g_android && g_android->doVibrate)
441          {
442             CALL_VOID_METHOD_PARAM(env, g_android->activity->clazz,
443                   g_android->doVibrate, (jint)-1, (jint)RETRO_RUMBLE_STRONG, (jint)255, (jint)1);
444          }
445          break;
446       }
447    }
448 }
449 
engine_handle_dpad_default(struct android_app * android,AInputEvent * event,int port,int source)450 static void engine_handle_dpad_default(struct android_app *android,
451       AInputEvent *event, int port, int source)
452 {
453    size_t motion_ptr = AMotionEvent_getAction(event) >>
454       AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
455    float x           = AMotionEvent_getX(event, motion_ptr);
456    float y           = AMotionEvent_getY(event, motion_ptr);
457 
458    android->analog_state[port][0] = (int16_t)(x * 32767.0f);
459    android->analog_state[port][1] = (int16_t)(y * 32767.0f);
460 }
461 
462 #ifdef HAVE_DYNAMIC
engine_handle_dpad_getaxisvalue(struct android_app * android,AInputEvent * event,int port,int source)463 static void engine_handle_dpad_getaxisvalue(struct android_app *android,
464       AInputEvent *event, int port, int source)
465 {
466    size_t motion_ptr = AMotionEvent_getAction(event) >>
467       AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
468    float x           = AMotionEvent_getAxisValue(event, AXIS_X, motion_ptr);
469    float y           = AMotionEvent_getAxisValue(event, AXIS_Y, motion_ptr);
470    float z           = AMotionEvent_getAxisValue(event, AXIS_Z, motion_ptr);
471    float rz          = AMotionEvent_getAxisValue(event, AXIS_RZ, motion_ptr);
472    float hatx        = AMotionEvent_getAxisValue(event, AXIS_HAT_X, motion_ptr);
473    float haty        = AMotionEvent_getAxisValue(event, AXIS_HAT_Y, motion_ptr);
474    float ltrig       = AMotionEvent_getAxisValue(event, AXIS_LTRIGGER, motion_ptr);
475    float rtrig       = AMotionEvent_getAxisValue(event, AXIS_RTRIGGER, motion_ptr);
476    float brake       = AMotionEvent_getAxisValue(event, AXIS_BRAKE, motion_ptr);
477    float gas         = AMotionEvent_getAxisValue(event, AXIS_GAS, motion_ptr);
478 
479    android->hat_state[port][0]    = (int)hatx;
480    android->hat_state[port][1]    = (int)haty;
481 
482    /* XXX: this could be a loop instead, but do we really want to
483     * loop through every axis? */
484    android->analog_state[port][0] = (int16_t)(x * 32767.0f);
485    android->analog_state[port][1] = (int16_t)(y * 32767.0f);
486    android->analog_state[port][2] = (int16_t)(z * 32767.0f);
487    android->analog_state[port][3] = (int16_t)(rz * 32767.0f);
488 #if 0
489    android->analog_state[port][4] = (int16_t)(hatx * 32767.0f);
490    android->analog_state[port][5] = (int16_t)(haty * 32767.0f);
491 #endif
492    android->analog_state[port][6] = (int16_t)(ltrig * 32767.0f);
493    android->analog_state[port][7] = (int16_t)(rtrig * 32767.0f);
494    android->analog_state[port][8] = (int16_t)(brake * 32767.0f);
495    android->analog_state[port][9] = (int16_t)(gas * 32767.0f);
496 }
497 #endif
498 
android_input_init_handle(void)499 static bool android_input_init_handle(void)
500 {
501 #ifdef HAVE_DYNAMIC
502    if (libandroid_handle != NULL) /* already initialized */
503       return true;
504 #if defined (ANDROID_AARCH64) || defined(ANDROID_X64)
505    if ((libandroid_handle = dlopen("/system/lib64/libandroid.so",
506                RTLD_LOCAL | RTLD_LAZY)) == 0)
507       return false;
508 #else
509    if ((libandroid_handle = dlopen("/system/lib/libandroid.so",
510                RTLD_LOCAL | RTLD_LAZY)) == 0)
511       return false;
512 #endif
513 
514    if ((p_AMotionEvent_getAxisValue = dlsym(RTLD_DEFAULT,
515                "AMotionEvent_getAxisValue")))
516       engine_handle_dpad            = engine_handle_dpad_getaxisvalue;
517 
518    p_AMotionEvent_getButtonState    = dlsym(RTLD_DEFAULT,
519                "AMotionEvent_getButtonState");
520 #endif
521 
522    pad_id1 = -1;
523    pad_id2 = -1;
524 
525    return true;
526 }
527 
android_input_init(const char * joypad_driver)528 static void *android_input_init(const char *joypad_driver)
529 {
530    int32_t sdk;
531    struct android_app *android_app = (struct android_app*)g_android;
532    android_input_t *android = (android_input_t*)
533       calloc(1, sizeof(*android));
534 
535    if (!android)
536       return NULL;
537 
538    android->pads_connected = 0;
539    android->quick_tap_time = 0;
540 
541    input_keymaps_init_keyboard_lut(rarch_key_map_android);
542 
543    frontend_android_get_version_sdk(&sdk);
544 
545    if (sdk >= 19)
546       engine_lookup_name = android_input_lookup_name;
547    else
548       engine_lookup_name = android_input_lookup_name_prekitkat;
549 
550    engine_handle_dpad         = engine_handle_dpad_default;
551 
552    if (!android_input_init_handle())
553    {
554       RARCH_WARN("Unable to open libandroid.so\n");
555    }
556 
557    frontend_android_get_name(android->device_model,
558          sizeof(android->device_model));
559 
560    android_app->input_alive = true;
561 
562    return android;
563 }
564 
android_check_quick_tap(android_input_t * android)565 static int android_check_quick_tap(android_input_t *android)
566 {
567    /* Check if the touch screen has been been quick tapped
568     * and then not touched again for 200ms
569     * If so then return true and deactivate quick tap timer */
570    retro_time_t now = cpu_features_get_time_usec();
571    if (android->quick_tap_time &&
572          (now / 1000 - android->quick_tap_time / 1000000) >= 200)
573    {
574       android->quick_tap_time = 0;
575       return 1;
576    }
577 
578    return 0;
579 }
580 
android_mouse_calculate_deltas(android_input_t * android,AInputEvent * event,size_t motion_ptr)581 static INLINE void android_mouse_calculate_deltas(android_input_t *android,
582       AInputEvent *event,size_t motion_ptr)
583 {
584    /* Adjust mouse speed based on ratio
585     * between core resolution and system resolution */
586    float x = 0, y = 0;
587    float                        x_scale = 1;
588    float                        y_scale = 1;
589    struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
590 
591    if (av_info)
592    {
593       video_viewport_t          *custom_vp   = video_viewport_get_custom();
594       const struct retro_game_geometry *geom = (const struct retro_game_geometry*)&av_info->geometry;
595       x_scale = 2 * (float)geom->base_width / (float)custom_vp->width;
596       y_scale = 2 * (float)geom->base_height / (float)custom_vp->height;
597    }
598 
599    /* This axis is only available on Android Nougat and on
600     * Android devices with NVIDIA extensions */
601    if (p_AMotionEvent_getAxisValue)
602    {
603       x = AMotionEvent_getAxisValue(event,AMOTION_EVENT_AXIS_RELATIVE_X,
604             motion_ptr);
605       y = AMotionEvent_getAxisValue(event,AMOTION_EVENT_AXIS_RELATIVE_Y,
606             motion_ptr);
607    }
608 
609    /* If AXIS_RELATIVE had 0 values it might be because we're not
610     * running Android Nougat or on a device
611     * with NVIDIA extension, so re-calculate deltas based on
612     * AXIS_X and AXIS_Y. This has limitations
613     * compared to AXIS_RELATIVE because once the Android mouse cursor
614     * hits the edge of the screen it is
615     * not possible to move the in-game mouse any further in that direction.
616     */
617    if (!x && !y)
618    {
619       x = (AMotionEvent_getX(event, motion_ptr) - android->mouse_x_prev);
620       y = (AMotionEvent_getY(event, motion_ptr) - android->mouse_y_prev);
621       android->mouse_x_prev = AMotionEvent_getX(event, motion_ptr);
622       android->mouse_y_prev = AMotionEvent_getY(event, motion_ptr);
623    }
624 
625    android->mouse_x_delta = ceil(x) * x_scale;
626    android->mouse_y_delta = ceil(y) * y_scale;
627 }
628 
android_input_poll_event_type_motion(android_input_t * android,AInputEvent * event,int port,int source,bool vibrate_on_keypress)629 static INLINE void android_input_poll_event_type_motion(
630       android_input_t *android, AInputEvent *event,
631       int port, int source, bool vibrate_on_keypress)
632 {
633    int btn;
634    int getaction     = AMotionEvent_getAction(event);
635    int action        = getaction & AMOTION_EVENT_ACTION_MASK;
636    size_t motion_ptr = getaction >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
637    bool keyup        = (
638          action == AMOTION_EVENT_ACTION_UP ||
639          action == AMOTION_EVENT_ACTION_CANCEL ||
640          action == AMOTION_EVENT_ACTION_POINTER_UP) ||
641       (source == AINPUT_SOURCE_MOUSE &&
642        action != AMOTION_EVENT_ACTION_DOWN);
643 
644    /* If source is mouse then calculate button state
645     * and mouse deltas and don't process as touchscreen event */
646    if (source == AINPUT_SOURCE_MOUSE)
647    {
648       /* getButtonState requires API level 14 */
649       if (p_AMotionEvent_getButtonState)
650       {
651          btn              = (int)AMotionEvent_getButtonState(event);
652 
653          android->mouse_l = (btn & AMOTION_EVENT_BUTTON_PRIMARY);
654          android->mouse_r = (btn & AMOTION_EVENT_BUTTON_SECONDARY);
655          android->mouse_m = (btn & AMOTION_EVENT_BUTTON_TERTIARY);
656 
657          btn              = (int)AMotionEvent_getAxisValue(event,
658                AMOTION_EVENT_AXIS_VSCROLL, motion_ptr);
659 
660          if (btn > 0)
661             android->mouse_wu = btn;
662          else if (btn < 0)
663             android->mouse_wd = btn;
664       }
665       else
666       {
667          /* If getButtonState is not available
668           * then treat all MotionEvent.ACTION_DOWN as left button presses */
669          if (action == AMOTION_EVENT_ACTION_DOWN)
670             android->mouse_l = 1;
671          if (action == AMOTION_EVENT_ACTION_UP)
672             android->mouse_l = 0;
673       }
674 
675       android_mouse_calculate_deltas(android,event,motion_ptr);
676 
677       return;
678    }
679 
680    if (keyup && motion_ptr < MAX_TOUCH)
681    {
682       if (action == AMOTION_EVENT_ACTION_UP && ENABLE_TOUCH_SCREEN_MOUSE)
683       {
684          /* If touchscreen was pressed for less than 200ms
685           * then register time stamp of a quick tap */
686          if ((AMotionEvent_getEventTime(event)-AMotionEvent_getDownTime(event))/1000000 < 200)
687             android->quick_tap_time = AMotionEvent_getEventTime(event);
688          android->mouse_l = 0;
689       }
690 
691       memmove(android->pointer + motion_ptr,
692             android->pointer + motion_ptr + 1,
693             (MAX_TOUCH - motion_ptr - 1) * sizeof(struct input_pointer));
694       if (android->pointer_count > 0)
695          android->pointer_count--;
696    }
697    else
698    {
699       int      pointer_max     = MIN(
700             AMotionEvent_getPointerCount(event), MAX_TOUCH);
701 
702       if (vibrate_on_keypress && action != AMOTION_EVENT_ACTION_MOVE)
703          android_app_write_cmd(g_android, APP_CMD_VIBRATE_KEYPRESS);
704 
705       if (action == AMOTION_EVENT_ACTION_DOWN && ENABLE_TOUCH_SCREEN_MOUSE)
706       {
707          /* When touch screen is pressed, set mouse
708           * previous position to current position
709           * before starting to calculate mouse movement deltas. */
710          android->mouse_x_prev = AMotionEvent_getX(event, motion_ptr);
711          android->mouse_y_prev = AMotionEvent_getY(event, motion_ptr);
712 
713          /* If another touch happened within 200ms after a quick tap
714           * then cancel the quick tap and register left mouse button
715           * as being held down */
716          if ((AMotionEvent_getEventTime(event) - android->quick_tap_time)/1000000 < 200)
717          {
718             android->quick_tap_time = 0;
719             android->mouse_l        = 1;
720          }
721       }
722 
723       if ((       action == AMOTION_EVENT_ACTION_MOVE
724                || action == AMOTION_EVENT_ACTION_HOVER_MOVE)
725             && ENABLE_TOUCH_SCREEN_MOUSE)
726          android_mouse_calculate_deltas(android,event,motion_ptr);
727 
728       for (motion_ptr = 0; motion_ptr < pointer_max; motion_ptr++)
729       {
730          struct video_viewport vp;
731          float x = AMotionEvent_getX(event, motion_ptr);
732          float y = AMotionEvent_getY(event, motion_ptr);
733 
734          vp.x                        = 0;
735          vp.y                        = 0;
736          vp.width                    = 0;
737          vp.height                   = 0;
738          vp.full_width               = 0;
739          vp.full_height              = 0;
740 
741          video_driver_translate_coord_viewport_wrap(
742                &vp,
743                x, y,
744                &android->pointer[motion_ptr].x,
745                &android->pointer[motion_ptr].y,
746                &android->pointer[motion_ptr].full_x,
747                &android->pointer[motion_ptr].full_y);
748 
749          android->pointer_count = MAX(
750                android->pointer_count,
751                motion_ptr + 1);
752       }
753    }
754 
755    /* If more than one pointer detected
756     * then count it as a mouse right click */
757    if (ENABLE_TOUCH_SCREEN_MOUSE)
758       android->mouse_r = (android->pointer_count == 2);
759 }
760 
android_is_keyboard_id(int id)761 static bool android_is_keyboard_id(int id)
762 {
763    unsigned i;
764    for (i = 0;  i < (unsigned)kbd_num; i++)
765       if (id == kbd_id[i])
766          return true;
767 
768    return false;
769 }
770 
android_input_poll_event_type_keyboard(AInputEvent * event,int keycode,int * handled)771 static INLINE void android_input_poll_event_type_keyboard(
772       AInputEvent *event, int keycode, int *handled)
773 {
774    int keydown           = (AKeyEvent_getAction(event)
775          == AKEY_EVENT_ACTION_DOWN);
776    unsigned keyboardcode = input_keymaps_translate_keysym_to_rk(keycode);
777    /* Set keyboard modifier based on shift,ctrl and alt state */
778    uint16_t mod          = 0;
779    int meta              = AKeyEvent_getMetaState(event);
780 
781    if (meta & AMETA_ALT_ON)
782       mod |= RETROKMOD_ALT;
783    if (meta & AMETA_CTRL_ON)
784       mod |= RETROKMOD_CTRL;
785    if (meta & AMETA_SHIFT_ON)
786       mod |= RETROKMOD_SHIFT;
787 
788    input_keyboard_event(keydown, keyboardcode,
789          keyboardcode, mod, RETRO_DEVICE_KEYBOARD);
790 
791    if ((keycode == AKEYCODE_VOLUME_UP || keycode == AKEYCODE_VOLUME_DOWN))
792       *handled = 0;
793 }
794 
android_input_poll_event_type_key(struct android_app * android_app,AInputEvent * event,int port,int keycode,int source,int type_event,int * handled)795 static INLINE void android_input_poll_event_type_key(
796       struct android_app *android_app,
797       AInputEvent *event, int port, int keycode, int source,
798       int type_event, int *handled)
799 {
800    uint8_t *buf = android_key_state[port];
801    int action   = AKeyEvent_getAction(event);
802 
803    /* some controllers send both the up and down events at once
804     * when the button is released for "special" buttons, like menu buttons
805     * work around that by only using down events for meta keys (which get
806     * cleared every poll anyway)
807     */
808    switch (action)
809    {
810       case AKEY_EVENT_ACTION_UP:
811          BIT_CLEAR(buf, keycode);
812          break;
813       case AKEY_EVENT_ACTION_DOWN:
814          BIT_SET(buf, keycode);
815          break;
816    }
817 
818    if ((keycode == AKEYCODE_VOLUME_UP || keycode == AKEYCODE_VOLUME_DOWN))
819       *handled = 0;
820 }
821 
android_input_get_id_port(android_input_t * android,int id,int source)822 static int android_input_get_id_port(android_input_t *android, int id,
823       int source)
824 {
825    unsigned i;
826    int ret = -1;
827    if (source & (AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE |
828             AINPUT_SOURCE_TOUCHPAD))
829          ret = 0; /* touch overlay is always user 1 */
830 
831    for (i = 0; i < android->pads_connected; i++)
832    {
833       if (android->pad_states[i].id == id)
834       {
835          ret = i;
836          break;
837       }
838    }
839 
840    return ret;
841 }
842 
843 #ifdef HAVE_DYNAMIC
844 /* Returns the index inside android->pad_state */
android_input_get_id_index_from_name(android_input_t * android,const char * name)845 static int android_input_get_id_index_from_name(android_input_t *android,
846       const char *name)
847 {
848    int i;
849    for (i = 0; i < android->pads_connected; i++)
850    {
851       if (string_is_equal(name, android->pad_states[i].name))
852          return i;
853    }
854 
855    return -1;
856 }
857 #endif
858 
handle_hotplug(android_input_t * android,struct android_app * android_app,int * port,int id,int source)859 static void handle_hotplug(android_input_t *android,
860       struct android_app *android_app, int *port, int id,
861       int source)
862 {
863    char device_name[256];
864    char name_buf[256];
865    int vendorId                 = 0;
866    int productId                = 0;
867    const char *device_model     = android->device_model;
868 
869    device_name[0] = name_buf[0] = '\0';
870 
871    if (!engine_lookup_name(device_name, &vendorId,
872             &productId, sizeof(device_name), id))
873       return;
874 
875    /* FIXME - per-device hacks for NVidia Shield, Xperia Play and
876     * similar devices
877     *
878     * These hacks depend on autoconf, but can work with user
879     * created autoconfs properly
880     */
881 
882    /* NVIDIA Shield Console
883     * This is the most complicated example, the built-in controller
884     * has an extra button that can't be used and a remote.
885     *
886     * We map the remote for navigation and overwrite whenever a
887     * real controller is connected.
888     * Also group the NVIDIA button on the controller with the
889     * main controller inputs so it's usable. It's mapped to
890     * menu by default
891     *
892     * The NVIDIA button is identified as "Virtual" device when first
893     * pressed. CEC remote input is also identified as "Virtual" device.
894     * If a virtual device is detected before a controller then it will
895     * be assigned to port 0 as "SHIELD Virtual Controller". When a real
896     * controller is detected it will overwrite the virtual controller
897     * and be grouped with the NVIDIA button of the virtual device.
898     *
899     */
900    if (strstr(device_model, "SHIELD Android TV") && (
901       strstr(device_name, "Virtual") ||
902       strstr(device_name, "NVIDIA Corporation NVIDIA Controller v01.0")))
903    {
904       /* only use the hack if the device is one of the built-in devices */
905       RARCH_LOG("Special Device Detected: %s\n", device_model);
906       {
907 #if 0
908          RARCH_LOG("- Pads Mapped: %d\n- Device Name: %s\n- IDS: %d, %d, %d",
909                android->pads_connected, device_name, id, pad_id1, pad_id2);
910 #endif
911          /* Remove the remote or virtual controller device if it is mapped */
912          if (strstr(android->pad_states[0].name,"SHIELD Remote") ||
913             strstr(android->pad_states[0].name,"SHIELD Virtual Controller"))
914          {
915             pad_id1 = -1;
916             pad_id2 = -1;
917             android->pads_connected = 0;
918             *port = 0;
919             strlcpy(name_buf, device_name, sizeof(name_buf));
920          }
921 
922          /* if the actual controller has not been mapped yet,
923           * then configure Virtual device for now */
924          if (strstr(device_name, "Virtual") && android->pads_connected==0)
925             strlcpy (name_buf, "SHIELD Virtual Controller", sizeof(name_buf));
926          else
927             strlcpy (name_buf, "NVIDIA SHIELD Controller", sizeof(name_buf));
928 
929          /* apply the hack only for the first controller
930           * store the id for later use
931          */
932          if (strstr(device_name, "NVIDIA Corporation NVIDIA Controller v01.0")
933                && android->pads_connected==0)
934             pad_id1 = id;
935          else if (strstr(device_name, "Virtual") && pad_id1 != -1)
936          {
937             id = pad_id1;
938             return;
939          }
940       }
941    }
942 
943    else if (strstr(device_model, "SHIELD") && (
944       strstr(device_name, "Virtual") || strstr(device_name, "gpio") ||
945       strstr(device_name, "NVIDIA Corporation NVIDIA Controller v01.01") ||
946       strstr(device_name, "NVIDIA Corporation NVIDIA Controller v01.02")))
947    {
948       /* only use the hack if the device is one of the built-in devices */
949       RARCH_LOG("Special Device Detected: %s\n", device_model);
950       {
951          if ( pad_id1 < 0 )
952             pad_id1 = id;
953          else
954             pad_id2 = id;
955 
956          if ( pad_id2 > 0)
957             return;
958          strlcpy (name_buf, "NVIDIA SHIELD Portable", sizeof(name_buf));
959       }
960    }
961 
962    else if (strstr(device_model, "SHIELD") && (
963       strstr(device_name, "Virtual") || strstr(device_name, "gpio") ||
964       strstr(device_name, "NVIDIA Corporation NVIDIA Controller v01.03")))
965    {
966       /* only use the hack if the device is one of the built-in devices */
967       RARCH_LOG("Special Device Detected: %s\n", device_model);
968       {
969          if (strstr(device_name, "NVIDIA Corporation NVIDIA Controller v01.03")
970              && android->pads_connected==0)
971             pad_id1 = id;
972          else if (strstr(device_name, "Virtual") || strstr(device_name, "gpio"))
973          {
974             id = pad_id1;
975             return;
976          }
977          strlcpy (name_buf, "NVIDIA SHIELD Gamepad", sizeof(name_buf));
978       }
979    }
980 
981    /* Other ATV Devices
982     * Add other common ATV devices that will follow the Android
983     * Gaempad convention as "Android Gamepad"
984     */
985     /* to-do: add DS4 on Bravia ATV */
986    else if (strstr(device_name, "NVIDIA"))
987       strlcpy (name_buf, "Android Gamepad", sizeof(name_buf));
988 
989    /* GPD XD
990     * This is a simple hack, basically groups the "back"
991     * button with the rest of the gamepad
992     */
993    else if (strstr(device_model, "XD") && (
994       strstr(device_name, "Virtual") || strstr(device_name, "rk29-keypad") ||
995       strstr(device_name,"Playstation3") || strstr(device_name,"XBOX")))
996    {
997       /* only use the hack if the device is one of the built-in devices */
998       RARCH_LOG("Special Device Detected: %s\n", device_model);
999       {
1000          if ( pad_id1 < 0 )
1001             pad_id1 = id;
1002          else
1003             pad_id2 = id;
1004 
1005          if ( pad_id2 > 0)
1006             return;
1007 
1008          strlcpy (name_buf, "GPD XD", sizeof(name_buf));
1009          *port = 0;
1010       }
1011    }
1012 
1013    /* XPERIA Play
1014     * This device is composed of two hid devices
1015     * We make it look like one device
1016     */
1017    else if(
1018             (
1019                string_starts_with_size(device_model, "R800", STRLEN_CONST("R800")) ||
1020                strstr(device_model, "Xperia Play") ||
1021                strstr(device_model, "Play") ||
1022                strstr(device_model, "SO-01D")
1023             ) && (
1024                strstr(device_name, "keypad-game-zeus") ||
1025                strstr(device_name, "keypad-zeus") ||
1026                strstr(device_name, "Android Gamepad")
1027             )
1028          )
1029    {
1030       /* only use the hack if the device is one of the built-in devices */
1031       RARCH_LOG("Special Device Detected: %s\n", device_model);
1032       {
1033          if ( pad_id1 < 0 )
1034             pad_id1 = id;
1035          else
1036             pad_id2 = id;
1037 
1038          if ( pad_id2 > 0)
1039             return;
1040 
1041          strlcpy (name_buf, "XPERIA Play", sizeof(name_buf));
1042          *port = 0;
1043       }
1044    }
1045 
1046    /* ARCHOS Gamepad
1047     * This device is composed of two hid devices
1048     * We make it look like one device
1049     */
1050    else if (strstr(device_model, "ARCHOS GAMEPAD") && (
1051       strstr(device_name, "joy_key") || strstr(device_name, "joystick")))
1052    {
1053       /* only use the hack if the device is one of the built-in devices */
1054       RARCH_LOG("ARCHOS GAMEPAD Detected: %s\n", device_model);
1055       {
1056          if ( pad_id1 < 0 )
1057             pad_id1 = id;
1058          else
1059             pad_id2 = id;
1060 
1061          if ( pad_id2 > 0)
1062             return;
1063 
1064          strlcpy (name_buf, "ARCHOS GamePad", sizeof(name_buf));
1065          *port = 0;
1066       }
1067    }
1068 
1069    /* Amazon Fire TV & Fire stick */
1070    else if (
1071              string_starts_with_size(device_model, "AFT", STRLEN_CONST("AFT")) &&
1072              (
1073               strstr(device_model, "AFTB") ||
1074               strstr(device_model, "AFTT") ||
1075               strstr(device_model, "AFTS") ||
1076               strstr(device_model, "AFTM") ||
1077               strstr(device_model, "AFTRS")
1078              )
1079          )
1080    {
1081       RARCH_LOG("Special Device Detected: %s\n", device_model);
1082       {
1083          /* always map remote to port #0 */
1084          if (strstr(device_name, "Amazon Fire TV Remote"))
1085          {
1086             android->pads_connected = 0;
1087             *port = 0;
1088             strlcpy(name_buf, device_name, sizeof(name_buf));
1089          }
1090          /* remove the remote when a gamepad enters */
1091          else if (strstr(android->pad_states[0].name,"Amazon Fire TV Remote"))
1092          {
1093             android->pads_connected = 0;
1094             *port = 0;
1095             strlcpy(name_buf, device_name, sizeof(name_buf));
1096          }
1097          else
1098             strlcpy(name_buf, device_name, sizeof(name_buf));
1099       }
1100    }
1101 
1102    /* Other uncommon devices
1103     * These are mostly remote control type devices, bind them always to port 0
1104     * And overwrite the binding whenever a controller button is pressed
1105     */
1106    else if (strstr(device_name, "Amazon Fire TV Remote")
1107          || strstr(device_name, "Nexus Remote")
1108          || strstr(device_name, "SHIELD Remote"))
1109    {
1110       android->pads_connected = 0;
1111       *port = 0;
1112       strlcpy(name_buf, device_name, sizeof(name_buf));
1113    }
1114 
1115    else if (strstr(device_name, "iControlPad-"))
1116       strlcpy(name_buf, "iControlPad HID Joystick profile", sizeof(name_buf));
1117 
1118    else if (strstr(device_name, "TTT THT Arcade console 2P USB Play"))
1119    {
1120       if (*port == 0)
1121          strlcpy(name_buf, "TTT THT Arcade (User 1)", sizeof(name_buf));
1122       else if (*port == 1)
1123          strlcpy(name_buf, "TTT THT Arcade (User 2)", sizeof(name_buf));
1124    }
1125    else if (strstr(device_name, "MOGA"))
1126       strlcpy(name_buf, "Moga IME", sizeof(name_buf));
1127 
1128    /* If device is keyboard only and didn't match any of the devices above
1129     * then assume it is a keyboard, register the id, and return unless the
1130     * maximum number of keyboards are already registered. */
1131    else if (source == AINPUT_SOURCE_KEYBOARD && kbd_num < MAX_NUM_KEYBOARDS)
1132    {
1133       kbd_id[kbd_num] = id;
1134       kbd_num++;
1135       return;
1136    }
1137 
1138    /* if device was not keyboard only, yet did not match any of the devices
1139     * then try to autoconfigure as gamepad based on device_name. */
1140    else if (!string_is_empty(device_name))
1141       strlcpy(name_buf, device_name, sizeof(name_buf));
1142 
1143    if (strstr(android_app->current_ime, "net.obsidianx.android.mogaime"))
1144       strlcpy(name_buf, android_app->current_ime, sizeof(name_buf));
1145    else if (strstr(android_app->current_ime, "com.ccpcreations.android.WiiUseAndroid"))
1146       strlcpy(name_buf, android_app->current_ime, sizeof(name_buf));
1147    else if (strstr(android_app->current_ime, "com.hexad.bluezime"))
1148       strlcpy(name_buf, android_app->current_ime, sizeof(name_buf));
1149 
1150    if (*port < 0)
1151       *port = android->pads_connected;
1152 
1153    input_autoconfigure_connect(
1154          name_buf,
1155          NULL,
1156          android_joypad.ident,
1157          *port,
1158          vendorId,
1159          productId);
1160 
1161    android->pad_states[android->pads_connected].id   =
1162       g_android->id[android->pads_connected]         = id;
1163    android->pad_states[android->pads_connected].port = *port;
1164 
1165    strlcpy(android->pad_states[*port].name, name_buf,
1166          sizeof(android->pad_states[*port].name));
1167 
1168    android->pads_connected++;
1169 }
1170 
android_input_get_id(AInputEvent * event)1171 static int android_input_get_id(AInputEvent *event)
1172 {
1173    int id = AInputEvent_getDeviceId(event);
1174 
1175    if (id == pad_id2)
1176       id = pad_id1;
1177 
1178    return id;
1179 }
1180 
android_input_poll_input(android_input_t * android,bool vibrate_on_keypress)1181 static void android_input_poll_input(android_input_t *android,
1182       bool vibrate_on_keypress)
1183 {
1184    AInputEvent              *event = NULL;
1185    struct android_app *android_app = (struct android_app*)g_android;
1186 
1187    /* Read all pending events. */
1188    while (AInputQueue_hasEvents(android_app->inputQueue))
1189    {
1190       while (AInputQueue_getEvent(android_app->inputQueue, &event) >= 0)
1191       {
1192          int32_t   handled = 1;
1193          int predispatched = AInputQueue_preDispatchEvent(
1194                android_app->inputQueue, event);
1195          int        source = AInputEvent_getSource(event);
1196          int    type_event = AInputEvent_getType(event);
1197          int            id = android_input_get_id(event);
1198          int          port = android_input_get_id_port(android, id, source);
1199 
1200          if (port < 0 && !android_is_keyboard_id(id))
1201             handle_hotplug(android, android_app,
1202             &port, id, source);
1203 
1204          switch (type_event)
1205          {
1206             case AINPUT_EVENT_TYPE_MOTION:
1207                /* Only handle events from a touchscreen or mouse */
1208                if ((source & (AINPUT_SOURCE_TOUCHSCREEN
1209                            | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)))
1210                   android_input_poll_event_type_motion(android, event,
1211                         port, source, vibrate_on_keypress);
1212                else
1213                   engine_handle_dpad(android_app, event, port, source);
1214                break;
1215             case AINPUT_EVENT_TYPE_KEY:
1216                {
1217                   int keycode = AKeyEvent_getKeyCode(event);
1218 
1219                   if (android_is_keyboard_id(id))
1220                   {
1221                      if (!predispatched)
1222                      {
1223                         android_input_poll_event_type_keyboard(
1224                               event, keycode, &handled);
1225                         android_input_poll_event_type_key(
1226                               android_app, event, ANDROID_KEYBOARD_PORT,
1227                               keycode, source, type_event, &handled);
1228                      }
1229                   }
1230                   else
1231                      android_input_poll_event_type_key(android_app,
1232                         event, port, keycode, source, type_event, &handled);
1233                }
1234                break;
1235          }
1236 
1237          if (!predispatched)
1238             AInputQueue_finishEvent(android_app->inputQueue, event,
1239                   handled);
1240       }
1241    }
1242 }
1243 
android_input_poll_user(android_input_t * android)1244 static void android_input_poll_user(android_input_t *android)
1245 {
1246    struct android_app *android_app = (struct android_app*)g_android;
1247    bool poll_accelerometer         = false;
1248    bool poll_gyroscope             = false;
1249 
1250    if (!android_app->sensorEventQueue)
1251       return;
1252 
1253    poll_accelerometer = (android_app->sensor_state_mask &
1254          (UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE)) &&
1255                android_app->accelerometerSensor;
1256 
1257    poll_gyroscope     = (android_app->sensor_state_mask &
1258          (UINT64_C(1) << RETRO_SENSOR_GYROSCOPE_ENABLE)) &&
1259                android_app->gyroscopeSensor;
1260 
1261    if (poll_accelerometer || poll_gyroscope)
1262    {
1263       ASensorEvent event;
1264       while (ASensorEventQueue_getEvents(
1265             android_app->sensorEventQueue, &event, 1) > 0)
1266       {
1267          switch (event.type)
1268          {
1269             case ASENSOR_TYPE_ACCELEROMETER:
1270                android->accelerometer_state.x = event.acceleration.x;
1271                android->accelerometer_state.y = event.acceleration.y;
1272                android->accelerometer_state.z = event.acceleration.z;
1273                break;
1274             case ASENSOR_TYPE_GYROSCOPE:
1275                /* ASensorEvent struct is mysterious - have to
1276                 * read the raw 'data' field to get rate of
1277                 * rotation... */
1278                android->gyroscope_state.x = event.data[0];
1279                android->gyroscope_state.y = event.data[1];
1280                android->gyroscope_state.z = event.data[2];
1281                break;
1282             default:
1283                break;
1284          }
1285       }
1286    }
1287 }
1288 
1289 /* Handle all events. If our activity is in pause state,
1290  * block until we're unpaused.
1291  */
android_input_poll(void * data)1292 static void android_input_poll(void *data)
1293 {
1294    int ident;
1295    struct android_app *android_app = (struct android_app*)g_android;
1296    android_input_t *android        = (android_input_t*)data;
1297    settings_t            *settings = config_get_ptr();
1298 
1299    while ((ident =
1300             ALooper_pollAll((input_config_binds[0][RARCH_PAUSE_TOGGLE].valid
1301                && input_key_pressed(RARCH_PAUSE_TOGGLE,
1302                   ANDROID_KEYBOARD_PORT_INPUT_PRESSED(input_config_binds[0],
1303                      RARCH_PAUSE_TOGGLE)))
1304                ? -1 : settings->uints.input_block_timeout,
1305                NULL, NULL, NULL)) >= 0)
1306    {
1307       bool vibrate_on_keypress     = settings
1308          ? settings->bools.vibrate_on_keypress
1309          : false;
1310 
1311       switch (ident)
1312       {
1313          case LOOPER_ID_INPUT:
1314             android_input_poll_input(android,
1315                   vibrate_on_keypress);
1316             break;
1317          case LOOPER_ID_USER:
1318             android_input_poll_user(android);
1319             break;
1320          case LOOPER_ID_MAIN:
1321             android_input_poll_main_cmd();
1322             break;
1323       }
1324 
1325       if (android_app->destroyRequested != 0)
1326       {
1327          rarch_ctl(RARCH_CTL_SET_SHUTDOWN, NULL);
1328          return;
1329       }
1330 
1331       if (android_app->reinitRequested != 0)
1332       {
1333          if (rarch_ctl(RARCH_CTL_IS_PAUSED, NULL))
1334             command_event(CMD_EVENT_REINIT, NULL);
1335          android_app_write_cmd(android_app, APP_CMD_REINIT_DONE);
1336          return;
1337       }
1338    }
1339 }
1340 
android_run_events(void * data)1341 bool android_run_events(void *data)
1342 {
1343    struct android_app *android_app = (struct android_app*)g_android;
1344 
1345    if (ALooper_pollOnce(-1, NULL, NULL, NULL) == LOOPER_ID_MAIN)
1346       android_input_poll_main_cmd();
1347 
1348    /* Check if we are exiting. */
1349    if (android_app->destroyRequested != 0)
1350    {
1351       rarch_ctl(RARCH_CTL_SET_SHUTDOWN, NULL);
1352       return false;
1353    }
1354 
1355    if (android_app->reinitRequested != 0)
1356    {
1357       if (rarch_ctl(RARCH_CTL_IS_PAUSED, NULL))
1358          command_event(CMD_EVENT_REINIT, NULL);
1359       android_app_write_cmd(android_app, APP_CMD_REINIT_DONE);
1360    }
1361 
1362    return true;
1363 }
1364 
android_input_state(void * data,const input_device_driver_t * joypad,const input_device_driver_t * sec_joypad,rarch_joypad_info_t * joypad_info,const struct retro_keybind ** binds,bool keyboard_mapping_blocked,unsigned port,unsigned device,unsigned idx,unsigned id)1365 static int16_t android_input_state(
1366       void *data,
1367       const input_device_driver_t *joypad,
1368       const input_device_driver_t *sec_joypad,
1369       rarch_joypad_info_t *joypad_info,
1370       const struct retro_keybind **binds,
1371       bool keyboard_mapping_blocked,
1372       unsigned port,
1373       unsigned device,
1374       unsigned idx,
1375       unsigned id)
1376 {
1377    android_input_t *android           = (android_input_t*)data;
1378 
1379    switch (device)
1380    {
1381       case RETRO_DEVICE_JOYPAD:
1382          if (id == RETRO_DEVICE_ID_JOYPAD_MASK)
1383          {
1384             unsigned i;
1385             int16_t ret = 0;
1386             for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
1387             {
1388                if (binds[port][i].valid)
1389                {
1390                   if (ANDROID_KEYBOARD_PORT_INPUT_PRESSED(binds[port], i))
1391                      ret |= (1 << i);
1392                }
1393             }
1394             return ret;
1395          }
1396 
1397          if (binds[port][id].valid)
1398             if (ANDROID_KEYBOARD_PORT_INPUT_PRESSED(binds[port], id))
1399                return 1;
1400          break;
1401       case RETRO_DEVICE_ANALOG:
1402          break;
1403       case RETRO_DEVICE_KEYBOARD:
1404          return (id < RETROK_LAST)
1405             && BIT_GET(android_key_state[ANDROID_KEYBOARD_PORT],
1406                   rarch_keysym_lut[id]);
1407       case RETRO_DEVICE_MOUSE:
1408          {
1409             int val = 0;
1410             if(port > 0) return 0; /* TODO: implement mouse for additional ports/players */
1411             switch (id)
1412             {
1413                case RETRO_DEVICE_ID_MOUSE_LEFT:
1414                   return android->mouse_l || android_check_quick_tap(android);
1415                case RETRO_DEVICE_ID_MOUSE_RIGHT:
1416                   return android->mouse_r;
1417                case RETRO_DEVICE_ID_MOUSE_MIDDLE:
1418                   return android->mouse_m;
1419                case RETRO_DEVICE_ID_MOUSE_X:
1420                   val = android->mouse_x_delta;
1421                   android->mouse_x_delta = 0;
1422                   /* flush delta after it has been read */
1423                   return val;
1424                case RETRO_DEVICE_ID_MOUSE_Y:
1425                   val = android->mouse_y_delta;
1426                   android->mouse_y_delta = 0;
1427                   /* flush delta after it has been read */
1428                   return val;
1429                case RETRO_DEVICE_ID_MOUSE_WHEELUP:
1430                   val = android->mouse_wu;
1431                   android->mouse_wu = 0;
1432                   return val;
1433                case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
1434                   val = android->mouse_wd;
1435                   android->mouse_wd = 0;
1436                   return val;
1437             }
1438          }
1439          break;
1440       case RETRO_DEVICE_LIGHTGUN:
1441          {
1442             int val = 0;
1443             if(port > 0) return 0; /* TODO: implement lightgun for additional ports/players */
1444             switch (id)
1445             {
1446                case RETRO_DEVICE_ID_LIGHTGUN_X:
1447                   val                    = android->mouse_x_delta;
1448                   android->mouse_x_delta = 0;
1449                   /* flush delta after it has been read */
1450                   return val;
1451                case RETRO_DEVICE_ID_LIGHTGUN_Y:
1452                   val                    = android->mouse_y_delta;
1453                   android->mouse_y_delta = 0;
1454                   /* flush delta after it has been read */
1455                   return val;
1456                case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER:
1457                   return android->mouse_l || android_check_quick_tap(android);
1458                case RETRO_DEVICE_ID_LIGHTGUN_CURSOR:
1459                   return android->mouse_m;
1460                case RETRO_DEVICE_ID_LIGHTGUN_TURBO:
1461                   return android->mouse_r;
1462                case RETRO_DEVICE_ID_LIGHTGUN_START:
1463                   return android->mouse_m && android->mouse_r;
1464                case RETRO_DEVICE_ID_LIGHTGUN_PAUSE:
1465                   return android->mouse_m && android->mouse_l;
1466             }
1467          }
1468          break;
1469       case RETRO_DEVICE_POINTER:
1470       case RARCH_DEVICE_POINTER_SCREEN:
1471          switch (id)
1472          {
1473             case RETRO_DEVICE_ID_POINTER_X:
1474                if (device == RARCH_DEVICE_POINTER_SCREEN)
1475                   return android->pointer[idx].full_x;
1476                return android->pointer[idx].x;
1477             case RETRO_DEVICE_ID_POINTER_Y:
1478                if (device == RARCH_DEVICE_POINTER_SCREEN)
1479                   return android->pointer[idx].full_y;
1480                return android->pointer[idx].y;
1481             case RETRO_DEVICE_ID_POINTER_PRESSED:
1482                if (device == RARCH_DEVICE_POINTER_SCREEN)
1483                   return (idx < android->pointer_count) &&
1484                      (android->pointer[idx].full_x != -0x8000) &&
1485                      (android->pointer[idx].full_y != -0x8000);
1486                return (idx < android->pointer_count) &&
1487                   (android->pointer[idx].x != -0x8000) &&
1488                   (android->pointer[idx].y != -0x8000);
1489             case RETRO_DEVICE_ID_POINTER_COUNT:
1490                return android->pointer_count;
1491             case RARCH_DEVICE_ID_POINTER_BACK:
1492             {
1493                const struct retro_keybind *keyptr =
1494                   &input_autoconf_binds[0][RARCH_MENU_TOGGLE];
1495                if (keyptr->joykey == 0)
1496                   return ANDROID_KEYBOARD_INPUT_PRESSED(AKEYCODE_BACK);
1497             }
1498          }
1499          break;
1500    }
1501 
1502    return 0;
1503 }
1504 
android_input_free_input(void * data)1505 static void android_input_free_input(void *data)
1506 {
1507    android_input_t *android = (android_input_t*)data;
1508    struct android_app *android_app = (struct android_app*)g_android;
1509    if (!android)
1510       return;
1511 
1512    if (android_app->sensorManager &&
1513        android_app->sensorEventQueue)
1514       ASensorManager_destroyEventQueue(android_app->sensorManager,
1515             android_app->sensorEventQueue);
1516 
1517    android_app->sensorEventQueue    = NULL;
1518    android_app->accelerometerSensor = NULL;
1519    android_app->gyroscopeSensor     = NULL;
1520    android_app->sensorManager       = NULL;
1521 
1522    android_app->input_alive = false;
1523 
1524 #ifdef HAVE_DYNAMIC
1525    dylib_close((dylib_t)libandroid_handle);
1526    libandroid_handle = NULL;
1527 #endif
1528 
1529    android_keyboard_free();
1530    free(data);
1531 }
1532 
android_input_get_capabilities(void * data)1533 static uint64_t android_input_get_capabilities(void *data)
1534 {
1535    return
1536       (1 << RETRO_DEVICE_JOYPAD)  |
1537       (1 << RETRO_DEVICE_POINTER) |
1538       (1 << RETRO_DEVICE_KEYBOARD)  |
1539       (1 << RETRO_DEVICE_LIGHTGUN)  |
1540       (1 << RETRO_DEVICE_ANALOG);
1541 }
1542 
android_input_enable_sensor_manager(struct android_app * android_app)1543 static void android_input_enable_sensor_manager(struct android_app *android_app)
1544 {
1545    if (!android_app->sensorManager)
1546       android_app->sensorManager = ASensorManager_getInstance();
1547 
1548    if (android_app->sensorManager)
1549    {
1550       if (!android_app->accelerometerSensor)
1551          android_app->accelerometerSensor =
1552             ASensorManager_getDefaultSensor(android_app->sensorManager,
1553                ASENSOR_TYPE_ACCELEROMETER);
1554 
1555       if (!android_app->gyroscopeSensor)
1556          android_app->gyroscopeSensor =
1557             ASensorManager_getDefaultSensor(android_app->sensorManager,
1558                ASENSOR_TYPE_GYROSCOPE);
1559 
1560       if (!android_app->sensorEventQueue)
1561          android_app->sensorEventQueue =
1562             ASensorManager_createEventQueue(android_app->sensorManager,
1563                android_app->looper, LOOPER_ID_USER, NULL, NULL);
1564    }
1565 }
1566 
android_input_set_sensor_state(void * data,unsigned port,enum retro_sensor_action action,unsigned event_rate)1567 static bool android_input_set_sensor_state(void *data, unsigned port,
1568       enum retro_sensor_action action, unsigned event_rate)
1569 {
1570    struct android_app *android_app = (struct android_app*)g_android;
1571    android_input_t *android        = (android_input_t*)data;
1572 
1573    if (port > 0)
1574       return false;
1575 
1576    if (event_rate == 0)
1577       event_rate = DEFAULT_ASENSOR_EVENT_RATE;
1578 
1579    switch (action)
1580    {
1581       case RETRO_SENSOR_ACCELEROMETER_ENABLE:
1582          if (!android_app->accelerometerSensor)
1583             android_input_enable_sensor_manager(android_app);
1584 
1585          if (android_app->sensorEventQueue &&
1586              android_app->accelerometerSensor)
1587          {
1588             ASensorEventQueue_enableSensor(android_app->sensorEventQueue,
1589                   android_app->accelerometerSensor);
1590 
1591             /* Events per second (in microseconds). */
1592             ASensorEventQueue_setEventRate(android_app->sensorEventQueue,
1593                   android_app->accelerometerSensor, (1000L / event_rate)
1594                   * 1000);
1595          }
1596 
1597          android_app->accelerometer_event_rate = event_rate;
1598 
1599          BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_DISABLE);
1600          BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_ENABLE);
1601          return true;
1602 
1603       case RETRO_SENSOR_ACCELEROMETER_DISABLE:
1604          if (android_app->sensorEventQueue &&
1605              android_app->accelerometerSensor)
1606             ASensorEventQueue_disableSensor(android_app->sensorEventQueue,
1607                   android_app->accelerometerSensor);
1608 
1609          android->accelerometer_state.x = 0.0f;
1610          android->accelerometer_state.y = 0.0f;
1611          android->accelerometer_state.z = 0.0f;
1612 
1613          BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_ENABLE);
1614          BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_DISABLE);
1615          return true;
1616 
1617       case RETRO_SENSOR_GYROSCOPE_ENABLE:
1618          if (!android_app->gyroscopeSensor)
1619             android_input_enable_sensor_manager(android_app);
1620 
1621          if (android_app->sensorEventQueue &&
1622              android_app->gyroscopeSensor)
1623          {
1624             ASensorEventQueue_enableSensor(android_app->sensorEventQueue,
1625                   android_app->gyroscopeSensor);
1626 
1627             /* Events per second (in microseconds). */
1628             ASensorEventQueue_setEventRate(android_app->sensorEventQueue,
1629                   android_app->gyroscopeSensor, (1000L / event_rate)
1630                   * 1000);
1631          }
1632 
1633          android_app->gyroscope_event_rate = event_rate;
1634 
1635          BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_DISABLE);
1636          BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_ENABLE);
1637          return true;
1638 
1639       case RETRO_SENSOR_GYROSCOPE_DISABLE:
1640          if (android_app->sensorEventQueue &&
1641              android_app->gyroscopeSensor)
1642             ASensorEventQueue_disableSensor(android_app->sensorEventQueue,
1643                   android_app->gyroscopeSensor);
1644 
1645          android->gyroscope_state.x = 0.0f;
1646          android->gyroscope_state.y = 0.0f;
1647          android->gyroscope_state.z = 0.0f;
1648 
1649          BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_ENABLE);
1650          BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_DISABLE);
1651          return true;
1652 
1653       default:
1654          break;
1655    }
1656 
1657    return false;
1658 }
1659 
android_input_get_sensor_input(void * data,unsigned port,unsigned id)1660 static float android_input_get_sensor_input(void *data,
1661       unsigned port, unsigned id)
1662 {
1663    android_input_t      *android      = (android_input_t*)data;
1664 
1665    if (port > 0)
1666       return 0.0f;
1667 
1668    switch (id)
1669    {
1670       case RETRO_SENSOR_ACCELEROMETER_X:
1671          return android->accelerometer_state.x;
1672       case RETRO_SENSOR_ACCELEROMETER_Y:
1673          return android->accelerometer_state.y;
1674       case RETRO_SENSOR_ACCELEROMETER_Z:
1675          return android->accelerometer_state.z;
1676       case RETRO_SENSOR_GYROSCOPE_X:
1677          return android->gyroscope_state.x;
1678       case RETRO_SENSOR_GYROSCOPE_Y:
1679          return android->gyroscope_state.y;
1680       case RETRO_SENSOR_GYROSCOPE_Z:
1681          return android->gyroscope_state.z;
1682    }
1683 
1684    return 0.0f;
1685 }
1686 
1687 input_driver_t input_android = {
1688    android_input_init,
1689    android_input_poll,
1690    android_input_state,
1691    android_input_free_input,
1692    android_input_set_sensor_state,
1693    android_input_get_sensor_input,
1694    android_input_get_capabilities,
1695    "android",
1696 
1697    NULL,                            /* grab_mouse */
1698    NULL
1699 };
1700