Skip to content

Commit

Permalink
Enable yahfa's cache
Browse files Browse the repository at this point in the history
  • Loading branch information
LoveSy authored and kotori2 committed Dec 24, 2020
1 parent ba6c61f commit 8c838c6
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ private static boolean isFileExists(String path) {

public static native String getPrefsPath(String suffix);

public static native String getCachePath(String suffix);

public static native String getBaseConfigPath();

public static native String getDataPathPrefix();
Expand Down
4 changes: 4 additions & 0 deletions edxp-core/src/main/cpp/main/src/config_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ namespace edxp {
return misc_path_ / "framework" / suffix;
}

inline static auto GetCachePath(const std::string &suffix = {}) {
return misc_path_ / "cache" / suffix;
}

inline static auto GetLibSandHookName() {
if constexpr(edxp::is64)
return GetFrameworkPath("lib64/libsandhook.edxp.so");
Expand Down
9 changes: 9 additions & 0 deletions edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ namespace edxp {
return env->NewStringUTF(result.c_str());
}

static jstring ConfigManager_getCachePath(JNI_START, jstring jSuffix) {
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
auto result = ConfigManager::GetCachePath(suffix);
env->ReleaseStringUTFChars(jSuffix, suffix);
return env->NewStringUTF(result.c_str());
}

static jstring ConfigManager_getBaseConfigPath(JNI_START) {
auto result = ConfigManager::GetInstance()->GetBaseConfigPath();
return env->NewStringUTF(result.c_str());
Expand Down Expand Up @@ -80,6 +87,8 @@ namespace edxp {
"(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getPrefsPath,
"(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getCachePath,
"(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getBaseConfigPath,"()Ljava/lang/String;"),
NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"),
};
Expand Down
3 changes: 3 additions & 0 deletions edxp-core/template_override/customize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ if [[ "${VARIANT}" == "SandHook" ]]; then
fi
set_perm_recursive /data/misc/$MISC_PATH/framework root root 0755 0644 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"

mkdir -p /data/misc/$MISC_PATH/cache
set_perm /data/misc/$MISC_PATH/cache root root 0777 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"

mv "${MODPATH}/system/lib/libriru_edxp.so" "${MODPATH}/system/lib/${LIB_RIRU_EDXP}"
if [[ "${IS64BIT}" == true ]]; then
mv "${MODPATH}/system/lib64/libriru_edxp.so" "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.elderdrivers.riru.edxp.yahfa.dexmaker;

import android.app.AndroidAppHelper;
import android.os.Build;
import android.text.TextUtils;

import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.util.Utils;

import java.io.File;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -16,19 +14,14 @@

public class DexMakerUtils {

private static final boolean IN_MEMORY_DEX_ELIGIBLE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
public static boolean canCache = true;

public static boolean shouldUseInMemoryHook() {
if (!IN_MEMORY_DEX_ELIGIBLE) {
return false;
}
String packageName = AndroidAppHelper.currentPackageName();
if (TextUtils.isEmpty(packageName)) { //default to true
DexLog.w("packageName is empty, processName=" + ConfigManager.appProcessName
+ ", appDataDir=" + ConfigManager.appDataDir);
return true;
static {
File cacheDir = new File(ConfigManager.getCachePath(""));
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
Utils.logW("Cache disabled");
canCache = false;
}
return !ConfigManager.shouldUseCompatMode(packageName);
}

public static void autoBoxIfNecessary(Code code, Local<Object> target, Local source) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,11 @@
import de.robv.android.xposed.EdHooker;
import de.robv.android.xposed.XposedBridge;

import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
import static com.elderdrivers.riru.edxp.util.FileUtils.getPackageName;
import static com.elderdrivers.riru.edxp.util.ProcessUtils.getCurrentProcessName;
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.shouldUseInMemoryHook;

public final class DynamicBridge {

private static final HashMap<Member, EdHooker> hookedInfo = new HashMap<>();
private static final HookerDexMaker dexMaker = new HookerDexMaker();
private static final AtomicBoolean dexPathInited = new AtomicBoolean(false);
private static File dexDir;
private static File dexOptDir;

/**
Expand All @@ -50,46 +44,16 @@ public static synchronized void hookMethod(Member hookMethod, XposedBridge.Addit
DexLog.d("start to generate class for: " + hookMethod);
long startTime = System.nanoTime();
try {
// for Android Oreo and later use InMemoryClassLoader
if (!shouldUseInMemoryHook()) {
setupDexCachePath();
}
dexMaker.start(hookMethod, additionalHookInfo,
hookMethod.getDeclaringClass().getClassLoader(), getDexDirPath());
hookMethod.getDeclaringClass().getClassLoader());
hookedInfo.put(hookMethod, dexMaker.getHooker());
} catch (Exception e) {
DexLog.e("error occur when generating dex. dexDir=" + dexDir, e);
DexLog.e("error occur when generating dex.", e);
}
long endTime = System.nanoTime();
DexLog.d("generated class for " + hookMethod + " in " + ((endTime-startTime) * 1.e-6) + "ms");
}

private static String getDexDirPath() {
if (dexDir == null) {
return null;
}
return dexDir.getAbsolutePath();
}

private static void setupDexCachePath() {
// using file based DexClassLoader
if (!dexPathInited.compareAndSet(false, true)) {
return;
}
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
String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
dexDir = new File(fixedAppDataDir, "/cache/edhookers/"
+ getCurrentProcessName(ConfigManager.appProcessName).replace(":", "_") + "/");
dexOptDir = new File(dexDir, "oat");
dexDir.mkdirs();
DexLog.d(ConfigManager.appProcessName + " deleting dir: " + dexOptDir.getAbsolutePath());
} catch (Throwable throwable) {
DexLog.e("error when init dex path", throwable);
}
}

private static boolean checkMember(Member member) {

if (member instanceof Method) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.os.Build;
import android.text.TextUtils;

import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.core.yahfa.HookMain;
import com.elderdrivers.riru.edxp.util.ProxyClassLoader;
import com.elderdrivers.riru.edxp.yahfa.BuildConfig;
Expand All @@ -26,9 +27,11 @@
import external.com.android.dx.Local;
import external.com.android.dx.MethodId;
import external.com.android.dx.TypeId;
import pxb.android.arsc.Config;

import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.autoBoxIfNecessary;
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.autoUnboxIfNecessary;
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.canCache;
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.createResultLocals;
import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.getObjTypeIdIfPrimitive;

Expand Down Expand Up @@ -69,7 +72,6 @@ public class HookerDexMaker {
private Class<?> mHookClass;
private Method mHookMethod;
private Method mBackupMethod;
private String mDexDirPath;
private EdHooker mHooker;

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

public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo,
ClassLoader appClassLoader, String dexDirPath) throws Exception {
ClassLoader appClassLoader) throws Exception {
if (member instanceof Method) {
Method method = (Method) member;
mIsStatic = Modifier.isStatic(method.getModifiers());
Expand Down Expand Up @@ -132,7 +134,6 @@ public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo,
}
mMember = member;
mHookInfo = hookInfo;
mDexDirPath = dexDirPath;
if (appClassLoader == null
|| appClassLoader.getClass().getName().equals("java.lang.BootClassLoader")) {
mAppClassLoader = getClass().getClassLoader();
Expand All @@ -145,27 +146,36 @@ public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo,

@TargetApi(Build.VERSION_CODES.O)
private void doMake(String hookedClassName) throws Exception {
final boolean useInMemoryCl = TextUtils.isEmpty(mDexDirPath);
mDexMaker = new DexMaker();
ClassLoader loader;
ClassLoader loader = null;
// 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 {
boolean usedCache = false;
if (canCache) {
try {
// className is also used as dex file name
// so it should be different from each other
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
className = className + suffix;
String dexFileName = className + ".jar";
File dexFile = new File(ConfigManager.getCachePath(dexFileName));
if (!dexFile.exists()) {
// if file exists, reuse it and skip generating
DexLog.d("Generating " + dexFileName);
doGenerate(className);
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName, false);
dexFile.setWritable(true, false);
dexFile.setReadable(true, false);
} else {
DexLog.d("Using cache " + dexFileName);
loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName);
}
usedCache = true;
} catch (Throwable ignored) {}
}
if (!usedCache) {
// do everything in memory
DexLog.d("Generating in memory");
if(BuildConfig.DEBUG)
className = className + hookedClassName.replace(".", "/");
doGenerate(className);
Expand Down

0 comments on commit 8c838c6

Please sign in to comment.