Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit a535c02

Browse files
committed
Invalidate callers of all methods overridden by XTypedArray
This is necessary because it's similar to a hook. Without this, some calls to these methods might still be inlined with the original implementation, not with the code in XTypedArray. This is only necessary for SDK24+, previously inlining was disabled completely.
1 parent 3d42b0e commit a535c02

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

app/src/main/java/de/robv/android/xposed/XposedBridge.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,8 @@ public static Object invokeOriginalMethod(Member method, Object thisObject, Obje
506506
/*package*/ static native void closeFilesBeforeForkNative();
507507
/*package*/ static native void reopenFilesAfterForkNative();
508508

509+
/*package*/ static native void invalidateCallersNative(Member[] methods);
510+
509511
/** @hide */
510512
public static final class CopyOnWriteSortedSet<E> {
511513
private transient volatile Object[] elements = EMPTY_ARRAY;

app/src/main/java/de/robv/android/xposed/XposedHelpers.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import java.security.MessageDigest;
2222
import java.security.NoSuchAlgorithmException;
2323
import java.util.HashMap;
24+
import java.util.HashSet;
2425
import java.util.LinkedList;
2526
import java.util.List;
27+
import java.util.Set;
2628
import java.util.WeakHashMap;
2729
import java.util.concurrent.atomic.AtomicInteger;
2830
import java.util.zip.ZipFile;
@@ -1663,6 +1665,52 @@ protected AtomicInteger initialValue() {
16631665
}
16641666
}
16651667

1668+
//#################################################################################################
1669+
1670+
/**
1671+
* Returns the method that is overridden by the given method.
1672+
* It returns {@code null} if the method doesn't override another method or if that method is
1673+
* abstract, i.e. if this is the first implementation in the hierarchy.
1674+
*/
1675+
/*package*/ static Method getOverriddenMethod(Method method) {
1676+
int modifiers = method.getModifiers();
1677+
if (Modifier.isStatic(modifiers) || Modifier.isPrivate(modifiers)) {
1678+
return null;
1679+
}
1680+
1681+
String name = method.getName();
1682+
Class<?>[] parameters = method.getParameterTypes();
1683+
Class<?> clazz = method.getDeclaringClass().getSuperclass();
1684+
while (clazz != null) {
1685+
try {
1686+
Method superMethod = clazz.getDeclaredMethod(name, parameters);
1687+
modifiers = superMethod.getModifiers();
1688+
if (!Modifier.isPrivate(modifiers) && !Modifier.isAbstract(modifiers)) {
1689+
return superMethod;
1690+
} else {
1691+
return null;
1692+
}
1693+
} catch (NoSuchMethodException ignored) {
1694+
clazz = clazz.getSuperclass();
1695+
}
1696+
}
1697+
return null;
1698+
}
1699+
1700+
/**
1701+
* Returns all methods which this class overrides.
1702+
*/
1703+
/*package*/ static Set<Method> getOverriddenMethods(Class<?> clazz) {
1704+
Set<Method> methods = new HashSet<>();
1705+
for (Method method : clazz.getDeclaredMethods()) {
1706+
Method overridden = getOverriddenMethod(method);
1707+
if (overridden != null) {
1708+
methods.add(overridden);
1709+
}
1710+
}
1711+
return methods;
1712+
}
1713+
16661714
//#################################################################################################
16671715
// TODO helpers for view traversing
16681716
/*To make it easier, I will try and implement some more helpers:

app/src/main/java/de/robv/android/xposed/XposedInit.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@
2626
import java.io.InputStream;
2727
import java.io.InputStreamReader;
2828
import java.lang.ref.WeakReference;
29+
import java.lang.reflect.Member;
30+
import java.lang.reflect.Method;
2931
import java.util.ArrayList;
3032
import java.util.Arrays;
3133
import java.util.HashSet;
3234
import java.util.Map;
35+
import java.util.Set;
3336
import java.util.zip.ZipEntry;
3437
import java.util.zip.ZipFile;
3538

@@ -50,6 +53,7 @@
5053
import static de.robv.android.xposed.XposedHelpers.findFieldIfExists;
5154
import static de.robv.android.xposed.XposedHelpers.getBooleanField;
5255
import static de.robv.android.xposed.XposedHelpers.getObjectField;
56+
import static de.robv.android.xposed.XposedHelpers.getOverriddenMethods;
5357
import static de.robv.android.xposed.XposedHelpers.getParameterIndexByType;
5458
import static de.robv.android.xposed.XposedHelpers.setObjectField;
5559
import static de.robv.android.xposed.XposedHelpers.setStaticBooleanField;
@@ -351,6 +355,12 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
351355
}
352356
}
353357

358+
// Invalidate callers of methods overridden by XTypedArray
359+
if (Build.VERSION.SDK_INT >= 24) {
360+
Set<Method> methods = getOverriddenMethods(XResources.XTypedArray.class);
361+
XposedBridge.invalidateCallersNative(methods.toArray(new Member[methods.size()]));
362+
}
363+
354364
// Replace TypedArrays with XTypedArrays
355365
hookAllConstructors(TypedArray.class, new XC_MethodHook() {
356366
@Override

0 commit comments

Comments
 (0)