diff --git a/app/build.gradle b/app/build.gradle
index 9667815..d2b4a48 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -21,6 +21,12 @@ android {
}
}
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+
}
buildTypes {
debug {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f79a64d..81d756b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,19 +6,22 @@
-
+
+
+
-
\ No newline at end of file
+
diff --git a/app/src/main/assets/xposed_init b/app/src/main/assets/xposed_init
index 441393b..dfc7ee8 100644
--- a/app/src/main/assets/xposed_init
+++ b/app/src/main/assets/xposed_init
@@ -1 +1 @@
-org.lsposed.lspatch.tester.Hook
\ No newline at end of file
+org.lsposed.org.lsposed.org.lsposed.lspatch.tester.Hook
diff --git a/app/src/main/java/de/robv/android/xposed/XposedHelper.java b/app/src/main/java/de/robv/android/xposed/XposedHelper.java
index 3ba39ad..6536513 100644
--- a/app/src/main/java/de/robv/android/xposed/XposedHelper.java
+++ b/app/src/main/java/de/robv/android/xposed/XposedHelper.java
@@ -1,9 +1,5 @@
package de.robv.android.xposed;
-import de.robv.android.xposed.IXposedHookZygoteInit;
-import de.robv.android.xposed.IXposedMod;
-import de.robv.android.xposed.XC_MethodHook;
-
import java.lang.reflect.Member;
public class XposedHelper {
diff --git a/app/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java b/app/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java
new file mode 100644
index 0000000..a3b4e9c
--- /dev/null
+++ b/app/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java
@@ -0,0 +1,36 @@
+package org.lsposed.lspatch.appstub;
+
+import android.app.Application;
+import android.content.Context;
+
+import java.io.ByteArrayOutputStream;
+
+public class LSPApplicationStub extends Application {
+
+ private static byte[] dex = null;
+
+ static {
+ try (var is = LSPApplicationStub.class.getClassLoader().getResourceAsStream("assets/lsp");
+ var os = new ByteArrayOutputStream()) {
+ byte[] buffer = new byte[8192];
+ int n;
+ while (-1 != (n = is.read(buffer))) {
+ os.write(buffer, 0, n);
+ }
+ dex = os.toByteArray();
+ } catch (Throwable e) {
+ android.util.Log.e("LSPatch", "load dex error", e);
+ }
+ System.loadLibrary("lspd");
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ }
+}
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 2621519..5ecff1c 100644
--- a/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java
+++ b/app/src/main/java/org/lsposed/lspatch/loader/LSPApplication.java
@@ -17,6 +17,7 @@ import org.lsposed.lspatch.loader.util.FileUtils;
import org.lsposed.lspatch.loader.util.XLog;
import org.lsposed.lspatch.loader.util.XpatchUtils;
import org.lsposed.lspatch.share.Constants;
+import org.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
import org.lsposed.lspd.nativebridge.SigBypass;
import org.lsposed.lspd.yahfa.hooker.YahfaHooker;
@@ -40,7 +41,8 @@ import de.robv.android.xposed.XposedInit;
public class LSPApplication {
private static final String ORIGINAL_APPLICATION_NAME_ASSET_PATH = "original_application_name.ini";
private static final String ORIGINAL_SIGNATURE_ASSET_PATH = "original_signature_info.ini";
- private static final String TAG = LSPApplication.class.getSimpleName();
+ private static final String TAG = "LSPatch";
+
private static String originalApplicationName = null;
private static String originalSignature = null;
private static Application sOriginalApplication = null;
@@ -49,51 +51,43 @@ public class LSPApplication {
private static int TRANSACTION_getPackageInfo_ID = -1;
- final static public int FIRST_ISOLATED_UID = 99000;
- final static public int LAST_ISOLATED_UID = 99999;
final static public int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
- final static public int LAST_APP_ZYGOTE_ISOLATED_UID = 98999;
- final static public int SHARED_RELRO_UID = 1037;
final static public int PER_USER_RANGE = 100000;
- static Context context;
+ final static private LSPApplication instance = new LSPApplication();
static public boolean isIsolated() {
- int uid = android.os.Process.myUid();
- uid = uid % PER_USER_RANGE;
- return (uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID) || (uid >= FIRST_APP_ZYGOTE_ISOLATED_UID && uid <= LAST_APP_ZYGOTE_ISOLATED_UID);
+ return (android.os.Process.myUid() % PER_USER_RANGE) >= FIRST_APP_ZYGOTE_ISOLATED_UID;
}
- static {
+ static public void onLoad() {
cacheSigbypassLv = -1;
if (isIsolated()) {
XLog.d(TAG, "skip isolated process");
+ return;
}
- else {
- context = XpatchUtils.createAppContext();
- if (context == null) {
- XLog.e(TAG, "create context err");
- }
- else {
- System.load(context.getApplicationInfo().nativeLibraryDir + "/liblspd.so");
- YahfaHooker.init();
- XposedInit.startsSystemServer = false;
+ Context context = XpatchUtils.createAppContext();
+ if (context == null) {
+ XLog.e(TAG, "create context err");
+ return;
+ }
+ YahfaHooker.init();
+ XposedBridge.initXResources();
+ PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
+ XposedInit.startsSystemServer = false;
- originalApplicationName = FileUtils.readTextFromAssets(context, ORIGINAL_APPLICATION_NAME_ASSET_PATH);
- originalSignature = FileUtils.readTextFromAssets(context, ORIGINAL_SIGNATURE_ASSET_PATH);
+ originalApplicationName = FileUtils.readTextFromAssets(context, ORIGINAL_APPLICATION_NAME_ASSET_PATH);
+ originalSignature = FileUtils.readTextFromAssets(context, ORIGINAL_SIGNATURE_ASSET_PATH);
- XLog.d(TAG, "original application class " + originalApplicationName);
- XLog.d(TAG, "original signature info " + originalSignature);
+ XLog.d(TAG, "original application class " + originalApplicationName);
+ XLog.d(TAG, "original signature info " + originalSignature);
- try {
- doHook();
- initAndLoadModules(context);
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
+ try {
+ doHook(context);
+ initAndLoadModules(context);
+ } catch (Throwable e) {
+ Log.e(TAG, "Do hook", e);
}
}
@@ -106,12 +100,7 @@ public class LSPApplication {
}
private static boolean isApplicationProxied() {
- if (originalApplicationName != null && !originalApplicationName.isEmpty() && !("android.app.Application").equals(originalApplicationName)) {
- return true;
- }
- else {
- return false;
- }
+ return originalApplicationName != null && !originalApplicationName.isEmpty() && !("android.app.Application").equals(originalApplicationName);
}
private static ClassLoader getAppClassLoader() {
@@ -122,14 +111,13 @@ public class LSPApplication {
Object mBoundApplication = XposedHelpers.getObjectField(getActivityThread(), "mBoundApplication");
Object loadedApkObj = XposedHelpers.getObjectField(mBoundApplication, "info");
appClassLoader = (ClassLoader) XposedHelpers.callMethod(loadedApkObj, "getClassLoader");
- }
- catch (Exception e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "getAppClassLoader", e);
}
return appClassLoader;
}
- private static void byPassSignature() throws ClassNotFoundException, IllegalAccessException {
+ private static void byPassSignature(Context context) throws ClassNotFoundException, IllegalAccessException {
Field[] pmStubFields = Class.forName("android.content.pm.IPackageManager$Stub").getDeclaredFields();
for (Field field : pmStubFields) {
if (!Modifier.isStatic(field.getModifiers()) || field.getType() != int.class) {
@@ -203,25 +191,26 @@ public class LSPApplication {
// reset pos
out.setDataPosition(0);
}
- }
- catch (Throwable err) {
+ } catch (Throwable err) {
err.printStackTrace();
}
}
});
}
- private static void doHook() throws IllegalAccessException, ClassNotFoundException, IOException {
+ private static void doHook(Context context) throws IllegalAccessException, ClassNotFoundException, IOException {
if (isApplicationProxied()) {
hookContextImplSetOuterContext();
hookInstallContentProviders();
hookActivityAttach();
hookServiceAttach();
}
- if (fetchSigbypassLv() >= Constants.SIGBYPASS_LV_PM) {
- byPassSignature();
+ hookApplicationStub();
+ int bypassLv = fetchSigbypassLv(context);
+ if (bypassLv >= Constants.SIGBYPASS_LV_PM) {
+ byPassSignature(context);
}
- if (fetchSigbypassLv() >= Constants.SIGBYPASS_LV_PM_OPENAT) {
+ if (bypassLv >= Constants.SIGBYPASS_LV_PM_OPENAT) {
File apk = new File(context.getCacheDir(), "lspatchapk.so");
if (!apk.exists()) {
try (InputStream inputStream = context.getAssets().open("origin_apk.bin");
@@ -241,7 +230,7 @@ public class LSPApplication {
private static int cacheSigbypassLv;
- private static int fetchSigbypassLv() {
+ private static int fetchSigbypassLv(Context context) {
if (cacheSigbypassLv != -1) {
return cacheSigbypassLv;
}
@@ -249,48 +238,82 @@ public class LSPApplication {
try (InputStream inputStream = context.getAssets().open(Constants.CONFIG_NAME_SIGBYPASSLV + i)) {
cacheSigbypassLv = i;
return i;
- }
- catch (IOException ignore) {
+ } catch (IOException ignore) {
}
}
- throw new IllegalStateException(Constants.CONFIG_NAME_SIGBYPASSLV + " err");
+ return 0;
+ }
+
+ private static void hookApplicationStub() {
+ try {
+ Class> appStub = XposedHelpers.findClass("org.lsposed.lspatch.appstub.LSPApplicationStub", getAppClassLoader());
+ XposedHelpers.findAndHookMethod(appStub, "onCreate", new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ instance.onCreate();
+ }
+ });
+ XposedHelpers.findAndHookMethod(appStub, "attachBaseContext", Context.class, new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ instance.attachBaseContext((Context) param.args[0]);
+ }
+ });
+ } catch (Throwable e) {
+ Log.e(TAG, "hookApplicationStub");
+ }
}
private static void hookContextImplSetOuterContext() {
- XposedHelpers.findAndHookMethod("android.app.ContextImpl", getAppClassLoader(), "setOuterContext", Context.class, new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) throws Throwable {
- replaceApplicationParam(param.args);
- // XposedHelpers.setObjectField(param.thisObject, "mOuterContext", sOriginalApplication);
- }
- });
+ try {
+ XposedHelpers.findAndHookMethod("android.app.ContextImpl", getAppClassLoader(), "setOuterContext", Context.class, new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ replaceApplicationParam(param.args);
+ }
+ });
+ } catch (Throwable e) {
+ Log.e(TAG, "hookContextImplSetOuterContext", e);
+ }
}
private static void hookInstallContentProviders() {
- XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.ActivityThread", getAppClassLoader()), "installContentProviders", new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- replaceApplicationParam(param.args);
- }
- });
+ try {
+ XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.ActivityThread", getAppClassLoader()), "installContentProviders", new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ replaceApplicationParam(param.args);
+ }
+ });
+ } catch (Throwable e) {
+ Log.e(TAG, "hookInstallContextProviders", e);
+ }
}
private static void hookActivityAttach() {
- XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Activity", getAppClassLoader()), "attach", new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- replaceApplicationParam(param.args);
- }
- });
+ try {
+ XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Activity", getAppClassLoader()), "attach", new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ replaceApplicationParam(param.args);
+ }
+ });
+ } catch (Throwable e) {
+ Log.e(TAG, "hookActivityAttach", e);
+ }
}
private static void hookServiceAttach() {
- XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Service", getAppClassLoader()), "attach", new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- replaceApplicationParam(param.args);
- }
- });
+ try {
+ XposedBridge.hookAllMethods(XposedHelpers.findClass("android.app.Service", getAppClassLoader()), "attach", new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ replaceApplicationParam(param.args);
+ }
+ });
+ } catch (Throwable e) {
+ Log.e(TAG, "hookServiceAttach", e);
+ }
}
private static void replaceApplicationParam(Object[] args) {
@@ -309,9 +332,8 @@ public class LSPApplication {
try {
Class> activityThreadClass = Class.forName("android.app.ActivityThread");
activityThread = XposedHelpers.callStaticMethod(activityThreadClass, "currentActivityThread");
- }
- catch (Exception e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "getActivityThread", e);
}
}
return activityThread;
@@ -328,29 +350,23 @@ public class LSPApplication {
private void attachOrignalBaseContext(Context base) {
try {
XposedHelpers.callMethod(sOriginalApplication, "attachBaseContext", base);
- }
- catch (Exception e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "attachOriginalBaseContext", e);
}
}
private void setLoadedApkField(Context base) {
- // mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
try {
Class> contextImplClass = Class.forName("android.app.ContextImpl");
Object contextImpl = XposedHelpers.callStaticMethod(contextImplClass, "getImpl", base);
Object loadedApk = XposedHelpers.getObjectField(contextImpl, "mPackageInfo");
XposedHelpers.setObjectField(sOriginalApplication, "mLoadedApk", loadedApk);
- }
- catch (Exception e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "setLoadedApkField", e);
}
}
public void onCreate() {
- // setLoadedApkField(sOriginalApplication);
- // XposedHelpers.setObjectField(sOriginalApplication, "mLoadedApk", XposedHelpers.getObjectField(this, "mLoadedApk"));
-
if (isApplicationProxied()) {
// replaceApplication();
replaceLoadedApkApplication();
@@ -371,18 +387,16 @@ public class LSPApplication {
// replace LoadedApk.java makeApplication() mApplication = app;
XposedHelpers.setObjectField(loadedApkObj, "mApplication", sOriginalApplication);
- }
- catch (Exception e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "replaceLoadedApkApplication", e);
}
}
private void replaceActivityThreadApplication() {
try {
XposedHelpers.setObjectField(getActivityThread(), "mInitialApplication", sOriginalApplication);
- }
- catch (Exception e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "replaceActivityThreadApplication", e);
}
}
@@ -390,9 +404,8 @@ public class LSPApplication {
if (sOriginalApplication == null) {
try {
sOriginalApplication = (Application) getAppClassLoader().loadClass(originalApplicationName).newInstance();
- }
- catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "createOriginalApplication", e);
}
}
return sOriginalApplication;
@@ -404,9 +417,8 @@ public class LSPApplication {
Object applicationInfoObj = XposedHelpers.getObjectField(mBoundApplication, "appInfo"); // info
XposedHelpers.setObjectField(applicationInfoObj, "className", originalApplicationName);
- }
- catch (Exception e) {
- e.printStackTrace();
+ } catch (Throwable e) {
+ Log.e(TAG, "modifyApplicationInfoClassName", e);
}
}
}
diff --git a/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java b/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java
index a58cb20..4996239 100644
--- a/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java
+++ b/app/src/main/java/org/lsposed/lspatch/loader/LSPLoader.java
@@ -158,12 +158,6 @@ public class LSPLoader {
appContext = context;
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
- if (!FileUtils.isSdcardPermissionGranted(context)) {
- XLog.e(TAG, "File permission is not granted, can not control xposed module by file " + XPOSED_MODULE_FILE_PATH);
- }
- }
-
initSELinux(context);
ClassLoader originClassLoader = context.getClassLoader();
@@ -195,7 +189,7 @@ public class LSPLoader {
if (!app.enabled) {
continue;
}
- if (app.metaData != null && (app.metaData.containsKey("xposedmodule"))) {
+ if (app.metaData != null && app.metaData.containsKey("xposedminversion")) {
String apkPath = pkg.applicationInfo.publicSourceDir;
String apkName = context.getPackageManager().getApplicationLabel(pkg.applicationInfo).toString();
if (TextUtils.isEmpty(apkPath)) {
@@ -211,27 +205,24 @@ public class LSPLoader {
final List> installedModuleListFinal = installedModuleList;
- new Thread(new Runnable() {
- @Override
- public void run() {
- List savedPackageNameList = loadPackageNameListFromFile(false);
- if (savedPackageNameList == null) {
- savedPackageNameList = new ArrayList<>();
- }
- List> addPackageList = new ArrayList<>();
- for (Pair packgagePair : installedModuleListFinal) {
- if (!savedPackageNameList.contains(packgagePair.first)) {
- XLog.d(TAG, "append " + packgagePair + " to " + XPOSED_MODULE_FILE_PATH);
- addPackageList.add(packgagePair);
- }
- }
- try {
- appendPackageNameToFile(addPackageList);
- }
- catch (IOException e) {
- e.printStackTrace();
+ new Thread(() -> {
+ List savedPackageNameList = loadPackageNameListFromFile(false);
+ if (savedPackageNameList == null) {
+ savedPackageNameList = new ArrayList<>();
+ }
+ List> addPackageList = new ArrayList<>();
+ for (Pair packgagePair : installedModuleListFinal) {
+ if (!savedPackageNameList.contains(packgagePair.first)) {
+ XLog.d(TAG, "append " + packgagePair + " to " + XPOSED_MODULE_FILE_PATH);
+ addPackageList.add(packgagePair);
}
}
+ try {
+ appendPackageNameToFile(addPackageList);
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
}).start();
return modulePathList;
}
diff --git a/app/src/main/java/org/lsposed/lspatch/tester/Hook.java b/app/src/main/java/org/lsposed/lspatch/tester/Hook.java
index e88a44d..a71052a 100644
--- a/app/src/main/java/org/lsposed/lspatch/tester/Hook.java
+++ b/app/src/main/java/org/lsposed/lspatch/tester/Hook.java
@@ -8,7 +8,7 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage;
public class Hook implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
- XposedHelpers.findAndHookMethod("org.lsposed.lspatch.tester.MainActivity", lpparam.classLoader, "checkXposed2", new XC_MethodHook() {
+ XposedHelpers.findAndHookMethod("org.lsposed.org.lsposed.org.lsposed.lspatch.tester.MainActivity", lpparam.classLoader, "checkXposed2", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
param.setResult(true);
diff --git a/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java b/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java
index ea75e87..525a0a1 100644
--- a/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java
+++ b/app/src/main/java/org/lsposed/lspatch/tester/MainActivity.java
@@ -26,12 +26,6 @@ public class MainActivity extends Activity {
param.setResult(true);
}
});
- XposedHelpers.findAndHookMethod(this.getClass(), "checkXposed2", new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- param.setResult(true);
- }
- });
TextView textView = findViewById(R.id.msg);
if (checkXposed() && checkXposed2()) {
diff --git a/app/src/main/java/org/lsposed/lspatch/tester/XposedTestApplication.java b/app/src/main/java/org/lsposed/lspatch/tester/XposedTestApplication.java
deleted file mode 100644
index c3f7628..0000000
--- a/app/src/main/java/org/lsposed/lspatch/tester/XposedTestApplication.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.lsposed.lspatch.tester;
-
-import android.app.Application;
-import android.content.Context;
-
-import org.lsposed.lspatch.loader.LSPLoader;
-import org.lsposed.lspd.yahfa.hooker.YahfaHooker;
-
-import de.robv.android.xposed.XposedInit;
-
-// you can run this app to test hook framework
-public class XposedTestApplication extends Application {
- @Override
- protected void attachBaseContext(Context base) {
- super.attachBaseContext(base);
- }
-
- static {
- System.loadLibrary("lspd");
- YahfaHooker.init();
- XposedInit.startsSystemServer = false;
- LSPLoader.initAndLoadModules();
- }
-}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 27011cb..820b4f2 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context="org.lsposed.lspatch.tester.MainActivity">
+ tools:context="org.lsposed.org.lsposed.tester.MainActivity">
-
\ No newline at end of file
+
diff --git a/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java b/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java
index 6ea482f..a3b4e9c 100644
--- a/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java
+++ b/appstub/src/main/java/org/lsposed/lspatch/appstub/LSPApplicationStub.java
@@ -1,120 +1,36 @@
package org.lsposed.lspatch.appstub;
-import android.app.ActivityThread;
import android.app.Application;
import android.content.Context;
-import android.util.Log;
import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.ByteBuffer;
-
-import dalvik.system.InMemoryDexClassLoader;
public class LSPApplicationStub extends Application {
- final static String TAG = LSPApplicationStub.class.getSimpleName();
- static Object realLSPApplication = null;
+ private static byte[] dex = null;
static {
- // load real lsp loader from asset
- Context context = createAppContext();
- if (context == null) {
- throw new IllegalStateException("create context err");
- }
- else {
- try (InputStream inputStream = context.getAssets().open("lsp.dex");
- ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
-
- int nRead;
- byte[] data = new byte[16384];
-
- while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
- buffer.write(data, 0, nRead);
- }
-
- // loader can load it's own so from app native library dir
- String libraryDir = context.getApplicationInfo().nativeLibraryDir;
-
- Log.d(TAG, "LSPApplicationStub cl: " + LSPApplicationStub.class.getClassLoader());
- Log.d(TAG, "NativePath : " + libraryDir);
-
- InMemoryDexClassLoader loaderClassLoader = new InMemoryDexClassLoader(ByteBuffer.wrap(buffer.toByteArray()),
- LSPApplicationStub.class.getClassLoader());
- Class> lspa = loaderClassLoader.loadClass("org.lsposed.lspatch.loader.LSPApplication");
- realLSPApplication = lspa.newInstance();
- }
- catch (Exception e) {
- throw new IllegalStateException("wtf", e);
+ try (var is = LSPApplicationStub.class.getClassLoader().getResourceAsStream("assets/lsp");
+ var os = new ByteArrayOutputStream()) {
+ byte[] buffer = new byte[8192];
+ int n;
+ while (-1 != (n = is.read(buffer))) {
+ os.write(buffer, 0, n);
}
+ dex = os.toByteArray();
+ } catch (Throwable e) {
+ android.util.Log.e("LSPatch", "load dex error", e);
}
+ System.loadLibrary("lspd");
}
@Override
public void onCreate() {
super.onCreate();
-
- try {
- realLSPApplication.getClass().getDeclaredMethod("onCreate").invoke(realLSPApplication);
- }
- catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
- throw new IllegalStateException("wtf", e);
- }
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
-
- try {
- Method method = realLSPApplication.getClass().getDeclaredMethod("attachBaseContext", Context.class);
- method.setAccessible(true);
- method.invoke(realLSPApplication, base);
- }
- catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
- throw new IllegalStateException("wtf", e);
- }
- }
-
- // copy from app project
- public static Context createAppContext() {
- try {
- Class> activityThreadClass = Class.forName("android.app.ActivityThread");
- Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
- currentActivityThreadMethod.setAccessible(true);
-
- Object activityThreadObj = currentActivityThreadMethod.invoke(null);
-
- Field boundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication");
- boundApplicationField.setAccessible(true);
- Object mBoundApplication = boundApplicationField.get(activityThreadObj); // AppBindData
- if (mBoundApplication == null) {
- Log.e(TAG, "mBoundApplication null");
- return null;
- }
- Field infoField = mBoundApplication.getClass().getDeclaredField("info"); // info
- infoField.setAccessible(true);
- Object loadedApkObj = infoField.get(mBoundApplication); // LoadedApk
- if (loadedApkObj == null) {
- Log.e(TAG, "loadedApkObj null");
- return null;
- }
- Class> contextImplClass = Class.forName("android.app.ContextImpl");
- Method createAppContextMethod = contextImplClass.getDeclaredMethod("createAppContext", activityThreadClass, loadedApkObj.getClass());
- createAppContextMethod.setAccessible(true);
-
- Object context = createAppContextMethod.invoke(null, (ActivityThread) activityThreadObj, loadedApkObj);
-
- if (context instanceof Context) {
- return (Context) context;
- }
- }
- catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) {
- throw new IllegalStateException("wtf", e);
- }
- return null;
}
}
diff --git a/core b/core
index 90b37a6..9e47e90 160000
--- a/core
+++ b/core
@@ -1 +1 @@
-Subproject commit 90b37a68aa32e79ea2dc58048f7657ba66abed89
+Subproject commit 9e47e9027c4244317085cce2a95ddcbb7b579ee0
diff --git a/patch/src/main/java/org/lsposed/patch/LSPatch.java b/patch/src/main/java/org/lsposed/patch/LSPatch.java
index cda1fc9..3cc0684 100644
--- a/patch/src/main/java/org/lsposed/patch/LSPatch.java
+++ b/patch/src/main/java/org/lsposed/patch/LSPatch.java
@@ -254,7 +254,7 @@ public class LSPatch {
}
try (var is = getClass().getClassLoader().getResourceAsStream("assets/dex/lsp.dex")) {
- zFile.add("assets/lsp.dex", is);
+ zFile.add("assets/lsp", is);
} catch (Throwable e) {
throw new PatchError("Error when add assets: " + e);
}