Use AppComponentFactoryStub to instantiate LSPApplication and original application
This commit is contained in:
parent
ed6eaec32c
commit
8cbf468d59
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<br/>
|
||||
* This method will be called at <b>instantiateClassLoader</b> by <b>createOrUpdateClassLoaderLocked</b>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue