forked from geode-sdk/android-launcher
found a better way to load libraries
This commit is contained in:
4 files changed
+24
-75
No files matched your search
@@ -23,5 +23,3 @@ if(NOT dobby_POPULATED)
|
|||||||
target_include_directories(launcherfix PRIVATE ${dobby_SOURCE_DIR}/include)
|
target_include_directories(launcherfix PRIVATE ${dobby_SOURCE_DIR}/include)
|
||||||
target_link_libraries(launcherfix dobby)
|
target_link_libraries(launcherfix dobby)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(launcherfix log)
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
#include <android/dlext.h>
|
|
||||||
#include <android/log.h>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifndef DISABLE_LAUNCHER_FIX
|
#ifndef DISABLE_LAUNCHER_FIX
|
||||||
#include <dobby.h>
|
#include <dobby.h>
|
||||||
@@ -51,36 +48,6 @@ JNIEXPORT void JNICALL Java_com_geode_launcher_LauncherFix_setOriginalDataPath(
|
|||||||
env->ReleaseStringUTFChars(data_path, data_path_str);
|
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) {
|
std::string redirect_path(const char* pathname) {
|
||||||
auto data_path = DataPaths::get_instance().data_path;
|
auto data_path = DataPaths::get_instance().data_path;
|
||||||
auto original_data_path = DataPaths::get_instance().original_data_path;
|
auto original_data_path = DataPaths::get_instance().original_data_path;
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ package com.geode.launcher
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.FileUtils
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -118,22 +117,33 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
|
|
||||||
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
||||||
private fun tryLoadLibrary(packageInfo: PackageInfo, libraryName: String) {
|
private fun tryLoadLibrary(packageInfo: PackageInfo, libraryName: String) {
|
||||||
try {
|
val nativeDir = getNativeLibraryDirectory(packageInfo.applicationInfo)
|
||||||
val nativeDir = packageInfo.applicationInfo.nativeLibraryDir
|
|
||||||
System.load("$nativeDir/lib$libraryName.so")
|
System.load("$nativeDir/lib$libraryName.so")
|
||||||
} catch (ule: UnsatisfiedLinkError) {
|
}
|
||||||
loadLibraryFromAssets(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/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadLibraryFromAssets(libraryName: String) {
|
// this configuration should never happen!
|
||||||
// for split apks, loads a library stored inside of the apk
|
// non split apk, but libraries are stored in apk
|
||||||
// maybe todo: is there really no way to load these libraries without weird workarounds?
|
val sourceDir = applicationInfo.sourceDir
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
return "$sourceDir!/lib/$architecture/"
|
||||||
loadLibraryFromAssetsNative(libraryName)
|
|
||||||
} else {
|
|
||||||
loadLibraryFromAssetsCopy(libraryName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
||||||
@@ -159,30 +169,6 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
return
|
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")
|
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
||||||
private fun loadGeodeLibrary(): Boolean {
|
private fun loadGeodeLibrary(): Boolean {
|
||||||
// Load Geode if exists
|
// Load Geode if exists
|
||||||
|
|||||||
@@ -10,6 +10,4 @@ object LauncherFix {
|
|||||||
external fun setDataPath(dataPath: String)
|
external fun setDataPath(dataPath: String)
|
||||||
|
|
||||||
external fun setOriginalDataPath(dataPath: String)
|
external fun setOriginalDataPath(dataPath: String)
|
||||||
|
|
||||||
external fun loadLibraryFromOffset(libraryName: String, fd: Int, offset: Long): Boolean
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user