CTS 认证踩坑记录:那些让人头疼的失败项

4 阅读4分钟

CTS 认证踩坑记录:那些让人头疼的失败项

前言

最近在做 GMS 认证,CTS 测试跑了无数遍,每次都有新的失败项冒出来。这篇文章记录下踩过的坑,希望能帮到同样在做认证的朋友。

什么是 CTS

CTS (Compatibility Test Suite) 是 Google 的兼容性测试套件,用来验证设备是否符合 Android 标准。想要预装 GMS(Google Mobile Services),必须通过 CTS 测试。

测试项超级多,涵盖:

  • API 兼容性
  • 系统行为
  • 性能指标
  • 安全机制
  • 媒体编解码
  • ...

一共几千个测试用例,跑完要好几个小时。

坑一:SELinux 权限问题

失败日志

FAILURES:
testSELinuxFileContexts FAIL
avc: denied { read } for pid=1234 scontext=u:r:system_app:s0
tcontext=u:object_r:vendor_file:s0 tclass=file

原因

我们在 /vendor 目录下放了个配置文件,系统应用需要读取。但 SELinux 策略没配置,导致权限被拒绝。

解决方案

添加 SELinux 规则:

# device/xxx/sepolicy/system_app.te
allow system_app vendor_configs_file:file r_file_perms;

重新编译系统,测试通过。

坑二:系统属性命名不规范

失败日志

FAILURES:
testSystemProperties FAIL
Property 'sys.device.temp' does not follow naming convention

原因

我们自定义的系统属性用了 sys. 前缀,但 CTS 要求厂商自定义属性必须用 persist.vendor.vendor. 前缀。

解决方案

修改属性名:

- SystemProperties.set("sys.device.temp", temp);
+ SystemProperties.set("persist.vendor.device.temp", temp);

同时修改读取的地方。这个改动影响面比较大,要全局搜索替换。

坑三:修改了系统 API 的行为

失败日志

FAILURES:
testActivityManagerGetRunningTasks FAIL
Expected max 1 task, but got 5

原因

为了实现某个需求,我们修改了 ActivityManager.getRunningTasks() 的返回逻辑,返回了所有任务。但 CTS 期望这个 API 最多返回 1 个任务(从 Android L 开始的限制)。

解决方案

回退修改,改用其他方式实现需求。不要随意修改系统 API 的行为,会导致兼容性问题。

坑四:预装应用的签名问题

失败日志

FAILURES:
testPreinstalledApps FAIL
App 'com.example.customapp' is signed with platform key

原因

我们预装的自定义应用用了 platform 签名,但 CTS 不允许第三方应用使用系统签名。

解决方案

重新用普通签名打包应用,去掉 android:sharedUserId="android.uid.system"

如果确实需要系统权限,可以通过白名单机制实现,而不是用系统签名。

坑五:性能测试不达标

失败日志

FAILURES:
testAppLaunchTime FAIL
Launch time: 1250ms, expected < 1000ms

原因

应用启动时在主线程做了太多初始化工作,导致启动慢。

解决方案

优化启动流程:

  • 延迟非必要的初始化
  • 异步加载资源
  • 减少 Application.onCreate() 的耗时
@Override
public void onCreate() {
    super.onCreate();
    // 只做必要的初始化
    initCrashHandler();

    // 其他初始化延迟到后台线程
    new Thread(() -> {
        initDatabase();
        initImageLoader();
    }).start();
}

CTS 调试技巧

1. 运行单个测试模块

不用每次跑全量测试,可以只跑失败的模块:

cts-tradefed run cts -m CtsPermissionTestCases

2. 查看详细日志

# 实时查看 logcat
adb logcat -v time > cts_log.txt

# 查看测试报告
# 在 android-cts/results/ 目录下

3. 复现单个失败用例

cts-tradefed run cts -m CtsPermissionTestCases -t android.permission.cts.PermissionTest#testSomePermission

经验总结

1. 提前规划,避免返工

CTS 测试要尽早做,不要等到项目后期才开始。很多失败项需要改系统代码,改动量大,风险高。

2. 不要随意修改 Framework

系统定制要克制,能在应用层实现就不要改 Framework。改了 Framework 很容易导致 CTS 失败。

3. 关注 Android 版本差异

不同 Android 版本的 CTS 测试项不一样。升级系统版本时,要重新跑 CTS。

4. 保持代码规范

SELinux 策略、系统属性命名、权限声明等,都要遵循 Android 规范。不规范的代码迟早会在 CTS 上暴露。

常见失败项速查

失败类型常见原因解决方向
SELinux权限策略缺失添加 sepolicy 规则
系统属性命名不规范使用 vendor. 前缀
API 行为修改了系统 API回退修改
签名问题滥用系统签名改用普通签名
性能测试启动/响应慢优化性能
权限测试权限声明错误检查 AndroidManifest.xml

最后

CTS 认证是个体力活,需要耐心和细心。每次失败都是学习的机会,能让你更深入理解 Android 系统的设计规范。

希望这篇文章能帮到正在做 CTS 的朋友,少踩点坑。


有问题欢迎评论区交流,点赞收藏支持一下!