Skip to content

Commit dfcf21c

Browse files
author
tiann
committed
1. fix the Application.attach may be hooked multi-times.
2. reduce the log of Xposed.
1 parent 510f056 commit dfcf21c

File tree

4 files changed

+101
-27
lines changed

4 files changed

+101
-27
lines changed

exposed-core/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ dependencies {
3131
}
3232

3333
group = 'me.weishu.exposed'
34-
version = '0.6.6'
34+
version = '0.6.7'
3535

3636
apply plugin: 'com.novoda.bintray-release'
3737

exposed-core/src/main/java/de/robv/android/xposed/ExposedHelper.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
package de.robv.android.xposed;
22

3+
import android.util.Log;
4+
35
import java.lang.reflect.Member;
46

57
/**
68
* Created by weishu on 17/11/30.
79
*/
810
public class ExposedHelper {
911

12+
private static final String TAG = "ExposedHelper";
13+
1014
public static void initSeLinux(String processName) {
1115
SELinuxHelper.initOnce();
1216
SELinuxHelper.initForProcess(processName);
1317
}
1418

1519
public static boolean isIXposedMod(Class<?> moduleClass) {
16-
XposedBridge.log("module's classLoader : " + moduleClass.getClassLoader() + ", super: " + moduleClass.getSuperclass());
17-
XposedBridge.log("IXposedMod's classLoader : " + IXposedMod.class.getClassLoader());
20+
Log.d(TAG, "module's classLoader : " + moduleClass.getClassLoader() + ", super: " + moduleClass.getSuperclass());
21+
Log.d(TAG, "IXposedMod's classLoader : " + IXposedMod.class.getClassLoader());
1822

1923
return IXposedMod.class.isAssignableFrom(moduleClass);
2024
}
@@ -30,4 +34,12 @@ public static void callInitZygote(String modulePath, Object moduleInstance) thro
3034
param.startsSystemServer = false;
3135
((IXposedHookZygoteInit) moduleInstance).initZygote(param);
3236
}
37+
38+
public static void beforeHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable{
39+
methodHook.beforeHookedMethod(param);
40+
}
41+
42+
public static void afterHookedMethod(XC_MethodHook methodHook, XC_MethodHook.MethodHookParam param) throws Throwable{
43+
methodHook.afterHookedMethod(param);
44+
}
3345
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package me.weishu.exposed;
2+
3+
import android.app.Application;
4+
import android.content.Context;
5+
import android.content.ContextWrapper;
6+
import android.util.Log;
7+
8+
import java.lang.reflect.Member;
9+
import java.lang.reflect.Method;
10+
11+
import de.robv.android.xposed.DexposedBridge;
12+
import de.robv.android.xposed.ExposedHelper;
13+
import de.robv.android.xposed.XC_MethodHook;
14+
import de.robv.android.xposed.XposedBridge;
15+
import de.robv.android.xposed.XposedHelpers;
16+
17+
/**
18+
* @author weishu
19+
* @date 2018/6/19.
20+
*/
21+
public final class CHAHelper {
22+
private static final String TAG = "CHAHelper";
23+
24+
static class ApplicationHookProxy extends XC_MethodHook {
25+
26+
XC_MethodHook original;
27+
28+
ApplicationHookProxy(XC_MethodHook original) {
29+
this.original = original;
30+
}
31+
32+
@Override
33+
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
34+
super.beforeHookedMethod(param);
35+
if (param.thisObject == null) {
36+
throw new IllegalArgumentException("can not use static method!!");
37+
}
38+
39+
if (param.thisObject instanceof Application) {
40+
ExposedHelper.beforeHookedMethod(this.original, param);
41+
} else {
42+
Log.d(TAG, "ignore non-application of ContextWrapper: " + param.thisObject);
43+
}
44+
}
45+
46+
@Override
47+
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
48+
super.afterHookedMethod(param);
49+
if (param.thisObject == null) {
50+
throw new IllegalArgumentException("can not use static method!!");
51+
}
52+
53+
if (param.thisObject instanceof Application) {
54+
ExposedHelper.afterHookedMethod(this.original, param);
55+
} else {
56+
Log.d(TAG, "ignore non-application of ContextWrapper: " + param.thisObject);
57+
}
58+
}
59+
}
60+
61+
static XC_MethodHook.Unhook replaceForCHA(Member member, final XC_MethodHook callback) {
62+
63+
if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) {
64+
XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA");
65+
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
66+
return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback));
67+
}
68+
69+
if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) {
70+
XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA");
71+
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
72+
return DexposedBridge.hookMethod(m, new ApplicationHookProxy(callback));
73+
}
74+
75+
return null;
76+
}
77+
}

exposed-core/src/main/java/me/weishu/exposed/ExposedBridge.java

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package me.weishu.exposed;
22

33
import android.annotation.SuppressLint;
4-
import android.app.Application;
54
import android.content.ComponentName;
65
import android.content.Context;
7-
import android.content.ContextWrapper;
86
import android.content.Intent;
97
import android.content.ServiceConnection;
108
import android.content.SharedPreferences;
@@ -36,7 +34,6 @@
3634
import java.lang.reflect.Field;
3735
import java.lang.reflect.InvocationTargetException;
3836
import java.lang.reflect.Member;
39-
import java.lang.reflect.Method;
4037
import java.util.Arrays;
4138
import java.util.HashMap;
4239
import java.util.HashSet;
@@ -205,11 +202,11 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod
205202
loadModuleConfig(rootDir, currentApplicationInfo.processName);
206203

207204
if (lastModuleList.second == null || !lastModuleList.second.contains(moduleApkPath)) {
208-
log("module:" + moduleApkPath + " is disabled, ignore");
205+
Log.i(TAG, "module:" + moduleApkPath + " is disabled, ignore");
209206
return ModuleLoadResult.DISABLED;
210207
}
211208

212-
log("Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName + " i s c: " + SYSTEM_CLASSLOADER_INJECT);
209+
Log.i(TAG, "Loading modules from " + moduleApkPath + " for process: " + currentApplicationInfo.processName + " i s c: " + SYSTEM_CLASSLOADER_INJECT);
213210

214211
if (!new File(moduleApkPath).exists()) {
215212
log(moduleApkPath + " does not exist");
@@ -249,7 +246,7 @@ public static ModuleLoadResult loadModule(final String moduleApkPath, String mod
249246
continue;
250247
}
251248
try {
252-
log(" Loading class " + moduleClassName);
249+
Log.i(TAG, " Loading class " + moduleClassName);
253250
Class<?> moduleClass = mcl.loadClass(moduleClassName);
254251

255252
sModuleLoadListener.onLoadingModule(moduleClassName, currentApplicationInfo, mcl);
@@ -334,7 +331,10 @@ public static XC_MethodHook.Unhook hookMethod(Member method, XC_MethodHook callb
334331
return null;
335332
}
336333

337-
method = replaceForCHA(method);
334+
XC_MethodHook.Unhook replaceUnhook = CHAHelper.replaceForCHA(method, callback);
335+
if (replaceUnhook != null) {
336+
return ExposedHelper.newUnHook(callback, replaceUnhook.getHookedMethod());
337+
}
338338

339339
final XC_MethodHook.Unhook unhook = DexposedBridge.hookMethod(method, callback);
340340
return ExposedHelper.newUnHook(callback, unhook.getHookedMethod());
@@ -346,22 +346,7 @@ public static Object invokeOriginalMethod(Member method, Object thisObject, Obje
346346
return DexposedBridge.invokeOriginalMethod(method, thisObject, args);
347347
}
348348

349-
private static Member replaceForCHA(Member member) {
350-
351-
if (member.getDeclaringClass() == Application.class && member.getName().equals("attach")) {
352-
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
353-
XposedBridge.log("replace Application.attach with ContextWrapper.attachBaseContext for CHA");
354-
return m;
355-
}
356-
357-
if (member.getDeclaringClass() == Application.class && member.getName().equals("onCreate")) {
358-
Method m = XposedHelpers.findMethodExact(ContextWrapper.class, "attachBaseContext", Context.class);
359-
XposedBridge.log("replace Application.onCreate with ContextWrapper.attachBaseContext for CHA");
360-
return m;
361-
}
362349

363-
return member;
364-
}
365350

366351
private static void initForXposedModule(Context context, ApplicationInfo applicationInfo, ClassLoader appClassLoader) {
367352
InputStream inputStream = null;
@@ -370,7 +355,7 @@ private static void initForXposedModule(Context context, ApplicationInfo applica
370355
inputStream = context.getAssets().open("xposed_init");
371356
System.setProperty("epic.force", "true");
372357
} catch (IOException e) {
373-
log(applicationInfo.packageName + " is not a Xposed module");
358+
Log.i(TAG, applicationInfo.packageName + " is not a Xposed module, do not init epic.force");
374359
} finally {
375360
closeSliently(inputStream);
376361
}
@@ -440,7 +425,7 @@ private static void initForXposedInstaller(Context context, ApplicationInfo appl
440425
if (!fakeVersionString.equals(oldVersion)) {
441426
writeXposedProperty(xposedProp, fakeVersionString, true);
442427
} else {
443-
log("xposed version keep same, continue.");
428+
Log.i(TAG, "xposed version keep same, continue.");
444429
}
445430
}
446431

0 commit comments

Comments
 (0)