diff --git a/frontend/drivers/platform_android.c b/frontend/drivers/platform_android.c index 3fa19d6a8a..f36cc3df0d 100644 --- a/frontend/drivers/platform_android.c +++ b/frontend/drivers/platform_android.c @@ -30,13 +30,8 @@ struct android_app *g_android; static pthread_key_t thread_key; -static INLINE void android_app_write_cmd(void *data, int8_t cmd) +void android_app_write_cmd(struct android_app *android_app, int8_t cmd) { - struct android_app *android_app = (struct android_app*)data; - - if (!android_app) - return; - if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) RARCH_ERR("Failure writing android_app cmd: %s\n", strerror(errno)); } diff --git a/frontend/drivers/platform_android.h b/frontend/drivers/platform_android.h index 159638d72f..28db2238c1 100644 --- a/frontend/drivers/platform_android.h +++ b/frontend/drivers/platform_android.h @@ -20,14 +20,15 @@ #include #include +#include #include +#include #include #include #include #include -#include #ifndef MAX_AXIS #define MAX_AXIS 10 @@ -79,26 +80,107 @@ typedef struct android_input_state unsigned pointer_count; } android_input_state_t; +struct android_poll_source +{ + /* The identifier of this source. May be LOOPER_ID_MAIN or + * LOOPER_ID_INPUT. */ + int32_t id; + + /* The android_app this ident is associated with. */ + struct android_app *app; + + /* Function to call to perform the standard processing of data from + * this source. */ + void (*process)(struct android_app *app, struct android_poll_source *source); +}; + +/** + * This is the interface for the standard glue code of a threaded + * application. In this model, the application's code is running + * in its own thread separate from the main thread of the process. + * It is not required that this thread be associated with the Java + * VM, although it will need to be in order to make JNI calls any + * Java objects. + */ struct android_app { + /* The application can place a pointer to its own state object + * here if it likes. */ + void *userData; + + /* Fill this in with the function to process main app commands (APP_CMD_*) */ + void (*onAppCmd)(struct android_app *app, int32_t cmd); + + /* Fill this in with the function to process input events. At this point + * the event has already been pre-dispatched, and it will be finished upon + * return. Return 1 if you have handled the event, 0 for any default + * dispatching. */ + int32_t (*onInputEvent)(struct android_app *app, AInputEvent *event); + + + /* The ANativeActivity object instance that this app is running in. */ ANativeActivity* activity; + + /* The current configuration the app is running in. */ + AConfiguration *config; + + /* This is the last instance's saved state, as provided at creation time. + * It is NULL if there was no state. You can use this as you need; the + * memory will remain around until you call android_app_exec_cmd() for + * APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. + * These variables should only be changed when processing a APP_CMD_SAVE_STATE, + * at which point they will be initialized to NULL and you can malloc your + * state and place the information here. In that case the memory will be + * freed for you later. */ + void* savedState; + size_t savedStateSize; + + /* The ALooper associated with the app's thread. */ ALooper* looper; + + /* When non-NULL, this is the input queue from which the app will + * receive user input events. */ AInputQueue* inputQueue; - AInputQueue* pendingInputQueue; + + /* When non-NULL, this is the window surface that the app can draw in. */ ANativeWindow* window; - ANativeWindow* pendingWindow; - ASensorManager *sensorManager; - ASensorEventQueue *sensorEventQueue; + + /* Current content rectangle of the window; this is the area where the + * window's content should be placed to be seen by the user. */ + ARect contentRect; + + /* Current state of the app's activity. May be either APP_CMD_START, + * APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. */ + int activityState; + + /* This is non-zero when the application's NativeActivity is being + * destroyed and waiting for the app thread to complete. */ + int destroyRequested; + + /* Below are "private" implementation variables of the glue code. */ + slock_t *mutex; scond_t *cond; - int activityState; + int msgread; int msgwrite; + + sthread_t *thread; + + struct android_poll_source cmdPollSource; + struct android_poll_source inputPollSource; + int running; + int stateSaved; + int destroyed; + int redrawNeeded; + AInputQueue* pendingInputQueue; + ANativeWindow* pendingWindow; + ARect pendingContentRect; + unsigned accelerometer_event_rate; const ASensor* accelerometerSensor; uint64_t sensor_state_mask; - sthread_t *thread; char current_ime[PATH_MAX_LENGTH]; jmethodID getIntent; jmethodID onRetroArchExit; @@ -110,19 +192,46 @@ struct android_app jmethodID getPendingIntentFullPath; jmethodID getPendingIntentIME; android_input_state_t thread_state; + + ASensorManager *sensorManager; + ASensorEventQueue *sensorEventQueue; }; enum { - LOOPER_ID_MAIN = 1, - LOOPER_ID_INPUT, - LOOPER_ID_USER, - LOOPER_ID_INPUT_MSG, + /** + * Looper data ID of commands coming from the app's main thread, which + * is returned as an identifier from ALooper_pollOnce(). The data for this + * identifier is a pointer to an android_poll_source structure. + * These can be retrieved and processed with android_app_read_cmd() + * and android_app_exec_cmd(). + */ + LOOPER_ID_MAIN = 1, + + /** + * Looper data ID of events coming from the AInputQueue of the + * application's window, which is returned as an identifier from + * ALooper_pollOnce(). The data for this identifier is a pointer to an + * android_poll_source structure. These can be read via the inputQueue + * object of android_app. + */ + LOOPER_ID_INPUT = 2, + + /** + * Start of user-defined ALooper identifiers. + */ + LOOPER_ID_USER = 3, }; enum { + /** + * Command from main thread: the AInputQueue has changed. Upon processing + * this command, android_app->inputQueue will be updated to the new queue + * (or NULL). + */ APP_CMD_INPUT_CHANGED, + /** * Command from main thread: a new ANativeWindow is ready for use. Upon * receiving this command, android_app->window will contain the new window @@ -283,7 +392,9 @@ enum bool (*engine_lookup_name)(char *buf, int *vendorId, int *productId, size_t size, int id); -extern JNIEnv *jni_thread_getenv(void); +JNIEnv *jni_thread_getenv(void); + +void android_app_write_cmd(struct android_app *android_app, int8_t cmd); extern struct android_app *g_android;