diff --git a/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java b/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java index 68d9b5e..9ece125 100644 --- a/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java +++ b/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java @@ -116,9 +116,6 @@ public class LSPApplication extends ApplicationServiceClient { } catch (Throwable e) { Log.e(TAG, "Do hook", e); } - if (isApplicationProxied()) { - instance.createOriginalApplication(); - } } public static void disableProfile(Context context) { @@ -265,17 +262,7 @@ public class LSPApplication extends ApplicationServiceClient { try { Object mBoundApplication = XposedHelpers.getObjectField(getActivityThread(), "mBoundApplication"); Object loadedApkObj = XposedHelpers.getObjectField(mBoundApplication, "info"); - var mClassLoader = (ClassLoader) XposedHelpers.getObjectField(loadedApkObj, "mClassLoader"); - - final String cacheApkPath = context.getCacheDir().getAbsolutePath() + "/origin_apk.bin"; - try (InputStream inputStream = context.getAssets().open("origin_apk.bin")) { - Files.copy(inputStream, Paths.get(cacheApkPath)); - } catch (FileAlreadyExistsException ignored) { - } - appClassLoader = new PathClassLoader(cacheApkPath, mClassLoader.getParent()); - XposedHelpers.setObjectField(loadedApkObj, "mClassLoader", appClassLoader); - - Log.d(TAG, "appClassLoader is now switched to " + appClassLoader); + appClassLoader = (ClassLoader) XposedHelpers.getObjectField(loadedApkObj, "mClassLoader"); } catch (Throwable e) { Log.e(TAG, "initAppClassLoader", e); } diff --git a/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPAppComponentFactoryStub.java b/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPAppComponentFactoryStub.java index 317ff49..97d34dc 100644 --- a/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPAppComponentFactoryStub.java +++ b/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPAppComponentFactoryStub.java @@ -23,13 +23,21 @@ import dalvik.system.PathClassLoader; @SuppressLint("NewApi") public class LSPAppComponentFactoryStub extends AppComponentFactory { private static final String TAG = "LSPatch"; + private static final String PROXY_APPLICATION = "org.lsposed.lspatch.appstub.LSPApplicationStub"; private static final String ORIGINAL_APK_ASSET_PATH = "assets/origin_apk.bin"; private static final String ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH = "assets/original_app_component_factory.ini"; + private ClassLoader appClassLoader = null; + private ClassLoader baseClassLoader = null; private AppComponentFactory originalAppComponentFactory = null; - // Proxy appComponentFactory to load the original one - private void initOrigin(ClassLoader cl, ApplicationInfo aInfo) { + /** + * Instantiate original AppComponentFactory
+ * This method will be called at instantiateClassLoader by createOrUpdateClassLoaderLocked + * + * @param cl PathClassLoader(originalApk) + **/ + private void initOriginalAppComponentFactory(ClassLoader cl, ApplicationInfo aInfo) { final String cacheApkPath = aInfo.dataDir + "/cache/origin_apk.bin"; final String originalAppComponentFactoryClass = FileUtils.readTextFromInputStream(cl.getResourceAsStream(ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH)); @@ -38,22 +46,27 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory { Files.copy(inputStream, Paths.get(cacheApkPath)); } catch (FileAlreadyExistsException ignored) { } - ClassLoader appClassLoader = new PathClassLoader(cacheApkPath, cl.getParent()); - originalAppComponentFactory = (AppComponentFactory) appClassLoader.loadClass(originalAppComponentFactoryClass).newInstance(); - Log.d(TAG, "appComponentFactory is now switched to " + originalAppComponentFactory); + appClassLoader = new PathClassLoader(cacheApkPath, cl.getParent()); + if (originalAppComponentFactoryClass == null || originalAppComponentFactoryClass.isEmpty()) + originalAppComponentFactory = new AppComponentFactory(); + else + originalAppComponentFactory = (AppComponentFactory) appClassLoader.loadClass(originalAppComponentFactoryClass).newInstance(); + Log.d(TAG, "Instantiate original AppComponentFactory: " + originalAppComponentFactory); } catch (Throwable e) { - Log.e(TAG, "initOrigin", e); + Log.e(TAG, "initOriginalAppComponentFactory", e); } } @Override public ClassLoader instantiateClassLoader(ClassLoader cl, ApplicationInfo aInfo) { - if (originalAppComponentFactory == null) initOrigin(cl, aInfo); - return originalAppComponentFactory.instantiateClassLoader(cl, aInfo); + baseClassLoader = cl; + initOriginalAppComponentFactory(cl, aInfo); + return originalAppComponentFactory.instantiateClassLoader(appClassLoader, aInfo); } @Override public Application instantiateApplication(ClassLoader cl, String className) throws IllegalAccessException, InstantiationException, ClassNotFoundException { + baseClassLoader.loadClass(PROXY_APPLICATION).newInstance(); return originalAppComponentFactory.instantiateApplication(cl, className); } diff --git a/build.gradle b/build.gradle index 4c88de4..20af5bf 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:7.0.0-beta04' + classpath 'com.android.tools.build:gradle:7.0.0-beta05' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32" } } diff --git a/patch/src/main/java/org/lsposed/patch/LSPatch.java b/patch/src/main/java/org/lsposed/patch/LSPatch.java index d9c451d..0be4f6c 100644 --- a/patch/src/main/java/org/lsposed/patch/LSPatch.java +++ b/patch/src/main/java/org/lsposed/patch/LSPatch.java @@ -94,7 +94,6 @@ public class LSPatch { )); private static JCommander jCommander; - private boolean hasAppComponentFactory; public static void main(String... args) throws IOException { LSPatch lsPatch = new LSPatch(); @@ -193,8 +192,7 @@ public class LSPatch { if (triple == null) throw new PatchError("Failed to parse AndroidManifest.xml"); String applicationName = triple.applicationName == null ? "" : triple.applicationName; - String appComponentFactory = triple.appComponentFactory; - hasAppComponentFactory = appComponentFactory != null; + String appComponentFactory = triple.appComponentFactory == null ? "" : triple.appComponentFactory; if (verbose) { System.out.println("original application name: " + applicationName); @@ -210,12 +208,11 @@ public class LSPatch { } // save original appComponentFactory name to asset file even its empty - if (appComponentFactory != null) - try (var is = new ByteArrayInputStream(appComponentFactory.getBytes(StandardCharsets.UTF_8))) { - zFile.add(APP_COMPONENT_FACTORY_ASSET_PATH, is); - } catch (Throwable e) { - throw new PatchError("Error when saving appComponentFactory class: " + e); - } + try (var is = new ByteArrayInputStream(appComponentFactory.getBytes(StandardCharsets.UTF_8))) { + zFile.add(APP_COMPONENT_FACTORY_ASSET_PATH, is); + } catch (Throwable e) { + throw new PatchError("Error when saving appComponentFactory class: " + e); + } // save original main application name to asset file even its empty try (var is = new ByteArrayInputStream(applicationName.getBytes(StandardCharsets.UTF_8))) { @@ -350,9 +347,8 @@ public class LSPatch { ModificationProperty property = new ModificationProperty(); property.addApplicationAttribute(new AttributeItem(NodeValue.Application.DEBUGGABLE, debuggableFlag)); - property.addApplicationAttribute(new AttributeItem(NodeValue.Application.NAME, PROXY_APPLICATION)); - if (hasAppComponentFactory) - property.addApplicationAttribute(new AttributeItem("appComponentFactory", PROXY_APP_COMPONENT_FACTORY)); + //property.addApplicationAttribute(new AttributeItem(NodeValue.Application.NAME, PROXY_APPLICATION)); + property.addApplicationAttribute(new AttributeItem("appComponentFactory", PROXY_APP_COMPONENT_FACTORY)); var os = new ByteArrayOutputStream(); (new ManifestEditor(is, os, property)).processManifest();