From a0c53668e6a85e59c4a80a3b4e8c95e78cd6e2e5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 4 Oct 2018 16:29:17 -0700 Subject: [PATCH] Allow SDL to use ReLinker if present. This fixes issues for applications that have a large number of shared libraries For more information, see https://github.com/KeepSafe/ReLinker for ReLinker's repository. --- .../app/HIDDeviceBLESteamController.java | 2 +- .../java/org/libsdl/app/HIDDeviceManager.java | 6 +-- .../app/src/main/java/org/libsdl/app/SDL.java | 47 +++++++++++++++++++ .../main/java/org/libsdl/app/SDLActivity.java | 2 +- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java index bd9de1954..0ab226957 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java @@ -577,7 +577,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe } // We need to skip the first byte, as that doesn't go over the air - byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1); + byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1); //Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(actual_report)); writeCharacteristic(reportCharacteristic, actual_report); return report.length; diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index 33ddb7120..ba30d0a01 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -80,14 +80,14 @@ public class HIDDeviceManager { public HIDDeviceManager(Context context) { mContext = context; - // Make sure we have the HIDAPI library loaded with the native functions + // Make sure we have the HIDAPI library loaded with the native functions try { - System.loadLibrary("hidapi"); + SDL.loadLibrary("hidapi"); } catch (Exception e) { Log.w(TAG, "Couldn't load hidapi: " + e.toString()); return; } - + HIDDeviceRegisterCallback(this); mSharedPreferences = mContext.getSharedPreferences("hidapi", Context.MODE_PRIVATE); diff --git a/android-project/app/src/main/java/org/libsdl/app/SDL.java b/android-project/app/src/main/java/org/libsdl/app/SDL.java index cfe483094..58597c655 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDL.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDL.java @@ -2,6 +2,8 @@ package org.libsdl.app; import android.content.Context; +import java.lang.reflect.*; + /** SDL library initialization */ @@ -33,5 +35,50 @@ public class SDL { return mContext; } + public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException { + + if (libraryName == null) { + throw new NullPointerException("No library name provided."); + } + + try { + // Let's see if we have ReLinker available in the project. This is necessary for + // some projects that have huge numbers of local libraries bundled, and thus may + // trip a bug in Android's native library loader which ReLinker works around. (If + // loadLibrary works properly, ReLinker will simply use the normal Android method + // internally.) + // + // To use ReLinker, just add it as a dependency. For more information, see + // https://github.com/KeepSafe/ReLinker for ReLinker's repository. + // + Class relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker"); + Class relinkListenerClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener"); + Class contextClass = mContext.getClassLoader().loadClass("android.content.Context"); + Class stringClass = mContext.getClassLoader().loadClass("java.lang.String"); + + // Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if + // they've changed during updates. + Method forceMethod = relinkClass.getDeclaredMethod("force"); + Object relinkInstance = forceMethod.invoke(null); + Class relinkInstanceClass = relinkInstance.getClass(); + + // Actually load the library! + Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass); + loadMethod.invoke(relinkInstance, mContext, libraryName, null, null); + } + catch (final Exception e) { + // Fall back + try { + System.loadLibrary(libraryName); + } + catch (final UnsatisfiedLinkError ule) { + throw ule; + } + catch (final SecurityException se) { + throw se; + } + } + } + protected static Context mContext; } diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index c53970f64..67cb3a387 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -154,7 +154,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh // Load the .so public void loadLibraries() { for (String lib : getLibraries()) { - System.loadLibrary(lib); + SDL.loadLibrary(lib); } }