From 7bc4a69a4acedd47215f4077a9eedc9310d2a495 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 1 May 2015 23:52:36 +0200 Subject: [PATCH] (Android) Create android_native_app_glue.h --- frontend/drivers/android_native_app_glue.h | 339 +++++++++++++++++++++ frontend/drivers/platform_android.h | 236 +------------- 2 files changed, 340 insertions(+), 235 deletions(-) create mode 100644 frontend/drivers/android_native_app_glue.h diff --git a/frontend/drivers/android_native_app_glue.h b/frontend/drivers/android_native_app_glue.h new file mode 100644 index 0000000000..6a3546a301 --- /dev/null +++ b/frontend/drivers/android_native_app_glue.h @@ -0,0 +1,339 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2015 - Daniel De Matteis + * Copyright (C) 2012-2015 - Michael Lelli + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _ANDROID_NATIVE_APP_GLUE_H +#define _ANDROID_NATIVE_APP_GLUE_H + +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The native activity interface provided by + * is based on a set of application-provided callbacks that will be called + * by the Activity's main thread when certain events occur. + * + * This means that each one of this callbacks _should_ _not_ block, or they + * risk having the system force-close the application. This programming + * model is direct, lightweight, but constraining. + * + * The 'threaded_native_app' static library is used to provide a different + * execution model where the application can implement its own main event + * loop in a different thread instead. Here's how it works: + * + * 1/ The application must provide a function named "android_main()" that + * will be called when the activity is created, in a new thread that is + * distinct from the activity's main thread. + * + * 2/ android_main() receives a pointer to a valid "android_app" structure + * that contains references to other important objects, e.g. the + * ANativeActivity obejct instance the application is running in. + * + * 3/ the "android_app" object holds an ALooper instance that already + * listens to two important things: + * + * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX + * declarations below. + * + * - input events coming from the AInputQueue attached to the activity. + * + * Each of these correspond to an ALooper identifier returned by + * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, + * respectively. + * + * Your application can use the same ALooper to listen to additional + * file-descriptors. They can either be callback based, or with return + * identifiers starting with LOOPER_ID_USER. + * + * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, + * the returned data will point to an android_poll_source structure. You + * can call the process() function on it, and fill in android_app->onAppCmd + * and android_app->onInputEvent to be called for your own processing + * of the event. + * + * Alternatively, you can call the low-level functions to read and process + * the data directly... look at the process_cmd() and process_input() + * implementations in the glue to see how to do this. + * + * See the sample named "native-activity" that comes with the NDK with a + * full usage example. Also look at the JavaDoc of NativeActivity. + */ + +struct android_app; + +/** + * Data associated with an ALooper fd that will be returned as the "outData" + * when that source has data ready. + */ +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; + + /* When non-NULL, this is the window surface that the app can draw in. */ + ANativeWindow* window; + + /* 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 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; +}; + +enum +{ + /** + * 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 + * surface. + */ + APP_CMD_INIT_WINDOW, + + /** + * Command from main thread: the existing ANativeWindow needs to be + * terminated. Upon receiving this command, android_app->window still + * contains the existing window; after calling android_app_exec_cmd + * it will be set to NULL. + */ + APP_CMD_TERM_WINDOW, + + /** + * Command from main thread: the current ANativeWindow has been resized. + * Please redraw with its new size. + */ + APP_CMD_WINDOW_RESIZED, + + /** + * Command from main thread: the system needs that the current ANativeWindow + * be redrawn. You should redraw the window before handing this to + * android_app_exec_cmd() in order to avoid transient drawing glitches. + */ + APP_CMD_WINDOW_REDRAW_NEEDED, + + /** + * Command from main thread: the content area of the window has changed, + * such as from the soft input window being shown or hidden. You can + * find the new content rect in android_app::contentRect. + */ + APP_CMD_CONTENT_RECT_CHANGED, + + /** + * Command from main thread: the app's activity window has gained + * input focus. + */ + APP_CMD_GAINED_FOCUS, + + /** + * Command from main thread: the app's activity window has lost + * input focus. + */ + APP_CMD_LOST_FOCUS, + + /** + * Command from main thread: the current device configuration has changed. + */ + APP_CMD_CONFIG_CHANGED, + + /** + * Command from main thread: the system is running low on memory. + * Try to reduce your memory use. + */ + APP_CMD_LOW_MEMORY, + + /** + * Command from main thread: the app's activity has been started. + */ + APP_CMD_START, + + /** + * Command from main thread: the app's activity has been resumed. + */ + APP_CMD_RESUME, + + /** + * Command from main thread: the app should generate a new saved state + * for itself, to restore from later if needed. + */ + APP_CMD_SAVE_STATE, + + /** + * Command from main thread: the app's activity has been paused. + */ + APP_CMD_PAUSE, + + /** + * Command from main thread: the app's activity has been stopped. + */ + APP_CMD_STOP, + + /** + * Command from main thread: the app's activity is being destroyed, + * and waiting for the app thread to clean up and exit before proceeding. + */ + APP_CMD_DESTROY, + + // Set by thread when it will no longer reply to commands. + APP_CMD_DEAD, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/frontend/drivers/platform_android.h b/frontend/drivers/platform_android.h index a52ba40903..2341dd9c9b 100644 --- a/frontend/drivers/platform_android.h +++ b/frontend/drivers/platform_android.h @@ -19,17 +19,11 @@ #define _PLATFORM_ANDROID_H #include -#include -#include -#include -#include -#include -#include +#include "android_native_app_glue.h" #include #include - #ifndef MAX_AXIS #define MAX_AXIS 10 #endif @@ -80,105 +74,6 @@ 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; - - /* When non-NULL, this is the window surface that the app can draw in. */ - ANativeWindow* window; - - /* 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 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; -}; - struct android_app_userdata { unsigned accelerometer_event_rate; @@ -199,135 +94,6 @@ struct android_app_userdata ASensorEventQueue *sensorEventQueue; }; -enum -{ - /** - * 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 - * surface. - */ - APP_CMD_INIT_WINDOW, - - /** - * Command from main thread: the existing ANativeWindow needs to be - * terminated. Upon receiving this command, android_app->window still - * contains the existing window; after calling android_app_exec_cmd - * it will be set to NULL. - */ - APP_CMD_TERM_WINDOW, - - /** - * Command from main thread: the current ANativeWindow has been resized. - * Please redraw with its new size. - */ - APP_CMD_WINDOW_RESIZED, - - /** - * Command from main thread: the system needs that the current ANativeWindow - * be redrawn. You should redraw the window before handing this to - * android_app_exec_cmd() in order to avoid transient drawing glitches. - */ - APP_CMD_WINDOW_REDRAW_NEEDED, - - /** - * Command from main thread: the content area of the window has changed, - * such as from the soft input window being shown or hidden. You can - * find the new content rect in android_app::contentRect. - */ - APP_CMD_CONTENT_RECT_CHANGED, - - /** - * Command from main thread: the app's activity window has gained - * input focus. - */ - APP_CMD_GAINED_FOCUS, - - /** - * Command from main thread: the app's activity window has lost - * input focus. - */ - APP_CMD_LOST_FOCUS, - - /** - * Command from main thread: the current device configuration has changed. - */ - APP_CMD_CONFIG_CHANGED, - - /** - * Command from main thread: the system is running low on memory. - * Try to reduce your memory use. - */ - APP_CMD_LOW_MEMORY, - - /** - * Command from main thread: the app's activity has been started. - */ - APP_CMD_START, - - /** - * Command from main thread: the app's activity has been resumed. - */ - APP_CMD_RESUME, - - /** - * Command from main thread: the app should generate a new saved state - * for itself, to restore from later if needed. - */ - APP_CMD_SAVE_STATE, - - /** - * Command from main thread: the app's activity has been paused. - */ - APP_CMD_PAUSE, - - /** - * Command from main thread: the app's activity has been stopped. - */ - APP_CMD_STOP, - - /** - * Command from main thread: the app's activity is being destroyed, - * and waiting for the app thread to clean up and exit before proceeding. - */ - APP_CMD_DESTROY, - - // Set by thread when it will no longer reply to commands. - APP_CMD_DEAD, -}; - #define JNI_EXCEPTION(env) \ if ((*env)->ExceptionOccurred(env)) \ { \