|
15 | 15 | import java.util.List; |
16 | 16 |
|
17 | 17 | import io.github.libxposed.api.error.HookFailedError; |
| 18 | +import io.github.libxposed.annotation.SinceApi; |
18 | 19 |
|
19 | 20 | /** |
20 | 21 | * Xposed interface for modules to operate on application processes. |
21 | 22 | */ |
22 | 23 | @SuppressWarnings("unused") |
23 | 24 | public interface XposedInterface { |
24 | 25 | /** |
25 | | - * Behavior changes: all modules |
| 26 | + * API version 101. |
| 27 | + * <p>Behavior changes: all modules</p> |
26 | 28 | * <ul> |
27 | | - * <li> Modules cannot be injected into zygote; |
| 29 | + * <li>Modules cannot be injected into zygote; |
28 | 30 | * they are only loaded within the process of the scope.</li> |
29 | 31 | * </ul> |
30 | | - * Behavior changes: Modules targeting 101 or higher |
| 32 | + * <p>Behavior changes: Modules targeting 101 or higher</p> |
31 | 33 | * <ul> |
32 | 34 | * <li>This is the first API version.</li> |
33 | 35 | * </ul> |
34 | 36 | */ |
35 | 37 | int API_101 = 101; |
36 | 38 |
|
| 39 | + /** |
| 40 | + * API version 102. |
| 41 | + * <p>New features</p> |
| 42 | + * <ul> |
| 43 | + * <li>Hot reload allows modules to be updated without restarting the process.</li> |
| 44 | + * <li>Module entries can stop receiving subsequent lifecycle callbacks.</li> |
| 45 | + * <li>Hooks can be atomically replaced by api or same id.</li> |
| 46 | + * </ul> |
| 47 | + * <p>Behavior changes: Modules targeting 102 or higher</p> |
| 48 | + * <ul> |
| 49 | + * <li>Libxposed modules can not call legacy {@code de.robv.android.xposed} APIs.</li> |
| 50 | + * </ul> |
| 51 | + */ |
| 52 | + int API_102 = 102; |
| 53 | + |
37 | 54 | /** |
38 | 55 | * The API version of this <b>library</b>. This is a static value for the framework. |
39 | 56 | * Modules should use {@link #getApiVersion()} to check the API version at runtime. |
40 | 57 | */ |
41 | | - int LIB_API = API_101; |
| 58 | + int LIB_API = API_102; |
42 | 59 |
|
43 | 60 | /** |
44 | 61 | * The framework has the capability to hook system_server and other system processes. |
@@ -279,6 +296,36 @@ interface HookHandle { |
279 | 296 | * Cancels the hook. This method is idempotent. It is safe to call this method multiple times. |
280 | 297 | */ |
281 | 298 | void unhook(); |
| 299 | + |
| 300 | + /** |
| 301 | + * Gets the unique id of the hook, or null if the hook is not assigned with an id. |
| 302 | + */ |
| 303 | + @SinceApi(API_102) |
| 304 | + @Nullable |
| 305 | + String getId(); |
| 306 | + |
| 307 | + /** |
| 308 | + * Atomically replaces this hook with a new hooker and returns the new hook handle. |
| 309 | + * <p> |
| 310 | + * The replacement keeps the executable, priority, exception handling mode, and id of this hook. |
| 311 | + * For a hook with an id, this targets the same hook as creating a new hook on the same executable |
| 312 | + * with the same id. This method is the handle-based form of replacement and can also replace a |
| 313 | + * hook without an id. It is useful during hot reloading when new code receives old hook handles |
| 314 | + * from {@link XposedModuleInterface.HotReloadedParam#getOldHookHandles()}. After a successful |
| 315 | + * replacement, this handle is no longer valid. |
| 316 | + * </p> |
| 317 | + * <p>The hook chain is snapshot based. Replacing a hook while a call is running does not affect |
| 318 | + * that in-flight call.</p> |
| 319 | + * |
| 320 | + * @param hooker The new hooker object |
| 321 | + * @return The new handle for the replaced hook |
| 322 | + * @throws IllegalArgumentException if hooker is invalid |
| 323 | + * @throws IllegalStateException if this hook handle is no longer valid |
| 324 | + * @throws HookFailedError if replacement fails due to framework internal error |
| 325 | + */ |
| 326 | + @SinceApi(API_102) |
| 327 | + @NonNull |
| 328 | + HookHandle replaceHook(@NonNull Hooker hooker); |
282 | 329 | } |
283 | 330 |
|
284 | 331 | /** |
@@ -344,10 +391,25 @@ interface HookBuilder { |
344 | 391 | */ |
345 | 392 | @NonNull |
346 | 393 | HookHandle intercept(@NonNull Hooker hooker); |
| 394 | + |
| 395 | + /** |
| 396 | + * Sets a unique id for the hook, default to {@code null}. An id is used for exclusively identifying |
| 397 | + * a hook in the same module on the executable. A new hook with the same id in the same module on |
| 398 | + * the executable will replace the old one atomically, and the old hook handle will be invalid. |
| 399 | + * Hook ids are isolated between modules. |
| 400 | + * |
| 401 | + * <p>The hook chain is snapshot based. Replacing or adding a hook while a call is running does not |
| 402 | + * affect that in-flight call.</p> |
| 403 | + * |
| 404 | + * @param id The id for the hook. It can be null if you don't care about replacing the hook later. |
| 405 | + * @return The builder itself for chaining |
| 406 | + */ |
| 407 | + @SinceApi(API_102) |
| 408 | + HookBuilder setId(@Nullable String id); |
347 | 409 | } |
348 | 410 |
|
349 | 411 | /** |
350 | | - * Gets the runtime Xposed API version. Framework implementations must <b>not</b> override this method. |
| 412 | + * Gets the runtime Xposed API version. Framework implementations <b>must not</b> override this method. |
351 | 413 | */ |
352 | 414 | default int getApiVersion() { |
353 | 415 | return LIB_API; |
|
0 commit comments