Reuse generated dex and oat files when using compat mode
This commit is contained in:
parent
09af8ce0b4
commit
6d08c0b2bc
|
|
@ -7,6 +7,7 @@ import android.text.TextUtils;
|
|||
import com.elderdrivers.riru.xposed.Main;
|
||||
import com.elderdrivers.riru.xposed.config.ConfigManager;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -226,4 +227,20 @@ public class DexMakerUtils {
|
|||
TypeId<?> boxTypeId;
|
||||
code.returnValue(resultLocals.get(returnType));
|
||||
}
|
||||
|
||||
public static String getSha1Hex(String text) {
|
||||
final MessageDigest digest;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-1");
|
||||
byte[] result = digest.digest(text.getBytes("UTF-8"));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : result) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (Exception e) {
|
||||
DexLog.e("error hashing target method: " + text, e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.elderdrivers.riru.xposed.dexmaker;
|
||||
|
||||
import com.elderdrivers.riru.xposed.Main;
|
||||
import com.elderdrivers.riru.xposed.util.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
|
@ -72,8 +71,6 @@ public final class DynamicBridge {
|
|||
if (!dexPathInited.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
// delete previous compiled dex to prevent potential crashing
|
||||
// TODO find a way to reuse them in consideration of performance
|
||||
try {
|
||||
// we always choose to use device encrypted storage data on android N and later
|
||||
// in case some app is installing hooks before phone is unlocked
|
||||
|
|
@ -83,10 +80,6 @@ public final class DynamicBridge {
|
|||
dexOptDir = new File(dexDir, "oat");
|
||||
dexDir.mkdirs();
|
||||
DexLog.d(Main.appProcessName + " deleting dir: " + dexOptDir.getAbsolutePath());
|
||||
try {
|
||||
FileUtils.delete(dexOptDir);
|
||||
} catch (Throwable throwable) {
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
DexLog.e("error when init dex path", throwable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class HookerDexMaker {
|
|||
public static final String METHOD_NAME_SETUP = "setup";
|
||||
public static final TypeId<Object[]> objArrayTypeId = TypeId.get(Object[].class);
|
||||
private static final String CLASS_DESC_PREFIX = "L";
|
||||
private static final String CLASS_NAME_PREFIX = "EdHooker";
|
||||
private static final String CLASS_NAME_PREFIX = "ed_";
|
||||
private static final String FIELD_NAME_HOOK_INFO = "additionalHookInfo";
|
||||
private static final String FIELD_NAME_METHOD = "method";
|
||||
private static final String PARAMS_FIELD_NAME_METHOD = "method";
|
||||
|
|
@ -183,26 +183,30 @@ public class HookerDexMaker {
|
|||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
private void doMake() throws Exception {
|
||||
final boolean useInMemoryCl = TextUtils.isEmpty(mDexDirPath);
|
||||
mDexMaker = new DexMaker();
|
||||
// Generate a Hooker class.
|
||||
String className = CLASS_NAME_PREFIX + sClassNameSuffix.getAndIncrement();
|
||||
String classDesc = CLASS_DESC_PREFIX + className + ";";
|
||||
mHookerTypeId = TypeId.get(classDesc);
|
||||
mDexMaker.declare(mHookerTypeId, className + ".generated", Modifier.PUBLIC, TypeId.OBJECT);
|
||||
generateFields();
|
||||
generateSetupMethod();
|
||||
generateBackupMethod();
|
||||
generateHookMethod();
|
||||
generateCallBackupMethod();
|
||||
|
||||
ClassLoader loader;
|
||||
if (TextUtils.isEmpty(mDexDirPath)) {
|
||||
// in memory dex classloader
|
||||
// Generate a Hooker class.
|
||||
String className = CLASS_NAME_PREFIX;
|
||||
if (!useInMemoryCl) {
|
||||
// if not using InMemoryDexClassLoader, className is also used as dex file name
|
||||
// so it should be different from each other
|
||||
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
|
||||
if (TextUtils.isEmpty(suffix)) { // just in case
|
||||
suffix = String.valueOf(sClassNameSuffix.getAndIncrement());
|
||||
}
|
||||
className = className + suffix;
|
||||
if (!new File(mDexDirPath, className).exists()) {
|
||||
// if file exists, reuse it and skip generating
|
||||
doGenerate(className);
|
||||
}
|
||||
// load dex file from disk
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), className);
|
||||
} else {
|
||||
// do everything in memory
|
||||
doGenerate(className);
|
||||
byte[] dexBytes = mDexMaker.generate();
|
||||
loader = new InMemoryDexClassLoader(ByteBuffer.wrap(dexBytes), mAppClassLoader);
|
||||
} else {
|
||||
// Create the dex file and load it.
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath));
|
||||
}
|
||||
|
||||
mHookClass = loader.loadClass(className);
|
||||
|
|
@ -216,6 +220,17 @@ public class HookerDexMaker {
|
|||
HookMain.backupAndHook(mMember, mHookMethod, mBackupMethod);
|
||||
}
|
||||
|
||||
private void doGenerate(String className) {
|
||||
String classDesc = CLASS_DESC_PREFIX + className + ";";
|
||||
mHookerTypeId = TypeId.get(classDesc);
|
||||
mDexMaker.declare(mHookerTypeId, className + ".generated", Modifier.PUBLIC, TypeId.OBJECT);
|
||||
generateFields();
|
||||
generateSetupMethod();
|
||||
generateBackupMethod();
|
||||
generateHookMethod();
|
||||
generateCallBackupMethod();
|
||||
}
|
||||
|
||||
public Method getHookMethod() {
|
||||
return mHookMethod;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import org.gradle.internal.os.OperatingSystem;
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
version "v0.3.1.3_beta-SNAPSHOT"
|
||||
version "v0.3.1.4_beta-SNAPSHOT"
|
||||
extensions["module_name"] = "EdXposed"
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/system/bin/sh
|
||||
|
||||
EDXP_VERSION="0.3.1.3_beta-SNAPSHOT (3130)"
|
||||
EDXP_VERSION="0.3.1.4_beta-SNAPSHOT (3140)"
|
||||
ANDROID_SDK=`getprop ro.build.version.sdk`
|
||||
BUILD_DESC=`getprop ro.build.description`
|
||||
PRODUCT=`getprop ro.build.product`
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ LATESTARTSERVICE=false
|
|||
|
||||
print_modname() {
|
||||
ui_print "************************************"
|
||||
ui_print " Riru - Ed Xposed v0.3.1.3 "
|
||||
ui_print " Riru - Ed Xposed v0.3.1.4 "
|
||||
ui_print "************************************"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
id=riru_edxposed
|
||||
name=Riru - Ed Xposed
|
||||
version=v0.3.1.3_beta-SNAPSHOT
|
||||
versionCode=3130
|
||||
version=v0.3.1.4_beta-SNAPSHOT
|
||||
versionCode=3140
|
||||
author=solohsu & MlgmXyysd
|
||||
description=Magisk version of Xposed. Require Riru - Core installed.
|
||||
minMagisk=17000
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
name=Ed Xposed
|
||||
version=v0.3.1.3_beta-SNAPSHOT
|
||||
versionCode=3130
|
||||
version=v0.3.1.4_beta-SNAPSHOT
|
||||
versionCode=3140
|
||||
author=solohsu & MlgmXyysd
|
||||
description=Magisk version of Xposed. Require Riru - Core installed.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version=90.0-0.3.1.3-beta-SNAPSHOT
|
||||
version=90.0-0.3.1.4-beta-SNAPSHOT
|
||||
arch=arm64
|
||||
minsdk=23
|
||||
maxsdk=28
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -471,6 +471,10 @@ public final class DexMaker {
|
|||
}
|
||||
}
|
||||
|
||||
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException {
|
||||
return generateAndLoad(parent, dexCache, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a dex file and loads its types into the current process.
|
||||
*
|
||||
|
|
@ -496,8 +500,9 @@ public final class DexMaker {
|
|||
* @param dexCache the destination directory where generated and optimized
|
||||
* dex files will be written. If null, this class will try to guess the
|
||||
* application's private data dir.
|
||||
* @param fileName the name of dex file
|
||||
*/
|
||||
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException {
|
||||
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String fileName) throws IOException {
|
||||
if (dexCache == null) {
|
||||
String property = System.getProperty("dexmaker.dexcache");
|
||||
if (property != null) {
|
||||
|
|
@ -511,7 +516,9 @@ public final class DexMaker {
|
|||
}
|
||||
}
|
||||
|
||||
File result = new File(dexCache, generateFileName());
|
||||
if (fileName == null || fileName.isEmpty())
|
||||
fileName = generateFileName();
|
||||
File result = new File(dexCache, fileName);
|
||||
// Check that the file exists. If it does, return a DexClassLoader and skip all
|
||||
// the dex bytecode generation.
|
||||
if (result.exists()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue