From 4c1ea0e4215e243f142e05b3fcd9f0c0e477928d Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 17 Apr 2021 22:14:54 -0700 Subject: [PATCH] Update stub implementation Prevent some potential issues --- .../com/topjohnwu/magisk/ClassLoaders.java | 6 ++- .../magisk/DelegateComponentFactory.java | 4 +- .../java/com/topjohnwu/magisk/InjectAPK.java | 48 ++++++++++++------- .../java/com/topjohnwu/magisk/Mapping.java | 3 -- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java b/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java index 512416b7e..381f283b7 100644 --- a/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java +++ b/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java @@ -4,10 +4,12 @@ import com.topjohnwu.magisk.utils.DynamicClassLoader; import java.io.File; -class InjectedClassLoader extends DynamicClassLoader { +// Wrap the actual classloader as we only want to resolve classname +// mapping when loading from platform (via LoadedApk.mClassLoader) +class InjectedClassLoader extends ClassLoader { InjectedClassLoader(File apk) { - super(apk); + super(new DynamicClassLoader(apk)); } @Override diff --git a/stub/src/main/java/com/topjohnwu/magisk/DelegateComponentFactory.java b/stub/src/main/java/com/topjohnwu/magisk/DelegateComponentFactory.java index 05cf0027a..d191b822c 100644 --- a/stub/src/main/java/com/topjohnwu/magisk/DelegateComponentFactory.java +++ b/stub/src/main/java/com/topjohnwu/magisk/DelegateComponentFactory.java @@ -12,12 +12,11 @@ import android.content.Intent; @SuppressLint("NewApi") public class DelegateComponentFactory extends AppComponentFactory { - static DelegateComponentFactory INSTANCE; ClassLoader loader; AppComponentFactory receiver; public DelegateComponentFactory() { - INSTANCE = this; + InjectAPK.componentFactory = this; } @Override @@ -53,7 +52,6 @@ public class DelegateComponentFactory extends AppComponentFactory { @Override public ContentProvider instantiateProvider(ClassLoader cl, String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException { - if (loader == null) loader = cl; if (receiver != null) return receiver.instantiateProvider(loader, className); return create(className); diff --git a/stub/src/main/java/com/topjohnwu/magisk/InjectAPK.java b/stub/src/main/java/com/topjohnwu/magisk/InjectAPK.java index 483625064..eaab4d9fb 100644 --- a/stub/src/main/java/com/topjohnwu/magisk/InjectAPK.java +++ b/stub/src/main/java/com/topjohnwu/magisk/InjectAPK.java @@ -5,6 +5,8 @@ import android.app.Application; import android.content.ContentResolver; import android.content.Context; import android.content.ContextWrapper; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.util.Log; @@ -17,6 +19,12 @@ import java.lang.reflect.Field; public class InjectAPK { + static Object componentFactory; + + private static DelegateComponentFactory getComponentFactory() { + return (DelegateComponentFactory) componentFactory; + } + @SuppressWarnings("ResultOfMethodCallIgnored") static Application setup(Context context) { // Get ContextImpl @@ -28,7 +36,6 @@ public class InjectAPK { File update = DynAPK.update(context); if (update.exists()) update.renameTo(apk); - Application result = null; if (!apk.exists()) { // Try copying APK Uri uri = new Uri.Builder().scheme("content") @@ -48,42 +55,47 @@ public class InjectAPK { } if (apk.exists()) { ClassLoader cl = new InjectedClassLoader(apk); + PackageManager pm = context.getPackageManager(); + ApplicationInfo info = pm.getPackageArchiveInfo(apk.getPath(), 0).applicationInfo; try { // Create the receiver Application - Object app = cl.loadClass(Mapping.get("APP")).getConstructor(Object.class) + Object app = cl.loadClass(info.className) + .getConstructor(Object.class) .newInstance(DynAPK.pack(dynData())); // Create the receiver component factory Object factory = null; if (Build.VERSION.SDK_INT >= 28) { - factory = cl.loadClass(Mapping.get("ACF")).newInstance(); + factory = cl.loadClass(info.appComponentFactory).newInstance(); } setClassLoader(context, cl); // Finally, set variables - result = (Application) app; if (Build.VERSION.SDK_INT >= 28) { - DelegateComponentFactory.INSTANCE.loader = cl; - DelegateComponentFactory.INSTANCE.receiver = (AppComponentFactory) factory; + getComponentFactory().loader = cl; + getComponentFactory().receiver = (AppComponentFactory) factory; } + + return (Application) app; } catch (Exception e) { Log.e(InjectAPK.class.getSimpleName(), "", e); apk.delete(); } - } else { - ClassLoader cl = new RedirectClassLoader(); - try { - setClassLoader(context, cl); - if (Build.VERSION.SDK_INT >= 28) { - DelegateComponentFactory.INSTANCE.loader = cl; - } - } catch (Exception e) { - // Should never happen - Log.e(InjectAPK.class.getSimpleName(), "", e); - } + // fallthrough } - return result; + + ClassLoader cl = new RedirectClassLoader(); + try { + setClassLoader(context, cl); + if (Build.VERSION.SDK_INT >= 28) { + getComponentFactory().loader = cl; + } + } catch (Exception e) { + Log.e(InjectAPK.class.getSimpleName(), "", e); + } + + return null; } // Replace LoadedApk mClassLoader diff --git a/stub/src/main/java/com/topjohnwu/magisk/Mapping.java b/stub/src/main/java/com/topjohnwu/magisk/Mapping.java index 8bdbe389f..1f4e17be3 100644 --- a/stub/src/main/java/com/topjohnwu/magisk/Mapping.java +++ b/stub/src/main/java/com/topjohnwu/magisk/Mapping.java @@ -34,9 +34,6 @@ public class Mapping { for (Map.Entry e : map.entrySet()) { inverseMap.put(e.getValue(), e.getKey()); } - - map.put("APP", "com.topjohnwu.magisk.core.App"); - map.put("ACF", "androidx.core.app.CoreComponentFactory"); } public static String get(String name) {