From d30d4cb008ebf586556de9de406477647b86fc8a Mon Sep 17 00:00:00 2001 From: qimiko <25387744+qimiko@users.noreply.github.com> Date: Sun, 7 Jan 2024 22:01:36 -0700 Subject: [PATCH] found a better way to load libraries --- app/src/main/cpp/CMakeLists.txt | 2 - app/src/main/cpp/launcher-fix.cpp | 33 ---------- .../geode/launcher/GeometryDashActivity.kt | 64 ++++++++----------- .../java/com/geode/launcher/LauncherFix.kt | 2 - 4 files changed, 25 insertions(+), 76 deletions(-) diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 5bf8e297..f79757f1 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -23,5 +23,3 @@ if(NOT dobby_POPULATED) target_include_directories(launcherfix PRIVATE ${dobby_SOURCE_DIR}/include) target_link_libraries(launcherfix dobby) endif() - -target_link_libraries(launcherfix log) \ No newline at end of file diff --git a/app/src/main/cpp/launcher-fix.cpp b/app/src/main/cpp/launcher-fix.cpp index 580c3fa4..245b4e9b 100644 --- a/app/src/main/cpp/launcher-fix.cpp +++ b/app/src/main/cpp/launcher-fix.cpp @@ -1,9 +1,6 @@ -#include -#include #include #include #include -#include #ifndef DISABLE_LAUNCHER_FIX #include @@ -51,36 +48,6 @@ JNIEXPORT void JNICALL Java_com_geode_launcher_LauncherFix_setOriginalDataPath( env->ReleaseStringUTFChars(data_path, data_path_str); } -extern "C" -JNIEXPORT jboolean JNICALL Java_com_geode_launcher_LauncherFix_loadLibraryFromOffset(JNIEnv *env, jobject, jstring library_name, jint fd, jlong offset) { - // loads a given library at an offset and file descriptor - // assumes we have ownership of the file passed in fd - - auto is_copy = jboolean(); - auto library_cname = env->GetStringUTFChars(library_name, &is_copy); - - android_dlextinfo ext_info{}; - ext_info.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET; - ext_info.library_fd = fd; - ext_info.library_fd_offset = offset; - - auto handle = android_dlopen_ext(library_cname, RTLD_NOW | RTLD_GLOBAL, &ext_info); - env->ReleaseStringUTFChars(library_name, library_cname); - close(fd); - - if (handle == nullptr) { - auto error = dlerror(); - __android_log_print(ANDROID_LOG_WARN, "GeodeLauncher-Fix", "dlopen_ext failed. given: %s\n", error); - - return false; - } - - // we don't need the library anymore - dlclose(handle); - - return true; -} - std::string redirect_path(const char* pathname) { auto data_path = DataPaths::get_instance().data_path; auto original_data_path = DataPaths::get_instance().original_data_path; diff --git a/app/src/main/java/com/geode/launcher/GeometryDashActivity.kt b/app/src/main/java/com/geode/launcher/GeometryDashActivity.kt index 0c281f33..be9292b7 100644 --- a/app/src/main/java/com/geode/launcher/GeometryDashActivity.kt +++ b/app/src/main/java/com/geode/launcher/GeometryDashActivity.kt @@ -2,15 +2,14 @@ package com.geode.launcher import android.annotation.SuppressLint import android.content.BroadcastReceiver -import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.pm.ActivityInfo +import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo import android.os.Build import android.os.Bundle import android.os.Environment -import android.os.FileUtils import android.util.Log import android.view.View import android.view.ViewGroup @@ -118,22 +117,33 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL @SuppressLint("UnsafeDynamicallyLoadedCode") private fun tryLoadLibrary(packageInfo: PackageInfo, libraryName: String) { - try { - val nativeDir = packageInfo.applicationInfo.nativeLibraryDir - System.load("$nativeDir/lib$libraryName.so") - } catch (ule: UnsatisfiedLinkError) { - loadLibraryFromAssets(libraryName) - } + val nativeDir = getNativeLibraryDirectory(packageInfo.applicationInfo) + System.load("$nativeDir/lib$libraryName.so") } - private fun loadLibraryFromAssets(libraryName: String) { - // for split apks, loads a library stored inside of the apk - // maybe todo: is there really no way to load these libraries without weird workarounds? - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - loadLibraryFromAssetsNative(libraryName) - } else { - loadLibraryFromAssetsCopy(libraryName) + private fun getNativeLibraryDirectory(applicationInfo: ApplicationInfo): String { + // native libraries have been extracted, so the path is same as usual + if (applicationInfo.flags and ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS == ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) { + return applicationInfo.nativeLibraryDir } + + // might be split apks, select the best path for the library + val sourceDirs = applicationInfo.splitSourceDirs + val architecture = LaunchUtils.getApplicationArchitecture() + + if (!sourceDirs.isNullOrEmpty()) { + val configAbi = architecture.replace("-", "_") + val abiDir = sourceDirs.find { it.contains(configAbi) } + + if (abiDir != null) { + return "$abiDir!/lib/$architecture/" + } + } + + // this configuration should never happen! + // non split apk, but libraries are stored in apk + val sourceDir = applicationInfo.sourceDir + return "$sourceDir!/lib/$architecture/" } @SuppressLint("UnsafeDynamicallyLoadedCode") @@ -159,30 +169,6 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL return } - private fun loadLibraryFromAssetsNative(libraryName: String) { - // loads a library loaded in assets (which points to the apk + an offset) - // these libraries are available to the application after merging - - val arch = LaunchUtils.getApplicationArchitecture() - val libraryFd = try { - assets.openNonAssetFd("lib/$arch/lib$libraryName.so") - } catch (_: Exception) { - throw UnsatisfiedLinkError("Could not find library lib$libraryName.so for abi $arch") - } - - val fdOffset = libraryFd.startOffset - val fdDescriptor = libraryFd.parcelFileDescriptor.detachFd() - - if (!LauncherFix.loadLibraryFromOffset("lib$libraryName.so", fdDescriptor, fdOffset)) { - throw UnsatisfiedLinkError("Failed to load asset lib$libraryName.so") - } - - // after the library is opened in native code, it should be available for loading - // you can read more about the behavior (added in android 11): - // https://android.googlesource.com/platform/libcore/+/7f3eb2e0ac87bdea471bc577380cf50025aebde5/ojluni/src/main/java/java/lang/Runtime.java#1060 - System.loadLibrary(libraryName) - } - @SuppressLint("UnsafeDynamicallyLoadedCode") private fun loadGeodeLibrary(): Boolean { // Load Geode if exists diff --git a/app/src/main/java/com/geode/launcher/LauncherFix.kt b/app/src/main/java/com/geode/launcher/LauncherFix.kt index 2394a649..b117ebd8 100644 --- a/app/src/main/java/com/geode/launcher/LauncherFix.kt +++ b/app/src/main/java/com/geode/launcher/LauncherFix.kt @@ -10,6 +10,4 @@ object LauncherFix { external fun setDataPath(dataPath: String) external fun setOriginalDataPath(dataPath: String) - - external fun loadLibraryFromOffset(libraryName: String, fd: Int, offset: Long): Boolean } \ No newline at end of file