diff --git a/app_pojavlauncher/src/main/jni/input_bridge_v3.c b/app_pojavlauncher/src/main/jni/input_bridge_v3.c index 04a1a1854..3dfd0cc36 100644 --- a/app_pojavlauncher/src/main/jni/input_bridge_v3.c +++ b/app_pojavlauncher/src/main/jni/input_bridge_v3.c @@ -60,6 +60,7 @@ jint JNI_OnLoad(JavaVM* vm, __attribute__((unused)) void* reserved) { jobject mouseDownBufferJ = (*pojav_environ->runtimeJNIEnvPtr_JRE)->GetStaticObjectField(pojav_environ->runtimeJNIEnvPtr_JRE, pojav_environ->vmGlfwClass, field_mouseDownBuffer); pojav_environ->mouseDownBuffer = (*pojav_environ->runtimeJNIEnvPtr_JRE)->GetDirectBufferAddress(pojav_environ->runtimeJNIEnvPtr_JRE, mouseDownBufferJ); hookExec(); + installLinkerBugMitigation(); } if(pojav_environ->dalvikJavaVMPtr == vm) { @@ -252,6 +253,46 @@ void hookExec() { printf("Registered forkAndExec\n"); } +/** + * Basically a verbatim implementation of ndlopen(), found at + * https://github.com/PojavLauncherTeam/lwjgl3/blob/3.3.1/modules/lwjgl/core/src/generated/c/linux/org_lwjgl_system_linux_DynamicLinkLoader.c#L11 + * The idea is that since, on Android 10 and earlier, the linker doesn't really do namespace nesting. + * It is not a problem as most of the libraries are in the launcher path, but when you try to run + * VulkanMod which loads shaderc outside of the default jni libs directory through this method, + * it can't load it because the path is not in the allowed paths for the anonymous namesapce. + * This method fixes the issue by being in libpojavexec, and thus being in the classloader namespace + */ +jlong ndlopen_bugfix(__attribute__((unused)) JNIEnv *env, + __attribute__((unused)) jclass class, + jlong filename_ptr, + jint jmode) { + const char* filename = (const char*) filename_ptr; + int mode = (int)jmode; + return (jlong) dlopen(filename, mode); +} + +/** + * Install the linker bug mitigation for Android 10 and lower. Fixes VulkanMod crashing on these + * Android versions due to missing namespace nesting. + */ +void installLinkerBugMitigation() { + if(android_get_device_api_level() >= 30) return; + __android_log_print(ANDROID_LOG_INFO, "Api29LinkerFix", "API < 30 detected, installing linker bug mitigation"); + JNIEnv* env = pojav_environ->runtimeJNIEnvPtr_JRE; + jclass dynamicLinkLoader = (*env)->FindClass(env, "org/lwjgl/system/linux/DynamicLinkLoader"); + if(dynamicLinkLoader == NULL) { + __android_log_print(ANDROID_LOG_ERROR, "Api29LinkerFix", "Failed to find the target class"); + (*env)->ExceptionClear(env); + return; + } + JNINativeMethod ndlopenMethod[] = { + {"ndlopen", "(JI)J", &ndlopen_bugfix} + }; + if((*env)->RegisterNatives(env, dynamicLinkLoader, ndlopenMethod, 1) != 0) { + __android_log_print(ANDROID_LOG_ERROR, "Api29LinkerFix", "Failed to register the bugfix method"); + (*env)->ExceptionClear(env); + } +} void critical_set_stackqueue(jboolean use_input_stack_queue) { pojav_environ->isUseStackQueueCall = (int) use_input_stack_queue; diff --git a/app_pojavlauncher/src/main/jni/utils.h b/app_pojavlauncher/src/main/jni/utils.h index 46f7b2bf4..ed2acbf8e 100644 --- a/app_pojavlauncher/src/main/jni/utils.h +++ b/app_pojavlauncher/src/main/jni/utils.h @@ -10,5 +10,6 @@ void free_char_array(JNIEnv *env, jobjectArray jstringArray, const char **charAr jstring convertStringJVM(JNIEnv* srcEnv, JNIEnv* dstEnv, jstring srcStr); void hookExec(); +void installLinkerBugMitigation(); JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jbyteArray copySrc);