Skip to content

Commit 8c838c6

Browse files
LoveSykotori2
LoveSy
authored andcommitted
Enable yahfa's cache
1 parent ba6c61f commit 8c838c6

File tree

7 files changed

+58
-73
lines changed

7 files changed

+58
-73
lines changed

edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ private static boolean isFileExists(String path) {
4545

4646
public static native String getPrefsPath(String suffix);
4747

48+
public static native String getCachePath(String suffix);
49+
4850
public static native String getBaseConfigPath();
4951

5052
public static native String getDataPathPrefix();

edxp-core/src/main/cpp/main/src/config_manager.h

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ namespace edxp {
6868
return misc_path_ / "framework" / suffix;
6969
}
7070

71+
inline static auto GetCachePath(const std::string &suffix = {}) {
72+
return misc_path_ / "cache" / suffix;
73+
}
74+
7175
inline static auto GetLibSandHookName() {
7276
if constexpr(edxp::is64)
7377
return GetFrameworkPath("lib64/libsandhook.edxp.so");

edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ namespace edxp {
5353
return env->NewStringUTF(result.c_str());
5454
}
5555

56+
static jstring ConfigManager_getCachePath(JNI_START, jstring jSuffix) {
57+
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
58+
auto result = ConfigManager::GetCachePath(suffix);
59+
env->ReleaseStringUTFChars(jSuffix, suffix);
60+
return env->NewStringUTF(result.c_str());
61+
}
62+
5663
static jstring ConfigManager_getBaseConfigPath(JNI_START) {
5764
auto result = ConfigManager::GetInstance()->GetBaseConfigPath();
5865
return env->NewStringUTF(result.c_str());
@@ -80,6 +87,8 @@ namespace edxp {
8087
"(Ljava/lang/String;)Ljava/lang/String;"),
8188
NATIVE_METHOD(ConfigManager, getPrefsPath,
8289
"(Ljava/lang/String;)Ljava/lang/String;"),
90+
NATIVE_METHOD(ConfigManager, getCachePath,
91+
"(Ljava/lang/String;)Ljava/lang/String;"),
8392
NATIVE_METHOD(ConfigManager, getBaseConfigPath,"()Ljava/lang/String;"),
8493
NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"),
8594
};

edxp-core/template_override/customize.sh

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ if [[ "${VARIANT}" == "SandHook" ]]; then
230230
fi
231231
set_perm_recursive /data/misc/$MISC_PATH/framework root root 0755 0644 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
232232

233+
mkdir -p /data/misc/$MISC_PATH/cache
234+
set_perm /data/misc/$MISC_PATH/cache root root 0777 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
235+
233236
mv "${MODPATH}/system/lib/libriru_edxp.so" "${MODPATH}/system/lib/${LIB_RIRU_EDXP}"
234237
if [[ "${IS64BIT}" == true ]]; then
235238
mv "${MODPATH}/system/lib64/libriru_edxp.so" "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}"

edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java

+8-15
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.elderdrivers.riru.edxp.yahfa.dexmaker;
22

3-
import android.app.AndroidAppHelper;
4-
import android.os.Build;
5-
import android.text.TextUtils;
6-
73
import com.elderdrivers.riru.edxp.config.ConfigManager;
4+
import com.elderdrivers.riru.edxp.util.Utils;
85

6+
import java.io.File;
97
import java.security.MessageDigest;
108
import java.util.HashMap;
119
import java.util.Map;
@@ -16,19 +14,14 @@
1614

1715
public class DexMakerUtils {
1816

19-
private static final boolean IN_MEMORY_DEX_ELIGIBLE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
17+
public static boolean canCache = true;
2018

21-
public static boolean shouldUseInMemoryHook() {
22-
if (!IN_MEMORY_DEX_ELIGIBLE) {
23-
return false;
24-
}
25-
String packageName = AndroidAppHelper.currentPackageName();
26-
if (TextUtils.isEmpty(packageName)) { //default to true
27-
DexLog.w("packageName is empty, processName=" + ConfigManager.appProcessName
28-
+ ", appDataDir=" + ConfigManager.appDataDir);
29-
return true;
19+
static {
20+
File cacheDir = new File(ConfigManager.getCachePath(""));
21+
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
22+
Utils.logW("Cache disabled");
23+
canCache = false;
3024
}
31-
return !ConfigManager.shouldUseCompatMode(packageName);
3225
}
3326

3427
public static void autoBoxIfNecessary(Code code, Local<Object> target, Local source) {

edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DynamicBridge.java

+2-38
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,11 @@
1515
import de.robv.android.xposed.EdHooker;
1616
import de.robv.android.xposed.XposedBridge;
1717

18-
import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
19-
import static com.elderdrivers.riru.edxp.util.FileUtils.getPackageName;
20-
import static com.elderdrivers.riru.edxp.util.ProcessUtils.getCurrentProcessName;
21-
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.shouldUseInMemoryHook;
22-
2318
public final class DynamicBridge {
2419

2520
private static final HashMap<Member, EdHooker> hookedInfo = new HashMap<>();
2621
private static final HookerDexMaker dexMaker = new HookerDexMaker();
2722
private static final AtomicBoolean dexPathInited = new AtomicBoolean(false);
28-
private static File dexDir;
2923
private static File dexOptDir;
3024

3125
/**
@@ -50,46 +44,16 @@ public static synchronized void hookMethod(Member hookMethod, XposedBridge.Addit
5044
DexLog.d("start to generate class for: " + hookMethod);
5145
long startTime = System.nanoTime();
5246
try {
53-
// for Android Oreo and later use InMemoryClassLoader
54-
if (!shouldUseInMemoryHook()) {
55-
setupDexCachePath();
56-
}
5747
dexMaker.start(hookMethod, additionalHookInfo,
58-
hookMethod.getDeclaringClass().getClassLoader(), getDexDirPath());
48+
hookMethod.getDeclaringClass().getClassLoader());
5949
hookedInfo.put(hookMethod, dexMaker.getHooker());
6050
} catch (Exception e) {
61-
DexLog.e("error occur when generating dex. dexDir=" + dexDir, e);
51+
DexLog.e("error occur when generating dex.", e);
6252
}
6353
long endTime = System.nanoTime();
6454
DexLog.d("generated class for " + hookMethod + " in " + ((endTime-startTime) * 1.e-6) + "ms");
6555
}
6656

67-
private static String getDexDirPath() {
68-
if (dexDir == null) {
69-
return null;
70-
}
71-
return dexDir.getAbsolutePath();
72-
}
73-
74-
private static void setupDexCachePath() {
75-
// using file based DexClassLoader
76-
if (!dexPathInited.compareAndSet(false, true)) {
77-
return;
78-
}
79-
try {
80-
// we always choose to use device encrypted storage data on android N and later
81-
// in case some app is installing hooks before phone is unlocked
82-
String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
83-
dexDir = new File(fixedAppDataDir, "/cache/edhookers/"
84-
+ getCurrentProcessName(ConfigManager.appProcessName).replace(":", "_") + "/");
85-
dexOptDir = new File(dexDir, "oat");
86-
dexDir.mkdirs();
87-
DexLog.d(ConfigManager.appProcessName + " deleting dir: " + dexOptDir.getAbsolutePath());
88-
} catch (Throwable throwable) {
89-
DexLog.e("error when init dex path", throwable);
90-
}
91-
}
92-
9357
private static boolean checkMember(Member member) {
9458

9559
if (member instanceof Method) {

edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/HookerDexMaker.java

+30-20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.os.Build;
55
import android.text.TextUtils;
66

7+
import com.elderdrivers.riru.edxp.config.ConfigManager;
78
import com.elderdrivers.riru.edxp.core.yahfa.HookMain;
89
import com.elderdrivers.riru.edxp.util.ProxyClassLoader;
910
import com.elderdrivers.riru.edxp.yahfa.BuildConfig;
@@ -26,9 +27,11 @@
2627
import external.com.android.dx.Local;
2728
import external.com.android.dx.MethodId;
2829
import external.com.android.dx.TypeId;
30+
import pxb.android.arsc.Config;
2931

3032
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.autoBoxIfNecessary;
3133
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.autoUnboxIfNecessary;
34+
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.canCache;
3235
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.createResultLocals;
3336
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.getObjTypeIdIfPrimitive;
3437

@@ -69,7 +72,6 @@ public class HookerDexMaker {
6972
private Class<?> mHookClass;
7073
private Method mHookMethod;
7174
private Method mBackupMethod;
72-
private String mDexDirPath;
7375
private EdHooker mHooker;
7476

7577
private static TypeId<?>[] getParameterTypeIds(Class<?>[] parameterTypes, boolean isStatic) {
@@ -101,7 +103,7 @@ private static Class<?>[] getParameterTypes(Class<?>[] parameterTypes, boolean i
101103
}
102104

103105
public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo,
104-
ClassLoader appClassLoader, String dexDirPath) throws Exception {
106+
ClassLoader appClassLoader) throws Exception {
105107
if (member instanceof Method) {
106108
Method method = (Method) member;
107109
mIsStatic = Modifier.isStatic(method.getModifiers());
@@ -132,7 +134,6 @@ public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo,
132134
}
133135
mMember = member;
134136
mHookInfo = hookInfo;
135-
mDexDirPath = dexDirPath;
136137
if (appClassLoader == null
137138
|| appClassLoader.getClass().getName().equals("java.lang.BootClassLoader")) {
138139
mAppClassLoader = getClass().getClassLoader();
@@ -145,27 +146,36 @@ public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo,
145146

146147
@TargetApi(Build.VERSION_CODES.O)
147148
private void doMake(String hookedClassName) throws Exception {
148-
final boolean useInMemoryCl = TextUtils.isEmpty(mDexDirPath);
149149
mDexMaker = new DexMaker();
150-
ClassLoader loader;
150+
ClassLoader loader = null;
151151
// Generate a Hooker class.
152152
String className = CLASS_NAME_PREFIX;
153-
if (!useInMemoryCl) {
154-
// if not using InMemoryDexClassLoader, className is also used as dex file name
155-
// so it should be different from each other
156-
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
157-
if (TextUtils.isEmpty(suffix)) { // just in case
158-
suffix = String.valueOf(sClassNameSuffix.getAndIncrement());
159-
}
160-
className = className + suffix;
161-
if (!new File(mDexDirPath, className).exists()) {
162-
// if file exists, reuse it and skip generating
163-
doGenerate(className);
164-
}
165-
// load dex file from disk
166-
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), className);
167-
} else {
153+
boolean usedCache = false;
154+
if (canCache) {
155+
try {
156+
// className is also used as dex file name
157+
// so it should be different from each other
158+
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
159+
className = className + suffix;
160+
String dexFileName = className + ".jar";
161+
File dexFile = new File(ConfigManager.getCachePath(dexFileName));
162+
if (!dexFile.exists()) {
163+
// if file exists, reuse it and skip generating
164+
DexLog.d("Generating " + dexFileName);
165+
doGenerate(className);
166+
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName, false);
167+
dexFile.setWritable(true, false);
168+
dexFile.setReadable(true, false);
169+
} else {
170+
DexLog.d("Using cache " + dexFileName);
171+
loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName);
172+
}
173+
usedCache = true;
174+
} catch (Throwable ignored) {}
175+
}
176+
if (!usedCache) {
168177
// do everything in memory
178+
DexLog.d("Generating in memory");
169179
if(BuildConfig.DEBUG)
170180
className = className + hookedClassName.replace(".", "/");
171181
doGenerate(className);

0 commit comments

Comments
 (0)