Skip to content

Commit

Permalink
found a better way to load libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
qimiko committed Jan 8, 2024
1 parent c3c1962 commit d30d4cb
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 76 deletions.
2 changes: 0 additions & 2 deletions app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
33 changes: 0 additions & 33 deletions app/src/main/cpp/launcher-fix.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#include <android/dlext.h>
#include <android/log.h>
#include <dlfcn.h>
#include <jni.h>
#include <string>
#include <unistd.h>

#ifndef DISABLE_LAUNCHER_FIX
#include <dobby.h>
Expand Down Expand Up @@ -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;
Expand Down
64 changes: 25 additions & 39 deletions app/src/main/java/com/geode/launcher/GeometryDashActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand All @@ -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
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/java/com/geode/launcher/LauncherFix.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit d30d4cb

Please sign in to comment.