android P 隐藏API对系统APP的影响

本文深入探讨AndroidP中对第三方APK调用@hideAPI的限制,详细分析了对不同签名状态APK的影响,以及系统APK如何规避这些限制。同时,讨论了hiddenapi-package-whitelist.xml的作用和CTS测试的影响。

转载至 https://www.jianshu.com/p/8286c91fdcb9

android P限制了第三方APK对@hide API的调用,那么对系统APK有什么影响呢?

国内各大手机厂商对ROM进行各种定制,可以很容易绕过这些限制,那对于需要出海并且满足CTS要求的厂商有什么影响呢?

先说结论:对系统厂商APK没有任何影响,依然可调用任何API

  • 第三方APK,受hide限制

  • 系统platform签名APK,不受限制

  • 非platform签名APK,集成在system分区,又在hiddenapi-package-whitelist.xml,不受限制。(且目前不影响CTS)

一、对第三方APK、系统APK的影响

SDK28@hide 浅灰@hide 黑名单@systemapi
非platform签名
/data/app是,警告是,需permisison权限
/system/app是,警告是,需permisison权限
/system/priv-app是,警告是,需permisison权限
hiddenapi-package-whitelist.xml
(/system/app、priv-app)
是,需permisison权限
platform签名
/data/app
/system/app
/system/priv-app
是,需permisison权限

二、新增hiddenapi-package-whitelist.xml名单,能否通过CTS?

实测无影响。
但不确定google后续CTS版本是否加强检查,有风险

相关测试项:
CtsHiddenApiBlacklistApi27TestCases
CtsHiddenApiBlacklistCurrentApiTestCases
CtsHiddenApiBlacklistDebugClassTestCases
CtsHiddenApiKillswitchDebugClassTestCases
CtsHiddenApiKillswitchWhitelistTestCases
CtsHiddenApiKillswitchWildcardTestCases

三、Hide API限制原理

详细的原理牵扯到编译时、运行时,还是比较复杂的,下面仅从较宏观的角度阐明受限原理、加白原理。

a.访问受限原理
hiddenapi-light-greylist.txt包含的api,会在dex中对应的Method结构生成HiddenApiAccessFlags::kLightGreylist访问权限标记。

  1. 生成正常framework dex
  2. Hiddenapi工具根据hiddenapi-light-greylist.txt等配置文件对dex的access_flags进行修改
  3. 新的带access标记的framework dex

ART通过access_flags判断是否可以调用:

  Action action = GetActionFromAccessFlags(member->GetHiddenApiAccessFlags());
  if (action == kAllow) {
    return action;
  }

b.加白不受限原理

  1. 构造ApplicationInfo时会判断platform签名、hide-package-whitelist,来确定HIDDEN_API_ENFORCEMENT的flag
private boolean isAllowedToUseHiddenApis() {
return isSignedWithPlatformKey()
|| (isPackageWhitelistedForHiddenApis() && (isSystemApp() || isUpdatedSystemApp()));
}
  1. ActivityManagerService中startProcessLocked()启动进程时会把是否检查hide api的flag传给zygote
@HiddenApiEnforcementPolicy int policy =app.info.getHiddenApiEnforcementPolicy();
int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
runtimeFlags |= policyBits;
  1. fork新的app进程后,调用ZygoteHooks_nativePostForkChild( ),初始化art虚拟机参数hidden_api_policy_,设置不进行hide api检查的kNoChecks选项。



作者:十八砖
链接:https://www.jianshu.com/p/8286c91fdcb9
來源:简书

 

另外在 https://blog.youkuaiyun.com/zhangbijun1230/article/details/81036592 《一种绕过Android P上非SDK接口限制的简单方法》 一文中对于限制原理及解决方法解释的比较透彻,可以参考下。

Android 开发中,某些 API 被标记为 `@hide`,意味着它们未被包含在标准 SDK 中,通常不允许直接访问。然而,在某些特定场景下(如系统应用或特殊需求的应用),开发者可能需要访问这些隐藏 API。 ### 使用隐藏 API 的方法 1. **使用反射机制** 反射是访问隐藏 API 最常见的方式之一。通过 `Class.getDeclaredMethod()` 或 `Class.getDeclaredField()` 获取私有方法或字段,并调用 `setAccessible(true)` 来绕过访问控制限制。 示例: ```java try { Class<?> activityManagerClass = Class.forName("android.app.ActivityManager"); Method getMemoryInfoMethod = activityManagerClass.getMethod("getMemoryInfo"); getMemoryInfoMethod.setAccessible(true); ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); Object memoryInfo = getMemoryInfoMethod.invoke(activityManager); // 处理获取的内存信息 } catch (Exception e) { e.printStackTrace(); } ``` 2. **利用第三方库(如 `android-hidden-api`)** 第三方库可以简化对隐藏 API 的访问。例如,`android-hidden-api` 提供了封装好的工具类来访问部分隐藏 API。使用方式如下: ```java import com.github.anggrayudi.hiddenapi.internal.InternalHelper; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (InternalHelper.isSystemApp(this)) { Log.d("MainActivity", "当前应用是系统应用"); } else { Log.d("MainActivity", "当前应用不是系统应用"); } } } ``` 这种方式适用于已经封装好的功能[^1]。 3. **修改编译配置以允许访问隐藏 API** 在新版本的 Android Studio 中,可以通过修改 `build.gradle` 文件来添加自定义的编译参数,从而允许访问隐藏 API。例如,在根目录下的 `build.gradle` 文件中添加以下代码: ```groovy gradle.projectsEvaluated { tasks.withType(JavaCompile) { Set<File> fileSet = options.bootstrapClasspath.getFiles() List<File> newFileList = new ArrayList<>(); String path = "${getRootDir().getAbsolutePath()}\\app\\libs\\mini_framework.jar" newFileList.add(new File(path)) newFileList.addAll(fileSet) options.bootstrapClasspath = files(newFileList.toArray()) } } ``` 此外,还可以通过指定 `-Xbootclasspath/p:` 参数来加载额外的框架 JAR 包,以覆盖隐藏 API 的引用路径[^4]。 4. **使用 AIDL 接口或绑定系统服务** 对于某些隐藏的系统服务接口,可以通过 AIDL 定义接口并绑定到系统服务,进而访问隐藏 API。这种方式较为复杂,但适用于与系统服务交互的场景。 5. **使用 Android 系统镜像和源码构建环境** 如果开发的是系统级应用,可以直接基于 Android 源码进行开发,并将应用集成进系统镜像中。这样可以直接访问所有隐藏 API 和内部实现。 ### 注意事项 - **兼容性问题** 隐藏 API 并不受官方支持,不同 Android 版本之间可能存在差异,可能导致应用在不同设备上行为不一致。 - **安全性与审核风险** 访问隐藏 API 可能会引发安全漏洞,且在 Google Play 等应用市场上提交此类应用时,可能会因违反政策而被拒绝。 - **依赖管理** 使用第三方库时,需确保其兼容性和维护状态,避免引入不可控的代码。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值