Skip to content

Commit 40f09cf

Browse files
authored
Adapt LSPosedBridge to convention-based hooker discovery (#534)
We update `LSPosedBridge` to align with upstream API changes, which have replaced annotation-based hooker discovery with a naming convention. The `doHook` implementation has been refactored to: - Remove dependencies on the deleted `io.github.libxposed.api.annotations` package (`XposedHooker`, `BeforeInvocation`, `AfterInvocation`). - Scan for public static methods explicitly named `before` and `after` instead of relying on annotations. - Enforce validation on these named methods to ensure they match the required signatures. To adapt to this change, existing Hooker classes are refactored by removing the deprecated annotations and renaming their callback methods to `before` and `after` respectively.
1 parent d61aa69 commit 40f09cf

File tree

11 files changed

+23
-58
lines changed

11 files changed

+23
-58
lines changed

core/proguard-rules.pro

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
-keepclassmembers class org.lsposed.lspd.impl.LSPosedHookCallback {
2323
public <methods>;
2424
}
25-
-keep,allowoptimization,allowobfuscation @io.github.libxposed.api.annotations.* class * {
26-
@io.github.libxposed.api.annotations.BeforeInvocation <methods>;
27-
@io.github.libxposed.api.annotations.AfterInvocation <methods>;
25+
-keepclassmembers,allowoptimization class ** implements io.github.libxposed.api.XposedInterface$Hooker {
26+
public static *** before();
27+
public static *** before(io.github.libxposed.api.XposedInterface$BeforeHookCallback);
28+
public static void after();
29+
public static void after(io.github.libxposed.api.XposedInterface$AfterHookCallback);
30+
public static void after(io.github.libxposed.api.XposedInterface$AfterHookCallback, ***);
2831
}
2932
-assumenosideeffects class android.util.Log {
3033
public static *** v(...);

core/src/main/java/org/lsposed/lspd/hooker/AttachHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@
44

55
import de.robv.android.xposed.XposedInit;
66
import io.github.libxposed.api.XposedInterface;
7-
import io.github.libxposed.api.annotations.AfterInvocation;
8-
import io.github.libxposed.api.annotations.XposedHooker;
97

10-
@XposedHooker
118
public class AttachHooker implements XposedInterface.Hooker {
129

13-
@AfterInvocation
14-
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
10+
public static void after(XposedInterface.AfterHookCallback callback) {
1511
XposedInit.loadModules((ActivityThread) callback.getThisObject());
1612
}
1713
}

core/src/main/java/org/lsposed/lspd/hooker/CrashDumpHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@
44
import org.lsposed.lspd.util.Utils.Log;
55

66
import io.github.libxposed.api.XposedInterface;
7-
import io.github.libxposed.api.annotations.BeforeInvocation;
8-
import io.github.libxposed.api.annotations.XposedHooker;
97

10-
@XposedHooker
118
public class CrashDumpHooker implements XposedInterface.Hooker {
129

13-
@BeforeInvocation
14-
public static void beforeHookedMethod(XposedInterface.BeforeHookCallback callback) {
10+
public static void before(XposedInterface.BeforeHookCallback callback) {
1511
try {
1612
var e = (Throwable) callback.getArgs()[0];
1713
LSPosedBridge.log("Crash unexpectedly: " + Log.getStackTraceString(e));

core/src/main/java/org/lsposed/lspd/hooker/HandleSystemServerProcessHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@
2727
import org.lsposed.lspd.util.Hookers;
2828

2929
import io.github.libxposed.api.XposedInterface;
30-
import io.github.libxposed.api.annotations.AfterInvocation;
31-
import io.github.libxposed.api.annotations.XposedHooker;
3230

3331
// system_server initialization
34-
@XposedHooker
3532
public class HandleSystemServerProcessHooker implements XposedInterface.Hooker {
3633

3734
public interface Callback {
@@ -42,8 +39,7 @@ public interface Callback {
4239
public static volatile Callback callback = null;
4340

4441
@SuppressLint("PrivateApi")
45-
@AfterInvocation
46-
public static void afterHookedMethod() {
42+
public static void after() {
4743
Hookers.logD("ZygoteInit#handleSystemServerProcess() starts");
4844
try {
4945
// get system_server classLoader

core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCreateCLHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,8 @@
5151
import de.robv.android.xposed.callbacks.XC_LoadPackage;
5252
import io.github.libxposed.api.XposedInterface;
5353
import io.github.libxposed.api.XposedModuleInterface;
54-
import io.github.libxposed.api.annotations.AfterInvocation;
55-
import io.github.libxposed.api.annotations.XposedHooker;
5654

5755
@SuppressLint("BlockedPrivateApi")
58-
@XposedHooker
5956
public class LoadedApkCreateCLHooker implements XposedInterface.Hooker {
6057
private final static Field defaultClassLoaderField;
6158

@@ -77,8 +74,7 @@ static void addLoadedApk(LoadedApk loadedApk) {
7774
loadedApks.add(loadedApk);
7875
}
7976

80-
@AfterInvocation
81-
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
77+
public static void after(XposedInterface.AfterHookCallback callback) {
8278
LoadedApk loadedApk = (LoadedApk) callback.getThisObject();
8379

8480
if (callback.getArgs()[0] != null || !loadedApks.contains(loadedApk)) {

core/src/main/java/org/lsposed/lspd/hooker/LoadedApkCtorHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,11 @@
2929
import de.robv.android.xposed.XposedHelpers;
3030
import de.robv.android.xposed.XposedInit;
3131
import io.github.libxposed.api.XposedInterface;
32-
import io.github.libxposed.api.annotations.AfterInvocation;
33-
import io.github.libxposed.api.annotations.XposedHooker;
3432

3533
// when a package is loaded for an existing process, trigger the callbacks as well
36-
@XposedHooker
3734
public class LoadedApkCtorHooker implements XposedInterface.Hooker {
3835

39-
@AfterInvocation
40-
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
36+
public static void after(XposedInterface.AfterHookCallback callback) {
4137
Hookers.logD("LoadedApk#<init> starts");
4238

4339
try {

core/src/main/java/org/lsposed/lspd/hooker/OpenDexFileHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@
66
import org.lsposed.lspd.nativebridge.HookBridge;
77

88
import io.github.libxposed.api.XposedInterface;
9-
import io.github.libxposed.api.annotations.AfterInvocation;
10-
import io.github.libxposed.api.annotations.XposedHooker;
119

12-
@XposedHooker
1310
public class OpenDexFileHooker implements XposedInterface.Hooker {
1411

15-
@AfterInvocation
16-
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
12+
public static void after(XposedInterface.AfterHookCallback callback) {
1713
ClassLoader classLoader = null;
1814
for (var arg : callback.getArgs()) {
1915
if (arg instanceof ClassLoader) {

core/src/main/java/org/lsposed/lspd/hooker/StartBootstrapServicesHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,10 @@
3232
import de.robv.android.xposed.callbacks.XC_LoadPackage;
3333
import io.github.libxposed.api.XposedInterface;
3434
import io.github.libxposed.api.XposedModuleInterface;
35-
import io.github.libxposed.api.annotations.BeforeInvocation;
36-
import io.github.libxposed.api.annotations.XposedHooker;
3735

38-
@XposedHooker
3936
public class StartBootstrapServicesHooker implements XposedInterface.Hooker {
4037

41-
@BeforeInvocation
42-
public static void beforeHookedMethod() {
38+
public static void before() {
4339
logD("SystemServer#startBootstrapServices() starts");
4440

4541
try {

core/src/main/java/org/lsposed/lspd/impl/LSPosedBridge.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212

1313
import de.robv.android.xposed.XposedBridge;
1414
import io.github.libxposed.api.XposedInterface;
15-
import io.github.libxposed.api.annotations.AfterInvocation;
16-
import io.github.libxposed.api.annotations.BeforeInvocation;
17-
import io.github.libxposed.api.annotations.XposedHooker;
1815
import io.github.libxposed.api.errors.HookFailedError;
1916

2017
public class LSPosedBridge {
@@ -218,16 +215,14 @@ public static void dummyCallback() {
218215
throw new IllegalArgumentException("Cannot hook Method.invoke");
219216
} else if (hooker == null) {
220217
throw new IllegalArgumentException("hooker should not be null!");
221-
} else if (hooker.getAnnotation(XposedHooker.class) == null) {
222-
throw new IllegalArgumentException("Hooker should be annotated with @XposedHooker");
223218
}
224219

225220
Method beforeInvocation = null, afterInvocation = null;
226221
var modifiers = Modifier.PUBLIC | Modifier.STATIC;
227222
for (var method : hooker.getDeclaredMethods()) {
228-
if (method.getAnnotation(BeforeInvocation.class) != null) {
223+
if (method.getName().equals("before")) {
229224
if (beforeInvocation != null) {
230-
throw new IllegalArgumentException("More than one method annotated with @BeforeInvocation");
225+
throw new IllegalArgumentException("More than one method named before");
231226
}
232227
boolean valid = (method.getModifiers() & modifiers) == modifiers;
233228
var params = method.getParameterTypes();
@@ -237,13 +232,12 @@ public static void dummyCallback() {
237232
valid = false;
238233
}
239234
if (!valid) {
240-
throw new IllegalArgumentException("BeforeInvocation method format is invalid");
235+
throw new IllegalArgumentException("before method format is invalid");
241236
}
242237
beforeInvocation = method;
243-
}
244-
if (method.getAnnotation(AfterInvocation.class) != null) {
238+
} else if (method.getName().equals("after")) {
245239
if (afterInvocation != null) {
246-
throw new IllegalArgumentException("More than one method annotated with @AfterInvocation");
240+
throw new IllegalArgumentException("More than one method named after");
247241
}
248242
boolean valid = (method.getModifiers() & modifiers) == modifiers;
249243
valid &= method.getReturnType().equals(void.class);
@@ -254,13 +248,13 @@ public static void dummyCallback() {
254248
valid = false;
255249
}
256250
if (!valid) {
257-
throw new IllegalArgumentException("AfterInvocation method format is invalid");
251+
throw new IllegalArgumentException("after method format is invalid");
258252
}
259253
afterInvocation = method;
260254
}
261255
}
262256
if (beforeInvocation == null && afterInvocation == null) {
263-
throw new IllegalArgumentException("No method annotated with @BeforeInvocation or @AfterInvocation");
257+
throw new IllegalArgumentException("No method named before or after found in " + hooker.getName());
264258
}
265259
try {
266260
if (beforeInvocation == null) {
@@ -271,7 +265,7 @@ public static void dummyCallback() {
271265
var ret = beforeInvocation.getReturnType();
272266
var params = afterInvocation.getParameterTypes();
273267
if (ret != void.class && params.length == 2 && !ret.equals(params[1])) {
274-
throw new IllegalArgumentException("BeforeInvocation and AfterInvocation method format is invalid");
268+
throw new IllegalArgumentException("before and after method format is invalid");
275269
}
276270
}
277271
} catch (NoSuchMethodException e) {

magisk-loader/src/main/java/org/lsposed/lspd/util/ParasiticManagerSystemHooker.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
import org.lsposed.lspd.util.Utils;
1313

1414
import io.github.libxposed.api.XposedInterface;
15-
import io.github.libxposed.api.annotations.AfterInvocation;
16-
import io.github.libxposed.api.annotations.XposedHooker;
1715

1816

1917
public class ParasiticManagerSystemHooker implements HandleSystemServerProcessHooker.Callback {
@@ -33,10 +31,8 @@ public static void beforeHookedMethod(XposedInterface.BeforeHookCallback callbac
3331
}
3432
}*/
3533

36-
@XposedHooker
3734
private static class Hooker implements XposedInterface.Hooker {
38-
@AfterInvocation
39-
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) throws Throwable {
35+
public static void after(XposedInterface.AfterHookCallback callback) throws Throwable {
4036
var intent = (Intent) callback.getArgs()[0];
4137
if (intent == null) return;
4238
if (!intent.hasCategory("org.lsposed.manager.LAUNCH_MANAGER")) return;

0 commit comments

Comments
 (0)