Android Compatibility

文章目录

    • 词汇表
    • [CTS 组件](#CTS 组件)
    • [Trade Federation](#Trade Federation)
    • [安装 aapt 和 adb](#安装 aapt 和 adb)
    • 源码
    • 下载
    • MCTS
    • 使用
    • 测试结果
    • 日志
    • CtsDeqpTestCases
    • CtsViewTestCases
    • CtsDisplayTestCases
    • [list module 中带有 [instant],[secondary_user] 等后缀](#list module 中带有 [instant],[secondary_user] 等后缀)
    • [Tradefed 如何处理 `--test` 选项的?](#Tradefed 如何处理 --test 选项的?)
    • [Tradefed 如何处理 `--include-filter` 选项的?](#Tradefed 如何处理 --include-filter 选项的?)
    • [Tradefed 是如何处理非通用选项的?](#Tradefed 是如何处理非通用选项的?)
    • [run plan 和 run module 的区别?](#run plan 和 run module 的区别?)
    • [测试结果为 `Assumption Failure`](#测试结果为 Assumption Failure)
    • [测试结果为 `IGNORED`](#测试结果为 IGNORED)
    • 参考资料
    • [一个 plan 是如何知道要运行那些模块的呢?](#一个 plan 是如何知道要运行那些模块的呢?)
    • 无法在设备上运行测试
    • [加了 Host 的 java 代理后失败](#加了 Host 的 java 代理后失败)
    • [ClearcutClient 组建失败](#ClearcutClient 组建失败)
    • [运行 CtsDisplayTestCases 报错](#运行 CtsDisplayTestCases 报错)

兼容的目标是可以运行 Android SDK 和 NDK 编写的任何第三方应用。这要求 Android 设备必须遵守 CDD,并通过 CTS 测试。

词汇表

DUT:Device Under Test,被测设备;

CDD:compatibility definition document,兼容性定义文档;AOSP 是 Android 的参考实现,设备厂商应尽可能基于 AOSP 实现。

CTS:compatibility test suite,兼容性测试套件;无法做到面面俱到,主要针对软件行为做测试,无法探测硬件的真实表现。

GMS:Google Mobile Services,谷歌移动服务;会有一个 Google Play Services,管理谷歌应用与谷歌服务器之间的连接,并对应用提供 API,实现 FCM 推送,登录服务,地图服务,支付服务等等。

CTS 组件

  1. Trade Federation:自动化测试框架
  2. CTS automated tests:可以运行在 Trade Federation 框架下的测试
  3. CTS Verifier (CTS-V) tests:需要手动运行的测试,通常和硬件相关,需要人来判断结果
  4. CTS Verifier (CTS-V) app:运行手动测试和收集结果的应用
  5. Test case:测试用例
  6. Test configuration:由一组测试用例 + 环境配置组成的自动化测试
  7. Test module:由一组用于测试相同功能的测试用例组成的测试配置
  8. Test plan:由一系列测试模块组成的测试配置,源码位于 aosp 工程的 cts/tools/cts-tradefed/res/config/xxx.xml

Trade Federation

Trade Federation 是一款在主机上运行的 Java 应用,它通过 adb 与一部或多部 Android 设备进行通信,专门用于在 Android 设备上运行测试。

工程源码路径:tools/tradefederation/

TF 测试生命周期

  1. build_provider:创建运行测试所需的所有文件,可能会从 google 服务器下载
  2. target_preparer:根据测试配置将测试环境设置为必要状态,包括主机和设备
  3. test:运行测试
  4. result_reporter:向配置的服务报告运行结果

TF 的测试单元是以 XML 格式定义的 .config 文件,上述四个测试配置即在该文件中定义。所有可配置的对象在 IConfiguration 接口 中定义:

xml 复制代码
<configuration description="<description of the configuration>">
    <!-- A build provider that takes local device information -->
    <build_provider class="com.android.tradefed.build.BootstrapBuildProvider" />

    <!-- Some target preparation, disabled by default -->
    <target_preparer class="com.android.tradefed.targetprep.PreloadedClassesPreparer">
        <option name="disable" value="true" />
    </target_preparer>

    <!-- One test running some unit tests -->
    <test class="com.android.tradefed.testtype.HostTest">
        <option name="class" value="com.android.tradefed.build.BuildInfoTest" />
    </test>

    <!-- [OPTIONAL] -->
    <logger class="com.android.tradefed.log.FileLogger">
        <option name="log-level" value="VERBOSE" />
        <option name="log-level-display" value="VERBOSE" />
    </logger>

    <!-- [OPTIONAL] -->
    <log_saver class="com.android.tradefed.result.FileSystemLogSaver" />

    <!-- As many reporters as we want -->
    <result_reporter class="com.android.tradefed.result.ConsoleResultReporter" />
    <result_reporter class="com.android.tradefed.result.suite.SuiteResultReporter" />
    <result_reporter class="com.android.tradefed.result.MetricsXMLResultReporter"/>
</configuration>

每个对象都有与其关联的 Java 类,该对象在 class= 中进行定义,并在运行时解析;因此,只要包含该类的 JAR 文件在运行时位于 Tradefed Java 类路径上,就会被找到并解析。

安装 aapt 和 adb

sdkmanager 是一个命令行工具,可用于查看、安装、更新和卸载 Android SDK 的软件包。该工具包含在 Command-Line Tools 中。

首先需要从 Android Studio 中下载 Command-Line Tools

因为下载的包文件路径不满足 sdkmanager 运行时对项目根路径的需求,官方文档用多个手工步骤来建立项目目录,过于复杂。

这里直接明确指定项目根路径 ,并重新下载 Command-Line Tools,自动创建项目路径:

shell 复制代码
$ unzip commandlinetools-linux-14742923_latest.zip
$ cd cmdline-tools/bin/
$ export JAVA_HOME=/data/cts/android-cts/jdk
$ export JAVA_TOOL_OPTIONS="-Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=18010"
$ ./sdkmanager --install "cmdline-tools;latest" --sdk_root=/data/sdk

此时 /data/sdk 下的工程路径已经准备好了,下面是完整的使用命令行的环境变量配置:

shell 复制代码
$ export JAVA_HOME=/data/cts/android-cts/jdk
$ export JAVA_TOOL_OPTIONS="-Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=18010"
$ export ANDROID_HOME=/data/sdk
$ export PATH=\
$ANDROID_HOME/cmdline-tools/latest/bin:\
$ANDROID_HOME/build-tools/36.1.0:\
$ANDROID_HOME/platform-tools:\
$PATH

sdkmanager 下载另外两个命令行工具:

shell 复制代码
$ sdkmanager --install "build-tools;36.1.0"
$ sdkmanager --install "platform-tools"

常用命令:

shell 复制代码
### 可安装的包
$ sdkmanager --list
### 已安装的包
$ sdkmanager --list_installed
### 安装
$ sdkmanager --install "cmdline-tools;latest"
### 卸载
$ sdkmanager --uninstall "cmdline-tools;latest"
### 更新
$ sdkmanager --update

源码

  1. cts/tests/:测试框架、辅助应用、工具等,为测试用例运行提供支持
  2. cts/tests/test/:测试用例

下载

下载 cts 环境:

shell 复制代码
### 自动测试
$ wget https://dl.google.com/dl/android/cts/android-cts-16.1_r3-linux_x86-arm.zip
### 手动确认测试
$ wget https://dl.google.com/dl/android/cts/android-cts-verifier-16.1_r3-linux_x86-arm.zip

如果要运行下面三个测试用例,可以先行下载媒体文件,加快测试速度,并以离线方式部署

  1. CtsMediaTestCases
  2. CtsMediaStressTestCases
  3. CtsMediaBitstreamsTestCases
shell 复制代码
$ wget https://dl.google.com/dl/android/cts/android-cts-media-1.5.zip
$ wget https://dl.google.com/dl/android/cts/android-cts-media-1.4.zip

MCTS

MCTS:Mainline Compatibility Test Suite,Mainline CTS;由 Google 管理、独立更新的 Mainline 模块。在 Android 10 之后,谷歌推出了 Project Mainline,它的核心思想是将 Android 系统"模块化",允许谷歌直接通过 Google Play 系统更新来修复核心组件(如 WiFi 驱动、媒体解码器、权限控制器等),而不需要等待手机厂商推送整个系统的 OTA 更新。MCTS 专门用来测试这些可以独立更新的模块。

目前该模块已经遗弃,所有模块均包含在标准侧 cts 包中,该脚本不会下载任何文件。

直接运行:

shell 复制代码
$ wget -O - \
"https://android.googlesource.com/platform/cts/+/refs/heads/main/tools/mcts/download_mcts.sh?format=TEXT" \
| base64 -d \
| bash -s -- --abi arm64 --android_version 34

先拷贝脚本为 download_mcts.sh 再运行:

shell 复制代码
$ ./download_mcts.sh  --abi arm64 --android_version 36
$ ./download_mcts.sh  --abi arm64 --year 2025 --month 12

使用

shell 复制代码
$ unzip android-cts-16.1_r2-linux_x86-arm.zip

解压后主要是三个文件夹:

  1. jdk:java 运行时
  2. testcases:jar 构成的测试用例
  3. tools:启动脚本和 Trade 框架(.jar)
shell 复制代码
$ export ANDROID_HOME=/data/sdk
$ export PATH=\
$ANDROID_HOME/cmdline-tools/latest/bin:\
$ANDROID_HOME/build-tools/36.1.0:\
$ANDROID_HOME/platform-tools:\
$PATH
$ export JAVA_TOOL_OPTIONS="-Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=18010"
$ ./android-cts/tools/cts-tradefed

常用命令:

shell 复制代码
### 列出测试计划,计划在项目工程的 cts/tools/cts-tradefed/res/config/ 路径下
### 在构建的时候会打包近 TF 的 jar 中
> list plans
### 列出模块
### 列出 CTS 包中 testcases 目录下的模块
### 模块和计划其实都是测试配置(Test configuration),只是计划可能有顶层的 target_preparer 来准备环境
> list modules
### 查看连接的设备及其状态
### Available:空闲设备
### Allocated:正在运行测试
> list devices
### 查看正在排队的命令
> list commands
### 查看正在运行的测试
> list invocations
### 查看测试结果摘要
> list results

测试结果

结果位于 android-cts/results/<start_time>.zip

可直接使用浏览器打开 test_result.html,它会帮忙解析 test_result.xml。在后者中,<StackTrace> 用来标记错误原因。

日志

OLC:OmniLab Client;OmniLab 是 Google 开发的一套用于 自动化测试管理和设备基础设施 的企业级平台。管理成百上千个引擎(Tradefed)、设备和测试任务的"中央指挥部"。

  1. inv_static_xts_:静态模块测试日志
    • device_logcat_setup_*:环境准备日志
    • device_logcat_test_*:测试执行日志
    • device_logcat_teardown_*:清理日志
  2. inv_mcts_:Mainline CTS 模块测试用例日志
  3. olc_server_session_logs:OmniLab Client 相关日志

CtsDeqpTestCases

dEQP:drawElements Quality Program;由 drawElements 公司开发的商业套件,后来被 Google 收购并开源,集成到了 Android 系统的开发和测试流程中。

源码:external/deqp/android/cts/AndroidTest.xml

跑完整的模块测试:

shell 复制代码
> run cts -m CtsDeqpTestCases --abi arm64-v8a

跑几个单独的测试用例:

shell 复制代码
> run cts \
--abi arm64-v8a \
--include-filter "CtsDeqpTestCases dEQP-EGL.functional.get_frame_timestamps#rgb888_no_depth_stencil" \
--include-filter "CtsDeqpTestCases dEQP-EGL.functional.get_frame_timestamps#rgb888_depth_stencil" \
--include-filter "CtsDeqpTestCases dEQP-EGL.functional.get_frame_timestamps#rgb565_depth_no_stencil"

dEQP-EGL 类测试用例:

shell 复制代码
> run cts \
--abi arm64-v8a \
--include-filter "CtsDeqpTestCases dEQP-EGL.*"

CtsViewTestCases

验证 Android 屏幕绘制、触摸事件、布局容器等 UI 核心机制是否严格符合 CDD 的 CTS 测试集合。

跑完整的模块测试:

shell 复制代码
> run cts -m CtsViewTestCases --abi arm64-v8a

跑单独的测试用例:

shell 复制代码
> run cts \
--abi arm64-v8a \
--include-filter "CtsViewTestCases android.view.cts.SystemGestureExclusionRectsTest#animatingView"

CtsDisplayTestCases

主要目的是确保 Android 设备的显示子系统(包括主屏幕、外部显示器、虚拟显示等)符合 Google 的兼容性标准,从而保证应用在不同设备上拥有一致且正确的显示表现。

为了不锁屏,需要在 Android 上加锁:

shell 复制代码
$ echo "my_app_lock" > /sys/power/wake_lock

跑完整的测试:

shell 复制代码
> run cts \
-m CtsDisplayTestCases

只跑 32 位,并且排除 instant 模式:

shell 复制代码
> run cts \
--abi armeabi-v7a \
-m CtsDisplayTestCases \
--exclude-filter "CtsDisplayTestCases[instant]"

只跑 32 位 instant 模式:

shell 复制代码
> run cts \
--abi armeabi-v7a \
--include-filter "CtsDisplayTestCases[instant]"

list module 中带有 [instant],[secondary_user] 等后缀

这是在 android-cts/testcases 的 xxx.config 中,有 config-descriptor:metadata 描述,Tradefed 会自动为这些后缀生成相应的测试用例:

xml 复制代码
    <option name="config-descriptor:metadata" key="component" value="sysui" />
    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
    <option name="config-descriptor:metadata" key="parameter" value="secondary_user_on_secondary_display" />
    <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
    <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />

Tradefed 如何处理 --test 选项的?

--test 选项会直接透传给 test runner 去解析,而不是 Tradefed 框架解析。

以最常见的 com.android.tradefed.testtype.AndroidJUnitTest 执行器为例:在 CtsMediaMiscTestCases 模块中包含了 android.media.misc.cts 包的 ThumbnailUtilsTest 类,并通过 @Test 装饰器定义了 testCreateImageThumbnail 方法:

java 复制代码
cts/tests/tests/media/misc/src/android/media/misc/cts/ThumbnailUtilsTest.java

package android.media.misc.cts;
......
public class ThumbnailUtilsTest {
    ......
    @Test
    public void testCreateImageThumbnail() throws Exception {
        final File file = stageFile("volantis.jpg", new File(mDir, "cts.jpg"));
        for (Size size : TEST_SIZES) {
            assertSaneThumbnail(size, ThumbnailUtils.createImageThumbnail(file, size, null));
        }
    }
    ......
}

则可以在运行 cts 时通过 --test 参数将 包名 + 类名 + 方法名 传入 apk 中,指定只执行这个方法:

shell 复制代码
$ run cts \
--abi arm64-v8a \
--module=CtsMediaMiscTestCases \
--test=android.media.misc.cts.ThumbnailUtilsTest#testCreateImageThumbnail

Tradefed 如何处理 --include-filter 选项的?

其实 --abi, --module, --test 就是 --include-filter 的特例,如果只指定单个模块、测试,可以使用前者;而如果有多个模块和测试,就需要使用后者。

  1. 不允许 --module--include-filter 一起使用
  2. 不允许多个 --test 使用
shell 复制代码
> run cts \
--abi arm64-v8a \
--include-filter "CtsDeqpTestCases dEQP-EGL.functional.get_frame_timestamps#rgb888_no_depth_stencil" \
--include-filter "CtsDeqpTestCases dEQP-EGL.functional.get_frame_timestamps#rgb888_depth_stencil" \
--include-filter "CtsDeqpTestCases dEQP-EGL.functional.get_frame_timestamps#rgb565_depth_no_stencil"

Tradefed 是如何处理非通用选项的?

下面是一个 java 类定义,其中两个变量(mWaitTime, mCalls)通过 @Option 装饰,可以在 java 外部通过 name 字段的映射(timeout, call)来修改这两个变量的值:

java 复制代码
public class PhoneCallFuncTest extends IRemoteTest {
    @Option(name = "timeout", description = "How long to wait for connection, in millis")
    private long mWaitTime = 30 * 1000;  // 30 seconds

    @Option(name = "call", description = "Key: Phone number to attempt. " +
            "Value: DTMF to expect. May be repeated.")
    private Map<String, String> mCalls = new HashMap<String, String>;

    public PhoneCallFuncTest() {
        mCalls.add("123-456-7890", "01134");  // default
    }

可以在测试配置的 XML 文件中通过在 class 中指定 java 类,在 <option/> 中修改:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration description="low-latency default test; low-latency.xml">
    <test class="com.example.PhoneCallFuncTest">
        <option name="timeout" value="5000" />
    </test>
</configuration>
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration description="call a bunch of numbers; many-numbers.xml">
    <test class="com.example.PhoneCallFuncTest">
        <option name="call" key="111-111-1111" value="#*#*TEST1*#*#" />
        <option name="call" key="222-222-2222" value="#*#*TEST2*#*#" />
        <!-- ... -->
    </test>
</configuration>

还可以在 tf 的命令行中通过选项修改:

shell 复制代码
tf> run low-latency.xml --call 111-111-1111 #*#*TEST1*#*# --call 222-222-2222 #*#*TEST2*#*#
tf> run many-numbers.xml --timeout 5000

run plan 和 run module 的区别?

plan 可能包含顶层的 target_preparer 来准备环境

测试结果为 Assumption Failure

这意味着不满足运行条件,测试被跳过了。DeviceConfig 维护了一组数据库,Java 层可以通过 DeviceConfig.getBoolean 来获取值,实现特性开关 (Feature Flag) 的功能。特性开关在 Android 10 引入,将"代码部署"与"功能发布"解耦,代码即使已经运行在用户的手机或服务器上,依然可以在不重新发布版本的情况下,远程开启或关闭某个特定的功能。

可通过 device_config list 查看动态特性开关的值。

Test Result Details
android.view.animation.cts.AnimationUtilsTest#testGetExpectedPresentationTimeNanos ASSUMPTION_FAILURE org.junit.AssumptionViolatedException: Flag android.view.flags.expected_presentation_time_api required to be enabled, but is disabled

测试结果为 IGNORED

测试用例被 @Ignore 或者 @Disabled 装饰,不会运行。

参考资料

  1. 【文档】Android Compatibility Program
  2. 【文档】Android platform testing

一个 plan 是如何知道要运行那些模块的呢?

  1. 用户输入: run cts
  2. 加载 cts.xml
    • 读取其引用的 cts-suite.xml
    • 启动 TestSuiteRunner
  3. 扫描文件系统: Runner 在 testcases/ 目录找到 CtsSensorTestCases.config
  4. 匹配标签: 发现该 .config 里有 <option name="test-suite-tag" value="cts" />
  5. 检查过滤器:
    • cts.xml 里有没有排除它?(没有)
    • 如果有包含列表,它在不在里面?(在,或者没有定义包含列表则默认全选)
  6. 确定调用: 该模块被加入执行队列。

无法在设备上运行测试

DynamicConfigPusher 希望从 Google 拉取最新的 DeviceConfig 配置,但网络通信失败。

复制代码
04-20 16:46:05 E/TestInvocation: Caught exception while running invocation
04-20 16:46:05 E/TestInvocation: Trying to access android partner remote server over internet but failed: Connection timed out
com.android.tradefed.targetprep.TargetSetupError[ANDROID_PARTNER_SERVER_ERROR|500505|DEPENDENCY_ISSUE]: Trying to access android partner remote server over internet but failed: Connection timed out
	at com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher.resolveUrl(DynamicConfigPusher.java:318)
	at com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher.setUp(DynamicConfigPusher.java:172)
	at com.android.tradefed.invoker.InvocationExecution.runPreparationOnDevice(InvocationExecution.java:672)
	at com.android.tradefed.invoker.InvocationExecution.runPreparersSetup(InvocationExecution.java:573)
	at com.android.tradefed.invoker.InvocationExecution.doSetup(InvocationExecution.java:407)
	at com.android.tradefed.invoker.TestInvocation.prepareAndRun(TestInvocation.java:667)
	at com.android.tradefed.invoker.TestInvocation.performInvocation(TestInvocation.java:304)
	at com.android.tradefed.invoker.TestInvocation.invoke(TestInvocation.java:1523)
	at com.android.tradefed.command.CommandScheduler$InvocationThread.run(CommandScheduler.java:723)
Caused by: java.net.ConnectException: Connection timed out
	at java.base/sun.nio.ch.Net.connect0(Native Method)
	at java.base/sun.nio.ch.Net.connect(Net.java:589)
	at java.base/sun.nio.ch.Net.connect(Net.java:578)
	at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:583)
	at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
	at java.base/java.net.Socket.connect(Socket.java:751)
	at java.base/sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:304)
	at java.base/sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:181)
	at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183)
	at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:531)
	at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:636)
	at java.base/sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:264)
	at java.base/sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:377)
	at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:193)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1237)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1123)
	at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:179)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1675)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1599)
	at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:223)
	at java.base/java.net.URL.openStream(URL.java:1325)
	at com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher.resolveUrl(DynamicConfigPusher.java:315)
	... 8 more

需要给 Host 上的 java 运行时添加代理:

shell 复制代码
$ export JAVA_TOOL_OPTIONS="-Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=18010"

加了 Host 的 java 代理后失败

复制代码
$ cat test_result.html
com.android.tradefed.targetprep.TargetSetupError[APK_INSTALLATION_FAILED|520001|DEPENDENCY_ISSUE]: Failed to install com.drawelements.deqp with [/tmp/tradefed-root-dir-11d0a0ba-773c-425b-addd-e0724ad8e661/android-cts/testcases/CtsDeqpTestCases/com.drawelements.deqp.apk] on 00000014150F18ZF. Reason: 'INSTALL_FAILED_INSUFFICIENT_STORAGE: Failed to override installation location' [00000014150F18ZF pd2508:pd2508 BP4A.251205.006] at com.android.tradefed.targetprep.TestAppInstallSetup.installSinglePackage(TestAppInstallSetup.java:608) at com.android.tradefed.targetprep.TestAppInstallSetup.installer(TestAppInstallSetup.java:568) at com.android.tradefed.targetprep.TestAppInstallSetup.setUp(TestAppInstallSetup.java:449) at com.android.tradefed.testtype.suite.ModuleDefinition.runPreparerSetup(ModuleDefinition.java:1111) at com.android.tradefed.testtype.suite.ModuleDefinition.runTargetPreparation(ModuleDefinition.java:1597) at com.android.tradefed.testtype.suite.ModuleDefinition.runPreparation(ModuleDefinition.java:1070) at com.android.tradefed.testtype.suite.ModuleDefinition.run(ModuleDefinition.java:542) at com.android.tradefed.testtype.suite.ITestSuite.runSingleModule(ITestSuite.java:1504) at com.android.tradefed.testtype.suite.ITestSuite.run(ITestSuite.java:1118) at com.android.tradefed.invoker.InvocationExecution.runTest(InvocationExecution.java:1538) at com.android.tradefed.invoker.InvocationExecution.runTests(InvocationExecution.java:1313) at com.android.tradefed.invoker.TestInvocation.prepareAndRun(TestInvocation.java:685) at com.android.tradefed.invoker.TestInvocation.performInvocation(TestInvocation.java:304) at com.android.tradefed.invoker.TestInvocation.invoke(TestInvocation.java:1523) at com.android.tradefed.command.CommandScheduler$InvocationThread.run(CommandScheduler.java:723)

Failed to override installation,需要扩盘

ClearcutClient 组建失败

用于上报日志给 google 服务器。

没有认证无法上传?已经给 Host 的 Java 添加了代理。

可以忽略该报错,不影响测试结果。

复制代码
04-23 11:59:36 E/ClearcutClient: Read timed out
java.net.SocketTimeoutException: Read timed out
	at java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:278)
	at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:304)
	at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:346)
	at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:796)
	at java.base/java.net.Socket$SocketInputStream.read(Socket.java:1099)
	at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:291)
	at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:347)
	at java.base/java.io.BufferedInputStream.implRead(BufferedInputStream.java:420)
	at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:399)
	at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:827)
	at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:759)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.doTunneling0(HttpURLConnection.java:2179)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.doTunneling(HttpURLConnection.java:2143)
	at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1446)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1417)
	at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:219)
	at com.android.tradefed.clearcut.ClearcutClient.sendToClearcut(ClearcutClient.java:344)
	at com.android.tradefed.clearcut.ClearcutClient.lambda$flushEvents$1(ClearcutClient.java:322)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)
04-23 11:59:36 E/ClearcutClient: Read timed out
java.net.SocketTimeoutException: Read timed out
	at java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:278)
	at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:304)
	at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:346)
	at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:796)
	at java.base/java.net.Socket$SocketInputStream.read(Socket.java:1099)
	at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:291)
	at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:347)
	at java.base/java.io.BufferedInputStream.implRead(BufferedInputStream.java:420)
	at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:399)
	at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:827)
	at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:759)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.doTunneling0(HttpURLConnection.java:2179)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.doTunneling(HttpURLConnection.java:2143)
	at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1446)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1417)
	at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:219)
	at com.android.tradefed.clearcut.ClearcutClient.sendToClearcut(ClearcutClient.java:344)

运行 CtsDisplayTestCases 报错

复制代码
04-28 16:19:10 D/NativeDevice: Device 10.31.95.204:5555 state is now NOT_AVAILABLE
04-28 16:19:10 E/AdbTcpConnection: Adb connection to 10.31.95.204:5555 was refused.
04-28 16:19:10 D/NativeDevice: Device 10.31.95.204:5555 state is now ONLINE
04-28 16:19:15 W/ShellStatusChecker: This module unexpectedly started in a root shell. Leaked from earlier module?
04-28 16:19:15 W/ITestSuite: System status checker [com.android.tradefed.suite.checker.ShellStatusChecker] failed.
04-28 16:19:16 W/ITestSuite: There are failed system status checkers: {com.android.tradefed.suite.checker.ShellStatusChecker=This module unexpectedly started in a root shell. Leaked from earlier module?}
04-28 16:19:16 D/ModuleDefinition: Running module arm64-v8a CtsDisplayTestCases[instant]
04-28 16:19:16 E/AaptParser: aapt2 dump badging stderr: 04-28 16:19:16.330 3789037 3789037 E aapt2   : Entry at index 0 is too small (0)
04-28 16:19:16.330 3789037 3789037 E aapt2   : Entry offset at index 0 points outside the Type's boundaries
04-28 16:19:16.330 3789037 3789037 E aapt2   : Entry offset at index 1 points outside the Type's boundaries
04-28 16:19:16 E/AaptParser: aapt2 dump xmltree AndroidManifest.xml stderr: 04-28 16:19:16.345 3789039 3789039 E aapt2   : Entry at index 0 is too small (0)
04-28 16:19:16.345 3789039 3789039 E aapt2   : Entry offset at index 0 points outside the Type's boundaries
04-28 16:19:16.345 3789039 3789039 E aapt2   : Entry offset at index 1 points outside the Type's boundaries
04-28 16:19:21 E/AaptParser: aapt2 dump badging stderr: 04-28 16:19:19.708 3789356 3789356 E aapt2   : Entry at index 0 is too small (0)
04-28 16:19:19.708 3789356 3789356 E aapt2   : Entry offset at index 0 points outside the Type's boundaries
04-28 16:19:19.708 3789356 3789356 E aapt2   : Entry offset at index 1 points outside the Type's boundaries
04-28 16:19:19.708 3789356 3789356 E aapt2   : Entry offset at index 2 points outside the Type's boundaries
04-28 16:19:19.708 3789356 3789356 E aapt2   : Index 3 points to entry with unaligned offset 0x03080001
04-28 16:19:19.708 3789356 3789356 E aapt2   : Entry at index 4 is too small (1)
04-28 16:19:19.708 3789356 3789356 E aapt2   : Index 5 points to entry with unaligned offset 0x03080002
......
04-28 16:24:14.571 3814797 3814797 E aapt2   : Index 20 points to entry with unaligned offset 0x019c0183
04-28 16:24:14.571 3814797 3814797 E aapt2   : Index 21 points to entry with unaligned offset 0x01b001a3
04-28 16:24:14.571 3814797 3814797 E aapt2   : Entry offset at index 22 points outside the Type's boundaries
04-28 16:24:15 E/AaptParser: Failed to run aapt2 on /tmp/tradefed-root-dir-94291d92-5965-4c6a-a2ce-45e6bf869e40/android-cts/testcases/CtsDisplayTestCases/CtsAppTestStubs.apk. stdout: 
04-28 16:24:15 E/ModuleDefinition: Unexpected Exception from preparer: com.android.tradefed.targetprep.suite.SuiteApkInstaller
04-28 16:24:15 E/ModuleDefinition: AaptParser failed for file CtsAppTestStubs.apk. The APK won't be installed
com.android.tradefed.targetprep.TargetSetupError[AAPT_PARSER_FAILED|520050|DEPENDENCY_ISSUE]: AaptParser failed for file CtsAppTestStubs.apk. The APK won't be installed
	at com.android.tradefed.targetprep.TestAppInstallSetup.parsePackageName(TestAppInstallSetup.java:788)
	at com.android.tradefed.targetprep.TestAppInstallSetup.resolveApkFiles(TestAppInstallSetup.java:676)
	at com.android.tradefed.targetprep.TestAppInstallSetup.setUp(TestAppInstallSetup.java:448)
	at com.android.tradefed.testtype.suite.ModuleDefinition.runPreparerSetup(ModuleDefinition.java:1111)
	at com.android.tradefed.testtype.suite.ModuleDefinition.runTargetPreparation(ModuleDefinition.java:1597)
	at com.android.tradefed.testtype.suite.ModuleDefinition.runPreparation(ModuleDefinition.java:1070)
	at com.android.tradefed.testtype.suite.ModuleDefinition.run(ModuleDefinition.java:542)
	at com.android.tradefed.testtype.suite.ITestSuite.runSingleModule(ITestSuite.java:1504)
	at com.android.tradefed.testtype.suite.ITestSuite.run(ITestSuite.java:1118)
	at com.android.tradefed.invoker.InvocationExecution.runTest(InvocationExecution.java:1538)
	at com.android.tradefed.invoker.InvocationExecution.runTests(InvocationExecution.java:1313)
	at com.android.tradefed.invoker.TestInvocation.prepareAndRun(TestInvocation.java:685)
	at com.android.tradefed.invoker.TestInvocation.performInvocation(TestInvocation.java:304)
	at com.android.tradefed.invoker.TestInvocation.invoke(TestInvocation.java:1523)
	at com.android.tradefed.command.CommandScheduler$InvocationThread.run(CommandScheduler.java:723)
04-28 16:24:15 E/ModuleDefinition: Some preparation step failed. failing the module armeabi-v7a CtsDisplayTestCases

反复出现 AaptParser 错误,以及 Entry at index 0 is too small (0) 这类解析异常,都是 aapt2 版本不兼容的典型特征。需要下载最新的 aapt2 工具。

相关推荐
马占柱1 小时前
MediaSession相关介绍
android·多媒体·mediasession·车载多媒体开发
张风捷特烈1 小时前
状态管理大乱斗#08 | MobX 源码评析 - 透明魔法
android·前端·flutter
i220818 Faiz Ul1 小时前
个人健康系统|健康管理|基于java+Android+微信小程序的个人健康系统设计与实现(源码+数据库+文档)
android·java·vue.js·spring boot·微信小程序·毕设·个人健康系统
赏金术士10 小时前
Kotlin 习题集 · 高级篇
android·开发语言·kotlin
问心无愧051312 小时前
ctf show web 入门42
android·前端·android studio
没什么本事13 小时前
关于C# panel 添加lable问题 -- 明确X和Y 位置错误
android·java·c#
REDcker16 小时前
Android HWASan 详解:硬件标记原理、Clang 启用与排障实践
android·linux·debug·编译·clang·asan·hwasan
2501_9159090617 小时前
全面解析前端开发中常用的浏览器调试工具及其使用场景
android·ios·小程序·https·uni-app·iphone·webview
angerdream17 小时前
Android手把手编写儿童手机远程监控App之SQLite详解2
android