尧图精选

Android 16 GTS权限测试失败定位与跳过检查完整攻略

🕒 发布时间:2026/9/8 7:55:10 📁 来源:尧图网络
Android 16 的 GTS 包出来之后GtsPermissionTestcases 这个模块可以说是刷存在感最强的模块之一。我在日常处理机型认证时十个项目里有七八个都会卡在权限用例上报错还五花八门有的日志提示 default-permissions.xml 被改过有的预置应用多拿了权限还有的是开机向导逻辑和 AOSP 默认行为不一致甚至有的用例直接因为 appops 状态没同步而挂掉。这篇文章就把我处理这类问题的完整思路写下来包括这个模块到底在查什么、怎么定位失败用例、以及从测试执行到系统配置各个层面“跳过权限检查”的实际操作方便正在跑 Android 16 GTS 的同行直接抄作业。顺便提两个热词相关的背景Android 16 内部代号是 Baklava对应的字母是 BAPI level 是 36所以 GTS 包版本也升级到了 gts_16 系。跑之前最好先确认手里的包和系统版本对得上不然权限枚举规则都对不齐后面排查全是白忙活。文章适合三类人做 Android 系统定制的工程师、做 GMS/GTS 认证集成的人、以及被 permission 相关测试用例折磨到准备放弃的测试开发。1. 先搞明白 GtsPermissionTestcases 到底在查什么1.1 权限测试模块的职责边界GTS 全称 Google Test Suite是 GMS 认证前必须跑过的一套测试GtsPermissionTestcases 是里面专门负责权限体系校验的模块。它不像是普通单元测试那样只验证某个 API 能调通而是从系统全局角度检查权限授予规则、appops 运行状态、特殊权限管理逻辑是否符合 AOSP 预期。换句话说它看的不是“这个 app 能不能用相机”而是“你 ROM 里的权限系统是不是跟 Google 钦定的那套规则一致”。这个模块在 Android 16 上尤为重要因为这一代 GTS 对权限枚举粒度、运行时权限迁移、部分受限权限比如照片选择器相关权限的检查都更细了。如果你在定制 ROM 时改过权限默认授予策略或者把某个系统应用的权限保护级别调整过很容易在权限模块里一次性引爆三四组测试。我见过最夸张的一个项目GtsPermissionTestcases 跑出来 27 个失败最后定位到根因就是厂商在 default-permissions.xml 里给某个输入法预置了本来不该授予的 READ_CONTACTS 权限。1.2 和开机向导、系统属性之间的隐性关联很多刚开始跑 GTS 的人不理解为什么权限测试会和开机向导有关系。这里头有个很关键的逻辑AOSP 在开机向导完成后会把一部分默认权限通过 permission controller 写入到用户 0 的运行时权限库中。如果你的设备在测试前压根没走完引导流程或者定制 ROM 直接把 SetupWizard 跳过了那么权限初始化数据就是不完整的。GtsPermissionTestcases 里有些用例会去校验这种“开机后默认状态”一旦系统里缺少了原本应该由向导触发写入的权限记录结果自然是一路红。另外 Android 16 里权限系统还沿用了按“角色”来分派权限的能力比如默认拨号应用、默认短信应用、默认相册应用这些角色对应的权限集合也会被 GtsPermissionTestcases 覆盖。所以排查失败时不要只盯着某个单独权限要从系统角色分配、权限授予来源、用户空间状态三个维度一起看。我自己的习惯是跑 GTS 之前先把设备恢复出厂然后把开机向导完整走一遍最后关闭屏幕超时和分析弹窗再开始执行测试这样能避开非常多“历史残留”导致的假失败。2. 跑测试前的准备工作和结果定位方法2.1 环境、版本和基础命令跑 Android 16 GTS 第一件事是确认包版本。不同厂商拿到的 GTS 包可能是 gts_16_r1、gts_16_r2 这类小版本一定要选择与系统版本匹配的那一版否则 permission policy 的 baseline 对不上。解压后进入目录执行./gts-tradefed run gts -m GtsPermissionTestcases这是跑全模块的命令。机器上只预置了必要工具的 Linux 环境就行设备通过 adb 连接确认设备已经解锁、ADB 授权正常、没有多余弹窗干扰。整个跑完大概需要半小时到一个小时具体取决于设备性能和用例数量。如果只想先跑一部分用例快速验证可以用./gts-tradefed run gts -m GtsPermissionTestcases --test-filter 测试类名测试类名不填包名全路径时tradefed 会自动匹配。比如跑某个类下的全部方法直接写类名跑某个具体方法就写成“类名#方法名”。这种精确筛选方式在开发阶段特别有用可以省掉大量等待时间。2.2 从 test_result.xml 里准确提取失败项测试跑完后所有结果都归档在 gts 目录下的 results 文件夹里每次 session 一个独立子目录核心文件是 test_result.xml。我第一次看这个 XML 的时候也犯过迷糊不知道怎么快速抓失败用例。后来找到一个非常直接的办法用 grep 过滤 Failed 和 NotExecuted 节点。grep -E (Failed|NotExecuted) test_result.xml这样能一次性把失败的测试 name 和 failed_scenario 抓出来再配合日志文件里的 stack trace 定位具体原因。如果失败项很多也可以写个简单的 Python 脚本把 XML 解析成表格结构方便后面按模块汇总。说句实在话用脚本整理结果不是装优雅而是 GtsPermissionTestcases 失败项经常会出现“同样一个类多个方法连续挂掉”的情况靠肉眼扫文本容易漏。2.3 重试机制的正确用法GTS 第一轮跑完一定有那种偶发失败比如设备响应超时、弹窗遮挡、性能波动导致的用例中断。遇到这种情况不用急着排除先重试一次再看。tradefed 里重试命令通常是这样run gts --retry在 gts-tradefed 的交互 shell 里直接执行不带参数就是重试上一次 session 里失败和未执行的用例如果想指定重试某个历史 session可以在命令后面跟上 session id。重试能过滤掉一部分环境类假失败剩下的才是真需要关注的逻辑问题。我个人建议第一轮全量跑完后无论失败多少都先重试一次再开始逐个分析不然很容易把精力浪费在“跑一次都不一定复现”的偶发问题上。3. 跳过权限检查的几种实操方式3.1 执行阶段的以命令直接跳过最直接、最容易出效果的跳过方式就是在 tradefed 执行命令时加上排除参数。比如我只想验证除 GtsPermissionTestcases 之外的其他模块又不想改任何系统配置可以在跑 GTS 时把权限模块的某个类或者某个方法排除掉run gts -m GtsPermissionTestcases --exclude-filter 测试类名这个方法级别的排除同样支持run gts -m GtsPermissionTestcases --exclude-filter 测试类名#测试方法名从实际经验来看排除掉单个方法是最常用的。很多时候你只是临时要跑另一个模块不想让权限模块里某个已知的环境类用例卡住整个流程或者你在开发阶段已经确认某个权限逻辑和 AOSP 不一致需要后续版本修复但现在又要验证其他功能这时候用 exclude-filter 最省事。不过要提个醒排除参数在 tradefed 里是按类名精确匹配的拼错一个字母会直接导致排除不生效。正确做法是从 test_result.xml 里复制完整类名和方法名不要手敲。多个排除项用逗号分隔也可以比如run gts -m GtsPermissionTestcases --exclude-filter 类A#方法1,类B#方法2这种方式在完整成文的命令行里比较方便不用反复进入交互模式。还有一个选项是--skip-all它表示把所有测试模块的 precondition 都跳过但这不等同于跳过权限用例本体不要混为一谈。3.2 测试计划里的 ignore 和 skip 机制如果你拿到的是可修改源码的 GTS 测试工程或者在自己的 AOSP 维护分支里同步了 GTS 测试代码那还可以从测试代码本身入手给特定用例加Ignore注解。不过这里必须说清楚GTS 官方包是不允许改测试代码的因为 GTS 的最终结果需要上传给 Google 做 GMS 认证审核改动测试代码到后期很难解释清楚。所以这个办法只适用于你本地有测试源码、且不是为了最终认证提交的探索性场景。还有一种做法是在测试工程的 AndroidTest.xml 里通过配置项跳过某类用例但对于 GtsPermissionTestcases 来说实际用得比较少。因为权限测试用例大多数是直接测试系统行为的跟测试用例配置的关联不如那些需要额外 mock 的模块强。我自己的判断标准是如果是本地验证和调试用 Ignore 或者 exclude-filter 都行如果是准备最终认证就不要在测试层面上动手脚老老实实去修系统行为或者把问题上报给 Google 作为已知问题沟通。3.3 从系统配置层面让“权限检查”直接通过这才是真正解决权限测试失败的根治方案。很多失败不是测试套件本身的 bug而是设备系统里的权限相关配置和 AOSP 预期不一致导致测试检查时发现异常。最典型的几个问题点第一default-permissions.xml 被厂商改过。设备上的/etc/permissions/default-permissions.xml或/system/etc/permissions/default-permissions.xml里如果加了自定义的默认授权GTS 比对时就会发现和 AOSP 不匹配。这一类问题通常的修复方式是把文件内容还原到 AOSP 默认版本或者把不合理的权限授予项删掉。第二预置应用在安装时被额外授予了权限。有些项目在第一次开机安装预置应用时会调用 PackageManager 的 grantRuntimePermission导致测试中途检查到权限状态异常。排查时可以用 adb 查询adb shell cmd permission list-permissions -t看设备当前的运行时权限授予状态和测试用例预期逐个对比。第三appops 状态不同步。权限授予了但 appops 表里对应的 op 状态异常也是常见的失败原因。可以先用adb shell cmd appops get 包名确认某个 app 的各 op 模式。如果和预期不一致可以尝试通过重置命令恢复adb shell cmd appops reset --package 包名或者干脆把设备恢复出厂再重新配置。系统侧的“跳过权限检查”本质上不是跳过而是把系统行为修正到测试期望的状态让检查自然通过。这也是我强烈建议优先采用的路径因为最终 GTS 报告里如果充满大量“被排除”“被跳过”的用例Google 在认证审核时一定会找你要解释到时候再回头修系统代价比一开始就修大得多。3.4 什么时候才应该用“跳过”方案说到底跳过权限检查只是权宜之计。我一般把请求分成三类第一类是临时验证比如我只需要跑 GTS 别的大模块不想等权限模块的 N 个用例跑完直接用 exclude-filter 过滤掉这个没有任何问题第二类是已知问题失败根因已经定位到是 AOSP 已知行为或设备硬件差异有完整日志和复测记录这种情况下可以暂时排除并在提交认证时做说明第三类是尚未定位的失败这种绝对不能靠跳过混过去一定要先把根因弄清楚再决定怎么处理。我见过最坑的项目是前期开发图省事遇到权限失败就加 exclude-filter最后到认证前才发现有 20 多个用例根本没法编进白名单底层权限策略完全是乱的最后一个月都在返工。所以实操上我建议每天跑权限模块时如果遇到失败先看一眼根因哪怕是相同的用例连续三天失败也值得花十分钟分析一下 crash 日志而不是无脑屏蔽。4. 常见问题与排查技巧实录4.1 高频失败场景速查表现象常见原因推荐处理方式整模块大量失败失败点分散default-permissions.xml 或系统预置应用默认权限被改动还原 AOSP 默认权限文件测试前完成开机向导某个权限用例反复超时系统弹窗、UI 动画或无障碍服务干扰关闭动画、弹窗恢复出厂后重试exclude-filter 不生效类名/方法名拼写错误参数化用例实际名称和源码不同从 test_result.xml 中复制完整名称重试后仍失败日志里有 NPE系统权限数据库状态异常尝试pm clear-permission-flags或恢复出厂跳过后再跑其他模块仍失败权限服务状态被污染重启 system_server 或整机 reboot表格里的第四项值得单独展开一下。权限数据库状态异常在 Android 16 上出现的概率不低尤其是从旧版本 OTA 升级上来的设备旧用户空间里的 runtime-permissions.xml 记录经常和 GTS 预期不一致。这类问题用排除命令是解决不了的必须清理权限状态。我试过的有效做法是把相关包卸载后重装或者直接恢复出厂。如果你不想整机重置可以尝试adb shell pm clear-permission-flags 权限名 user-set --package 包名清除掉“用户手动设置”的标志位之后再重新授予或拒绝目标权限有时候能临时绕过状态不一致的问题。但注意这只适合调试场景最终认证前还是建议在干净用户空间里重跑全套。4.2 关于跳过率和 GTS 上报的几个细节很多工程师以为只要 GTS 跑完没有 failed只有 skipped 就没问题。实际上 GTS 上报时会统计模块执行率和跳过率GtsPermissionTestcases 作为认证重点模块如果跳过率明显高于正常水平Google 审阅报告时很可能会标记为“需提供解释”。这里分享一个我从实际认证过程中学到的经验尽量让最终上报的那一轮 GTS 保持低跳过率所有曾经被 exclude 过的用例最终都要回到系统修复或明确理由的轨道上。另外有同行问过我能不能修改 test_result.xml 来“手动跳过”我的建议是绝对不要。GTS 结果在提交时会经过安全和完整性校验修改本地生成报告文件不仅无法通过校验还可能直接影响项目认证资质属于高风险操作。宁可失败项多一点用重试和系统修复把它变成通过也不要动报告的歪脑筋。4.3 设备本身状态清理的心得跑权限测试模块前我建议按下面这个顺序把设备环境清理一遍恢复出厂设置确保没有旧数据污染。完整走一遍开机向导不要直接跳过。关闭“开发者选项”里的动画缩放避免 UI 动画导致的超时。检查设备上是否有多余的通知权限弹窗必要时临时关闭预置应用的通知。确认时间和时区正确有些测试依赖系统时间戳时间错乱会产生奇怪失败。这套流程看起来简单但跑 GTS 这类依赖系统状态的测试环境清理往往决定了失败率和复现率。我接手的新项目第一次跑权限模块前都会强制要求测试组按这个流程准备设备之后排查问题能少走很多弯路。5. 不要只盯着“跳过”先把失败归因做扎实GtsPermissionTestcases 的失败归因说难不难说容易也不容易。大多数失败最终都能落到四个维度权限授予配置、appops 状态、固件版本差异、测试环境残留。我处理的时候会在每次跑完测试后把失败用例的完整类名、错误信息、设备当时的权限状态一起导出存档方便对比验证。日志里如果出现权限枚举不一致优先检查设备是不是有深层定制的 permission; 如果出现空指针优先怀疑权限状态库损坏如果出现超时优先排查弹窗和动画。这里顺带说一个 Android 16 的新情况由于系统权限策略更细部分厂商把权限控制器裁剪或者替换成了自己的版本导致 GtsPermissionTestcases 在调用 permission controller 相关接口时拿到异常返回值。遇到这种问题命令行排除和系统配置都帮不上忙只能把权限控制器还原到 AOSP 原生实现。判断方法也不复杂在失败日志里搜“PermissionController”如果看到版本号或者包名不是 AOSP 原生那基本就是这条线的问题。6. 实操总结与个人建议跑了几轮 Android 16 GTS 之后我最大的感受是权限模块的问题很少是孤立存在的。一个 GtsPermissionTestcases 的失败背后往往连着默认权限配置、预置应用行为、开机向导状态、甚至权限控制器版本这一整条链。所以与其说“跳过权限检查”我更愿意把它当成一个临时手段而不是解决问题的终点。最后分享两个小技巧。第一个排查时多用cmd permission和cmd appops命令组合能把设备当前权限状态完整拉出来比看界面和瞎猜快得多。第二个如果发现是权限授予状态不一致导致的失败先试着重启 system_server 或者复跑一次该用例不要急着改系统配置因为很多状态类问题在服务重启后就会自愈。这样能把真正需要修改系统配置的问题压缩到最小范围。如果你现在正被 GtsPermissionTestcases 折磨希望这篇内容能帮你少踩几个坑。权限模块没有银弹但把基础流程打扎实大多数失败都是可以快速定位的。祝你跑测一把过。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →