From 8116d118dd7e6f1f6225121ca40a767c7eae874f Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 15 Sep 2015 20:43:54 +0200 Subject: [PATCH] (Android/Linux) platform_linux.c now also used for Android --- frontend/drivers/platform_android.c | 1063 ------------------------- frontend/drivers/platform_linux.c | 1123 +++++++++++++++++++++++++-- frontend/frontend_driver.c | 5 +- griffin/griffin.c | 4 +- 4 files changed, 1070 insertions(+), 1125 deletions(-) delete mode 100644 frontend/drivers/platform_android.c diff --git a/frontend/drivers/platform_android.c b/frontend/drivers/platform_android.c deleted file mode 100644 index 612a5fbf7e..0000000000 --- a/frontend/drivers/platform_android.c +++ /dev/null @@ -1,1063 +0,0 @@ -/* 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 -#include -#include -#include -#include - -#include -#include - -#include "platform_android.h" - -#include "../frontend.h" -#include "../../general.h" -#include "../../msg_hash.h" -#include "../../runloop_data.h" - -#define SDCARD_ROOT_WRITABLE 1 -#define SDCARD_EXT_DIR_WRITABLE 2 -#define SDCARD_NOT_WRITABLE 3 - -struct android_app *g_android; -static pthread_key_t thread_key; - -char screenshot_dir[PATH_MAX_LENGTH]; -char downloads_dir[PATH_MAX_LENGTH]; -char apk_path[PATH_MAX_LENGTH]; -char sdcard_dir[PATH_MAX_LENGTH]; -char app_dir[PATH_MAX_LENGTH]; -char ext_dir[PATH_MAX_LENGTH]; - -static INLINE void android_app_write_cmd(void *data, 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)); -} - -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; - struct android_app* android_app = (struct android_app*)g_android; - int status = (*android_app->activity->vm)-> - AttachCurrentThread(android_app->activity->vm, &env, 0); - - if (status < 0) - { - RARCH_ERR("jni_thread_getenv: Failed to attach current thread.\n"); - return NULL; - } - pthread_setspecific(thread_key, (void*)env); - - return env; -} - -static void jni_thread_destruct(void *value) -{ - JNIEnv *env = (JNIEnv*)value; - struct android_app *android_app = (struct android_app*)g_android; - RARCH_LOG("jni_thread_destruct()\n"); - - if (!env) - return; - - if (android_app) - (*android_app->activity->vm)-> - DetachCurrentThread(android_app->activity->vm); - pthread_setspecific(thread_key, NULL); -} - -static void android_app_entry(void *data) -{ - char *argv[1]; - int argc = 0; - int ret = 0; - - if (rarch_main(argc, argv, data) != 0) - goto end; -#ifndef HAVE_MAIN - do - { - unsigned sleep_ms = 0; - ret = rarch_main_iterate(&sleep_ms); - - if (ret == 1 && sleep_ms > 0) - rarch_sleep(sleep_ms); - rarch_main_data_iterate(); - }while (ret != -1); - - main_exit(data); -#endif - -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)); - if (!android_app) - { - RARCH_ERR("Failed to initialize android_app\n"); - return; - } - - 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] = {0}; - char cmd[PATH_MAX_LENGTH] = {0}; - 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 *s, size_t len) -{ - system_property_get("ro.product.model", s); -} - -static void frontend_android_get_version(int32_t *major, - int32_t *minor, int32_t *rel) -{ - char os_version_str[PROP_VALUE_MAX] = {0}; - system_property_get("ro.build.version.release", os_version_str); - - *major = 0; - *minor = 0; - *rel = 0; - - /* Parse out the OS version numbers from the system properties. */ - if (os_version_str[0]) - { - /* Try to parse out the version numbers from the string. */ - int num_read = sscanf(os_version_str, "%d.%d.%d", major, minor, rel); - - if (num_read > 0) - { - if (num_read < 2) - *minor = 0; - if (num_read < 3) - *rel = 0; - return; - } - } -} - -static void frontend_android_get_os(char *s, size_t len, int *major, int *minor) -{ - int rel; - - frontend_android_get_version(major, minor, &rel); - - strlcpy(s, "Android", len); -} - -static void frontend_android_get_version_sdk(int32_t *sdk) -{ - char os_version_str[PROP_VALUE_MAX] = {0}; - system_property_get("ro.build.version.sdk", os_version_str); - - *sdk = 0; - if (os_version_str[0]) - { - int num_read = sscanf(os_version_str, "%d", sdk); - (void) num_read; - } -} - -static bool device_is_xperia_play(const char *name) -{ - if ( - !strcmp(name, "R800x") || - !strcmp(name, "R800at") || - !strcmp(name, "R800i") || - !strcmp(name, "R800a") || - !strcmp(name, "SO-01D") - ) - return true; - - return false; -} - -static bool device_is_game_console(const char *name) -{ - if ( - !strcmp(name, "OUYA Console") || - device_is_xperia_play(name) || - !strcmp(name, "GAMEMID_BT") || - !strcmp(name, "S7800") || - !strcmp(name, "SHIELD") - ) - return true; - - return false; -} - -bool test_permissions(const char *path) -{ - char buf[PATH_MAX_LENGTH]; - bool ret; - - RARCH_LOG("Testing permissions for %s\n",path); - - fill_pathname_join(buf, path, ".retroarch", sizeof(buf)); - ret = path_mkdir(buf); - - RARCH_LOG("Create %s %s\n", buf, ret ? "true" : "false"); - - if(ret) - rmdir(buf); - - return ret; -} - -static void frontend_android_get_environment_settings(int *argc, - char *argv[], void *data, void *params_data) -{ - int32_t major, minor, rel; - int perms = 0; - char device_model[PROP_VALUE_MAX] = {0}; - char device_id[PROP_VALUE_MAX] = {0}; - struct rarch_main_wrap *args = NULL; - JNIEnv *env = NULL; - jobject obj = NULL; - jstring jstr = NULL; - struct android_app *android_app = (struct android_app*)data; - char buf[PATH_MAX_LENGTH] = {0}; - - if (!android_app) - return; - - env = jni_thread_getenv(); - if (!env) - return; - - args = (struct rarch_main_wrap*)params_data; - - if (args) - { - args->touched = true; - args->no_content = false; - args->verbose = false; - args->sram_path = NULL; - args->state_path = NULL; - } - - frontend_android_get_version(&major, &minor, &rel); - - RARCH_LOG("Android OS version (major : %d, minor : %d, rel : %d)\n", - major, minor, rel); - - CALL_OBJ_METHOD(env, obj, android_app->activity->clazz, - android_app->getIntent); - RARCH_LOG("Checking arguments passed from intent ...\n"); - - /* Config file. */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "CONFIGFILE")); - - if (android_app->getStringExtra && jstr) - { - static char config_path[PATH_MAX_LENGTH] = {0}; - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - if (argv && *argv) - strlcpy(config_path, argv, sizeof(config_path)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - RARCH_LOG("Config file: [%s].\n", config_path); - if (args && *config_path) - args->config_path = config_path; - } - - /* Current IME. */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "IME")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - strlcpy(android_app->current_ime, argv, - sizeof(android_app->current_ime)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - RARCH_LOG("Current IME: [%s].\n", android_app->current_ime); - } - - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "USED")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - bool used = (!strcmp(argv, "false")) ? false : true; - - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - RARCH_LOG("USED: [%s].\n", used ? "true" : "false"); - } - - /* LIBRETRO. */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "LIBRETRO")); - - if (android_app->getStringExtra && jstr) - { - static char core_path[PATH_MAX_LENGTH]; - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *core_path = '\0'; - if (argv && *argv) - strlcpy(core_path, argv, sizeof(core_path)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - RARCH_LOG("Libretro path: [%s]\n", core_path); - if (args && *core_path) - args->libretro_path = core_path; - } - - /* Content. */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "ROM")); - - if (android_app->getStringExtra && jstr) - { - static char path[PATH_MAX_LENGTH]; - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *path = '\0'; - - if (argv && *argv) - strlcpy(path, argv, sizeof(path)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - if (*path) - { - RARCH_LOG("Auto-start game %s.\n", path); - if (args && *path) - args->content_path = path; - } - } - - /* External Storage */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "SDCARD")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *sdcard_dir = '\0'; - - if (argv && *argv) - strlcpy(sdcard_dir, argv, sizeof(sdcard_dir)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - if (*sdcard_dir) - { - RARCH_LOG("External storage location [%s]\n", sdcard_dir); - /* TODO base dir handler */ - } - } - - /* Screenshots */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "SCREENSHOTS")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *screenshot_dir = '\0'; - - if (argv && *argv) - strlcpy(screenshot_dir, argv, sizeof(screenshot_dir)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - if (*screenshot_dir) - { - RARCH_LOG("Picture folder location [%s]\n", screenshot_dir); - /* TODO: screenshot handler */ - } - } - - /* Downloads */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "DOWNLOADS")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *downloads_dir = '\0'; - - if (argv && *argv) - strlcpy(downloads_dir, argv, sizeof(downloads_dir)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - if (*downloads_dir) - { - RARCH_LOG("Download folder location [%s].\n", downloads_dir); - /* TODO: downloads handler */ - } - } - - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "APK")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *apk_path = '\0'; - - if (argv && *argv) - strlcpy(apk_path, argv, sizeof(apk_path)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - if (*apk_path) - { - RARCH_LOG("APK location [%s].\n", apk_path); - } - } - - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "EXTERNAL")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *ext_dir = '\0'; - - if (argv && *argv) - strlcpy(ext_dir, argv, sizeof(ext_dir)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - if (*ext_dir) - { - RARCH_LOG("External files location [%s]\n", ext_dir); - } - } - - /* Content. */ - CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, - (*env)->NewStringUTF(env, "DATADIR")); - - if (android_app->getStringExtra && jstr) - { - const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); - - *app_dir = '\0'; - - if (argv && *argv) - strlcpy(app_dir, argv, sizeof(app_dir)); - (*env)->ReleaseStringUTFChars(env, jstr, argv); - - //set paths depending on the ability to write to sdcard_dir - - if(*sdcard_dir) - { - if(test_permissions(sdcard_dir)) - perms = SDCARD_ROOT_WRITABLE; - } - else if(*ext_dir) - { - if(test_permissions(ext_dir)) - perms = SDCARD_EXT_DIR_WRITABLE; - } - else - perms = SDCARD_NOT_WRITABLE; - - RARCH_LOG("SD permissions: %d",perms); - - if (*app_dir) - { - RARCH_LOG("Application location: [%s].\n", app_dir); - if (args && *app_dir) - { - fill_pathname_join(g_defaults.dir.assets, app_dir, - "assets", sizeof(g_defaults.dir.assets)); - fill_pathname_join(g_defaults.dir.extraction, app_dir, - "tmp", sizeof(g_defaults.dir.extraction)); - fill_pathname_join(g_defaults.dir.shader, app_dir, - "shaders", sizeof(g_defaults.dir.shader)); - fill_pathname_join(g_defaults.dir.overlay, app_dir, - "overlays", sizeof(g_defaults.dir.overlay)); - fill_pathname_join(g_defaults.dir.osk_overlay, app_dir, - "overlays", sizeof(g_defaults.dir.osk_overlay)); - fill_pathname_join(g_defaults.dir.core, app_dir, - "cores", sizeof(g_defaults.dir.core)); - fill_pathname_join(g_defaults.dir.core_info, - app_dir, "info", sizeof(g_defaults.dir.core_info)); - fill_pathname_join(g_defaults.dir.autoconfig, - app_dir, "autoconfig", sizeof(g_defaults.dir.autoconfig)); - fill_pathname_join(g_defaults.dir.audio_filter, - app_dir, "audio_filters", sizeof(g_defaults.dir.audio_filter)); - fill_pathname_join(g_defaults.dir.video_filter, - app_dir, "video_filters", sizeof(g_defaults.dir.video_filter)); - strlcpy(g_defaults.dir.content_history, - app_dir, sizeof(g_defaults.dir.content_history)); - fill_pathname_join(g_defaults.dir.database, - app_dir, "database/rdb", sizeof(g_defaults.dir.database)); - fill_pathname_join(g_defaults.dir.cursor, - app_dir, "database/cursors", sizeof(g_defaults.dir.cursor)); - fill_pathname_join(g_defaults.dir.cheats, - app_dir, "cheats", sizeof(g_defaults.dir.cheats)); - fill_pathname_join(g_defaults.dir.playlist, - app_dir, "playlists", sizeof(g_defaults.dir.playlist)); - fill_pathname_join(g_defaults.dir.remap, - app_dir, "remaps", sizeof(g_defaults.dir.remap)); - fill_pathname_join(g_defaults.dir.wallpapers, - app_dir, "wallpapers", sizeof(g_defaults.dir.wallpapers)); - if(*downloads_dir && test_permissions(downloads_dir)) - { - fill_pathname_join(g_defaults.dir.core_assets, - downloads_dir, "", sizeof(g_defaults.dir.core_assets)); - } - else - { - fill_pathname_join(g_defaults.dir.core_assets, - app_dir, "downloads", sizeof(g_defaults.dir.core_assets)); - path_mkdir(g_defaults.dir.core_assets); - } - - RARCH_LOG("Default download folder: [%s]", g_defaults.dir.core_assets); - - if(*screenshot_dir && test_permissions(screenshot_dir)) - { - fill_pathname_join(g_defaults.dir.screenshot, - screenshot_dir, "", sizeof(g_defaults.dir.screenshot)); - } - else - { - fill_pathname_join(g_defaults.dir.screenshot, - app_dir, "screenshots", sizeof(g_defaults.dir.screenshot)); - path_mkdir(g_defaults.dir.screenshot); - } - - RARCH_LOG("Default screenshot folder: [%s]", g_defaults.dir.screenshot); - - switch (perms) - { - case SDCARD_EXT_DIR_WRITABLE: - fill_pathname_join(g_defaults.dir.sram, - ext_dir, "saves", sizeof(g_defaults.dir.sram)); - path_mkdir(g_defaults.dir.sram); - - fill_pathname_join(g_defaults.dir.savestate, - ext_dir, "states", sizeof(g_defaults.dir.savestate)); - path_mkdir(g_defaults.dir.savestate); - - fill_pathname_join(g_defaults.dir.system, - ext_dir, "system", sizeof(g_defaults.dir.system)); - path_mkdir(g_defaults.dir.system); - break; - case SDCARD_NOT_WRITABLE: - fill_pathname_join(g_defaults.dir.sram, - app_dir, "saves", sizeof(g_defaults.dir.sram)); - path_mkdir(g_defaults.dir.sram); - fill_pathname_join(g_defaults.dir.savestate, - app_dir, "states", sizeof(g_defaults.dir.savestate)); - path_mkdir(g_defaults.dir.savestate); - fill_pathname_join(g_defaults.dir.system, - app_dir, "system", sizeof(g_defaults.dir.system)); - path_mkdir(g_defaults.dir.system); - break; - case SDCARD_ROOT_WRITABLE: - default: - break; - } - - /* create save and system directories in the internal dir too */ - fill_pathname_join(buf, - app_dir, "saves", sizeof(buf)); - path_mkdir(buf); - - fill_pathname_join(buf, - app_dir, "states", sizeof(buf)); - path_mkdir(buf); - - fill_pathname_join(buf, - app_dir, "system", sizeof(buf)); - path_mkdir(buf); - - /* create save and system directories in the internal sd too */ - - fill_pathname_join(buf, - ext_dir, "saves", sizeof(buf)); - path_mkdir(buf); - - fill_pathname_join(buf, - ext_dir, "states", sizeof(buf)); - path_mkdir(buf); - - fill_pathname_join(buf, - ext_dir, "system", sizeof(buf)); - path_mkdir(buf); - - RARCH_LOG("Default savefile folder: [%s]", g_defaults.dir.sram); - RARCH_LOG("Default savestate folder: [%s]", g_defaults.dir.savestate); - RARCH_LOG("Default system folder: [%s]", g_defaults.dir.system); - } - } - } - - frontend_android_get_name(device_model, sizeof(device_model)); - system_property_get("ro.product.id", device_id); - - g_defaults.settings.video_threaded_enable = true; - - /* Set automatic default values per device */ - if (device_is_xperia_play(device_model)) - { - g_defaults.settings.out_latency = 128; - g_defaults.settings.video_refresh_rate = 59.19132938771038; - g_defaults.settings.video_threaded_enable = false; - } - else if (!strcmp(device_model, "GAMEMID_BT")) - g_defaults.settings.out_latency = 160; - else if (!strcmp(device_model, "SHIELD")) - g_defaults.settings.video_refresh_rate = 60.0; - else if (!strcmp(device_model, "JSS15J")) - g_defaults.settings.video_refresh_rate = 59.65; - -#if 0 - /* Explicitly disable input overlay by default - * for gamepad-like/console devices. */ - if (device_is_game_console(device_model)) - g_defaults.settings.input_overlay_enable = false; -#endif -} - -static void frontend_android_deinit(void *data) -{ - JNIEnv *env = NULL; - struct android_app *android_app = (struct android_app*)data; - - if (!android_app) - return; - - RARCH_LOG("Deinitializing RetroArch ...\n"); - android_app->activityState = APP_CMD_DEAD; - - env = jni_thread_getenv(); - - if (env && android_app->onRetroArchExit) - CALL_VOID_METHOD(env, android_app->activity->clazz, - android_app->onRetroArchExit); - - if (android_app->inputQueue) - { - RARCH_LOG("Detaching Android input queue looper ...\n"); - AInputQueue_detachLooper(android_app->inputQueue); - } -} - -static void frontend_android_shutdown(bool unused) -{ - (void)unused; - /* Cleaner approaches don't work sadly. */ - exit(0); -} - -bool android_run_events(void *data); - -static void frontend_android_init(void *data) -{ - JNIEnv *env = NULL; - ALooper *looper = NULL; - jclass class = NULL; - jobject obj = NULL; - struct android_app* android_app = (struct android_app*)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; - - slock_lock(android_app->mutex); - android_app->running = 1; - scond_broadcast(android_app->cond); - slock_unlock(android_app->mutex); - - memset(&g_android, 0, sizeof(g_android)); - g_android = (struct android_app*)android_app; - - RARCH_LOG("Waiting for Android Native Window to be initialized ...\n"); - - while (!android_app->window) - { - if (!android_run_events(android_app)) - { - frontend_android_deinit(android_app); - frontend_android_shutdown(android_app); - return; - } - } - - RARCH_LOG("Android Native Window initialized.\n"); - - env = jni_thread_getenv(); - if (!env) - return; - - GET_OBJECT_CLASS(env, class, android_app->activity->clazz); - GET_METHOD_ID(env, android_app->getIntent, class, - "getIntent", "()Landroid/content/Intent;"); - GET_METHOD_ID(env, android_app->onRetroArchExit, class, - "onRetroArchExit", "()V"); - CALL_OBJ_METHOD(env, obj, android_app->activity->clazz, - android_app->getIntent); - - GET_OBJECT_CLASS(env, class, obj); - GET_METHOD_ID(env, android_app->getStringExtra, class, - "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;"); -} - -static int frontend_android_get_rating(void) -{ - char device_model[PROP_VALUE_MAX] = {0}; - frontend_android_get_name(device_model, sizeof(device_model)); - - RARCH_LOG("ro.product.model: (%s).\n", device_model); - - if (device_is_xperia_play(device_model)) - return 6; - else if (!strcmp(device_model, "GT-I9505")) - return 12; - else if (!strcmp(device_model, "SHIELD")) - return 13; - return -1; -} - -#define ANDROID_ARCH_ARMV7 0x26257a91U -#define ANDROID_ARCH_ARM 0x406a3516U -#define ANDROID_ARCH_MIPS 0x7c9aa25eU -#define ANDROID_ARCH_X86 0x0b88b8cbU - -static enum frontend_architecture frontend_android_get_architecture(void) -{ - uint32_t abi_hash; - char abi[PROP_VALUE_MAX] = {0}; - system_property_get("ro.product.cpu.abi", abi); - - abi_hash = msg_hash_calculate(abi); - - switch (abi_hash) - { - case ANDROID_ARCH_ARMV7: - return FRONTEND_ARCH_ARM; - case ANDROID_ARCH_ARM: - return FRONTEND_ARCH_ARM; - case ANDROID_ARCH_MIPS: - return FRONTEND_ARCH_MIPS; - case ANDROID_ARCH_X86: - return FRONTEND_ARCH_X86; - } - - return FRONTEND_ARCH_NONE; -} - -static int frontend_android_parse_drive_list(void *data) -{ - file_list_t *list = (file_list_t*)data; - - // MENU_FILE_DIRECTORY is not working with labels, placeholders for now - menu_list_push(list, - app_dir, "Application Dir", MENU_FILE_DIRECTORY, 0, 0); - menu_list_push(list, - ext_dir, "External Application Dir", MENU_FILE_DIRECTORY, 0, 0); - menu_list_push(list, - sdcard_dir, "Internal Memory", MENU_FILE_DIRECTORY, 0, 0); - - menu_list_push(list, "/", "", - MENU_FILE_DIRECTORY, 0, 0); - - return 0; -} - -frontend_ctx_driver_t frontend_ctx_android = { - frontend_android_get_environment_settings, - frontend_android_init, - frontend_android_deinit, - NULL, /* exitspawn */ - NULL, /* process_args */ - NULL, /* exec */ - NULL, /* set_fork */ - frontend_android_shutdown, - frontend_android_get_name, - frontend_android_get_os, - frontend_android_get_rating, - NULL, /* load_content */ - frontend_android_get_architecture, - NULL, /* get_powerstate */ - frontend_android_parse_drive_list, - "android", -}; diff --git a/frontend/drivers/platform_linux.c b/frontend/drivers/platform_linux.c index 7f3c82fedf..3005e43e74 100644 --- a/frontend/drivers/platform_linux.c +++ b/frontend/drivers/platform_linux.c @@ -2,6 +2,7 @@ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * Copyright (C) 2011-2015 - Daniel De Matteis * Copyright (C) 2012-2015 - Jason Fetters + * 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- @@ -23,7 +24,7 @@ #include #include #include -#include /* PATH_MAX */ +#include #include #include @@ -31,10 +32,457 @@ #include #include +#include "../frontend.h" #include "../frontend_driver.h" #include "../../general.h" -#ifndef ANDROID +#ifdef ANDROID +#include "platform_android.h" + +#define SDCARD_ROOT_WRITABLE 1 +#define SDCARD_EXT_DIR_WRITABLE 2 +#define SDCARD_NOT_WRITABLE 3 + +struct android_app *g_android; +static pthread_key_t thread_key; + +char screenshot_dir[PATH_MAX_LENGTH]; +char downloads_dir[PATH_MAX_LENGTH]; +char apk_path[PATH_MAX_LENGTH]; +char sdcard_dir[PATH_MAX_LENGTH]; +char app_dir[PATH_MAX_LENGTH]; +char ext_dir[PATH_MAX_LENGTH]; + +/* forward declaration */ +bool android_run_events(void *data); + +static INLINE void android_app_write_cmd(void *data, 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)); +} + +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; + struct android_app* android_app = (struct android_app*)g_android; + int status = (*android_app->activity->vm)-> + AttachCurrentThread(android_app->activity->vm, &env, 0); + + if (status < 0) + { + RARCH_ERR("jni_thread_getenv: Failed to attach current thread.\n"); + return NULL; + } + pthread_setspecific(thread_key, (void*)env); + + return env; +} + +static void jni_thread_destruct(void *value) +{ + JNIEnv *env = (JNIEnv*)value; + struct android_app *android_app = (struct android_app*)g_android; + RARCH_LOG("jni_thread_destruct()\n"); + + if (!env) + return; + + if (android_app) + (*android_app->activity->vm)-> + DetachCurrentThread(android_app->activity->vm); + pthread_setspecific(thread_key, NULL); +} + +static void android_app_entry(void *data) +{ + char *argv[1]; + int argc = 0; + int ret = 0; + + if (rarch_main(argc, argv, data) != 0) + goto end; +#ifndef HAVE_MAIN + do + { + unsigned sleep_ms = 0; + ret = rarch_main_iterate(&sleep_ms); + + if (ret == 1 && sleep_ms > 0) + rarch_sleep(sleep_ms); + rarch_main_data_iterate(); + }while (ret != -1); + + main_exit(data); +#endif + +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)); + if (!android_app) + { + RARCH_ERR("Failed to initialize android_app\n"); + return; + } + + 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] = {0}; + char cmd[PATH_MAX_LENGTH] = {0}; + 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 *s, size_t len) +{ + system_property_get("ro.product.model", s); +} + +static void frontend_android_get_version(int32_t *major, + int32_t *minor, int32_t *rel) +{ + char os_version_str[PROP_VALUE_MAX] = {0}; + system_property_get("ro.build.version.release", os_version_str); + + *major = 0; + *minor = 0; + *rel = 0; + + /* Parse out the OS version numbers from the system properties. */ + if (os_version_str[0]) + { + /* Try to parse out the version numbers from the string. */ + int num_read = sscanf(os_version_str, "%d.%d.%d", major, minor, rel); + + if (num_read > 0) + { + if (num_read < 2) + *minor = 0; + if (num_read < 3) + *rel = 0; + return; + } + } +} + +static void frontend_android_get_version_sdk(int32_t *sdk) +{ + char os_version_str[PROP_VALUE_MAX] = {0}; + system_property_get("ro.build.version.sdk", os_version_str); + + *sdk = 0; + if (os_version_str[0]) + { + int num_read = sscanf(os_version_str, "%d", sdk); + (void) num_read; + } +} + +static bool device_is_xperia_play(const char *name) +{ + if ( + !strcmp(name, "R800x") || + !strcmp(name, "R800at") || + !strcmp(name, "R800i") || + !strcmp(name, "R800a") || + !strcmp(name, "SO-01D") + ) + return true; + + return false; +} + +static bool device_is_game_console(const char *name) +{ + if ( + !strcmp(name, "OUYA Console") || + device_is_xperia_play(name) || + !strcmp(name, "GAMEMID_BT") || + !strcmp(name, "S7800") || + !strcmp(name, "SHIELD") + ) + return true; + + return false; +} + +bool test_permissions(const char *path) +{ + char buf[PATH_MAX_LENGTH]; + bool ret; + + RARCH_LOG("Testing permissions for %s\n",path); + + fill_pathname_join(buf, path, ".retroarch", sizeof(buf)); + ret = path_mkdir(buf); + + RARCH_LOG("Create %s %s\n", buf, ret ? "true" : "false"); + + if(ret) + rmdir(buf); + + return ret; +} + +static void frontend_android_shutdown(bool unused) +{ + (void)unused; + /* Cleaner approaches don't work sadly. */ + exit(0); +} + +#else static const char *proc_apm_path = "/proc/apm"; static const char *proc_acpi_battery_path = "/proc/acpi/battery"; static const char *proc_acpi_sysfs_ac_adapter_path= "/sys/class/power_supply/ACAD"; @@ -499,6 +947,24 @@ error: } #endif +static int frontend_linux_get_rating(void) +{ +#ifdef ANDROID + char device_model[PROP_VALUE_MAX] = {0}; + frontend_android_get_name(device_model, sizeof(device_model)); + + RARCH_LOG("ro.product.model: (%s).\n", device_model); + + if (device_is_xperia_play(device_model)) + return 6; + else if (!strcmp(device_model, "GT-I9505")) + return 12; + else if (!strcmp(device_model, "SHIELD")) + return 13; +#endif + return -1; +} + static enum frontend_powerstate frontend_linux_get_powerstate(int *seconds, int *percent) { enum frontend_powerstate ret = FRONTEND_POWERSTATE_NONE; @@ -514,7 +980,7 @@ static enum frontend_powerstate frontend_linux_get_powerstate(int *seconds, int return ret; #endif - return FRONTEND_POWERSTATE_NONE; + return ret; } #define LINUX_ARCH_X86_64 0x23dea434U @@ -524,18 +990,35 @@ static enum frontend_powerstate frontend_linux_get_powerstate(int *seconds, int #define LINUX_ARCH_MIPS 0x7c9aa25eU #define LINUX_ARCH_TILE 0x7c9e7873U +#define ANDROID_ARCH_ARMV7 0x26257a91U +#define ANDROID_ARCH_ARM 0x406a3516U + static enum frontend_architecture frontend_linux_get_architecture(void) { uint32_t buffer_hash; + const char *val; +#ifdef ANDROID + char abi[PROP_VALUE_MAX] = {0}; + system_property_get("ro.product.cpu.abi", abi); + val = abi; +#else struct utsname buffer; if (uname(&buffer) != 0) return FRONTEND_ARCH_NONE; - buffer_hash = djb2_calculate(buffer.machine); + val = buffer.machine; +#endif + buffer_hash = djb2_calculate(val); switch (buffer_hash) { +#ifdef ANDROID + case ANDROID_ARCH_ARMV7: + return FRONTEND_ARCH_ARM; + case ANDROID_ARCH_ARM: + return FRONTEND_ARCH_ARM; +#endif case LINUX_ARCH_X86_64: return FRONTEND_ARCH_X86_64; case LINUX_ARCH_X86: @@ -555,7 +1038,12 @@ static enum frontend_architecture frontend_linux_get_architecture(void) static void frontend_linux_get_os(char *s, size_t len, int *major, int *minor) { -#ifndef ANDROID +#ifdef ANDROID + int rel; + frontend_android_get_version(major, minor, &rel); + + strlcpy(s, "Android", len); +#else unsigned krel; struct utsname buffer; @@ -570,79 +1058,604 @@ static void frontend_linux_get_os(char *s, size_t len, int *major, int *minor) static void frontend_linux_get_env(int *argc, char *argv[], void *data, void *params_data) { - char base_path[PATH_MAX]; - const char *xdg = getenv("XDG_CONFIG_HOME"); - const char *home = getenv("HOME"); +#ifdef ANDROID + int32_t major, minor, rel; + int perms = 0; + char device_model[PROP_VALUE_MAX] = {0}; + char device_id[PROP_VALUE_MAX] = {0}; + struct rarch_main_wrap *args = NULL; + JNIEnv *env = NULL; + jobject obj = NULL; + jstring jstr = NULL; + struct android_app *android_app = (struct android_app*)data; + char buf[PATH_MAX_LENGTH] = {0}; - if (xdg) - snprintf(base_path, sizeof(base_path), "%s/retroarch", xdg); - else if (home) - snprintf(base_path, sizeof(base_path), "%s/.config/retroarch", home); - else - snprintf(base_path, sizeof(base_path), "retroarch"); + if (!android_app) + return; - fill_pathname_join(g_defaults.dir.core, base_path, - "cores", sizeof(g_defaults.dir.core)); - fill_pathname_join(g_defaults.dir.core_info, base_path, - "cores", sizeof(g_defaults.dir.core_info)); - fill_pathname_join(g_defaults.dir.autoconfig, base_path, - "autoconf", sizeof(g_defaults.dir.autoconfig)); - fill_pathname_join(g_defaults.dir.assets, base_path, - "assets", sizeof(g_defaults.dir.assets)); - fill_pathname_join(g_defaults.dir.remap, base_path, - "remap", sizeof(g_defaults.dir.remap)); - fill_pathname_join(g_defaults.dir.playlist, base_path, - "playlists", sizeof(g_defaults.dir.playlist)); - fill_pathname_join(g_defaults.dir.cursor, base_path, - "database/cursors", sizeof(g_defaults.dir.cursor)); - fill_pathname_join(g_defaults.dir.database, base_path, - "database/rdb", sizeof(g_defaults.dir.database)); - fill_pathname_join(g_defaults.dir.shader, base_path, - "shaders", sizeof(g_defaults.dir.shader)); - fill_pathname_join(g_defaults.dir.cheats, base_path, - "cheats", sizeof(g_defaults.dir.cheats)); - fill_pathname_join(g_defaults.dir.overlay, base_path, - "overlay", sizeof(g_defaults.dir.overlay)); - fill_pathname_join(g_defaults.dir.osk_overlay, base_path, - "overlay", sizeof(g_defaults.dir.osk_overlay)); + env = jni_thread_getenv(); + if (!env) + return; - if(home) + args = (struct rarch_main_wrap*)params_data; + + if (args) { - fill_pathname_join(g_defaults.dir.screenshot, home, - "Pictures", sizeof(g_defaults.dir.screenshot)); - fill_pathname_join(g_defaults.dir.core_assets, home, - "Downloads", sizeof(g_defaults.dir.core_assets)); - } - else - { - fill_pathname_join(g_defaults.dir.screenshot, home, - "retroArch/screenshots", sizeof(g_defaults.dir.screenshot)); - fill_pathname_join(g_defaults.dir.core_assets, home, - "retroarch/downloads", sizeof(g_defaults.dir.core_assets)); + args->touched = true; + args->no_content = false; + args->verbose = false; + args->sram_path = NULL; + args->state_path = NULL; } - return; + frontend_android_get_version(&major, &minor, &rel); + + RARCH_LOG("Android OS version (major : %d, minor : %d, rel : %d)\n", + major, minor, rel); + + CALL_OBJ_METHOD(env, obj, android_app->activity->clazz, + android_app->getIntent); + RARCH_LOG("Checking arguments passed from intent ...\n"); + + /* Config file. */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "CONFIGFILE")); + + if (android_app->getStringExtra && jstr) + { + static char config_path[PATH_MAX_LENGTH] = {0}; + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + if (argv && *argv) + strlcpy(config_path, argv, sizeof(config_path)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + RARCH_LOG("Config file: [%s].\n", config_path); + if (args && *config_path) + args->config_path = config_path; + } + + /* Current IME. */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "IME")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + strlcpy(android_app->current_ime, argv, + sizeof(android_app->current_ime)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + RARCH_LOG("Current IME: [%s].\n", android_app->current_ime); + } + + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "USED")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + bool used = (!strcmp(argv, "false")) ? false : true; + + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + RARCH_LOG("USED: [%s].\n", used ? "true" : "false"); + } + + /* LIBRETRO. */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "LIBRETRO")); + + if (android_app->getStringExtra && jstr) + { + static char core_path[PATH_MAX_LENGTH]; + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *core_path = '\0'; + if (argv && *argv) + strlcpy(core_path, argv, sizeof(core_path)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + RARCH_LOG("Libretro path: [%s]\n", core_path); + if (args && *core_path) + args->libretro_path = core_path; + } + + /* Content. */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "ROM")); + + if (android_app->getStringExtra && jstr) + { + static char path[PATH_MAX_LENGTH]; + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *path = '\0'; + + if (argv && *argv) + strlcpy(path, argv, sizeof(path)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + if (*path) + { + RARCH_LOG("Auto-start game %s.\n", path); + if (args && *path) + args->content_path = path; + } + } + + /* External Storage */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "SDCARD")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *sdcard_dir = '\0'; + + if (argv && *argv) + strlcpy(sdcard_dir, argv, sizeof(sdcard_dir)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + if (*sdcard_dir) + { + RARCH_LOG("External storage location [%s]\n", sdcard_dir); + /* TODO base dir handler */ + } + } + + /* Screenshots */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "SCREENSHOTS")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *screenshot_dir = '\0'; + + if (argv && *argv) + strlcpy(screenshot_dir, argv, sizeof(screenshot_dir)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + if (*screenshot_dir) + { + RARCH_LOG("Picture folder location [%s]\n", screenshot_dir); + /* TODO: screenshot handler */ + } + } + + /* Downloads */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "DOWNLOADS")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *downloads_dir = '\0'; + + if (argv && *argv) + strlcpy(downloads_dir, argv, sizeof(downloads_dir)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + if (*downloads_dir) + { + RARCH_LOG("Download folder location [%s].\n", downloads_dir); + /* TODO: downloads handler */ + } + } + + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "APK")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *apk_path = '\0'; + + if (argv && *argv) + strlcpy(apk_path, argv, sizeof(apk_path)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + if (*apk_path) + { + RARCH_LOG("APK location [%s].\n", apk_path); + } + } + + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "EXTERNAL")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *ext_dir = '\0'; + + if (argv && *argv) + strlcpy(ext_dir, argv, sizeof(ext_dir)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + if (*ext_dir) + { + RARCH_LOG("External files location [%s]\n", ext_dir); + } + } + + /* Content. */ + CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, + (*env)->NewStringUTF(env, "DATADIR")); + + if (android_app->getStringExtra && jstr) + { + const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); + + *app_dir = '\0'; + + if (argv && *argv) + strlcpy(app_dir, argv, sizeof(app_dir)); + (*env)->ReleaseStringUTFChars(env, jstr, argv); + + //set paths depending on the ability to write to sdcard_dir + + if(*sdcard_dir) + { + if(test_permissions(sdcard_dir)) + perms = SDCARD_ROOT_WRITABLE; + } + else if(*ext_dir) + { + if(test_permissions(ext_dir)) + perms = SDCARD_EXT_DIR_WRITABLE; + } + else + perms = SDCARD_NOT_WRITABLE; + + RARCH_LOG("SD permissions: %d",perms); + + if (*app_dir) + { + RARCH_LOG("Application location: [%s].\n", app_dir); + if (args && *app_dir) + { + fill_pathname_join(g_defaults.dir.assets, app_dir, + "assets", sizeof(g_defaults.dir.assets)); + fill_pathname_join(g_defaults.dir.extraction, app_dir, + "tmp", sizeof(g_defaults.dir.extraction)); + fill_pathname_join(g_defaults.dir.shader, app_dir, + "shaders", sizeof(g_defaults.dir.shader)); + fill_pathname_join(g_defaults.dir.overlay, app_dir, + "overlays", sizeof(g_defaults.dir.overlay)); + fill_pathname_join(g_defaults.dir.osk_overlay, app_dir, + "overlays", sizeof(g_defaults.dir.osk_overlay)); + fill_pathname_join(g_defaults.dir.core, app_dir, + "cores", sizeof(g_defaults.dir.core)); + fill_pathname_join(g_defaults.dir.core_info, + app_dir, "info", sizeof(g_defaults.dir.core_info)); + fill_pathname_join(g_defaults.dir.autoconfig, + app_dir, "autoconfig", sizeof(g_defaults.dir.autoconfig)); + fill_pathname_join(g_defaults.dir.audio_filter, + app_dir, "audio_filters", sizeof(g_defaults.dir.audio_filter)); + fill_pathname_join(g_defaults.dir.video_filter, + app_dir, "video_filters", sizeof(g_defaults.dir.video_filter)); + strlcpy(g_defaults.dir.content_history, + app_dir, sizeof(g_defaults.dir.content_history)); + fill_pathname_join(g_defaults.dir.database, + app_dir, "database/rdb", sizeof(g_defaults.dir.database)); + fill_pathname_join(g_defaults.dir.cursor, + app_dir, "database/cursors", sizeof(g_defaults.dir.cursor)); + fill_pathname_join(g_defaults.dir.cheats, + app_dir, "cheats", sizeof(g_defaults.dir.cheats)); + fill_pathname_join(g_defaults.dir.playlist, + app_dir, "playlists", sizeof(g_defaults.dir.playlist)); + fill_pathname_join(g_defaults.dir.remap, + app_dir, "remaps", sizeof(g_defaults.dir.remap)); + fill_pathname_join(g_defaults.dir.wallpapers, + app_dir, "wallpapers", sizeof(g_defaults.dir.wallpapers)); + if(*downloads_dir && test_permissions(downloads_dir)) + { + fill_pathname_join(g_defaults.dir.core_assets, + downloads_dir, "", sizeof(g_defaults.dir.core_assets)); + } + else + { + fill_pathname_join(g_defaults.dir.core_assets, + app_dir, "downloads", sizeof(g_defaults.dir.core_assets)); + path_mkdir(g_defaults.dir.core_assets); + } + + RARCH_LOG("Default download folder: [%s]", g_defaults.dir.core_assets); + + if(*screenshot_dir && test_permissions(screenshot_dir)) + { + fill_pathname_join(g_defaults.dir.screenshot, + screenshot_dir, "", sizeof(g_defaults.dir.screenshot)); + } + else + { + fill_pathname_join(g_defaults.dir.screenshot, + app_dir, "screenshots", sizeof(g_defaults.dir.screenshot)); + path_mkdir(g_defaults.dir.screenshot); + } + + RARCH_LOG("Default screenshot folder: [%s]", g_defaults.dir.screenshot); + + switch (perms) + { + case SDCARD_EXT_DIR_WRITABLE: + fill_pathname_join(g_defaults.dir.sram, + ext_dir, "saves", sizeof(g_defaults.dir.sram)); + path_mkdir(g_defaults.dir.sram); + + fill_pathname_join(g_defaults.dir.savestate, + ext_dir, "states", sizeof(g_defaults.dir.savestate)); + path_mkdir(g_defaults.dir.savestate); + + fill_pathname_join(g_defaults.dir.system, + ext_dir, "system", sizeof(g_defaults.dir.system)); + path_mkdir(g_defaults.dir.system); + break; + case SDCARD_NOT_WRITABLE: + fill_pathname_join(g_defaults.dir.sram, + app_dir, "saves", sizeof(g_defaults.dir.sram)); + path_mkdir(g_defaults.dir.sram); + fill_pathname_join(g_defaults.dir.savestate, + app_dir, "states", sizeof(g_defaults.dir.savestate)); + path_mkdir(g_defaults.dir.savestate); + fill_pathname_join(g_defaults.dir.system, + app_dir, "system", sizeof(g_defaults.dir.system)); + path_mkdir(g_defaults.dir.system); + break; + case SDCARD_ROOT_WRITABLE: + default: + break; + } + + /* create save and system directories in the internal dir too */ + fill_pathname_join(buf, + app_dir, "saves", sizeof(buf)); + path_mkdir(buf); + + fill_pathname_join(buf, + app_dir, "states", sizeof(buf)); + path_mkdir(buf); + + fill_pathname_join(buf, + app_dir, "system", sizeof(buf)); + path_mkdir(buf); + + /* create save and system directories in the internal sd too */ + + fill_pathname_join(buf, + ext_dir, "saves", sizeof(buf)); + path_mkdir(buf); + + fill_pathname_join(buf, + ext_dir, "states", sizeof(buf)); + path_mkdir(buf); + + fill_pathname_join(buf, + ext_dir, "system", sizeof(buf)); + path_mkdir(buf); + + RARCH_LOG("Default savefile folder: [%s]", g_defaults.dir.sram); + RARCH_LOG("Default savestate folder: [%s]", g_defaults.dir.savestate); + RARCH_LOG("Default system folder: [%s]", g_defaults.dir.system); + } + } + } + + frontend_android_get_name(device_model, sizeof(device_model)); + system_property_get("ro.product.id", device_id); + + g_defaults.settings.video_threaded_enable = true; + + /* Set automatic default values per device */ + if (device_is_xperia_play(device_model)) + { + g_defaults.settings.out_latency = 128; + g_defaults.settings.video_refresh_rate = 59.19132938771038; + g_defaults.settings.video_threaded_enable = false; + } + else if (!strcmp(device_model, "GAMEMID_BT")) + g_defaults.settings.out_latency = 160; + else if (!strcmp(device_model, "SHIELD")) + g_defaults.settings.video_refresh_rate = 60.0; + else if (!strcmp(device_model, "JSS15J")) + g_defaults.settings.video_refresh_rate = 59.65; + +#if 0 + /* Explicitly disable input overlay by default + * for gamepad-like/console devices. */ + if (device_is_game_console(device_model)) + g_defaults.settings.input_overlay_enable = false; +#endif +#else + char base_path[PATH_MAX]; + const char *xdg = getenv("XDG_CONFIG_HOME"); + const char *home = getenv("HOME"); + + if (xdg) + snprintf(base_path, sizeof(base_path), "%s/retroarch", xdg); + else if (home) + snprintf(base_path, sizeof(base_path), "%s/.config/retroarch", home); + else + snprintf(base_path, sizeof(base_path), "retroarch"); + + fill_pathname_join(g_defaults.dir.core, base_path, + "cores", sizeof(g_defaults.dir.core)); + fill_pathname_join(g_defaults.dir.core_info, base_path, + "cores", sizeof(g_defaults.dir.core_info)); + fill_pathname_join(g_defaults.dir.autoconfig, base_path, + "autoconf", sizeof(g_defaults.dir.autoconfig)); + fill_pathname_join(g_defaults.dir.assets, base_path, + "assets", sizeof(g_defaults.dir.assets)); + fill_pathname_join(g_defaults.dir.remap, base_path, + "remap", sizeof(g_defaults.dir.remap)); + fill_pathname_join(g_defaults.dir.playlist, base_path, + "playlists", sizeof(g_defaults.dir.playlist)); + fill_pathname_join(g_defaults.dir.cursor, base_path, + "database/cursors", sizeof(g_defaults.dir.cursor)); + fill_pathname_join(g_defaults.dir.database, base_path, + "database/rdb", sizeof(g_defaults.dir.database)); + fill_pathname_join(g_defaults.dir.shader, base_path, + "shaders", sizeof(g_defaults.dir.shader)); + fill_pathname_join(g_defaults.dir.cheats, base_path, + "cheats", sizeof(g_defaults.dir.cheats)); + fill_pathname_join(g_defaults.dir.overlay, base_path, + "overlay", sizeof(g_defaults.dir.overlay)); + fill_pathname_join(g_defaults.dir.osk_overlay, base_path, + "overlay", sizeof(g_defaults.dir.osk_overlay)); + + if(home) + { + fill_pathname_join(g_defaults.dir.screenshot, home, + "Pictures", sizeof(g_defaults.dir.screenshot)); + fill_pathname_join(g_defaults.dir.core_assets, home, + "Downloads", sizeof(g_defaults.dir.core_assets)); + } + else + { + fill_pathname_join(g_defaults.dir.screenshot, home, + "retroArch/screenshots", sizeof(g_defaults.dir.screenshot)); + fill_pathname_join(g_defaults.dir.core_assets, home, + "retroarch/downloads", sizeof(g_defaults.dir.core_assets)); + } +#endif } +static void frontend_linux_deinit(void *data) +{ +#ifdef ANDROID + JNIEnv *env = NULL; + struct android_app *android_app = (struct android_app*)data; + + if (!android_app) + return; + + RARCH_LOG("Deinitializing RetroArch ...\n"); + android_app->activityState = APP_CMD_DEAD; + + env = jni_thread_getenv(); + + if (env && android_app->onRetroArchExit) + CALL_VOID_METHOD(env, android_app->activity->clazz, + android_app->onRetroArchExit); + + if (android_app->inputQueue) + { + RARCH_LOG("Detaching Android input queue looper ...\n"); + AInputQueue_detachLooper(android_app->inputQueue); + } +#endif +} + +static void frontend_linux_init(void *data) +{ +#ifdef ANDROID + JNIEnv *env = NULL; + ALooper *looper = NULL; + jclass class = NULL; + jobject obj = NULL; + struct android_app* android_app = (struct android_app*)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; + + slock_lock(android_app->mutex); + android_app->running = 1; + scond_broadcast(android_app->cond); + slock_unlock(android_app->mutex); + + memset(&g_android, 0, sizeof(g_android)); + g_android = (struct android_app*)android_app; + + RARCH_LOG("Waiting for Android Native Window to be initialized ...\n"); + + while (!android_app->window) + { + if (!android_run_events(android_app)) + { + frontend_linux_deinit(android_app); + frontend_android_shutdown(android_app); + return; + } + } + + RARCH_LOG("Android Native Window initialized.\n"); + + env = jni_thread_getenv(); + if (!env) + return; + + GET_OBJECT_CLASS(env, class, android_app->activity->clazz); + GET_METHOD_ID(env, android_app->getIntent, class, + "getIntent", "()Landroid/content/Intent;"); + GET_METHOD_ID(env, android_app->onRetroArchExit, class, + "onRetroArchExit", "()V"); + CALL_OBJ_METHOD(env, obj, android_app->activity->clazz, + android_app->getIntent); + + GET_OBJECT_CLASS(env, class, obj); + GET_METHOD_ID(env, android_app->getStringExtra, class, + "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;"); +#endif +} + +#ifdef ANDROID +static int frontend_android_parse_drive_list(void *data) +{ + file_list_t *list = (file_list_t*)data; + + // MENU_FILE_DIRECTORY is not working with labels, placeholders for now + menu_list_push(list, + app_dir, "Application Dir", MENU_FILE_DIRECTORY, 0, 0); + menu_list_push(list, + ext_dir, "External Application Dir", MENU_FILE_DIRECTORY, 0, 0); + menu_list_push(list, + sdcard_dir, "Internal Memory", MENU_FILE_DIRECTORY, 0, 0); + + menu_list_push(list, "/", "", + MENU_FILE_DIRECTORY, 0, 0); + + return 0; +} +#endif + frontend_ctx_driver_t frontend_ctx_linux = { frontend_linux_get_env, /* environment_get */ - NULL, /* init */ - NULL, /* deinit */ + frontend_linux_init, /* init */ + frontend_linux_deinit, /* deinit */ NULL, /* exitspawn */ NULL, /* process_args */ NULL, /* exec */ NULL, /* set_fork */ +#ifdef ANDROID + frontend_android_shutdown, /* shutdown */ + frontend_android_get_name, /* get_name */ +#else NULL, /* shutdown */ NULL, /* get_name */ +#endif frontend_linux_get_os, - NULL, /* get_rating */ + frontend_linux_get_rating, /* get_rating */ NULL, /* load_content */ frontend_linux_get_architecture, frontend_linux_get_powerstate, - NULL, /* parse_drive_list */ #ifdef ANDROID + frontend_android_parse_drive_list, /* parse_drive_list */ "android", #else + NULL, /* parse_drive_list */ "linux", #endif }; diff --git a/frontend/frontend_driver.c b/frontend/frontend_driver.c index 97dd6411e4..508a55a730 100644 --- a/frontend/frontend_driver.c +++ b/frontend/frontend_driver.c @@ -38,10 +38,7 @@ static frontend_ctx_driver_t *frontend_ctx_drivers[] = { #if defined(__APPLE__) && defined(__MACH__) &frontend_ctx_darwin, #endif -#if defined(ANDROID) - &frontend_ctx_android, -#endif -#if defined(__linux__) && !defined(ANDROID) +#if defined(__linux__) &frontend_ctx_linux, #endif #if defined(PSP) || defined(VITA) diff --git a/griffin/griffin.c b/griffin/griffin.c index 0d39b62289..8b1f610538 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -636,9 +636,7 @@ FRONTEND #include "../frontend/drivers/platform_xenon.c" #elif defined(__QNX__) #include "../frontend/drivers/platform_qnx.c" -#elif defined(ANDROID) -#include "../frontend/drivers/platform_android.c" -#elif defined(__linux__) && !defined(ANDROID) +#elif defined(__linux__) #include "../frontend/drivers/platform_linux.c" #endif #include "../frontend/drivers/platform_null.c"