23、CTS/VTS 认证:兼容性测试套件、测试用例编写、常见失败修复
做嵌入式Android系统,最头疼的环节之一就是过认证。CTS和VTS,说白了就是Google给你设的两道关卡。CTS管的是应用兼容性,VTS管的是底层驱动和内核。我刚开始带项目时,觉得这玩意儿就是跑个分,后来被坑了几次才明白——不过认证,你的ROM连出厂都别想。
这一章,我就把CTS/VTS的底裤扒干净。从测试套件怎么跑,到用例怎么写,再到那些常见的失败怎么修,咱们一条一条捋清楚。
CTS与VTS:到底测什么?
先搞清楚两个东西的区别。
| 项目 | CTS (Compatibility Test Suite) | VTS (Vendor Test Suite) |
|---|---|---|
| 测试对象 | Framework、API、应用行为 | HAL、内核、Vendor接口 |
| 关注点 | App能不能跑、API是否一致 | 驱动是否稳定、HAL实现是否正确 |
| 失败后果 | Google Play无法认证 | 系统稳定性差,可能死机 |
| 测试工具 | cts-tradefed | vts-tradefed |
CTS失败,用户装个微信可能闪退。VTS失败,你的摄像头可能打不开。我遇到过最离谱的一次,VTS的Camera HAL测试全挂,查了两天发现是HIDL接口里少传了一个参数。
测试套件怎么跑?
跑测试其实不复杂,但环境配置容易踩坑。我个人习惯用Linux环境,Ubuntu 20.04最稳。
先下载套件:
# 从AOSP源码编译
source build/envsetup.sh
lunch aosp_arm64-userdebug
make cts -j16
make vts -j16
# 或者直接下载预编译包
wget https://dl.google.com/dl/android/cts/android-cts-12.0_r1-linux_x86-arm.zip
unzip android-cts-12.0_r1-linux_x86-arm.zip
然后连接设备,开始跑:
# 进入CTS目录
cd android-cts/tools
./cts-tradefed
# 跑全量测试
run cts --plan CTS
# 跑某个模块
run cts --module CtsCameraTestCases
# 跑单个用例
run cts --module CtsCameraTestCases --test android.camera.cts.CameraTest#testPreview
VTS的跑法类似,只是命令换成vts-tradefed。嗯,这里要注意:跑VTS前,设备必须解锁bootloader,并且刷入userdebug版本。我刚开始用user版本跑,结果一堆测试直接跳过,浪费了半天。
测试用例编写:从零开始写一个CTS用例
有时候官方用例覆盖不全,或者你加了自定义硬件,就得自己写。写CTS用例说白了就是写一个Android JUnit测试,然后加上CTS的注解。
举个例子,假设你加了一个自定义传感器,需要验证它的数据范围:
package android.cts.mydevice;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.test.AndroidTestCase;
import com.android.compatibility.common.util.CtsTest;
@CtsTest
public class MySensorTest extends AndroidTestCase {
private SensorManager mSensorManager;
@Override
protected void setUp() throws Exception {
super.setUp();
mSensorManager = (SensorManager) getContext()
.getSystemService(Context.SENSOR_SERVICE);
}
public void testSensorRange() {
Sensor sensor = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
assertNotNull("Accelerometer not found", sensor);
float maxRange = sensor.getMaximumRange();
// 我遇到过传感器返回0的情况,所以加个边界检查
assertTrue("Range should be positive", maxRange > 0);
assertTrue("Range too small", maxRange > 19.6f); // 2g
}
}
写完之后,编译成APK,放到CTS的testcases目录下,然后通过tradefed跑。说白了,Google的CTS框架就是一个超级JUnit Runner,你只要遵循它的规则就行。
常见失败修复:那些年我踩过的坑
CTS/VTS失败的原因千奇百怪,但归纳起来就几类。我按频率排个序:
1. SELinux策略违规
这是最常见的失败。你加了新驱动,但没给对应的SELinux权限。日志里会看到avc: denied。
修复方法:
- 先看dmesg或logcat,找到被denied的domain和context
- 在device/manufacturer/device-name/sepolicy/下添加.te文件
- 比如:allow hal_sensors_default sensor_device:chr_file rw_file_perms;
我曾经因为少写了一个file_type的声明,导致VTS的Sensor测试全挂。查了两天,最后发现是.te文件里忘了加type_transition。
2. HIDL接口实现不完整
VTS会遍历所有HIDL接口,如果你的HAL没实现某个方法,直接fail。
举个例子,Camera HAL必须实现getCameraIdList,如果你返回了空列表,VTS就报错。
修复方法:
- 用vts-tradefed的--retry选项,只跑失败的用例
- 看VTS的详细日志,找到哪个接口没实现
- 补全HAL代码,重新编译vendor镜像
3. 资源文件缺失
CTS里有些测试会检查系统资源,比如壁纸、铃声、字体。如果你裁剪了系统,删了默认壁纸,CTS的CtsWallpaperTestCases就会挂。
修复方法:
- 在device.mk里确保PRODUCT_COPY_FILES包含了必要资源
- 或者直接继承aosp的通用资源包
4. 时间戳与系统时间问题
VTS里有些测试会检查系统启动时间、休眠时间。如果你的RTC驱动没调好,时间戳对不上,测试就fail。
我遇到过最奇葩的一个:VTS的SystemVendorTest,因为系统时区设成了UTC+8,但测试期望的是UTC,结果差了8小时。最后在build.prop里加了ro.timezone=UTC才过。
知识体系总览
下面这张图,是我自己总结的CTS/VTS认证知识结构。你可以把它当成一个检查清单:
避坑指南:我踩过的那些雷
最后,分享几个实战经验。这些坑我当年都踩过,你遇到了直接照着修就行。
- 跑CTS前一定要关掉动画: 开发者选项里把窗口动画、过渡动画、动画时长都设为0。否则有些UI测试会因为动画没结束而超时失败。
- VTS测试最好用userdebug版本: user版本会跳过很多需要root权限的测试,导致覆盖率不够。
- 日志要保留原始文件: CTS/VTS生成的test_result.xml和logcat.txt,别删。Google审核时可能会要求你提供这些文件。
- 不要一次性改太多: 我习惯每次只修一个失败,然后重新跑那个模块。如果一次性改一堆,出了问题都不知道是哪个改动引起的。
嗯,CTS/VTS认证说白了就是一场耐心战。你只要把SELinux、HIDL、资源文件这三个大头搞定,剩下的都是小问题。我当年第一次过CTS,整整磨了两周,但第二次做新项目时,三天就搞定了——因为踩过的坑都记在本子上了。