static void frontend_android_init(void *data) { JNIEnv *env; ALooper *looper; 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;"); CALL_OBJ_METHOD(env, obj, android_app->activity->clazz, android_app->getIntent); #if 0 GET_METHOD_ID(env, android_app->hasPendingIntent, class, "hasPendingIntent", "()Z"); GET_METHOD_ID(env, android_app->clearPendingIntent, class, "clearPendingIntent", "()V"); GET_METHOD_ID(env, android_app->getPendingIntentConfigPath, class, "getPendingIntentConfigPath", "()Ljava/lang/String;"); GET_METHOD_ID(env, android_app->getPendingIntentLibretroPath, class, "getPendingIntentLibretroPath", "()Ljava/lang/String;"); GET_METHOD_ID(env, android_app->getPendingIntentFullPath, class, "getPendingIntentFullPath", "()Ljava/lang/String;"); GET_METHOD_ID(env, android_app->getPendingIntentIME, class, "getPendingIntentIME", "()Ljava/lang/String;"); #endif GET_OBJECT_CLASS(env, class, obj); GET_METHOD_ID(env, android_app->getStringExtra, class, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;"); }
static void jni_get (void *data_in, void *data_out) { struct jni_params *in_params = (struct jni_params*)data_in; struct jni_out_params_char *out_args = (struct jni_out_params_char*)data_out; char obj_method_name[128]; char obj_method_signature[128]; jclass class_ptr = NULL; jobject obj = NULL; jmethodID giid = NULL; jstring ret_char; snprintf(obj_method_name, sizeof(obj_method_name), "getStringExtra"); snprintf(obj_method_signature, sizeof(obj_method_signature), "(Ljava/lang/String;)Ljava/lang/String;"); GET_OBJECT_CLASS(in_params->env, class_ptr, in_params->class_obj); GET_METHOD_ID(in_params->env, giid, class_ptr, in_params->method_name, in_params->method_signature); CALL_OBJ_METHOD(in_params->env, obj, in_params->class_obj, giid); GET_OBJECT_CLASS(in_params->env, class_ptr, obj); GET_METHOD_ID(in_params->env, giid, class_ptr, obj_method_name, obj_method_signature); CALL_OBJ_METHOD_PARAM(in_params->env, ret_char, obj, giid, (*in_params->env)->NewStringUTF(in_params->env, out_args->in)); if (giid != NULL && ret_char) { const char *test_argv = (*in_params->env)->GetStringUTFChars(in_params->env, ret_char, 0); strncpy(out_args->out, test_argv, out_args->out_sizeof); (*in_params->env)->ReleaseStringUTFChars(in_params->env, ret_char, test_argv); } }
static void input_autodetect_get_device_name(void *data, char *buf, size_t size, int id) { struct android_app *android_app = (struct android_app*)data; buf[0] = '\0'; JavaVM *vm = android_app->activity->vm; JNIEnv *env = NULL; (*vm)->AttachCurrentThread(vm, &env, 0); jclass input_device_class = NULL; FIND_CLASS(env, input_device_class, "android/view/InputDevice"); if (!input_device_class) goto end; jmethodID method = NULL; GET_STATIC_METHOD_ID(env, method, input_device_class, "getDevice", "(I)Landroid/view/InputDevice;"); if (!method) goto end; jobject device = NULL; CALL_OBJ_STATIC_METHOD_PARAM(env, device, input_device_class, method, (jint)id); if (!device) { RARCH_ERR("Failed to find device for ID: %d\n", id); goto end; } jmethodID getName = NULL; GET_METHOD_ID(env, getName, input_device_class, "getName", "()Ljava/lang/String;"); if (!getName) goto end; jobject name = NULL; CALL_OBJ_METHOD(env, name, device, getName); if (!name) { RARCH_ERR("Failed to find name for device ID: %d\n", id); goto end; } const char *str = (*env)->GetStringUTFChars(env, name, 0); if (str) strlcpy(buf, str, size); (*env)->ReleaseStringUTFChars(env, name, str); end: (*vm)->DetachCurrentThread(vm); }
static void frontend_android_get_environment_settings(int *argc, char *argv[], void *data, void *params_data) { static char config_path[PATH_MAX]; static char core_path[PATH_MAX]; static char path[PATH_MAX]; JNIEnv *env; jobject obj = NULL; jstring jstr = NULL; struct android_app* android_app = (struct android_app*)data; if (!android_app) return; env = jni_thread_getenv(); if (!env) return; struct rarch_main_wrap *args = (struct rarch_main_wrap*)params_data; if (args) { args->touched = true; args->no_rom = false; args->verbose = false; args->sram_path = NULL; args->state_path = NULL; } 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")); *config_path = '\0'; if (android_app->getStringExtra && jstr) { 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") == 0) ? 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")); *core_path = '\0'; if (android_app->getStringExtra && jstr) { const char *argv = (*env)->GetStringUTFChars(env, jstr, 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")); *path = '\0'; if (android_app->getStringExtra && jstr) { const char *argv = (*env)->GetStringUTFChars(env, jstr, 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->rom_path = path; } } }
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 = NULL; 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 = NULL; *core_path = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *path = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *sdcard_dir = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *screenshot_dir = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *downloads_dir = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *apk_path = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *ext_dir = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *app_dir = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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.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_get_environment_settings(int *argc, char *argv[], void *data, void *params_data) { int32_t major, minor, rel; 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; 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 = NULL; 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 = NULL; *core_path = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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 = NULL; *path = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 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; } } /* Content. */ CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, (*env)->NewStringUTF(env, "DATADIR")); if (android_app->getStringExtra && jstr) { static char path[PATH_MAX_LENGTH]; const char *argv = NULL; *path = '\0'; argv = (*env)->GetStringUTFChars(env, jstr, 0); if (argv && *argv) strlcpy(path, argv, sizeof(path)); (*env)->ReleaseStringUTFChars(env, jstr, argv); if (*path) { RARCH_LOG("Data path: [%s].\n", path); if (args && *path) { fill_pathname_join(g_defaults.assets_dir, path, "assets", sizeof(g_defaults.savestate_dir)); fill_pathname_join(g_defaults.extraction_dir, path, "tmp", sizeof(g_defaults.extraction_dir)); fill_pathname_join(g_defaults.shader_dir, path, "shaders_glsl", sizeof(g_defaults.shader_dir)); fill_pathname_join(g_defaults.overlay_dir, path, "overlays", sizeof(g_defaults.overlay_dir)); fill_pathname_join(g_defaults.core_dir, path, "cores", sizeof(g_defaults.core_dir)); fill_pathname_join(g_defaults.core_info_dir, path, "info", sizeof(g_defaults.core_info_dir)); fill_pathname_join(g_defaults.autoconfig_dir, path, "autoconfig", sizeof(g_defaults.autoconfig_dir)); fill_pathname_join(g_defaults.audio_filter_dir, path, "audio_filters", sizeof(g_defaults.audio_filter_dir)); fill_pathname_join(g_defaults.video_filter_dir, path, "video_filters", sizeof(g_defaults.video_filter_dir)); strlcpy(g_defaults.content_history_dir, path, sizeof(g_defaults.content_history_dir)); fill_pathname_join(g_defaults.database_dir, path, "database/rdb", sizeof(g_defaults.database_dir)); fill_pathname_join(g_defaults.cursor_dir, path, "database/cursors", sizeof(g_defaults.cursor_dir)); fill_pathname_join(g_defaults.cheats_dir, path, "cheats", sizeof(g_defaults.cheats_dir)); fill_pathname_join(g_defaults.playlist_dir, path, "playlists", sizeof(g_defaults.playlist_dir)); fill_pathname_join(g_defaults.remap_dir, path, "remaps", sizeof(g_defaults.remap_dir)); fill_pathname_join(g_defaults.wallpapers_dir, path, "wallpapers", sizeof(g_defaults.wallpapers_dir)); fill_pathname_join(g_defaults.core_assets_dir, path, "downloads", sizeof(g_defaults.core_assets_dir)); } } } 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; /* FIXME - needs to be refactored */ #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_get_environment_settings(int *argc, char *argv[], void *data, void *params_data) { char device_model[PROP_VALUE_MAX], device_id[PROP_VALUE_MAX]; JNIEnv *env; jobject obj = NULL; jstring jstr = NULL; struct android_app* android_app = (struct android_app*)data; if (!android_app) return; env = jni_thread_getenv(); if (!env) return; struct rarch_main_wrap *args = (struct rarch_main_wrap*)params_data; if (args) { args->touched = true; args->no_rom = false; args->verbose = false; args->sram_path = NULL; args->state_path = NULL; } 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]; *config_path = '\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") == 0) ? 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]; *core_path = '\0'; const char *argv = (*env)->GetStringUTFChars(env, jstr, 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]; *path = '\0'; const char *argv = (*env)->GetStringUTFChars(env, jstr, 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->rom_path = path; } } // Content CALL_OBJ_METHOD_PARAM(env, jstr, obj, android_app->getStringExtra, (*env)->NewStringUTF(env, "DATADIR")); if (android_app->getStringExtra && jstr) { static char path[PATH_MAX]; *path = '\0'; const char *argv = (*env)->GetStringUTFChars(env, jstr, 0); if (argv && *argv) strlcpy(path, argv, sizeof(path)); (*env)->ReleaseStringUTFChars(env, jstr, argv); if (*path) { RARCH_LOG("Data path: [%s].\n", path); if (args && *path) { fill_pathname_join(g_defaults.savestate_dir, path, "savestates", sizeof(g_defaults.savestate_dir)); fill_pathname_join(g_defaults.sram_dir, path, "savefiles", sizeof(g_defaults.sram_dir)); fill_pathname_join(g_defaults.system_dir, path, "system", sizeof(g_defaults.system_dir)); } } } frontend_android_get_name(device_model, sizeof(device_model)); __system_property_get("ro.product.id", device_id); g_defaults.settings.video_threaded_enable = true; g_defaults.settings.input_overlay_enable = true; // Enable input overlay by default // 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; // 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; }