GTS 在测试 case armeabi-v7a GtsMemoryHostTestCases 的时候出现下面异常,本文总结一下。
com.google.android.memory.gts.AllAppsMemoryHostTest#testPeakPssOfAllApps
- 09-14 10:16:34 I/TestFailureListener: FailureListener.testFailed com.google.android.memory.gts.AllAppsMemoryHostTest#testPeakPssOfAllApps false
- 09-14 10:16:34 D/PrettyTestEventLogger:
- ==================== com.google.android.memory.gts.AllAppsMemoryHostTest#testPeakPssOfAllApps ENDED: Thu Sep 14 10:16:34 CST 2023 ====================
- 09-14 10:16:34 I/ModuleListener: [1/1] d4081bc5 com.android.compatibility.common.tradefed.testtype.JarHostTest com.google.android.memory.gts.AllAppsMemoryHostTest#testPeakPssOfAllApps FAILURE: com.android.tradefed.device.DeviceUnresponsiveException[DEVICE_UNRESPONSIVE|520751|LOST_SYSTEM_UNDER_TEST]: Attempted shell am start -W -S -f 10008000 'com.google.android.apps.mapslite/com.google.maps.lite.twa.MapsLiteTwaLauncherActivity' multiple times on device d4081bc5 without communication success. Aborting.
- at com.android.tradefed.device.NativeDevice.performDeviceAction(NativeDevice.java:2577)
- at com.android.tradefed.device.NativeDevice.executeShellCommand(NativeDevice.java:902)
- at com.android.tradefed.device.NativeDevice.executeShellCommand(NativeDevice.java:959)
- at com.google.android.memory.gts.AllAppsMemoryHostTest.testPeakPssOfAllApps(AllAppsMemoryHostTest.java:109)
- at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
- at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
- at java.base/java.lang.reflect.Method.invoke(Method.java:568)
- at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
- at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
- at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:61)
- at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
- at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
- at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
- at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
- at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
- at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
- at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
- at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
- at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.runChild(DeviceJUnit4ClassRunner.java:111)
- at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.runChild(DeviceJUnit4ClassRunner.java:63)
- at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
- at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
- at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
- at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
- at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
- at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
- at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.run(DeviceJUnit4ClassRunner.java:147)
- at com.android.tradefed.testtype.junit4.ExceptionThrowingRunnerWrapper.run(ExceptionThrowingRunnerWrapper.java:43)
- at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
- at com.android.tradefed.testtype.HostTest.runJUnit4Tests(HostTest.java:736)
- at com.android.tradefed.testtype.HostTest.runTestClasses(HostTest.java:616)
- at com.android.tradefed.testtype.HostTest.run(HostTest.java:564)
- at com.android.compatibility.common.tradefed.testtype.JarHostTest.run(JarHostTest.java:56)
- at com.android.tradefed.testtype.suite.GranularRetriableTestWrapper.intraModuleRun(GranularRetriableTestWrapper.java:379)
- at com.android.tradefed.testtype.suite.GranularRetriableTestWrapper.run(GranularRetriableTestWrapper.java:289)
- at com.android.tradefed.testtype.suite.ModuleDefinition.run(ModuleDefinition.java:595)
- at com.android.tradefed.testtype.suite.ITestSuite.runSingleModule(ITestSuite.java:951)
- at com.android.tradefed.testtype.suite.ITestSuite.run(ITestSuite.java:828)
- at com.android.tradefed.invoker.InvocationExecution.runTest(InvocationExecution.java:1359)
- at com.android.tradefed.invoker.InvocationExecution.runTests(InvocationExecution.java:1138)
- at com.android.tradefed.invoker.TestInvocation.prepareAndRun(TestInvocation.java:626)
- at com.android.tradefed.invoker.TestInvocation.performInvocation(TestInvocation.java:278)
- at com.android.tradefed.invoker.TestInvocation.invoke(TestInvocation.java:1357)
- at com.android.tradefed.command.CommandScheduler$InvocationThread.run(CommandScheduler.java:686)
- Caused by: com.android.ddmlib.ShellCommandUnresponsiveException
- at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:731)
- at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:511)
- at com.android.ddmlib.internal.DeviceImpl.executeShellCommand(DeviceImpl.java:722)
- at com.android.tradefed.device.NativeDevice$2.run(NativeDevice.java:897)
- at com.android.tradefed.device.NativeDevice.performDeviceAction(NativeDevice.java:2525)
- ... 44 more
- public void testPeakPssOfAllApps() throws Exception {
- final int flags = 268468224;
- //------------step1
- final String[] activities = ActivityQueryHelper.ALL_APPS_QUERY.run(this.getDevice());
- Assert.assertTrue("No activities found", activities.length > 0);
- final Set
exemptedActivities = new HashSet(); - for (final ActivityQuery query : ActivityQueryHelper.APPS_BY_CATEGORY) {
- exemptedActivities.addAll(Arrays.asList(query.run(this.getDevice())));
- }
-
- //------------step2
- final Set
exemptedPackages = new HashSet(); - exemptedPackages.addAll(this.readExemptions("gallery_exemptions"));
- exemptedPackages.addAll(this.readExemptions("streaming_music_apps"));
- exemptedPackages.addAll(this.readExemptions("streaming_video_apps"));
- exemptedPackages.addAll(this.readExemptions("all_apps_memory_exemptions"));
- final List
activityList = new ArrayList(Arrays.asList(activities)); -
- //------------step3
- final Iterator
it = activityList.iterator(); - while (it.hasNext()) {
- final String activity = it.next();
- final String packageName = activity.split("/")[0];
- if (exemptedPackages.contains(packageName)) {
- LogUtil.CLog.d("exempt package " + packageName);
- it.remove();
- }
- else {
- if (!exemptedActivities.contains(activity)) {
- continue;
- }
- LogUtil.CLog.d("exempt activity " + activity);
- it.remove();
- }
- }
-
- //------------step4
- LogUtil.CLog.d("These apps will be checked: " + String.join(",", activityList));
-
- //------------step5
- final long maxPeakPssAllowed = this.calculateMaxAllowedPeakPssUsage("max_memory_all_apps");
- final StringBuilder violations = new StringBuilder();
- for (final String activity2 : activityList) {
-
- //------------step6
- final String packageName2 = activity2.split("/")[0];
- this.runPostNotificationPermissionTest("grantRuntimePermission", packageName2);
- final String amOutput = this.getDevice().executeShellCommand(this.buildStartActivityCommand(activity2, 268468224));
- Assert.assertTrue(activity2 + " failed to start", amOutput.contains("Status: ok"));
- TimeUnit.SECONDS.sleep(30L);
- if (this.shouldExemptTopActivity(exemptedActivities)) {
- continue;
- }
-
- //------------step7
- final long memoryKb = this.getMemoryUsage(packageName2);
- this.stopApplication(packageName2);
- if (memoryKb >= maxPeakPssAllowed) {
- violations.append(packageName2).append(" ").append(memoryKb).append(",");
- }
- this.runPostNotificationPermissionTest("revokeRuntimePermission", packageName2);
- }
-
- //------------step8
- if (violations.length() > 0) {
- violations.append(" failed to keep to the max pss of ");
- violations.append(maxPeakPssAllowed);
- Assert.fail(violations.toString());
- }
- }
源码比较多,都封装在 GtsMemoryHostTestCases.jar 中。这里只是来看下 test 接口。
通过 ActivityQueryHelper.ALL_APPS_QUERY 来查询所有符合条件的 activities:
- ActivityQueryHelper.java
-
- ALL_APPS_QUERY = new ActivityQuery().setAction("android.intent.action.MAIN").setCategory("android.intent.category.LAUNCHER");
要求Action 为 android.intent.action.MAIN,category 为 android.intent.category.LAUNCHER 的所有 Activities。
- final Set
exemptedPackages = new HashSet(); - exemptedPackages.addAll(this.readExemptions("gallery_exemptions"));
- exemptedPackages.addAll(this.readExemptions("streaming_music_apps"));
- exemptedPackages.addAll(this.readExemptions("streaming_video_apps"));
- exemptedPackages.addAll(this.readExemptions("all_apps_memory_exemptions"));
这些可以免除的 package 都定义在 GtsMemoryHostTestCases.dynamic 文件中。
被免除的应用会在 log 中打印出来:
- 09-14 10:02:54 D/AllAppsMemoryHostTest: exempt activity com.android.chrome/com.google.android.apps.chrome.Main
- 09-14 10:02:54 D/AllAppsMemoryHostTest: exempt activity com.google.android.apps.photosgo/.home.HomeActivity
- 09-14 10:02:54 D/AllAppsMemoryHostTest: exempt package com.google.android.youtube
- 09-14 10:02:54 D/AllAppsMemoryHostTest: exempt activity org.codeaurora.dialer/com.android.dialer.main.impl.MainActivity
- 09-14 10:02:54 D/AllAppsMemoryHostTest: exempt package com.google.android.apps.nbu.files
在经过 step3 之后,log 中会打印出最终需要 check 的acitivity:
- 09-14 10:02:54 D/AllAppsMemoryHostTest: These apps will be checked: com.android.mms/.ui.ConversationList,
- com.android.settings/.Settings,
- com.android.soundrecorder/.SoundRecorder,
- com.android.vending/.AssetBrowserActivity,
- com.google.android.apps.assistant/.go.MainActivity,
- com.google.android.apps.messaging/.ui.ConversationListActivity,
- com.google.android.apps.tachyon/.MainActivity,
- com.google.android.calculator/com.android.calculator2.Calculator,
- com.google.android.calendar/com.android.calendar.AllInOneActivity,
- com.google.android.contacts/com.android.contacts.activities.PeopleActivity,
- com.google.android.deskclock/com.android.deskclock.DeskClock,
- com.google.android.dialer/.extensions.GoogleDialtactsActivity,
- org.codeaurora.snapcam/com.android.camera.CameraLauncher,
- com.caf.fmradio/.FMRadio,
- com.google.android.apps.mapslite/com.google.maps.lite.twa.MapsLiteTwaLauncherActivity,
- com.google.android.apps.searchlite/.ui.SearchActivity
设备的layout size 在《GTS 中testPersistentProcessMemory fail 详解》一文中已经分析过,详细看第 2.1 节。
这里最终根据 layout size 确定 peakPss,该属性值都定义 GtsMemoryHostTestCases.dynamic 文件中:
- ...
-
-
"max_memory_all_apps_2gb_hd"> -
153600 -
-
- ...
step6. 轮询待check的activities,确定package name,并申请 android.permission.POST_NOTIFICATIONS 权限。
通过 dumpsys -t 30 meminfo --package packageName 的命令确定进程内存,依然通过 Pattern 类确定内存:
- final List
usages = new ArrayList(); - final Matcher matcher = Pattern.compile("TOTAL\\s+([\\d]+)").matcher(output);
- while (matcher.find()) {
- usages.add(matcher.group(1));
- }
-
- Assert.assertFalse("Could not get meminfo total for " + packageName, usages.isEmpty());
- return usages.stream().mapToLong((ToLongFunction super Object>)Long::valueOf).sum();
如果有进程的 memory 超过了 peakPss,则会打印显示
本文中的 error log 从host log 中比较清晰:
- 09-14 10:12:33 W/NativeDevice: Command: 'shell am start -W -S -f 10008000 'com.google.android.apps.mapslite/com.google.maps.lite.twa.MapsLiteTwaLauncherActivity'' on 'd4081bc5' went over its timeout for outputing a response.
- 09-14 10:14:34 W/NativeDevice: Command: 'shell am start -W -S -f 10008000 'com.google.android.apps.mapslite/com.google.maps.lite.twa.MapsLiteTwaLauncherActivity'' on 'd4081bc5' went over its timeout for outputing a response.
- 09-14 10:16:34 W/NativeDevice: Command: 'shell am start -W -S -f 10008000 'com.google.android.apps.mapslite/com.google.maps.lite.twa.MapsLiteTwaLauncherActivity'' on 'd4081bc5' went over its timeout for outputing a response.
- 09-14 10:16:34 I/TestFailureListener: FailureListener.testFailed com.google.android.memory.gts.AllAppsMemoryHostTest#testPeakPssOfAllApps false
-
- ...
-
- 09-14 10:16:34 W/GranularRetriableTestWrapper: com.android.tradefed.device.DeviceUnresponsiveException[DEVICE_UNRESPONSIVE|520751|LOST_SYSTEM_UNDER_TEST]: Attempted shell am start -W -S -f 10008000 'com.google.android.apps.mapslite/com.google.maps.lite.twa.MapsLiteTwaLauncherActivity' multiple times on device d4081bc5 without communication success. Aborting.
根本原因是启动这个 acitivity 没有返回 Staatus: ok 的状态
另外,同 《testPersistentProcessMemory failed》 一文,如果是非 GO device,该case 会被 skip,也就是说只有在 GO 平台才会出现这样的failed case:
- 09-22 14:21:31 I/ModuleListener: [1/1] cb080378 com.android.compatibility.common.tradefed.testtype.JarHostTest com.google.android.memory.gts.AllAppsMemoryHostTest#testPeakPssOfAllApps ASSUMPTION_FAILURE: org.junit.AssumptionViolatedException: Skipping AllAppsMemoryHostTest on non-Go device
- at org.junit.Assume.assumeTrue(Assume.java:68)
- at com.google.android.memory.gts.MemoryHostTestBase.checkGoDevice(MemoryHostTestBase.java:89)
- at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
- at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
- at java.base/java.lang.reflect.Method.invoke(Method.java:568)
- at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
- at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
- at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:61)
- at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
- at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
- at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
- at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
- at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
- at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
- at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
- at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
- at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.runChild(DeviceJUnit4ClassRunner.java:111)
- at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.runChild(DeviceJUnit4ClassRunner.java:63)
- at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
- at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
- at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
- at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
- at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
- at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
- at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.run(DeviceJUnit4ClassRunner.java:147)
- at com.android.tradefed.testtype.junit4.ExceptionThrowingRunnerWrapper.run(ExceptionThrowingRunnerWrapper.java:43)
- at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
- at com.android.tradefed.testtype.HostTest.runJUnit4Tests(HostTest.java:736)
- at com.android.tradefed.testtype.HostTest.runTestClasses(HostTest.java:616)
- at com.android.tradefed.testtype.HostTest.run(HostTest.java:564)
- at com.android.compatibility.common.tradefed.testtype.JarHostTest.run(JarHostTest.java:56)
- at com.android.tradefed.testtype.suite.GranularRetriableTestWrapper.intraModuleRun(GranularRetriableTestWrapper.java:379)
- at com.android.tradefed.testtype.suite.GranularRetriableTestWrapper.run(GranularRetriableTestWrapper.java:289)
- at com.android.tradefed.testtype.suite.ModuleDefinition.run(ModuleDefinition.java:595)
- at com.android.tradefed.testtype.suite.ITestSuite.runSingleModule(ITestSuite.java:951)
- at com.android.tradefed.testtype.suite.ITestSuite.run(ITestSuite.java:828)
- at com.android.tradefed.invoker.InvocationExecution.runTest(InvocationExecution.java:1359)
- at com.android.tradefed.invoker.InvocationExecution.runTests(InvocationExecution.java:1138)
- at com.android.tradefed.invoker.TestInvocation.prepareAndRun(TestInvocation.java:626)
- at com.android.tradefed.invoker.TestInvocation.performInvocation(TestInvocation.java:278)
- at com.android.tradefed.invoker.TestInvocation.invoke(TestInvocation.java:1357)
- at com.android.tradefed.command.CommandScheduler$InvocationThread.run(CommandScheduler.java:686)