From 2954b70dc0354bdeb1f64e7ac25f1e183828fda9 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Fri, 29 Jul 2022 22:27:17 +0800 Subject: [PATCH] Added invokeOriginalMember function in MethodFinder and merge some code --- docs/api/public/MethodFinder.md | 18 +++++++++++++ .../hook/core/finder/MethodFinder.kt | 26 ++++++++++++++++--- .../hook/param/wrapper/HookParamWrapper.kt | 4 +-- .../xposed/bridge/factory/YukiHookFactory.kt | 17 ++++++++++++ 4 files changed, 59 insertions(+), 6 deletions(-) diff --git a/docs/api/public/MethodFinder.md b/docs/api/public/MethodFinder.md index 40e40b40..7b9661d6 100644 --- a/docs/api/public/MethodFinder.md +++ b/docs/api/public/MethodFinder.md @@ -513,6 +513,24 @@ inner class Instance internal constructor(private val instance: Any?) > `Method` 实例处理类。 +##### original [method] + +```kotlin +fun original(): Instance +``` + +**变更记录** + +`v1.0.93` `新增` + +**功能描述** + +> 标识需要调用当前 `Method` 未经 Hook 的原始方法。 + +若当前 `Method` 并未 Hook 则会使用原始的 `Method.invoke` 方法调用。 + +!> 你只能在 (Xposed) 宿主环境中使用此功能。 + ##### call [method] ```kotlin diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt index 0f2493a1..242f1612 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt @@ -40,6 +40,7 @@ import com.highcapable.yukihookapi.hook.factory.hasExtends import com.highcapable.yukihookapi.hook.log.yLoggerW import com.highcapable.yukihookapi.hook.type.defined.UndefinedType import com.highcapable.yukihookapi.hook.utils.runBlocking +import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiHookHelper import java.lang.reflect.Method /** @@ -443,15 +444,32 @@ class MethodFinder @PublishedApi internal constructor( */ inner class Instance internal constructor(private val instance: Any?) { + /** 标识需要调用当前 [Method] 未经 Hook 的原始方法 */ + private var isCallOriginal = false + + /** + * 标识需要调用当前 [Method] 未经 Hook 的原始方法 + * + * 若当前 [Method] 并未 Hook 则会使用原始的 [Method.invoke] 方法调用 + * + * - ❗你只能在 (Xposed) 宿主环境中使用此功能 + * @return [Instance] 可继续向下监听 + */ + fun original(): Instance { + isCallOriginal = true + return this + } + /** * 执行方法 * @param param 方法参数 * @return [Any] or null */ - private fun baseCall(vararg param: Any?) = - if (param.isNotEmpty()) - (memberInstance as? Method?)?.invoke(instance, *param) - else (memberInstance as? Method?)?.invoke(instance) + private fun baseCall(vararg param: Any?) = (memberInstance as? Method?)?.let { + if (isCallOriginal) + YukiHookHelper.invokeOriginalMember(it, instance, *param) ?: it.invoke(instance, *param) + else it.invoke(instance, *param) + } /** * 执行方法 - 不指定返回值类型 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/HookParamWrapper.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/HookParamWrapper.kt index 03d9d24b..4b94a567 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/HookParamWrapper.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/HookParamWrapper.kt @@ -29,8 +29,8 @@ package com.highcapable.yukihookapi.hook.param.wrapper import com.highcapable.yukihookapi.annotation.YukiPrivateApi import com.highcapable.yukihookapi.hook.param.HookParam +import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiHookHelper import de.robv.android.xposed.XC_MethodHook -import de.robv.android.xposed.XposedBridge import java.lang.reflect.Member /** @@ -95,7 +95,7 @@ class HookParamWrapper internal constructor(private var baseParam: XC_MethodHook * @param args 参数实例 * @return [Any] or null */ - fun invokeOriginalMember(member: Member, vararg args: Any?): Any? = XposedBridge.invokeOriginalMethod(member, instance, args) + fun invokeOriginalMember(member: Member, vararg args: Any?): Any? = YukiHookHelper.invokeOriginalMember(member, instance, args) override fun toString() = "HookParamWrapper[$baseParam]" } \ No newline at end of file diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/factory/YukiHookFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/factory/YukiHookFactory.kt index 2d13a461..dad5caec 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/factory/YukiHookFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/factory/YukiHookFactory.kt @@ -173,6 +173,23 @@ internal object YukiHookHelper { return Pair(hookedMembers, isAlreadyHook) } + /** + * 执行原始 [Member] + * + * 未进行 Hook 的 [Member] + * @param member 实例 + * @param args 参数实例 + * @return [Any] or null + */ + internal fun invokeOriginalMember(member: Member, instance: Any?, vararg args: Any?): Any? { + val isHookedMember = YukiHookedMembers.hookedMembers.any { it.member.toString() == member.toString() } + val isQueueMethod = YukiHookedMembers.hookedQueueMethods.any { it.value.any { e -> e.member.toString() == member.toString() } } + val isQueueConstructor = YukiHookedMembers.hookedQueueConstructors.any { it.value.any { e -> e.member.toString() == member.toString() } } + return if (isHookedMember || isQueueMethod || isQueueConstructor) + XposedBridge.invokeOriginalMethod(member, instance, args) + else null + } + /** * 兼容对接 Hook 回调接口 * @return [XC_MethodHook] 原始接口