再聊解除HiddenApi限制
内容提要
本文讨论了Android系统中躲藏接口的约束免除方法,包括Android 9.0版本和Android 11.0版本的约束免除方法。解决方案包括反射调用和直接函数调用。最后,讨论了在Android 14和鸿蒙4版本中的反常补丁方法。
延伸解读
Android 9.0 豁免机制的核心
文章指出,Android 9.0 首次引入隐藏 API 限制,但通过反射调用 VMRuntime.setHiddenApiExemptions 并传入前缀 "L" 可豁免所有隐藏 API。其原理是系统在 ShouldDenyAccessToMemberImpl 中检查豁免列表,匹配则视为公开 API。这为后续版本提供了基础思路。
Android 11.0 的约束升级与应对
从 Android 11.0 开始,上层接口访问被收紧,VMRuntime 的 setHiddenApiExemptions 无法直接通过 Java 反射调用,只能从 native 层访问。文章给出两种方案:在 JNI_OnLoad 中反射调用,或直接 dlsym 调用 libart.so 中的导出函数。两者均需传入 "L" 前缀数组。
Android 14 与鸿蒙4 的异常与补丁
在 Android 14 和鸿蒙4 上,即使豁免成功,某些隐藏方法仍可能被拒绝,且日志显示 max-target-p 限制。文章推测 ROM 增加了缓存机制,并提出通过新建线程破坏调用栈历史,使 VM 无法识别调用者。该方法异步转同步,效率较低,仅建议在获取失败时作为补偿使用。
Q&A
如何在Android 9.0中解除HiddenApi的限制?
在Android 9.0中,可以通过找到API判别规则豁免点和成员特点位置来解除HiddenApi的限制,并设置豁免点。
Android 11.0中HiddenApi的访问限制有什么变化?
Android 11.0升级了上层接口的访问限制,用户只能通过native层访问HiddenApi。
解除HiddenApi限制的两种解决方案是什么?
解除HiddenApi限制的两种解决方案是反射调用和直接函数调用。
在Android 14和鸿蒙4中遇到的反常补丁问题是什么?
在Android 14和鸿蒙4中,某些情况下仍会出现访问HiddenApi的日志错误,可能与ROM的缓存机制有关。
如何使用新线程规避调用历史记录的问题?
可以通过创建新线程来规避调用历史记录的问题,从而避免HiddenApi访问的限制。
反射调用和直接函数调用的具体实现有什么不同?
反射调用通过Java反射机制实现,而直接函数调用则是通过导出C函数名直接调用系统库中的函数。