diff --git a/frontend/drivers/android_native_app_glue.c b/frontend/drivers/android_native_app_glue.c
new file mode 100644
index 0000000000..fc55a86e91
--- /dev/null
+++ b/frontend/drivers/android_native_app_glue.c
@@ -0,0 +1,330 @@
+/* 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 .
+ */
+
+#include "platform_android.h"
+
+struct android_app *g_android;
+struct android_app_userdata *g_android_userdata;
+
+void android_app_write_cmd(struct android_app *android_app, int8_t cmd)
+{
+ if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd))
+ RARCH_ERR("Failure writing android_app cmd: %s\n", strerror(errno));
+}
+
+static void android_app_set_input(void *data, AInputQueue* inputQueue)
+{
+ struct android_app *android_app = (struct android_app*)data;
+
+ if (!android_app)
+ return;
+
+ slock_lock(android_app->mutex);
+ android_app->pendingInputQueue = inputQueue;
+ android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
+
+ while (android_app->inputQueue != android_app->pendingInputQueue)
+ scond_wait(android_app->cond, android_app->mutex);
+
+ slock_unlock(android_app->mutex);
+}
+
+static void android_app_set_window(void *data, ANativeWindow* window)
+{
+ struct android_app *android_app = (struct android_app*)data;
+
+ if (!android_app)
+ return;
+
+ slock_lock(android_app->mutex);
+ if (android_app->pendingWindow)
+ android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
+
+ android_app->pendingWindow = window;
+
+ if (window)
+ android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
+
+ while (android_app->window != android_app->pendingWindow)
+ scond_wait(android_app->cond, android_app->mutex);
+
+ slock_unlock(android_app->mutex);
+}
+
+static void android_app_set_activity_state(void *data, int8_t cmd)
+{
+ struct android_app *android_app = (struct android_app*)data;
+
+ if (!android_app)
+ return;
+
+ slock_lock(android_app->mutex);
+ android_app_write_cmd(android_app, cmd);
+ while (android_app->activityState != cmd
+ && android_app->activityState != APP_CMD_DEAD)
+ scond_wait(android_app->cond, android_app->mutex);
+ slock_unlock(android_app->mutex);
+
+ if (android_app->activityState == APP_CMD_DEAD)
+ RARCH_LOG("RetroArch native thread is dead.\n");
+}
+
+static void onDestroy(ANativeActivity* activity)
+{
+ struct android_app *android_app = (struct android_app*)activity->instance;
+
+ if (!android_app)
+ return;
+
+ RARCH_LOG("onDestroy: %p\n", activity);
+ sthread_join(android_app->thread);
+ RARCH_LOG("Joined with RetroArch native thread.\n");
+
+ close(android_app->msgread);
+ close(android_app->msgwrite);
+ scond_free(android_app->cond);
+ slock_free(android_app->mutex);
+
+ free(android_app);
+}
+
+static void onStart(ANativeActivity* activity)
+{
+ RARCH_LOG("Start: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)
+ activity->instance, APP_CMD_START);
+}
+
+static void onResume(ANativeActivity* activity)
+{
+ RARCH_LOG("Resume: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)
+ activity->instance, APP_CMD_RESUME);
+}
+
+static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
+{
+ struct android_app* android_app = (struct android_app*)activity->instance;
+ void* savedState = NULL;
+
+ slock_lock(android_app->mutex);
+ android_app->stateSaved = 0;
+ android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
+ while (!android_app->stateSaved)
+ scond_wait(android_app->cond, android_app->mutex);
+
+ if (android_app->savedState != NULL)
+ {
+ savedState = android_app->savedState;
+ *outLen = android_app->savedStateSize;
+ android_app->savedState = NULL;
+ android_app->savedStateSize = 0;
+ }
+
+ slock_unlock(android_app->mutex);
+
+ return savedState;
+}
+
+static void onPause(ANativeActivity* activity)
+{
+ RARCH_LOG("Pause: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)
+ activity->instance, APP_CMD_PAUSE);
+}
+
+static void onStop(ANativeActivity* activity)
+{
+ RARCH_LOG("Stop: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)
+ activity->instance, APP_CMD_STOP);
+}
+
+static void onConfigurationChanged(ANativeActivity *activity)
+{
+ struct android_app* android_app = (struct android_app*)
+ activity->instance;
+
+ if (!android_app)
+ return;
+
+ RARCH_LOG("ConfigurationChanged: %p\n", activity);
+ android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
+}
+
+static void onLowMemory(ANativeActivity* activity)
+{
+ struct android_app* android_app = (struct android_app*)activity->instance;
+ android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
+}
+
+static void onWindowFocusChanged(ANativeActivity* activity, int focused)
+{
+ RARCH_LOG("WindowFocusChanged: %p -- %d\n", activity, focused);
+ android_app_write_cmd((struct android_app*)activity->instance,
+ focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
+}
+
+static void onNativeWindowCreated(ANativeActivity* activity,
+ ANativeWindow* window)
+{
+ RARCH_LOG("NativeWindowCreated: %p -- %p\n", activity, window);
+ android_app_set_window((struct android_app*)activity->instance, window);
+}
+
+static void onNativeWindowDestroyed(ANativeActivity* activity,
+ ANativeWindow* window)
+{
+ RARCH_LOG("NativeWindowDestroyed: %p -- %p\n", activity, window);
+ android_app_set_window((struct android_app*)activity->instance, NULL);
+}
+
+static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
+{
+ RARCH_LOG("InputQueueCreated: %p -- %p\n", activity, queue);
+ android_app_set_input((struct android_app*)activity->instance, queue);
+}
+
+static void onInputQueueDestroyed(ANativeActivity* activity,
+ AInputQueue* queue)
+{
+ RARCH_LOG("InputQueueDestroyed: %p -- %p\n", activity, queue);
+ android_app_set_input((struct android_app*)activity->instance, NULL);
+}
+
+static void android_app_entry(void *param)
+{
+ struct android_app* android_app = (struct android_app*)param;
+ ALooper *looper = (ALooper*)ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
+ ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN,
+ ALOOPER_EVENT_INPUT, NULL, NULL);
+ android_app->looper = looper;
+
+ slock_lock(android_app->mutex);
+ android_app->running = 1;
+ scond_broadcast(android_app->cond);
+ slock_unlock(android_app->mutex);
+
+ android_main(android_app);
+}
+
+static struct android_app* android_app_create(ANativeActivity* activity,
+ void* savedState, size_t savedStateSize)
+{
+ int msgpipe[2];
+ struct android_app* android_app = (struct android_app*)
+ calloc(1, sizeof(*android_app));
+ android_app->activity = activity;
+
+ android_app->mutex = slock_new();
+ android_app->cond = scond_new();
+
+ if (savedState != NULL)
+ {
+ android_app->savedState = malloc(savedStateSize);
+ android_app->savedStateSize = savedStateSize;
+ memcpy(android_app->savedState, savedState, savedStateSize);
+ }
+
+ if (pipe(msgpipe))
+ {
+ RARCH_ERR("could not create pipe: %s.\n", strerror(errno));
+ activity->instance = NULL;
+ }
+ android_app->msgread = msgpipe[0];
+ android_app->msgwrite = msgpipe[1];
+
+ android_app->thread = sthread_create(android_app_entry, android_app);
+
+ /* Wait for thread to start. */
+ slock_lock(android_app->mutex);
+ while (!android_app->running)
+ scond_wait(android_app->cond, android_app->mutex);
+ slock_unlock(android_app->mutex);
+
+ /* These are set only for the native activity,
+ * and are reset when it ends. */
+ ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON
+ | AWINDOW_FLAG_FULLSCREEN, 0);
+
+ return android_app;
+}
+
+/*
+ * Native activity interaction (called from main thread)
+ **/
+
+void ANativeActivity_onCreate(ANativeActivity* activity,
+ void* savedState, size_t savedStateSize)
+{
+ RARCH_LOG("Creating Native Activity: %p\n", activity);
+ activity->callbacks->onDestroy = onDestroy;
+ activity->callbacks->onStart = onStart;
+ activity->callbacks->onResume = onResume;
+ activity->callbacks->onSaveInstanceState = onSaveInstanceState;
+ activity->callbacks->onPause = onPause;
+ activity->callbacks->onStop = onStop;
+ activity->callbacks->onConfigurationChanged = onConfigurationChanged;
+ activity->callbacks->onLowMemory = onLowMemory;
+ activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
+ activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
+ activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
+ activity->callbacks->onInputQueueCreated = onInputQueueCreated;
+ activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
+
+ activity->instance = android_app_create(activity, savedState, savedStateSize);
+}
+
+int system_property_get(const char *name, char *value)
+{
+ FILE *pipe;
+ int length = 0;
+ char buffer[PATH_MAX_LENGTH];
+ char cmd[PATH_MAX_LENGTH];
+ char *curpos = NULL;
+
+ snprintf(cmd, sizeof(cmd), "getprop %s", name);
+
+ pipe = popen(cmd, "r");
+
+ if (!pipe)
+ {
+ RARCH_ERR("Could not create pipe.\n");
+ return 0;
+ }
+
+ curpos = value;
+
+ while (!feof(pipe))
+ {
+ if (fgets(buffer, 128, pipe) != NULL)
+ {
+ int curlen = strlen(buffer);
+
+ memcpy(curpos, buffer, curlen);
+
+ curpos += curlen;
+ length += curlen;
+ }
+ }
+
+ *curpos = '\0';
+
+ pclose(pipe);
+
+ return length;
+}
diff --git a/frontend/drivers/platform_android.c b/frontend/drivers/platform_android.c
index addf9a7940..2f8bfc69c5 100644
--- a/frontend/drivers/platform_android.c
+++ b/frontend/drivers/platform_android.c
@@ -27,166 +27,8 @@
#include "../../general.h"
#include
-struct android_app *g_android;
-struct android_app_userdata *g_android_userdata;
static pthread_key_t thread_key;
-void android_app_write_cmd(struct android_app *android_app, int8_t cmd)
-{
- if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd))
- RARCH_ERR("Failure writing android_app cmd: %s\n", strerror(errno));
-}
-
-static void android_app_set_input(void *data, AInputQueue* inputQueue)
-{
- struct android_app *android_app = (struct android_app*)data;
-
- if (!android_app)
- return;
-
- slock_lock(android_app->mutex);
- android_app->pendingInputQueue = inputQueue;
- android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
-
- while (android_app->inputQueue != android_app->pendingInputQueue)
- scond_wait(android_app->cond, android_app->mutex);
-
- slock_unlock(android_app->mutex);
-}
-
-static void android_app_set_window(void *data, ANativeWindow* window)
-{
- struct android_app *android_app = (struct android_app*)data;
-
- if (!android_app)
- return;
-
- slock_lock(android_app->mutex);
- if (android_app->pendingWindow)
- android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
-
- android_app->pendingWindow = window;
-
- if (window)
- android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
-
- while (android_app->window != android_app->pendingWindow)
- scond_wait(android_app->cond, android_app->mutex);
-
- slock_unlock(android_app->mutex);
-}
-
-static void android_app_set_activity_state(void *data, int8_t cmd)
-{
- struct android_app *android_app = (struct android_app*)data;
-
- if (!android_app)
- return;
-
- slock_lock(android_app->mutex);
- android_app_write_cmd(android_app, cmd);
- while (android_app->activityState != cmd
- && android_app->activityState != APP_CMD_DEAD)
- scond_wait(android_app->cond, android_app->mutex);
- slock_unlock(android_app->mutex);
-
- if (android_app->activityState == APP_CMD_DEAD)
- RARCH_LOG("RetroArch native thread is dead.\n");
-}
-
-static void onDestroy(ANativeActivity* activity)
-{
- struct android_app *android_app = (struct android_app*)activity->instance;
-
- if (!android_app)
- return;
-
- RARCH_LOG("onDestroy: %p\n", activity);
- sthread_join(android_app->thread);
- RARCH_LOG("Joined with RetroArch native thread.\n");
-
- close(android_app->msgread);
- close(android_app->msgwrite);
- scond_free(android_app->cond);
- slock_free(android_app->mutex);
-
- free(android_app);
-}
-
-static void onStart(ANativeActivity* activity)
-{
- RARCH_LOG("Start: %p\n", activity);
- android_app_set_activity_state((struct android_app*)
- activity->instance, APP_CMD_START);
-}
-
-static void onResume(ANativeActivity* activity)
-{
- RARCH_LOG("Resume: %p\n", activity);
- android_app_set_activity_state((struct android_app*)
- activity->instance, APP_CMD_RESUME);
-}
-
-static void onPause(ANativeActivity* activity)
-{
- RARCH_LOG("Pause: %p\n", activity);
- android_app_set_activity_state((struct android_app*)
- activity->instance, APP_CMD_PAUSE);
-}
-
-static void onStop(ANativeActivity* activity)
-{
- RARCH_LOG("Stop: %p\n", activity);
- android_app_set_activity_state((struct android_app*)
- activity->instance, APP_CMD_STOP);
-}
-
-static void onConfigurationChanged(ANativeActivity *activity)
-{
- struct android_app* android_app = (struct android_app*)
- activity->instance;
-
- if (!android_app)
- return;
-
- RARCH_LOG("ConfigurationChanged: %p\n", activity);
- android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
-}
-
-static void onWindowFocusChanged(ANativeActivity* activity, int focused)
-{
- RARCH_LOG("WindowFocusChanged: %p -- %d\n", activity, focused);
- android_app_write_cmd((struct android_app*)activity->instance,
- focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
-}
-
-static void onNativeWindowCreated(ANativeActivity* activity,
- ANativeWindow* window)
-{
- RARCH_LOG("NativeWindowCreated: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, window);
-}
-
-static void onNativeWindowDestroyed(ANativeActivity* activity,
- ANativeWindow* window)
-{
- RARCH_LOG("NativeWindowDestroyed: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, NULL);
-}
-
-static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
-{
- RARCH_LOG("InputQueueCreated: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, queue);
-}
-
-static void onInputQueueDestroyed(ANativeActivity* activity,
- AInputQueue* queue)
-{
- RARCH_LOG("InputQueueDestroyed: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, NULL);
-}
-
JNIEnv *jni_thread_getenv(void)
{
JNIEnv *env;
@@ -219,21 +61,15 @@ static void jni_thread_destruct(void *value)
pthread_setspecific(thread_key, NULL);
}
-static void android_app_entry(void *data)
+void android_main(struct android_app *android_app)
{
char *argv[1];
int argc = 0;
int ret_iterate;
- struct android_app *android_app = (struct android_app*)data;
g_android = android_app;
g_android_userdata = (struct android_app_userdata*)calloc(1, sizeof(*g_android_userdata));
- slock_lock(android_app->mutex);
- android_app->running = 1;
- scond_broadcast(android_app->cond);
- slock_unlock(android_app->mutex);
-
if (rarch_main(argc, argv, android_app) != 0)
goto end;
@@ -242,7 +78,7 @@ static void android_app_entry(void *data)
}while(ret_iterate != 1);
end:
- main_exit(data);
+ main_exit(android_app);
if (g_android_userdata)
free(g_android_userdata);
@@ -251,110 +87,6 @@ end:
exit(0);
}
-/*
- * Native activity interaction (called from main thread)
- **/
-
-void ANativeActivity_onCreate(ANativeActivity* activity,
- void* savedState, size_t savedStateSize)
-{
- int msgpipe[2];
- struct android_app* android_app;
-
- (void)savedState;
- (void)savedStateSize;
-
- RARCH_LOG("Creating Native Activity: %p\n", activity);
- activity->callbacks->onDestroy = onDestroy;
- activity->callbacks->onStart = onStart;
- activity->callbacks->onResume = onResume;
- activity->callbacks->onSaveInstanceState = NULL;
- activity->callbacks->onPause = onPause;
- activity->callbacks->onStop = onStop;
- activity->callbacks->onConfigurationChanged = onConfigurationChanged;
- activity->callbacks->onLowMemory = NULL;
- activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
- activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
- activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
- activity->callbacks->onInputQueueCreated = onInputQueueCreated;
- activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
-
- /* These are set only for the native activity,
- * and are reset when it ends. */
- ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON
- | AWINDOW_FLAG_FULLSCREEN, 0);
-
- if (pthread_key_create(&thread_key, jni_thread_destruct))
- RARCH_ERR("Error initializing pthread_key\n");
-
- android_app = (struct android_app*)calloc(1, sizeof(*android_app));
-
- memset(android_app, 0, sizeof(struct android_app));
-
- android_app->activity = activity;
- android_app->mutex = slock_new();
- android_app->cond = scond_new();
-
- if (pipe(msgpipe))
- {
- RARCH_ERR("could not create pipe: %s.\n", strerror(errno));
- activity->instance = NULL;
- }
- android_app->msgread = msgpipe[0];
- android_app->msgwrite = msgpipe[1];
-
- android_app->thread = sthread_create(android_app_entry, android_app);
-
- /* Wait for thread to start. */
- slock_lock(android_app->mutex);
- while (!android_app->running)
- scond_wait(android_app->cond, android_app->mutex);
- slock_unlock(android_app->mutex);
-
- activity->instance = android_app;
-}
-
-
-int system_property_get(const char *name, char *value)
-{
- FILE *pipe;
- int length = 0;
- char buffer[PATH_MAX_LENGTH];
- char cmd[PATH_MAX_LENGTH];
- char *curpos = NULL;
-
- snprintf(cmd, sizeof(cmd), "getprop %s", name);
-
- pipe = popen(cmd, "r");
-
- if (!pipe)
- {
- RARCH_ERR("Could not create pipe.\n");
- return 0;
- }
-
- curpos = value;
-
- while (!feof(pipe))
- {
- if (fgets(buffer, 128, pipe) != NULL)
- {
- int curlen = strlen(buffer);
-
- memcpy(curpos, buffer, curlen);
-
- curpos += curlen;
- length += curlen;
- }
- }
-
- *curpos = '\0';
-
- pclose(pipe);
-
- return length;
-}
-
static void frontend_android_get_name(char *name, size_t sizeof_name)
{
int len = system_property_get("ro.product.model", name);
@@ -832,7 +564,6 @@ static void frontend_android_init(void *data)
{
int32_t sdk;
JNIEnv *env;
- ALooper *looper;
jclass class = NULL;
jobject obj = NULL;
struct android_app* android_app = (struct android_app*)data;
@@ -842,10 +573,8 @@ static void frontend_android_init(void *data)
if (!android_app)
return;
- looper = (ALooper*)ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
- ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN,
- ALOOPER_EVENT_INPUT, NULL, NULL);
- android_app->looper = looper;
+ if (pthread_key_create(&thread_key, jni_thread_destruct))
+ RARCH_ERR("Error initializing pthread_key\n");
RARCH_LOG("Waiting for Android Native Window to be initialized ...\n");
diff --git a/frontend/drivers/platform_android.h b/frontend/drivers/platform_android.h
index aeb1a89c3a..a52ba40903 100644
--- a/frontend/drivers/platform_android.h
+++ b/frontend/drivers/platform_android.h
@@ -401,4 +401,6 @@ void android_app_write_cmd(struct android_app *android_app, int8_t cmd);
extern struct android_app *g_android;
extern struct android_app_userdata *g_android_userdata;
+void android_main(struct android_app *android_app);
+
#endif /* _PLATFORM_ANDROID_H */
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 37fe8b65c6..a2a68b744d 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -612,6 +612,7 @@ FRONTEND
#elif defined(__QNX__)
#include "../frontend/drivers/platform_qnx.c"
#elif defined(ANDROID)
+#include "../frontend/drivers/android_native_app_glue.c"
#include "../frontend/drivers/platform_android.c"
#elif defined(__linux__) && !defined(ANDROID)
#include "../frontend/drivers/platform_linux.c"