summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2020-08-27 10:17:03 -0700
committerXin Li <delphij@google.com>2020-08-27 10:17:03 -0700
commit30073dd9eb46ae8977d1fc231f2d1ff930c7a2db (patch)
treea2ced80babe6b075ea59391ccee628595294dbd1
parentfc5b07e6879e9095114e56e21ce79794feba7e2f (diff)
parent7db9f5b81b44f9f46f9f3efdc631be6e7d033eb0 (diff)
downloadplatform_testing-30073dd9eb46ae8977d1fc231f2d1ff930c7a2db.tar.gz
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)
Bug: 166295507 Merged-In: I3612d6dab57cd710b4446aec240ef70f5b9e1f18 Change-Id: I9684eff6d87bee98ee98a6a0573043346cc6d31b
-rw-r--r--build/tasks/tests/instrumentation_metric_test_list.mk10
-rw-r--r--build/tasks/tests/instrumentation_test_list.mk3
-rw-r--r--build/tasks/tests/native_metric_test_list.mk1
-rw-r--r--build/tasks/tests/native_test_list.mk9
-rw-r--r--build/tasks/tests/platform_test_list.mk5
-rw-r--r--emu_test/cts.gpu.module.11
-rw-r--r--emu_test/cts.gpu.module.212
-rw-r--r--emu_test/cts.module.198
-rw-r--r--emu_test/cts.module.298
-rw-r--r--emu_test/cts.module.399
-rw-r--r--emu_test/cts.module.499
-rw-r--r--emu_test/gts.module3
-rwxr-xr-xemu_test/run_test.sh9
-rwxr-xr-xemu_test/run_test_suite.sh225
-rw-r--r--emu_test/vts.module1
-rw-r--r--libraries/annotations/src/android/platform/test/annotations/SocPresubmit.java32
-rw-r--r--libraries/app-helpers/OWNERS3
-rw-r--r--libraries/app-helpers/interfaces/Android.bp5
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialContactDetailsHelper.java47
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java130
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoLockScreenHelper.java46
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMapsHelper.java8
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterHelper.java14
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterNowPlayingHelper.java9
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java29
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoNotificationMockingHelper.java9
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSecuritySettingsHelper.java70
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSettingHelper.java14
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoUsersSettingsHelper.java45
-rw-r--r--libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoVehicleHardKeysHelper.java45
-rw-r--r--libraries/app-helpers/interfaces/common/src/android/platform/helpers/IContactsHelper.java13
-rw-r--r--libraries/app-helpers/interfaces/common/src/android/platform/helpers/IMapsHelper.java27
-rw-r--r--libraries/app-helpers/interfaces/common/src/android/platform/helpers/IYouTubeHelper.java8
-rw-r--r--libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/INotificationHelper.java142
-rw-r--r--libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/IQuickSettingsHelper.java14
-rw-r--r--libraries/aupt-lib/src/android/support/test/aupt/FilesystemUtil.java2
-rw-r--r--libraries/car-helpers/multiuser-helper/Android.bp3
-rw-r--r--libraries/car-helpers/multiuser-helper/src/android/platform/helpers/MultiUserHelper.java124
-rw-r--r--libraries/collectors-helper/memory/Android.bp1
-rw-r--r--libraries/collectors-helper/memory/src/com/android/helpers/DumpsysMeminfoHelper.java198
-rw-r--r--libraries/collectors-helper/memory/src/com/android/helpers/FreeMemHelper.java48
-rw-r--r--libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ProcessShowmapHelperTest.java2
-rw-r--r--libraries/collectors-helper/statsd/src/com/android/helpers/StatsdHelper.java12
-rw-r--r--libraries/device-collectors/src/main/java/android/device/collectors/FreeMemListener.java20
-rw-r--r--libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java143
-rw-r--r--libraries/device-collectors/src/main/java/android/device/preparers/GarbageCollectionPreparer.java9
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/README.md5
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/app-start/app-start.pbbin119 -> 284 bytes
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/README.md3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-run-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-test-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/README.md3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-run-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-test-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/README.md3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-run-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-test-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/README.md3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-run-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-test-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/README.md3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-run-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-test-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/README.md3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-run-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-test-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/README.md3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-run-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-test-level.pb3
-rw-r--r--libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/StatsdListener.java38
-rw-r--r--libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java4
-rw-r--r--libraries/device-collectors/src/test/java/android/device/preparers/GarbageCollectionPreparerTest.java29
-rw-r--r--libraries/device-collectors/src/test/platform/Android.bp1
-rw-r--r--libraries/device-collectors/src/test/platform/android/device/collectors/StatsdListenerTest.java29
-rw-r--r--libraries/flicker/src/com/android/server/wm/flicker/WindowManagerTrace.java88
-rw-r--r--libraries/flicker/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java6
-rw-r--r--libraries/health/composers/platform/src/android/platform/test/composer/Shuffle.java3
-rw-r--r--libraries/health/options/src/android/platform/test/option/BooleanOption.java (renamed from libraries/health/options/src/android/platform/test/options/BooleanOption.java)0
-rw-r--r--libraries/health/options/src/android/platform/test/option/DoubleOption.java (renamed from libraries/health/options/src/android/platform/test/options/DoubleOption.java)0
-rw-r--r--libraries/health/options/src/android/platform/test/option/IntegerOption.java (renamed from libraries/health/options/src/android/platform/test/options/IntegerOption.java)0
-rw-r--r--libraries/health/options/src/android/platform/test/option/LongOption.java (renamed from libraries/health/options/src/android/platform/test/options/LongOption.java)0
-rw-r--r--libraries/health/options/src/android/platform/test/option/StringOption.java (renamed from libraries/health/options/src/android/platform/test/options/StringOption.java)0
-rw-r--r--libraries/health/options/src/android/platform/test/option/TestOption.java (renamed from libraries/health/options/src/android/platform/test/options/TestOption.java)4
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/CompilationFilterRule.java8
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/DropCachesRule.java37
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/IorapCompilationRule.java24
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/KillAppsRule.java5
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/PressHomeRule.java5
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/QuickstepPressureRule.java9
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/StopwatchRule.java8
-rw-r--r--libraries/health/rules/src/android/platform/test/rule/TracePointRule.java6
-rw-r--r--libraries/health/rules/tests/src/android/platform/test/rule/DropCachesRuleTest.java7
-rw-r--r--libraries/health/runners/longevity/host/src/android/host/test/longevity/LongevitySuite.java24
-rw-r--r--libraries/health/runners/longevity/host/src/android/host/test/longevity/listener/TimeoutTerminator.java9
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevityClassRunner.java16
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevitySuite.java65
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/Profile.java91
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ProfileSuite.java68
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScenarioRunner.java67
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScheduledScenarioRunner.java29
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/BatteryTerminator.java2
-rw-r--r--libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/TimeoutTerminator.java3
-rw-r--r--libraries/health/runners/longevity/platform/tests/AndroidTest.xml4
-rw-r--r--libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_registeredBeforeTest.textpb23
-rw-r--r--libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_unregisteredAfterTest.textpb44
-rw-r--r--libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/LongevitySuiteTest.java61
-rw-r--r--libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ProfileSuiteTest.java82
-rw-r--r--libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScenarioRunnerTest.java176
-rw-r--r--libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScheduledScenarioRunnerTest.java122
-rw-r--r--libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleExtraArgsSuite.java143
-rw-r--r--libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleTimedProfileSuite.java4
-rw-r--r--libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java140
-rw-r--r--libraries/health/utils/src/android/platform/test/util/HealthRunnerBuilder.java6
-rw-r--r--libraries/launcher-helper/src/android/support/test/launcherhelper/AutoLauncherStrategy.java34
-rw-r--r--libraries/launcher-helper/src/android/support/test/launcherhelper/IAutoLauncherStrategy.java3
-rw-r--r--libraries/launcher-helper/src/android/support/test/launcherhelper/VolvoLauncherStrategy.java28
-rw-r--r--libraries/system-helpers/OWNERS2
-rw-r--r--libraries/system-helpers/settings-helper/src/android/system/helpers/SettingsHelper.java17
-rwxr-xr-xscripts/perf-setup/angler-setup.sh39
-rwxr-xr-xscripts/perf-setup/b1c1-setup.sh1
-rwxr-xr-xscripts/perf-setup/b4s4-setup.sh1
-rw-r--r--scripts/perf-setup/bullhead-setup.sh36
-rwxr-xr-xscripts/perf-setup/c2f2-setup.sh1
-rwxr-xr-xscripts/perf-setup/dragon-setup.sh22
-rw-r--r--scripts/perf-setup/sailin-setup.sh20
-rw-r--r--scripts/perfetto-setup/Android.mk10
-rw-r--r--tests/functional/devicehealthchecks/Android.bp3
-rw-r--r--tests/functional/devicehealthchecks/AndroidManifest.xml6
-rw-r--r--tests/functional/devicehealthchecks/AndroidTest.xml1
-rw-r--r--tests/functional/devicehealthchecks/assets/bug_map21
-rw-r--r--tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheckBase.java73
-rw-r--r--tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/KnownFailures.java25
-rw-r--r--tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/MediaBootCheck.java58
-rw-r--r--tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SensorsBootCheck.java4
-rw-r--r--tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SystemAppCheck.java51
-rw-r--r--tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SystemCheck.java (renamed from tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheck.java)33
-rw-r--r--tests/functional/notificationtests/src/com/android/notification/functional/HeadsUpNotificationTests.java33
-rw-r--r--tests/health/scenarios/Android.bp1
-rw-r--r--tests/health/scenarios/src/android/platform/test/scenario/annotation/FixedApp.java27
-rw-r--r--tests/health/scenarios/src/android/platform/test/scenario/sample/PrintListener.java65
-rw-r--r--tests/health/scenarios/src/android/platform/test/scenario/sample/SampleTest.java139
-rw-r--r--tests/health/scenarios/tests/src/android/platform/test/scenario/sample/SampleMicrobenchmark.java55
-rw-r--r--tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/LauncherJankTests.java34
-rw-r--r--tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/SystemUiJankTests.java6
-rw-r--r--tests/jank/androidtvjanktests/Android.bp4
-rw-r--r--tests/jank/androidtvjanktests/AndroidManifest.xml4
-rw-r--r--tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemAppJankTests.java41
-rw-r--r--tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemUiJankTests.java24
-rw-r--r--tests/microbenchmarks/uibench/AndroidManifest.xml1
-rw-r--r--tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/IUiBenchJankHelper.java2
-rw-r--r--tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchJankHelper.java24
-rw-r--r--tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchWindowInsetsControllerMicrobenchmark.java68
152 files changed, 3351 insertions, 1169 deletions
diff --git a/build/tasks/tests/instrumentation_metric_test_list.mk b/build/tasks/tests/instrumentation_metric_test_list.mk
index 30cf5c9b9..be7952939 100644
--- a/build/tasks/tests/instrumentation_metric_test_list.mk
+++ b/build/tasks/tests/instrumentation_metric_test_list.mk
@@ -14,15 +14,21 @@
instrumentation_metric_tests := \
AutofillPerfTests \
+ BlobStorePerfTests \
crashcollector \
CorePerfTests \
DocumentsUIAppPerfTests \
- MtpDocumentsProviderPerfTests \
+ MtpServicePerfTests \
RsBlasBenchmark \
ImageProcessingJB \
+ MediaProviderClientTests \
+ MultiUserPerfDummyApp \
MultiUserPerfTests \
NeuralNetworksApiBenchmark \
- TextClassifierPerfTests
+ PackageManagerPerfTests \
+ TextClassifierPerfTests \
+ WmPerfTests \
+ trace_config_detailed.textproto
# TODO(b/72332760): Uncomment when fixed
#DocumentsUIPerfTests
diff --git a/build/tasks/tests/instrumentation_test_list.mk b/build/tasks/tests/instrumentation_test_list.mk
index f51f9ae74..0c4282cf0 100644
--- a/build/tasks/tests/instrumentation_test_list.mk
+++ b/build/tasks/tests/instrumentation_test_list.mk
@@ -32,7 +32,7 @@ instrumentation_tests := \
JobTestApp \
SuspendTestApp \
FrameworksUtilTests \
- MtpDocumentsProviderTests \
+ MtpServiceTests \
MtpTests \
DocumentsUITests \
ShellTests \
@@ -70,6 +70,7 @@ instrumentation_tests := \
FrameworksLocationTests \
FrameworksPrivacyLibraryTests \
SettingsUITests \
+ SettingsPerfTests \
ExtServicesUnitTests\
FrameworksNetSmokeTests\
diff --git a/build/tasks/tests/native_metric_test_list.mk b/build/tasks/tests/native_metric_test_list.mk
index ecddd6c15..4f136ec60 100644
--- a/build/tasks/tests/native_metric_test_list.mk
+++ b/build/tasks/tests/native_metric_test_list.mk
@@ -19,6 +19,7 @@ native_metric_tests := \
crashcollector \
hwuimacro \
hwuimicro \
+ inputflinger_benchmarks \
libandroidfw_benchmarks \
libjavacore-benchmarks \
minikin_perftests \
diff --git a/build/tasks/tests/native_test_list.mk b/build/tasks/tests/native_test_list.mk
index c1ef943e9..a31b33411 100644
--- a/build/tasks/tests/native_test_list.mk
+++ b/build/tasks/tests/native_test_list.mk
@@ -39,6 +39,7 @@ native_tests := \
dvr_api-test \
dvr_buffer_queue-test \
dvr_display-test \
+ gpuservice_unittest \
gwp_asan_unittest \
hello_world_test \
hwui_unit_tests \
@@ -64,7 +65,6 @@ native_tests := \
libminijail_unittest_gtest \
libnativehelper_tests \
libnetdbpf_test \
- libperfmgr_test \
libprocinfo_test \
libtextclassifier_tests \
libsurfaceflinger_unittest \
@@ -123,12 +123,15 @@ native_tests := \
vintf_object_test \
wificond_unit_test \
ziparchive-tests \
- BufferHub_test \
- BufferHubServer_test \
GraphicBuffer_test \
NeuralNetworksTest_mt_static \
NeuralNetworksTest_operations \
NeuralNetworksTest_static \
+ NeuralNetworksTest_utils \
SurfaceFlinger_test \
lmkd_unit_test \
vrflinger_test
+
+ifeq ($(BOARD_IS_AUTOMOTIVE), true)
+native_tests += libwatchdog_test
+endif
diff --git a/build/tasks/tests/platform_test_list.mk b/build/tasks/tests/platform_test_list.mk
index 151d00fd4..b4f7bd5bc 100644
--- a/build/tasks/tests/platform_test_list.mk
+++ b/build/tasks/tests/platform_test_list.mk
@@ -1,5 +1,8 @@
platform_tests += \
ActivityManagerPerfTests \
+ ActivityManagerPerfTestsStubApp1 \
+ ActivityManagerPerfTestsStubApp2 \
+ ActivityManagerPerfTestsStubApp3 \
ActivityManagerPerfTestsTestApp \
AndroidTVJankTests \
ApiDemos \
@@ -53,7 +56,6 @@ platform_tests += \
InternalLocTestApp \
JankMicroBenchmarkTests \
long_trace_config.textproto \
- LauncherRotationStressTest \
MemoryUsage \
MultiDexLegacyTestApp \
MultiDexLegacyTestApp2 \
@@ -82,6 +84,7 @@ platform_tests += \
PlatformCommonScenarioTests \
PowerPerfTest \
SettingsUITests \
+ SimpleServiceTestApp \
SimpleTestApp \
skia_dm \
skia_nanobench \
diff --git a/emu_test/cts.gpu.module.1 b/emu_test/cts.gpu.module.1
new file mode 100644
index 000000000..241fb6d77
--- /dev/null
+++ b/emu_test/cts.gpu.module.1
@@ -0,0 +1 @@
+cts.CtsDeqpTestCases
diff --git a/emu_test/cts.gpu.module.2 b/emu_test/cts.gpu.module.2
new file mode 100644
index 000000000..40a73c382
--- /dev/null
+++ b/emu_test/cts.gpu.module.2
@@ -0,0 +1,12 @@
+cts.CtsMediaTestCases
+cts.CtsCameraTestCases
+cts.CtsMediaStressTestCases
+cts.CtsGraphicsTestCases
+cts.CtsOpenGlPerf2TestCases
+cts.CtsGpuToolsHostTestCases
+cts.CtsSkQPTestCases
+cts.CtsOpenGLTestCases
+cts.CtsMediaHostTestCases
+cts.CtsOpenGlPerfTestCases
+cts.CtsCameraApi25TestCases
+cts.cts-platform-version-check
diff --git a/emu_test/cts.module.1 b/emu_test/cts.module.1
new file mode 100644
index 000000000..a78704e84
--- /dev/null
+++ b/emu_test/cts.module.1
@@ -0,0 +1,98 @@
+cts.CtsKeystoreTestCases
+cts.CtsAppTestCases
+cts.CtsTfliteNnapiDelegateTestCases
+cts.CtsSecurityTestCases
+cts.CtsStatsdHostTestCases
+cts.CtsPrintTestCases
+cts.CtsContentTestCases
+cts.CtsIcuTestCases
+cts.CtsWebkitTestCases
+cts.CtsLibcoreFileIOTestCases
+cts.CtsInputMethodTestCases
+cts.CtsInputMethodServiceHostTestCases
+cts.CtsUiRenderingTestCases
+cts.CtsLocationFineTestCases
+cts.CtsProviderUiTestCases
+cts.CtsLibcoreOkHttpTestCases
+cts.CtsAccountManagerTestCases
+cts.CtsLocationCoarseTestCases
+cts.CtsRsBlasTestCases
+cts.CtsHiddenApiKillswitchWhitelistTestCases
+cts.CtsDownloadManagerApi28
+cts.CtsShortcutManagerThrottlingTest
+cts.CtsAppBindingHostTestCases
+cts.CtsOsHostTestCases
+cts.CtsToastLegacyTestCases
+cts.CtsShortcutManagerPackage2
+cts.CtsCalendarProviderTestCases
+cts.CtsShortcutManagerLauncher3
+cts.CtsFileSystemTestCases
+cts.CtsClassloaderSplitsHostTestCases
+cts.CtsLibcoreJsr166TestCases
+cts.CtsTetheringTest
+cts.CtsEdiHostTestCases
+cts.CtsSeccompHostTestCases
+cts.CtsUiAutomationTestCases
+cts.CtsRsCppTestCases
+cts.CtsNetApi23TestCases
+cts.CtsJvmtiRunTest1931HostTestCases
+cts.CtsJvmtiAttachingHostTestCases
+cts.CtsThemeDeviceTestCases
+cts.CtsAccessibilityTestCases
+cts.CtsHostTzDataTests
+cts.CtsJvmtiRunTest989HostTestCases
+cts.CtsSystemApiSignatureTestCases
+cts.CtsJvmtiRunTest993HostTestCases
+cts.CtsDpiTestCases
+cts.CtsWrapWrapDebugMallocDebugTestCases
+cts.CtsJvmtiRunTest1941HostTestCases
+cts.CtsUidIsolationTestCases
+cts.CtsFsMgrTestCases
+cts.CtsJvmtiRunTest913HostTestCases
+cts.CtsUsesLibraryHostTestCases
+cts.CtsWrapWrapDebugTestCases
+cts.CtsJvmtiRunTest1906HostTestCases
+cts.CtsMidiTestCases
+cts.CtsJvmtiRunTest923HostTestCases
+cts.CtsSampleHostTestCases
+cts.CtsNetSecConfigCleartextTrafficTestCases
+cts.CtsJvmtiRunTest983HostTestCases
+cts.CtsApacheHttpLegacyCurrentApiSignatureTestCases
+cts.CtsNetSecConfigBasicDebugEnabledTestCases
+cts.CtsJniTestCases
+cts.CtsAndroidTestBase28ApiSignatureTestCases
+cts.CtsJvmtiRunTest1901HostTestCases
+cts.CtsJvmtiRunTest1913HostTestCases
+cts.CtsJvmtiRunTest927HostTestCases
+cts.CtsJvmtiRunTest908HostTestCases
+cts.CtsJvmtiRunTest928HostTestCases
+cts.CtsJvmtiRunTest1915HostTestCases
+cts.CtsJvmtiRunTest915HostTestCases
+cts.CtsJvmtiRunTest1910HostTestCases
+cts.CtsJvmtiRunTest947HostTestCases
+cts.CtsJvmtiRunTest920HostTestCases
+cts.CtsJvmtiRunTest940HostTestCases
+cts.CtsJvmtiRunTest995HostTestCases
+cts.CtsJvmtiRunTest914HostTestCases
+cts.CtsNoPermissionTestCases25
+cts.CtsAppUsageHostTestCases
+cts.CtsNetSecConfigAttributeTestCases
+cts.CtsPermissionTestCasesTelephony
+cts.CtsSecureElementAccessControlTestCases2
+cts.CtsViewInspectorAnnotationProcessorTestCases
+cts.signed-CtsSecureElementAccessControlTestCases3
+cts.CtsBluetoothTestCases
+cts.CtsIntentSignatureTestCases
+cts.CtsLegacyNotification20TestCases
+cts.CtsMimeMapTestCases
+cts.CtsLeanbackJankTestCases
+cts.CtsContactsProviderWipe
+cts.CtsLibcoreApiEvolutionTestCases
+cts.CtsExternalServiceTestCases
+cts.CtsNetSecPolicyUsesCleartextTrafficTrueTestCases
+cts.CtsSustainedPerformanceHostTestCases
+cts.CtsAttentionServiceDeviceTestCases
+cts.CtsLegacyNotification28TestCases
+cts.CtsNativeMediaXaTestCases
+cts.CtsApexTestCases
+cts.CtsHostsideTvTests
diff --git a/emu_test/cts.module.2 b/emu_test/cts.module.2
new file mode 100644
index 000000000..94c45718b
--- /dev/null
+++ b/emu_test/cts.module.2
@@ -0,0 +1,98 @@
+cts.CtsAppSecurityHostTestCases
+cts.CtsUsageStatsTestCases
+cts.CtsPreferenceTestCases
+cts.CtsTelecomTestCases
+cts.vm-tests-tf
+cts.CtsSecurityBulletinHostTestCases
+cts.CtsHostsideNetworkTests
+cts.CtsJobSchedulerTestCases
+cts.CtsTextTestCases
+cts.CtsIncidentHostTestCases
+cts.CtsPdfTestCases
+cts.CtsFragmentTestCases
+cts.CtsNNAPITestCases
+cts.CtsProviderTestCases
+cts.CtsPermission2TestCases
+cts.CtsHiddenApiBlacklistApi28TestCases
+cts.CtsSimpleperfTestCases
+cts.CtsAlarmManagerTestCases
+cts.CtsContentCaptureServiceTestCases
+cts.CtsAppEnumerationTestCases
+cts.CtsHiddenApiKillswitchWildcardTestCases
+cts.CtsThemeHostTestCases
+cts.CtsShortcutManagerLauncher2
+cts.CtsHiddenApiBlacklistTestApiTestCases
+cts.CtsAssistTestCases
+cts.CtsShortcutManagerTestCases
+cts.CtsAtraceHostTestCases
+cts.CtsLegacyNotification29TestCases
+cts.CtsBootStatsTestCases
+cts.CtsSettingsHostTestCases
+cts.CtsSliceTestCases
+cts.CtsDisplayTestCases
+cts.CtsDeviceIdleHostTestCases
+cts.CtsToastTestCases
+cts.CtsNetSecPolicyUsesCleartextTrafficUnspecifiedTestCases
+cts.CtsNetSecPolicyUsesCleartextTrafficFalseTestCases
+cts.CtsAtomicInstallTestCases
+cts.CtsTvTestCases
+cts.CtsJvmtiRunTest1958HostTestCases
+cts.CtsSdkExtensionsTestCases
+cts.CtsWifiBroadcastsHostTestCases
+cts.CtsAslrMallocTestCases
+cts.CtsJvmtiRunTest1932HostTestCases
+cts.CtsColorModeTestCases
+cts.CtsNdkBinderTestCases
+cts.CtsNativeHardwareTestCases
+cts.CtsDrmTestCases
+cts.CtsPackageInstallerTapjackingTestCases
+cts.CtsDumpsysHostTestCases
+cts.CtsJvmtiRunTest931HostTestCases
+cts.CtsJvmtiRunTest990HostTestCases
+cts.CtsJvmtiRunTest1942HostTestCases
+cts.CtsNetSecConfigInvalidPinTestCases
+cts.CtsLibcoreWycheproofConscryptTestCases
+cts.CtsJvmtiRunTest1908HostTestCases
+cts.CtsJvmtiRunTest1921HostTestCases
+cts.CtsWrapNoWrapTestCases
+cts.CtsLocationNoneTestCases
+cts.CtsAndroidTestRunnerCurrentApiSignatureTestCases
+cts.CtsJvmtiRunTest907HostTestCases
+cts.CtsWrapWrapNoDebugTestCases
+cts.CtsAndroidTestMockCurrentApiSignatureTestCases
+cts.CtsJvmtiRunTest1922HostTestCases
+cts.CtsJvmtiRunTest1927HostTestCases
+cts.CtsJvmtiRunTest902HostTestCases
+cts.CtsJvmtiRunTest1900HostTestCases
+cts.CtsJvmtiRunTest919HostTestCases
+cts.CtsJvmtiRunTest982HostTestCases
+cts.CtsJvmtiRunTest903HostTestCases
+cts.CtsJvmtiRunTest930HostTestCases
+cts.CtsJvmtiRunTest1914HostTestCases
+cts.CtsJvmtiRunTest1933HostTestCases
+cts.CtsJvmtiRunTest922HostTestCases
+cts.CtsJvmtiRunTest1930HostTestCases
+cts.CtsJvmtiRunTest986HostTestCases
+cts.CtsJvmtiRunTest942HostTestCases
+cts.CtsJvmtiRunTest951HostTestCases
+cts.CtsNetSecConfigBasicDomainConfigTestCases
+cts.CtsInitTestCases
+cts.CtsAccessibilityServiceSdk29TestCases
+cts.CtsTelephony2TestCases
+cts.signed-CtsSecureElementAccessControlTestCases1
+cts.CtsSecureElementAccessControlTestCases1
+cts.CtsAppComponentFactoryTestCases
+cts.CtsCronetTestCases
+cts.CtsCppToolsTestCases
+cts.CtsSelinuxEphemeralTestCases
+cts.CtsNetSecConfigPrePCleartextTrafficTestCases
+cts.CtsTrustedVoiceHostTestCases
+cts.CtsLibcoreLegacy22TestCases
+cts.CtsNetTestCasesInternetPermission
+cts.CtsSelinuxTargetSdk27TestCases
+cts.CtsSelinuxTargetSdk25TestCases
+cts.CtsSelinuxTargetSdk28TestCases
+cts.CtsTvProviderTestCases
+cts.CtsCalendarcommon2TestCases
+cts.CtsNativeMediaSlTestCases
+cts.CtsNativeEncryptionTestCases
diff --git a/emu_test/cts.module.3 b/emu_test/cts.module.3
new file mode 100644
index 000000000..aac8278e5
--- /dev/null
+++ b/emu_test/cts.module.3
@@ -0,0 +1,99 @@
+cts.CtsWindowManagerDeviceTestCases
+cts.CtsNetTestCases
+cts.CtsWifiTestCases
+cts.CtsAccessibilityServiceTestCases
+cts.CtsDevicePolicyManagerTestCases
+cts.CtsLocationGnssTestCases
+cts.CtsRollbackManagerHostTestCases
+cts.CtsStagedInstallHostTestCases
+cts.CtsVideoTestCases
+cts.CtsSecurityHostTestCases
+cts.CtsOsTestCases
+cts.CtsSystemUiTestCases
+cts.CtsShortcutHostTestCases
+cts.CtsPerfettoTestCases
+cts.CtsRenderscriptTestCases
+cts.CtsHardwareTestCases
+cts.CtsHiddenApiBlacklistDebugClassTestCases
+cts.CtsNativeMediaAAudioTestCases
+cts.CtsHiddenApiBlacklistApi27TestCases
+cts.CtsTransitionTestCases
+cts.CtsHiddenApiKillswitchDebugClassTestCases
+cts.CtsSyncContentHostTestCases
+cts.CtsDownloadManagerLegacy
+cts.CtsInlineMockingTestCases
+cts.CtsDatabaseTestCases
+cts.CtsLogdTestCases
+cts.CtsSimpleCpuTestCases
+cts.CtsShortcutManagerPackage4
+cts.CtsShortcutManagerPackage3
+cts.CtsCheckpointTestCases
+cts.CtsKernelConfigTestCases
+cts.CtsHostsideWebViewTests
+cts.CtsPackageInstallTestCases
+cts.CtsSyncAccountAccessOtherCertTestCases
+cts.CtsBionicTestCases
+cts.CtsLegacyNotification27TestCases
+cts.CtsVoiceSettingsTestCases
+cts.CtsCurrentApiSignatureTestCases
+cts.CtsDropBoxManagerTestCases
+cts.CtsSyncManagerTestsCases
+cts.CtsBackgroundRestrictionsTestCases
+cts.CtsVoiceInteractionTestCases
+cts.CtsAccelerationTestCases
+cts.CtsJvmtiRedefineClassesHostTestCases
+cts.CtsLibcoreWycheproofBCTestCases
+cts.CtsNoPermissionTestCases
+cts.CtsHostsideNumberBlockingTestCases
+cts.CtsJvmtiRunTest911HostTestCases
+cts.CtsApacheHttpLegacy27ApiSignatureTestCases
+cts.CtsJvmtiTaggingHostTestCases
+cts.CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases
+cts.CtsSystemApiAnnotationTestCases
+cts.CtsSampleDeviceTestCases
+cts.CtsProtoTestCases
+cts.CtsJvmtiRunTest1907HostTestCases
+cts.CtsJvmtiRunTest1920HostTestCases
+cts.CtsAndroidAppTestCases
+cts.CtsNativeMidiTestCases
+cts.CtsJvmtiRunTest1924HostTestCases
+cts.CtsJvmtiRunTest912HostTestCases
+cts.CtsJvmtiRunTest1925HostTestCases
+cts.CtsJvmtiRunTest944HostTestCases
+cts.CtsJvmtiRunTest1953HostTestCases
+cts.CtsEffectTestCases
+cts.CtsJvmtiRunTest988HostTestCases
+cts.CtsJvmtiRunTest904HostTestCases
+cts.CtsJvmtiRunTest917HostTestCases
+cts.CtsJvmtiRunTest910HostTestCases
+cts.CtsJvmtiRunTest926HostTestCases
+cts.CtsJvmtiRunTest1912HostTestCases
+cts.CtsExtractNativeLibsHostTestCases
+cts.CtsJvmtiRunTest985HostTestCases
+cts.CtsJvmtiRunTest991HostTestCases
+cts.CtsFragmentTestCasesSdk26
+cts.CtsJvmtiRunTest1939HostTestCases
+cts.CtsJvmtiRunTest984HostTestCases
+cts.CtsJvmtiRunTest994HostTestCases
+cts.CtsJvmtiRunTest1928HostTestCases
+cts.CtsNetSecConfigBasicDebugDisabledTestCases
+cts.CtsLiblogTestCases
+cts.CtsViewTestCasesSdk28
+cts.CtsDynamicLinkerTestCases
+cts.CtsMultiUserTestCases
+cts.CtsSecureElementAccessControlTestCases3
+cts.CtsCarTestCases
+cts.CtsJvmtiAttachingTestCases
+cts.CtsClassLoaderFactoryPathClassLoaderTestCases
+cts.CtsHdmiCecHostTestCases
+cts.CtsDreamsTestCases
+cts.CtsPermissionTestCasesSdk28
+cts.CtsSaxTestCases
+cts.CtsNetSecConfigDownloadManagerTestCases
+cts.CtsContentSuggestionsTestCases
+cts.CtsSelinuxTargetSdkCurrentTestCases
+cts.CtsTelecom4TestCases
+cts.CtsNetTestCasesLegacyPermission22
+cts.CtsNdefTestCases
+cts.CtsTelephony3TestCases
+cts.CtsNativeNetTestCases
diff --git a/emu_test/cts.module.4 b/emu_test/cts.module.4
new file mode 100644
index 000000000..bc12a29e5
--- /dev/null
+++ b/emu_test/cts.module.4
@@ -0,0 +1,99 @@
+cts.CtsAutoFillServiceTestCases
+cts.CtsTelephonyTestCases
+cts.CtsBatterySavingTestCases
+cts.CtsViewTestCases
+cts.CtsSensorTestCases
+cts.CtsLibcoreOjTestCases
+cts.CtsLibcoreTestCases
+cts.CtsWidgetTestCases
+cts.CtsJdwpTestCases
+cts.CtsBackupHostTestCases
+cts.CtsPermissionTestCases
+cts.CtsAppWidgetTestCases
+cts.CtsActivityManagerBackgroundActivityTestCases
+cts.CtsAnimationTestCases
+cts.CtsNetTestCasesLegacyApi22
+cts.CtsHiddenApiBlacklistCurrentApiTestCases
+cts.CtsContactsProviderTestCases
+cts.CtsRoleTestCases
+cts.CtsAppOpsTestCases
+cts.CtsExtendedMockingTestCases
+cts.CtsTelephonySdk28TestCases
+cts.CtsCarrierApiTestCases
+cts.CtsShortcutManagerLauncher4
+cts.CtsShortcutManagerLauncher1
+cts.CtsMultiUserHostTestCases
+cts.CtsBackupTestCases
+cts.CtsShortcutManagerPackage1
+cts.CtsMockingDebuggableTestCases
+cts.CtsSignedConfigHostTestCases
+cts.CtsMonkeyTestCases
+cts.CtsTelephonyProviderTestCases
+cts.CtsNNAPIBenchmarkTestCases
+cts.CtsAngleIntegrationHostTestCases
+cts.CtsMockingTestCases
+cts.CtsVrTestCases
+cts.CtsAdminPackageInstallerTestCases
+cts.CtsJdwpTunnelHostTestCases
+cts.CtsJvmtiRunTest924HostTestCases
+cts.CtsTelecomTestCases2
+cts.CtsUtilTestCases
+cts.CtsAdminTestCases
+cts.CtsDexMetadataHostTestCases
+cts.CtsTelecomTestCases3
+cts.CtsTextClassifierTestCases
+cts.cts-system-all.txt
+cts.CtsUiRenderingTestCases27
+cts.CtsJdwpSecurityHostTestCases
+cts.CtsSystemUiHostTestCases
+cts.CtsJvmtiRunTest1904HostTestCases
+cts.CtsJvmtiRunTest1902HostTestCases
+cts.CtsAppPredictionServiceTestCases
+cts.CtsJvmtiRunTest905HostTestCases
+cts.CtsDeviceConfigTestCases
+cts.CtsJvmtiRunTest906HostTestCases
+cts.CtsJobSchedulerSharedUidTestCases
+cts.CtsSystemIntentTestCases
+cts.CtsAbiOverrideHostTestCases
+cts.CtsJvmtiRunTest1936HostTestCases
+cts.CtsJvmtiRunTest1923HostTestCases
+cts.CtsSharedLibsApiSignatureTestCases
+cts.CtsJvmtiRunTest1926HostTestCases
+cts.CtsJvmtiRunTest997HostTestCases
+cts.CtsCompilationTestCases
+cts.CtsJvmtiRunTest932HostTestCases
+cts.CtsJvmtiRunTest1903HostTestCases
+cts.CtsJvmtiRunTest1943HostTestCases
+cts.CtsJvmtiRunTest1917HostTestCases
+cts.CtsJvmtiRunTest1909HostTestCases
+cts.CtsJvmtiRunTest945HostTestCases
+cts.CtsJvmtiRunTest1937HostTestCases
+cts.CtsJvmtiRunTest918HostTestCases
+cts.CtsJvmtiRunTest1934HostTestCases
+cts.CtsJvmtiRunTest1911HostTestCases
+cts.CtsJvmtiRunTest992HostTestCases
+cts.CtsJvmtiRunTest1916HostTestCases
+cts.CtsJvmtiRunTest996HostTestCases
+cts.CtsJvmtiTrackingHostTestCases
+cts.CtsNetSecConfigNestedDomainConfigTestCases
+cts.CtsGestureTestCases
+cts.CtsNetSecConfigResourcesSrcTestCases
+cts.signed-CtsSecureElementAccessControlTestCases2
+cts.CtsOmapiTestCases
+cts.CtsAndroidTestBaseCurrentApiSignatureTestCases
+cts.CtsClassLoaderFactoryInMemoryDexClassLoaderTestCases
+cts.CtsWindowManagerSdk28TestCases
+cts.CtsWindowManagerSdk25TestCases
+cts.CtsSpeechTestCases
+cts.CtsNetTestCasesUpdateStatsPermission
+cts.CtsPackageUninstallTestCases
+cts.CtsUsbTests
+cts.CtsRenderscriptLegacyTestCases
+cts.CtsBlobStoreTestCases
+cts.CtsSimRestrictedApisTestCases
+cts.CtsHarmfulAppWarningHostTestCases
+cts.CtsResolverServiceTestCases
+cts.CtsDpiTestCases2
+cts.CtsNativeNetDnsTestCases
+cts.CtsNativeMediaMetricsTestCases
+cts.CtsUserspaceRebootHostSideTestCases
diff --git a/emu_test/gts.module b/emu_test/gts.module
new file mode 100644
index 000000000..b157ea252
--- /dev/null
+++ b/emu_test/gts.module
@@ -0,0 +1,3 @@
+gts.GtsLauncherHostTestCases
+gts.GtsMemoryHostTestCases
+gts.GtsWebViewTestCases
diff --git a/emu_test/run_test.sh b/emu_test/run_test.sh
index f2d5c402c..d003e0395 100755
--- a/emu_test/run_test.sh
+++ b/emu_test/run_test.sh
@@ -48,9 +48,12 @@ echo "Run Boot tests from $ADT_INFRA"
cmd="$ADT_INFRA/emu_test/utils/run_boot_test.sh"
run_with_timeout $cmd $DIST_DIR $ORI $API 5400
-echo "Run UI tests from $ADT_INFRA"
-cmd="$ADT_INFRA/emu_test/utils/run_ui_test.sh"
-run_with_timeout $cmd $DIST_DIR $ORI $API 10800
+# Skip UI tests for presubmit build which has a build number starts with P.
+if [[ $BUILD_NUMBER != P* ]]; then
+ echo "Run UI tests from $ADT_INFRA"
+ cmd="$ADT_INFRA/emu_test/utils/run_ui_test.sh"
+ run_with_timeout $cmd $DIST_DIR $ORI $API 10800
+fi
echo "Cleanup prebuilts"
rm -rf /buildbot/prebuilt/*
diff --git a/emu_test/run_test_suite.sh b/emu_test/run_test_suite.sh
index 1a9bade37..0c8dc1c6d 100755
--- a/emu_test/run_test_suite.sh
+++ b/emu_test/run_test_suite.sh
@@ -1,68 +1,193 @@
#!/bin/bash
# It is to be used with BYOB setup to run CTS tests.
#
-# It takes 1 command line argument.
-# DIST_DIR => Absolute path for the distribution directory.
-#
# It will return 0 if it is able to execute tests, otherwise
# it will return 1.
#
-# Owner: akagrawal@google.com
+# Owner: mattwachakagrawal@google.com
+
+# Echo vars to the log
+set -x
DIST_DIR=$1
+# Build ID is used for identifying the builds during upload
BUILD_ID=$2
+# Module list file
+MODULE_LIST_FILE=$3
+# Emulator GPU option
+GPU_FLAG=$4
+# Directory containing the system image to run the tests against. Default is gphone_x86_64-user
+PRODUCT_DIR=${5:-gphone_x86_64-user}
-BUILD_DIR="out/prebuilt_cached/builds"
+# Kill any emulators that might still be active from older sessions.
+killall qemu-system-x86_64-headless
-if [ ! -d "$BUILD_DIR/test_suite" ];
-then
- echo "Test suite does not exist"
- exit 1
-fi
-#for cts, android-cts.zip
-#for gts, android-gts.zip
-if [[ `ls $BUILD_DIR/test_suite` == *"cts"* ]]
-then
- TEST_SUITE="android-cts.zip"
-elif [[ `ls $BUILD_DIR/test_suite` == *"gts"* ]]
-then
- TEST_SUITE="android-gts.zip"
+# Working files for the testing process
+WORK_DIR="$DIST_DIR/tradefed-make"
+TEST_DIR="$DIST_DIR/tradefed-test"
+rm -rf $WORK_DIR
+mkdir -p $WORK_DIR
+
+function cleanup_dirs {
+ echo "Cleanup prebuilts"
+ rm -rf /buildbot/prebuilt/*
+ rm -rf $WORK_DIR
+ rm -rf $TEST_DIR/common
+ # Extra files that may sometimes be of use, but in general seem
+ # to create a lot of artifact clutter.
+ find $TEST_DIR \( \
+ -name 'adbkey*' -o \
+ -name '*.cache' -o \
+ -name '*.conf' -o \
+ -name 'cts.dynamic' -o \
+ -name '*.data' -o \
+ -name '*.json' -o \
+ -name '*.lock' -o \
+ -name 'modem-nv-ram-*' -o \
+ -name '*.pb' -o \
+ -name '*.png' -o \
+ -name '*.protobuf' -o \
+ -name 'sepolicy' -o \
+ -name '*.zip' \
+ \) -print0 | xargs -0 -n 10 rm
+}
+# Always remove working files, even on error
+trap cleanup_dirs EXIT
+# Exit on errors.
+set -e
+
+function die {
+ echo "run_test_suite.sh: $1">&2
+ exit 1
+}
+
+function fetch_latest_emulator {
+ local emu_dir=$1
+ mkdir -p $emu_dir
+ local fetch_stdout=$(fetch_artifacts.py \
+ -build_target linux-sdk_tools_linux \
+ -branch aosp-emu-master-dev \
+ -image_path gs://android-build-emu/builds \
+ -dest $emu_dir)
+ # extract build_id from fetch fetch_artifacts.py stdout
+ # stdout looks like:
+ # Fetching latest build 5800753 for linux-sdk_tools_linux
+ echo $(echo $fetch_stdout | grep "Fetching latest build" | awk '{ print $4 }')
+}
+
+function find_zip_in_dir {
+ local target_name=$1
+ local zip_dir=$2
+ [[ -d $zip_dir ]] || die "Could not find $target_name dir: $zip_dir"
+ local zip_path=$zip_dir/$(ls $zip_dir)
+ [[ -f $zip_path ]] || die "Could not find $target_name zip file: $zip_path"
+ [[ "$zip_path" == *.zip ]] || die "Bad image $target_name zip pathname: $zip_path"
+ echo $zip_path
+}
+
+# Check that we have the expected version of java.
+EXPECTED_VERSION=9.0.4
+export PATH=~/jdk-${EXPECTED_VERSION}/bin:$PATH
+java --version | grep $EXPECTED_VERSION # Fails if version string not found.
+
+MODULE_LIST_PATH=$(dirname ${BASH_SOURCE[0]})/$MODULE_LIST_FILE
+[[ -f $MODULE_LIST_PATH ]] || die "The module list path $MODULE_LIST_PATH was not found"
+
+# Directory where tradefed-make tools are cloned
+TRADEFED_MAKE_DIR="$WORK_DIR/tradefed-make"
+git clone \
+ https://team.googlesource.com/android-devtools-emulator/tradefed-make \
+ $TRADEFED_MAKE_DIR
+
+# The emulator requires files in the platforms directory
+PLATFORMS_DIR="${HOME}/Android_sys_image/sdk/platforms/android-28"
+
+# Platform tools contain core tools, like adb
+PLATFORM_TOOLS_DIR="${HOME}/Android_sys_image/sdk/platform-tools"
+
+# More tools dependencies.
+SDK_TOOLS_DIR="${HOME}/Android_sys_image/sdk/build-tools/27.0.3"
+
+# Where to put the testing configuration file
+CONFIG_PATH="$WORK_DIR/tradefed-make-config.yaml"
+
+# Fetch the latest emulator
+EMU_DIR=$WORK_DIR/emulator
+EMU_BUILD_ID=$(fetch_latest_emulator $EMU_DIR)
+EMU_ZIP=$(find_zip_in_dir emulator $EMU_DIR)
+ls -l $EMU_ZIP
+
+# Directory where system images, and cts can be found
+BUILD_DIR=out/prebuilt_cached/builds
+
+IMAGE_DIR=$BUILD_DIR/$PRODUCT_DIR
+IMAGE_ZIP=$(find_zip_in_dir image $IMAGE_DIR)
+ls -l $IMAGE_ZIP
+
+if [[ -f "$BUILD_DIR/test_suite/android-cts.zip" ]]; then
+ TEST_SUITE=cts
+ IMAGE_FLAVOR=user
+elif [[ -f "$BUILD_DIR/test_suite/android-gts.zip" ]]; then
+ TEST_SUITE=gts
+ IMAGE_FLAVOR=user
+elif [[ -f "$BUILD_DIR/test_suite/android-vts.zip" ]]; then
+ TEST_SUITE=vts
+ IMAGE_FLAVOR=userdebug
+ export VTS_PYPI_PATH=$WORK_DIR/venv
+ pip install --user virtualenv
+ virtualenv $VTS_PYPI_PATH
+ curl https://android.googlesource.com/platform/test/vts/+/master/script/pip_requirements.txt?format=TEXT | base64 -d > $WORK_DIR/pip_requirements.txt
+ pip download -d $VTS_PYPI_PATH -r $WORK_DIR/pip_requirements.txt --no-binary protobuf,grpcio,matplotlib,numpy,Pillow,scipy==1.2.2
else
- echo "Test suite does not exist"
- exit 1
-fi
-echo "$TEST_SUITE"
-
-mkdir -p $BUILD_DIR/emulator
-fetch_artifacts.py -build_target linux-sdk_tools_linux -branch aosp-emu-master-dev -image_path gs://android-build-emu/builds -dest $BUILD_DIR/emulator/
-EMU_BIN=`ls $BUILD_DIR/emulator`
-echo "$EMU_BIN"
-
-if [ -d "$BUILD_DIR/gphone_x86-user" ];
-then
- SYS_IMAGE=`ls $BUILD_DIR/gphone_x86-user`
- if [[ $TEST_SUITE == *"cts"* ]]
- then
- echo "Run CTS with $SYS_IMAGE"
- elif [[ $TEST_SUITE == *"gts"* ]]
- then
- echo "Run GTS with $SYS_IMAGE"
- fi
+ die "Could not find android-cts.zip, android-gts.zip or android-vts.zip in $BUILD_DIR/test_suite"
fi
-if [ -d "$BUILD_DIR/gphone_x86_64-user" ];
-then
- SYS_IMAGE_64=`ls $BUILD_DIR/gphone_x86_64-user`
- if [[ $TEST_SUITE == *"cts"* ]]
- then
- echo "Run CTS with $SYS_IMAGE_64"
- elif [[ $TEST_SUITE == *"gts"* ]]
- then
- echo "Run GTS with $SYS_IMAGE_64"
- fi
+
+# Setup the testing configuration
+$TRADEFED_MAKE_DIR/make-config \
+ $TRADEFED_MAKE_DIR/config.yaml \
+ $CONFIG_PATH \
+ --override \
+ config.tradefed.ape_api_key=/home/android-build/gts-android-emulator.json \
+ vars.emulator.files.download.build_id=$EMU_BUILD_ID \
+ vars.emulator.files.local_zip_path=$EMU_ZIP \
+ vars.emulator.flags.feature=PlayStoreImage,GLAsyncSwap,GLESDynamicVersion \
+ vars.emulator.flags.gpu=$GPU_FLAG \
+ vars.image.files.local_zip_path.${IMAGE_FLAVOR}=$IMAGE_ZIP \
+ vars.image.files.download.branch=git_rvc-release \
+ vars.image.files.download.build_id=$BUILD_ID \
+ vars.image.flavor.default=user \
+ vars.root_dir=$TEST_DIR \
+ vars.tradefed.timeout_seconds=10000 \
+ vars.tools.android_level=28 \
+ vars.tools.files.download.build_id=0 \
+ vars.tools.files.local_dir.platforms=$PLATFORMS_DIR \
+ vars.tools.files.local_dir.platform_tools=$PLATFORM_TOOLS_DIR \
+ vars.tools.files.local_dir.sdk_tools=$SDK_TOOLS_DIR \
+ vars.tradefed.files.download.build_id=$BUILD_ID \
+ vars.tradefed.files.local_zip_path.$TEST_SUITE=$BUILD_DIR/test_suite/android-$TEST_SUITE.zip \
+ --add \
+ vars.emulator.flags.no-window=True \
+
+if [[ "$GPU_FLAG" == "host" ]]; then
+ $TRADEFED_MAKE_DIR/make-config \
+ $CONFIG_PATH \
+ --inline \
+ --override \
+ config.emulator.command_prefix='vglrun +v -c proxy' \
+
fi
-echo "Cleanup prebuilts"
-rm -rf /buildbot/prebuilt/*
+# Start the tests
+set +x
+set -e
+# Override the jdk's built-in certs to use the system ones.
+export RDBG_FLAG=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts
+export DISPLAY=:0
+$TRADEFED_MAKE_DIR/tradefed-make $CONFIG_PATH -j4 prepare.$TEST_SUITE.all_modules
+$TRADEFED_MAKE_DIR/tradefed-make $CONFIG_PATH -j4 $(cat $MODULE_LIST_PATH | sed 's/^/run./')
+$TRADEFED_MAKE_DIR/tradefed-make $CONFIG_PATH stop.emulator.$TEST_SUITE
+
+# TODO: Further analyze the results.
exit 0
diff --git a/emu_test/vts.module b/emu_test/vts.module
new file mode 100644
index 000000000..86d5bdaa9
--- /dev/null
+++ b/emu_test/vts.module
@@ -0,0 +1 @@
+vts
diff --git a/libraries/annotations/src/android/platform/test/annotations/SocPresubmit.java b/libraries/annotations/src/android/platform/test/annotations/SocPresubmit.java
new file mode 100644
index 000000000..d4116b370
--- /dev/null
+++ b/libraries/annotations/src/android/platform/test/annotations/SocPresubmit.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.test.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Include Widevine security level 1 tests.
+ *
+ * <p>To minimize regression, we are going run some GTS tests. Add this annotation to select tests
+ * to verify changes from SOC chip vendors. Only L1 tests are run.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE_USE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SocPresubmit {}
diff --git a/libraries/app-helpers/OWNERS b/libraries/app-helpers/OWNERS
new file mode 100644
index 000000000..19fe33415
--- /dev/null
+++ b/libraries/app-helpers/OWNERS
@@ -0,0 +1,3 @@
+include ../OWNERS
+#SystemUI
+include platform/frameworks/base:/packages/SystemUI/OWNERS
diff --git a/libraries/app-helpers/interfaces/Android.bp b/libraries/app-helpers/interfaces/Android.bp
index 2866eec2e..264d0a526 100644
--- a/libraries/app-helpers/interfaces/Android.bp
+++ b/libraries/app-helpers/interfaces/Android.bp
@@ -57,7 +57,10 @@ java_library {
"ub-uiautomator",
"app-helpers-core",
],
- static_libs: ["app-helpers-common-interfaces"],
+ static_libs: [
+ "app-helpers-common-interfaces",
+ "androidx.annotation_annotation"
+ ],
srcs: ["handheld/**/*.java"],
sdk_version: "test_current",
}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialContactDetailsHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialContactDetailsHelper.java
new file mode 100644
index 000000000..da0183338
--- /dev/null
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialContactDetailsHelper.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.helpers;
+
+public interface IAutoDialContactDetailsHelper extends IAppHelper {
+ /** enum class for contact number types. */
+ enum ContactType {
+ WORK,
+ HOME,
+ MOBILE
+ }
+
+ /**
+ * Setup expectations: The contact's details page is open.
+ *
+ * <p>This method is used to add/remove a contact to Favorites.
+ */
+ void addRemoveFavoriteContact();
+
+ /**
+ * Setup expectations: The contact's details page is open.
+ *
+ * <p>This method is used to call the contact from detail page.
+ */
+ void makeCallFromDetailsPageByType(ContactType type);
+
+ /**
+ * Setup expectations: The contact's details page is open.
+ *
+ * <p>This method is used to close the details page.
+ */
+ void closeDetailsPage();
+}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java
index 6e093167f..77ec8a37f 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoDialHelper.java
@@ -16,7 +16,20 @@
package android.platform.helpers;
+
public interface IAutoDialHelper extends IAppHelper {
+
+ /** enum class for contact list order type. */
+ enum OrderType {
+ FIRST_NAME,
+ LAST_NAME
+ }
+ /** enum class for phone call audio channel. */
+ enum AudioSource {
+ PHONE,
+ CAR_SPEAKERS,
+ }
+
/**
* Setup expectations: The app is open and the dialpad is open
*
@@ -85,39 +98,136 @@ public interface IAutoDialHelper extends IAppHelper {
String getRecentCallHistory();
/**
- * Setup expectations: The app is open and phonenumber is entered on the dialpad
+ * Setup expectations: The app is open and phonenumber is entered on the dialpad.
*
- * <p>This method is used to make/receive a call using softkey
+ * <p>This method is used to make/receive a call using softkey.
*/
void makeCall();
/**
- * Setup expectations: The app is open
+ * Setup expectations: The app is open.
*
- * <p>This method is used to dial a number from a list (Favorites, Call History, Contact)
+ * <p>This method is used to dial a number from a list (Favorites, Call History, Contact).
*
* @param contact (number or name) dial.
*/
void dialFromList(String contact);
/**
- * Setup expectations: The app is open and there is an ongoing call
+ * Setup expectations: The app is open and there is an ongoing call.
+ *
+ * <p>This method is used to enter number on the in-call dialpad.
*
- * <p>This method is used to enter number on the in-call dialpad
+ * @param phoneNumber to dial.
*/
void inCallDialPad(String phoneNumber);
/**
- * Setup expectations: The app is open and there is an ongoing call
+ * Setup expectations: The app is open and there is an ongoing call.
*
- * <p>This method is used to mute the ongoing call
+ * <p>This method is used to mute the ongoing call.
*/
void muteCall();
/**
- * Setup expectations: The app is open and there is an ongoing call
+ * Setup expectations: The app is open and there is an ongoing call.
*
- * <p>This method is used to unmute the ongoing call
+ * <p>This method is used to unmute the ongoing call.
*/
void unmuteCall();
+
+ /**
+ * Setup expectations: The app is open and there is an ongoing call.
+ *
+ * <p>This method is used to change voice channel to handset/bluetooth.
+ *
+ * @param source to switch to.
+ */
+ void changeAudioSource(AudioSource source);
+
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to make a call to the first history from Call History.
+ */
+ void callMostRecentHistory();
+
+ /**
+ * Setup expectations: The app is open and there is an ongoing call.
+ *
+ * <p>This method is used to get the contact name being called.
+ */
+ String getContactName();
+
+ /**
+ * Setup expectations: The app is open and there is an ongoing call
+ *
+ * <p>This method is used to get the contact type (Mobile, Work, Home and etc.) being called.
+ */
+ String getContactType();
+
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to search a contact in the contact list.
+ *
+ * @param contact to search.
+ */
+ void searchContactsByName(String contact);
+
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to search a number in the contact list.
+ *
+ * @param number to search.
+ */
+ void searchContactsByNumber(String number);
+
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to get the first search result for contact.
+ */
+ String getFirstSearchResult();
+
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to order the contact list based on first/last name.
+ *
+ * @param orderType to use.
+ */
+ void sortContactListBy(OrderType orderType);
+
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to get the first contact name from contact list.
+ */
+ String getFirstContactFromContactList();
+
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to verify if a contact is added to Favorites.
+ *
+ * @param contact to check.
+ */
+ boolean isContactInFavorites(String contact);
+
+ /**
+ * Setup expectations: The contact's details page is open.
+ *
+ * <p>This method is used to close the details page.
+ *
+ * @param contact Contact's details page to be opened.
+ */
+ void openDetailsPage(String contact);
+ /**
+ * Setup expectations: The app is open.
+ *
+ * <p>This method is used to check if phone is paired.
+ */
+ boolean isPhonePaired();
}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoLockScreenHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoLockScreenHelper.java
new file mode 100644
index 000000000..e292a459c
--- /dev/null
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoLockScreenHelper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.helpers;
+
+/** Helper class for functional tests of Lock Screen */
+public interface IAutoLockScreenHelper extends IAppHelper {
+
+ /** Enum class for supported lock type. */
+ enum LockType {
+ PIN,
+ PASSWORD
+ }
+ /**
+ * Setup expectation: none.
+ *
+ * <p>This method is to lock device screen.
+ *
+ * @param lockType is the lock type used to lock screen.
+ * @param credential is the pin/password used.
+ */
+ void lockScreenBy(LockType lockType, String credential);
+
+ /**
+ * Setup expectation: none.
+ *
+ * <p>This method is to unlock device screen.
+ *
+ * @param lockType is the lock type used to lock screen.
+ * @param credential is the pin/password used.
+ */
+ void unlockScreenBy(LockType lockType, String credential);
+}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMapsHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMapsHelper.java
index 5bf3f03f8..f42b928a3 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMapsHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMapsHelper.java
@@ -17,6 +17,14 @@
package android.platform.helpers;
public interface IAutoMapsHelper extends IAppHelper {
+
+ /**
+ * Setup expectations: Maps app is open
+ *
+ * <p>This method is used to verify whether search bar is present.
+ */
+ boolean isSearchBarPresent();
+
/**
* Setup expectations: Maps app is open
*
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterHelper.java
index 52caa07e5..e69e4ce3b 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterHelper.java
@@ -83,4 +83,18 @@ public interface IAutoMediaCenterHelper extends IAppHelper {
* else returns false
*/
boolean isPlaying();
+
+ /**
+ * Setup expectations: media test app is open.
+ *
+ * clicks on a particular album
+ */
+ void clickAlbum();
+
+ /**
+ * Setup expectations: media test app is open.
+ *
+ * clicks to go back to previous screen
+ */
+ void clickBackButton();
}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterNowPlayingHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterNowPlayingHelper.java
index bbe0e2bc7..a73e19bc6 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterNowPlayingHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaCenterNowPlayingHelper.java
@@ -49,13 +49,20 @@ public interface IAutoMediaCenterNowPlayingHelper extends IAppHelper {
/**
* Setup expectations: Now Playing is open.
*
- * @return to get current playing track name from home screen.
+ * @return to get current playing track name from screen.
*/
String getTrackName();
/**
* Setup expectations: Now Playing is open.
*
+ * @return to get current playing track's artist name from screen.
+ */
+ String getArtistName();
+
+ /**
+ * Setup expectations: Now Playing is open.
+ *
* This method is used to minimize now playing.
*/
void minimizeNowPlaying();
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java
index ada56e72f..569c5a3b3 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoMediaHelper.java
@@ -21,15 +21,20 @@ public interface IAutoMediaHelper extends IAppHelper {
* Setup expectations: media app is open
*
* This method is used to play media.
- *
*/
void playMedia();
/**
+ * Setup expectations: on home screen.
+ *
+ * This method is used to play media from home screen.
+ */
+ void playPauseMediaFromHomeScreen();
+
+ /**
* Setup expectations: media app is open.
*
* This method is used to pause media.
- *
*/
void pauseMedia();
@@ -37,23 +42,34 @@ public interface IAutoMediaHelper extends IAppHelper {
* Setup expectations: media app is open.
*
* This method is used to select next track.
- *
*/
void clickNextTrack();
/**
+ * Setup expectations: on home screen.
+ *
+ * This method is used to select next track from home screen.
+ */
+ void clickNextTrackFromHomeScreen();
+
+ /**
* Setup expectations: media app is open.
*
* This method is used to select previous track.
- *
*/
void clickPreviousTrack();
/**
+ * Setup expectations: on home screen.
+ *
+ * This method is used to select previous track from home screen.
+ */
+ void clickPreviousTrackFromHomeScreen();
+
+ /**
* Setup expectations: media app is open.
*
* This method is used to shuffle tracks.
- *
*/
void clickShuffleAll();
@@ -74,7 +90,6 @@ public interface IAutoMediaHelper extends IAppHelper {
* openMenuWith(Folder,mediafilename,trackName);
*
* @param - menuOptions used to pass multiple level of menu options in one go.
- *
*/
void openMenuWith(String... menuOptions);
@@ -104,7 +119,7 @@ public interface IAutoMediaHelper extends IAppHelper {
/**
* Setup expectations: Media app is open. User navigates to sub-page of the Media Player
*
- * <p>This method is to go back to the Media Player main page from any sub-page.
+ * This method is to go back to the Media Player main page from any sub-page.
*/
void goBackToMediaHomePage();
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoNotificationMockingHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoNotificationMockingHelper.java
index 9903832ba..5d14d8e76 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoNotificationMockingHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoNotificationMockingHelper.java
@@ -1,3 +1,10 @@
package android.platform.helpers;
-public interface IAutoNotificationMockingHelper extends INotificationHelper, IAppHelper {}
+public interface IAutoNotificationMockingHelper extends INotificationHelper, IAppHelper {
+ /**
+ * Setup expectations: No.
+ *
+ * <p>Clear all notifications generated.
+ */
+ void clearAllNotification();
+}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSecuritySettingsHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSecuritySettingsHelper.java
new file mode 100644
index 000000000..1d93de4e0
--- /dev/null
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSecuritySettingsHelper.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.helpers;
+
+/** Helper class for functional tests of Security settings */
+public interface IAutoSecuritySettingsHelper extends IAppHelper {
+ /**
+ * Setup expectation: Security setting is open.
+ *
+ * <p>This method is to set password using password lock type.
+ *
+ * @param password - input password
+ */
+ void setLockByPassword(String password);
+
+ /**
+ * Setup expectation: Security setting is open.
+ *
+ * <p>This method is to set PIN using PIN lock type.
+ *
+ * @param password - input PIN
+ */
+ void setLockByPin(String pin);
+
+ /**
+ * Setup expectation: Security setting is open.
+ *
+ * <p>This method is to check if the device is locked.
+ */
+ boolean isDeviceLocked();
+
+ /**
+ * Setup expectation: Security setting is open.
+ *
+ * <p>This method is to unlock the device by password.
+ *
+ * @param password - input password
+ */
+ void unlockByPassword(String password);
+
+ /**
+ * Setup expectation: Security setting is open.
+ *
+ * <p>This method is to unlock the device by pin.
+ *
+ * @param password - input PIN
+ */
+ void unlockByPin(String pin);
+
+ /**
+ * Setup expectation: Security setting is open and device is unlocked.
+ *
+ * <p>This method is to remove any lock, i.e. set the device lock to none.
+ */
+ void removeLock();
+}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSettingHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSettingHelper.java
index 82f443b85..403b50e6c 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSettingHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoSettingHelper.java
@@ -84,6 +84,13 @@ public interface IAutoSettingHelper extends IAppHelper, Scrollable {
void turnOnOffBluetooth(boolean turnOn);
/**
+ * Setup expectations: The app is open and Hotspot & tethering setting options is selected
+ *
+ * @param turnOn to turn on/off Hotspot
+ */
+ void turnOnOffHotspot(boolean turnOn);
+
+ /**
* Setup expectations: The app is open.
*
* Checks if the wifi is enabled.
@@ -98,6 +105,13 @@ public interface IAutoSettingHelper extends IAppHelper, Scrollable {
boolean isBluetoothOn();
/**
+ * Setup expectations: The app is open.
+ *
+ * Checks if hotspot is enabled.
+ */
+ boolean isHotspotOn();
+
+ /**
* Setup expectations: The app is open and the settings facet is open
*/
void goBackToSettingsScreen();
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoUsersSettingsHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoUsersSettingsHelper.java
new file mode 100644
index 000000000..911ecfa29
--- /dev/null
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoUsersSettingsHelper.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.helpers;
+
+/** Helper class for functional tests of Users settings */
+public interface IAutoUsersSettingsHelper extends IAppHelper {
+ /**
+ * Setup expectation: Users setting is open.
+ *
+ * <p>This method is to add a new user.
+ */
+ void addUser();
+
+ /**
+ * Setup expectation: Users setting is open.
+ *
+ * <p>This method is to check whether a user is in the current user list.
+ *
+ * @param userName - the user name of the user
+ */
+ boolean isUserPresented(String userName);
+
+ /**
+ * Setup expectation: Users setting is open.
+ *
+ * <p>This method is to remove a user by its userID.
+ *
+ * @param userName - the user name of the user to be removed
+ */
+ void removeUser(String userName);
+}
diff --git a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoVehicleHardKeysHelper.java b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoVehicleHardKeysHelper.java
index 73b5c76fb..81b64a7a2 100644
--- a/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoVehicleHardKeysHelper.java
+++ b/libraries/app-helpers/interfaces/auto/src/android/platform/helpers/IAutoVehicleHardKeysHelper.java
@@ -18,6 +18,14 @@ package android.platform.helpers;
public interface IAutoVehicleHardKeysHelper extends IAppHelper {
+ /** Enum class for volume types */
+ enum VolumeType {
+ Media,
+ Ring,
+ Notification,
+ Navigation,
+ }
+
/**
* Setup expectations: incoming call in progress.
*
@@ -60,19 +68,13 @@ public interface IAutoVehicleHardKeysHelper extends IAppHelper {
*/
void tuneVolumeDownKey();
- /**
- * Increase brightness.
- */
+ /** Increase brightness. */
void pressBrightnessUpKey();
- /**
- * Decrease brighness.
- */
+ /** Decrease brighness. */
void pressBrightnessDownKey();
- /**
- * Launch assistant.
- */
+ /** Launch assistant. */
void pressAssistantKey();
/**
@@ -82,28 +84,25 @@ public interface IAutoVehicleHardKeysHelper extends IAppHelper {
*/
void tuneMuteKey();
- /**
- * Switch off screen.
- */
+ /** Switch off screen. */
void pressScreenOffKey();
- /**
- * Select content.
- */
+ /** Select content. */
void tuneKnobKey();
- /**
- * Open selected content.
- */
+ /** Open selected content. */
void pressKnobButtonKey();
- /**
- * Increase/decrease volume
- */
+ /** Increase/decrease volume */
void tuneVolumeKnobKey();
+ /** Mute media by pressing volume knob. */
+ void pressVolumeKnobButtonKey();
+
/**
- * Mute media by pressing volume knob.
+ * Get current volume level for a specific type of volume. Eg: Media, In-call, Alarm, Navigation
+ *
+ * @param type type of volume to get current volume level from.
*/
- void pressVolumeKnobButtonKey();
+ int getCurrentVolumeLevel(VolumeType type);
}
diff --git a/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IContactsHelper.java b/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IContactsHelper.java
index 7ef499caa..610409bb2 100644
--- a/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IContactsHelper.java
+++ b/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IContactsHelper.java
@@ -16,6 +16,8 @@
package android.platform.helpers;
+import android.support.test.uiautomator.Direction;
+
public interface IContactsHelper extends IAppHelper {
/**
* Setup expectation: Contacts is open
@@ -60,4 +62,15 @@ public interface IContactsHelper extends IAppHelper {
public default void chooseContactByIndex(int index) {
throw new UnsupportedOperationException("Not yet implemented.");
}
+
+ /**
+ * Setup expectations: Contacts is open.
+ *
+ * <p>Fling contacts page.
+ *
+ * @param direction The direction to fling the page.
+ */
+ public default void flingPage(Direction direction) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
}
diff --git a/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IMapsHelper.java b/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IMapsHelper.java
index a91a30335..af91ae332 100644
--- a/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IMapsHelper.java
+++ b/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IMapsHelper.java
@@ -121,4 +121,31 @@ public interface IMapsHelper extends IAppHelper {
public default void swipeStreetView(Direction direction) {
throw new UnsupportedOperationException("Not yet implemented.");
}
+
+ /**
+ * Setup expectation: On the home screen.
+ *
+ * <p>Scroll the page to view the map.
+ */
+ public default void scrollPage(Direction dir, float percent) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup expectation: On the home screen.
+ *
+ * <p>Click the button of my location on the home screen.
+ */
+ public default void clickMyLocationButton() {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup expectation: On the home screen.
+ *
+ * <p>Click the button of compass when exist on the home screen.
+ */
+ public default void clickBaseCompassButton() {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
}
diff --git a/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IYouTubeHelper.java b/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IYouTubeHelper.java
index bf7c5df34..a71ac15c1 100644
--- a/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IYouTubeHelper.java
+++ b/libraries/app-helpers/interfaces/common/src/android/platform/helpers/IYouTubeHelper.java
@@ -16,6 +16,8 @@
package android.platform.helpers;
+import android.support.test.uiautomator.Direction;
+
public interface IYouTubeHelper extends IAppHelper {
public enum VideoQuality {
@@ -138,4 +140,10 @@ public interface IYouTubeHelper extends IAppHelper {
public default void exitFullScreenMode() {
throw new UnsupportedOperationException("Not yet implemented.");
}
+ /**
+ * Setup expectation: YouTube is open on home page.
+ *
+ * <p>Scroll the home page by specified direction.
+ */
+ public void scrollHomePage(Direction direction);
}
diff --git a/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/INotificationHelper.java b/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/INotificationHelper.java
index cada5da5a..4babad12f 100644
--- a/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/INotificationHelper.java
+++ b/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/INotificationHelper.java
@@ -16,8 +16,28 @@
package android.platform.helpers;
+import android.app.Notification;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiObject2;
+
+import androidx.annotation.Nullable;
+
/** An App Helper interface for the Notification. */
public interface INotificationHelper extends IAppHelper {
+
+ String UI_PACKAGE_NAME_SYSUI = "com.android.systemui";
+ String UI_PACKAGE_NAME_ANDROID = "android";
+ String UI_NOTIFICATION_ID = "status_bar_latest_event_content";
+ String NOTIFICATION_TITLE_TEXT = "TEST NOTIFICATION";
+ String NOTIFICATION_CONTENT_TEXT = "Test notification content";
+ String NOTIFICATION_BIG_TEXT = "lorem ipsum dolor sit amet\n"
+ + "lorem ipsum dolor sit amet\n"
+ + "lorem ipsum dolor sit amet\n"
+ + "lorem ipsum dolor sit amet";
+ String NOTIFICATION_CHANNEL_NAME = "Test Channel";
+ String EXPAND_BUTTON_ID = "expand_button";
+ String APP_ICON_ID = "icon";
+
/**
* Setup expectations: Notification shade opened.
*
@@ -25,7 +45,7 @@ public interface INotificationHelper extends IAppHelper {
*
* @param index The index of the notification to open.
*/
- default public void openNotificationbyIndex(int index) {
+ default void openNotificationbyIndex(int index) {
throw new UnsupportedOperationException("Not yet implemented.");
}
@@ -38,7 +58,66 @@ public interface INotificationHelper extends IAppHelper {
*
* @param count The number of notifications to post.
*/
- default public void postNotifications(int count) {
+ default void postNotifications(int count) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup Expectations: Shade is open
+ *
+ * <p>Posts a notification using {@link android.app.Notification.BigTextStyle}.
+ *
+ * @param pkg App to launch, when clicking on notification.
+ */
+ default UiObject2 postBigTextNotification(@Nullable String pkg) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup Expectations: Shade is open
+ *
+ * <p>Posts a notification using {@link android.app.Notification.BigPictureStyle}.
+ *
+ * @param pkg App to launch, when clicking on notification.
+ */
+ default UiObject2 postBigPictureNotification(String pkg) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup Expectations: Shade is open
+ *
+ * <p>Posts a notification using {@link android.app.Notification.MessagingStyle}.
+ *
+ * @param pkg App to launch, when clicking on notification.
+ */
+ default UiObject2 postMessagingStyleNotification(String pkg) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup Expectations: Shade is open
+ *
+ * <p>Posts a conversation notification. This notification is associated with a conversation
+ * shortcut and in {@link android.app.Notification.MessagingStyle}.
+ *
+ * @param pkg App to launch, when clicking on notification.
+ */
+ default UiObject2 postConversationNotification(String pkg) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup Expectations: None
+ *
+ * <p>Posts a number of notifications to the device with a package to launch. Successive calls
+ * to this should post new notifications in addition to those previously posted. Note that this
+ * may fail if the helper has surpassed the system-defined limit for per-package notifications.
+ *
+ * @param count The number of notifications to post.
+ * @param pkg The application that will be launched by notifications.
+ */
+ default void postNotifications(int count, String pkg) {
throw new UnsupportedOperationException("Not yet implemented.");
}
@@ -51,8 +130,20 @@ public interface INotificationHelper extends IAppHelper {
*
* @param count The number of notifications to post.
* @param pkg The application that will be launched by notifications.
+ * @param interrupting If notification should make sounds and be on top section of the shade.
+ */
+ default void postNotifications(int count, String pkg, boolean interrupting) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup Expectations: None
+ *
+ * <p>Posts notification.
+ *
+ * @param builder Builder for notification to post.
*/
- public default void postNotifications(int count, String pkg) {
+ default void postNotification(Notification.Builder builder) {
throw new UnsupportedOperationException("Not yet implemented.");
}
@@ -61,7 +152,7 @@ public interface INotificationHelper extends IAppHelper {
*
* <p>Cancel any notifications posted by this helper.
*/
- default public void cancelNotifications() {
+ default void cancelNotifications() {
throw new UnsupportedOperationException("Not yet implemented.");
}
@@ -75,7 +166,48 @@ public interface INotificationHelper extends IAppHelper {
* @param expectedPkg The foreground application after opening a notification. Won't check the
* foreground application if the application is null
*/
- public default void openNotificationByTitle(String title, String expectedPkg) {
+ default void openNotificationByTitle(String title, String expectedPkg) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup expectations: Notification shade opened.
+ *
+ * <p>Taps the chevron or swipes down on the specified notification and checks if the
+ * expanded view contains the expected text.
+ *
+ * @param notification Notification that should be expanded.
+ * @param dragging By swiping down when {@code true}, by tapping the chevron otherwise.
+ */
+ default void expandNotification(UiObject2 notification, boolean dragging) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Long press on notification to show its hidden menu (a.k.a. guts)
+ *
+ * @param notification Notification.
+ */
+ default void showGuts(UiObject2 notification) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Taps the "Done" button on the notification guts.
+ *
+ * @param notification Notification.
+ */
+ default void hideGuts(UiObject2 notification) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Setup expectations: Notification shade opened.
+ *
+ * <p>Find the screenshot notification; expand the notification if it's collapsed and click on
+ * the "share" button.
+ */
+ default void shareScreenshotFromNotification(BySelector pageSelector) {
throw new UnsupportedOperationException("Not yet implemented.");
}
}
diff --git a/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/IQuickSettingsHelper.java b/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/IQuickSettingsHelper.java
index b0aab8a01..fcecffb70 100644
--- a/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/IQuickSettingsHelper.java
+++ b/libraries/app-helpers/interfaces/handheld/src/android/platform/helpers/IQuickSettingsHelper.java
@@ -30,13 +30,13 @@ public interface IQuickSettingsHelper extends IAppHelper {
/** Represents a Quick Setting switch that can be toggled ON and OFF during a test. */
public enum Setting {
- AIRPLANE("Airplane", 1000),
- AUTO_ROTATE("Auto-rotate", 1000),
- BLUETOOTH("Bluetooth", 10000),
- DO_NOT_DISTURB("Do Not Disturb", 1000),
- FLASHLIGHT("Flashlight", 1000),
- NIGHT_LIGHT("Night Light", 1000),
- WIFI("Wi-Fi", 5000);
+ AIRPLANE("Airplane", 2000),
+ AUTO_ROTATE("Auto-rotate", 2000),
+ BLUETOOTH("Bluetooth", 15000),
+ DO_NOT_DISTURB("Do Not Disturb", 2000),
+ FLASHLIGHT("Flashlight", 5000),
+ NIGHT_LIGHT("Night Light", 2000),
+ WIFI("Wi-Fi", 10000);
private final String mContentDescSubstring;
private final long mExpectedWait;
diff --git a/libraries/aupt-lib/src/android/support/test/aupt/FilesystemUtil.java b/libraries/aupt-lib/src/android/support/test/aupt/FilesystemUtil.java
index 078000006..ea092b8d1 100644
--- a/libraries/aupt-lib/src/android/support/test/aupt/FilesystemUtil.java
+++ b/libraries/aupt-lib/src/android/support/test/aupt/FilesystemUtil.java
@@ -88,7 +88,7 @@ public class FilesystemUtil {
/** Save a bugreport to the given file */
public static void saveBugreportz(Instrumentation instr) throws IOException {
try {
- ActivityManager.getService().requestBugReport(ActivityManager.BUGREPORT_OPTION_FULL);
+ ActivityManager.getService().requestFullBugReport();
} catch (RemoteException e) {
throw new IOException("Could not capture bugreportz", e);
}
diff --git a/libraries/car-helpers/multiuser-helper/Android.bp b/libraries/car-helpers/multiuser-helper/Android.bp
index 0286bd21a..668079097 100644
--- a/libraries/car-helpers/multiuser-helper/Android.bp
+++ b/libraries/car-helpers/multiuser-helper/Android.bp
@@ -19,7 +19,8 @@ java_library_static {
"src/**/*.java",
],
static_libs: [
+ "android.car",
"androidx.test.runner",
- "android.car.userlib",
+ "ub-uiautomator",
],
} \ No newline at end of file
diff --git a/libraries/car-helpers/multiuser-helper/src/android/platform/helpers/MultiUserHelper.java b/libraries/car-helpers/multiuser-helper/src/android/platform/helpers/MultiUserHelper.java
index 34bb20445..dd55a610c 100644
--- a/libraries/car-helpers/multiuser-helper/src/android/platform/helpers/MultiUserHelper.java
+++ b/libraries/car-helpers/multiuser-helper/src/android/platform/helpers/MultiUserHelper.java
@@ -13,47 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// TODO(b/129771420): Use different package name for car-helper packages
package android.platform.helpers;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.UserSwitchObserver;
-import android.car.userlib.CarUserManagerHelper;
+import android.car.Car;
+import android.car.user.CarUserManager;
+import android.car.user.CarUserManager.UserLifecycleListener;
+import android.car.user.UserSwitchResult;
+import android.content.Context;
import android.content.pm.UserInfo;
-import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.UserManager;
+import android.support.test.uiautomator.UiDevice;
import androidx.test.InstrumentationRegistry;
+import com.android.internal.infra.AndroidFuture;
+
+import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
- * Helper class that is used by integration test only. It is wrapping around {@link
- * CarUserManagerHelper} to expose user management functions. Unlike {@link CarUserManagerHelper} ,
- * some user management functions such as user switch will be synchronous calls in order to meet
- * testing requirements.
+ * Helper class that is used by integration test only. It is wrapping around exiting platform APIs
+ * {@link CarUserManager}, {@link UserManager} to expose functions for user switch end-to-end tests.
*/
public class MultiUserHelper {
- private static final String DEFAULT_GUEST_NAME = "Guest";
-
- private static final String TAG = MultiUserHelper.class.getSimpleName();
-
/** For testing purpose we allow a wide range of switching time. */
private static final int USER_SWITCH_TIMEOUT_SECOND = 300;
private static MultiUserHelper sMultiUserHelper;
- private CarUserManagerHelper mUserManagerHelper;
+ private CarUserManager mCarUserManager;
+ private UserManager mUserManager;
private MultiUserHelper() {
- mUserManagerHelper = new CarUserManagerHelper(InstrumentationRegistry.getTargetContext());
- }
-
- public enum UserType {
- GUEST,
- ADMIN,
- NON_ADMIN
+ Context context = InstrumentationRegistry.getTargetContext();
+ mUserManager = UserManager.get(context);
+ Car car = Car.createCar(context);
+ mCarUserManager = (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE);
}
/**
@@ -69,24 +67,18 @@ public class MultiUserHelper {
}
/**
- * Creates a user given the user name and type, e.g. guest, admin or non-admin
+ * Creates a regular user or guest
*
- * @param name the name of the user
- * @param userType the type of user as defined by the helper
- * @return A {@link UserInfo} for newly created user or {@code null} if fail to create one
+ * @param name the name of the user or guest
+ * @param isGuestUser true if want to create a guest, otherwise create a regular user
+ * @return User Id for newly created user
*/
- @Nullable
- public UserInfo createUser(String name, UserType userType) throws Exception {
- switch (userType) {
- case GUEST:
- return mUserManagerHelper.createNewOrFindExistingGuest(name);
- case ADMIN:
- return mUserManagerHelper.createNewAdminUser(name);
- case NON_ADMIN:
- return mUserManagerHelper.createNewNonAdminUser(name);
- default:
- throw new Exception("Unsupported user type: " + userType);
+ public int createUser(String name, boolean isGuestUser) throws Exception {
+ if (isGuestUser) {
+ return mUserManager.createUser(name, UserManager.USER_TYPE_FULL_GUEST, /* flags= */ 0)
+ .id;
}
+ return mUserManager.createUser(name, /* flags= */ 0).id;
}
/**
@@ -112,16 +104,36 @@ public class MultiUserHelper {
*/
public void switchToUserId(int id) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
- registerUserSwitchObserver(latch, id);
- if (!mUserManagerHelper.switchToUserId(id)) {
- throw new Exception(String.format("Failed to switch to user: %d", id));
+ // A UserLifeCycleListener to wait for user switch event. It is equivalent to
+ // UserSwitchObserver#onUserSwitchComplete callback
+ // TODO(b/155434907): Should eventually wait for "user unlocked" event which is better
+ UserLifecycleListener userSwitchListener =
+ e -> {
+ if (e.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
+ latch.countDown();
+ }
+ };
+ mCarUserManager.addListener(Runnable::run, userSwitchListener);
+ AndroidFuture<UserSwitchResult> future = mCarUserManager.switchUser(id);
+ UserSwitchResult result = null;
+ try {
+ result = future.get(USER_SWITCH_TIMEOUT_SECOND, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ throw new Exception(
+ String.format("Exception when switching to target user: %d", id), e);
}
+
+ if (!result.isSuccess()) {
+ throw new Exception(String.format("User switch failed: %s", result));
+ }
+ // Wait for user switch complete event, which seems to happen later than UserSwitchResult.
if (!latch.await(USER_SWITCH_TIMEOUT_SECOND, TimeUnit.SECONDS)) {
throw new Exception(
String.format(
"Timeout while switching to user %d after %d seconds",
id, USER_SWITCH_TIMEOUT_SECOND));
}
+ mCarUserManager.removeListener(userSwitchListener);
}
/**
@@ -131,15 +143,26 @@ public class MultiUserHelper {
* @return true if removed successfully
*/
public boolean removeUser(UserInfo userInfo) {
- return mUserManagerHelper.removeUser(userInfo, DEFAULT_GUEST_NAME);
+ return mUserManager.removeUser(userInfo.id);
}
public UserInfo getCurrentForegroundUserInfo() {
- return mUserManagerHelper.getCurrentForegroundUserInfo();
+ return mUserManager.getUserInfo(ActivityManager.getCurrentUser());
}
+ /**
+ * Get default initial user
+ *
+ * @return user ID of initial user
+ */
public int getInitialUser() {
- return mUserManagerHelper.getInitialUser();
+ UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ try {
+ String userId = device.executeShellCommand("cmd car_service get-initial-user").trim();
+ return Integer.parseInt(userId);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to get initial user", e);
+ }
}
/**
@@ -150,26 +173,11 @@ public class MultiUserHelper {
*/
@Nullable
public UserInfo getUserByName(String name) {
- return mUserManagerHelper
- .getAllUsers()
+ return mUserManager
+ .getUsers(/* excludeDying= */ true)
.stream()
.filter(user -> user.name.equals(name))
.findFirst()
.orElse(null);
}
-
- private void registerUserSwitchObserver(final CountDownLatch switchLatch, final int userId)
- throws RemoteException {
- ActivityManager.getService()
- .registerUserSwitchObserver(
- new UserSwitchObserver() {
- @Override
- public void onUserSwitchComplete(int newUserId) {
- if (switchLatch != null && userId == newUserId) {
- switchLatch.countDown();
- }
- }
- },
- TAG);
- }
}
diff --git a/libraries/collectors-helper/memory/Android.bp b/libraries/collectors-helper/memory/Android.bp
index c34e4a682..b7798e8b8 100644
--- a/libraries/collectors-helper/memory/Android.bp
+++ b/libraries/collectors-helper/memory/Android.bp
@@ -25,6 +25,7 @@ java_library {
"androidx.test.runner",
"ub-uiautomator",
"collector-helper-utilities",
+ "platformprotosnano",
],
sdk_version: "current",
diff --git a/libraries/collectors-helper/memory/src/com/android/helpers/DumpsysMeminfoHelper.java b/libraries/collectors-helper/memory/src/com/android/helpers/DumpsysMeminfoHelper.java
index 168b3a2d6..431faf306 100644
--- a/libraries/collectors-helper/memory/src/com/android/helpers/DumpsysMeminfoHelper.java
+++ b/libraries/collectors-helper/memory/src/com/android/helpers/DumpsysMeminfoHelper.java
@@ -16,71 +16,50 @@
package com.android.helpers;
-import android.support.test.uiautomator.UiDevice;
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import com.android.server.am.nano.MemInfoDumpProto;
+
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
- * This is a collector helper to use adb "dumpsys meminfo -a" command to get important memory
- * metrics like PSS, Shared Dirty, Private Dirty, e.t.c. for the specified packages
+ * This is a collector helper to use adb "dumpsys meminfo -a --proto" command to get important
+ * memory metrics like PSS, Shared Dirty, Private Dirty, e.t.c. for the specified packages.
*/
public class DumpsysMeminfoHelper implements ICollectorHelper<Long> {
private static final String TAG = DumpsysMeminfoHelper.class.getSimpleName();
- private static final String SEPARATOR = "\\s+";
- private static final String LINE_SEPARATOR = "\\n";
-
- private static final String DUMPSYS_MEMINFO_CMD = "dumpsys meminfo -a %s";
- private static final String PIDOF_CMD = "pidof %s";
+ private static final String DUMPSYS_MEMINFO_CMD = "dumpsys meminfo -a --proto %s";
private static final String METRIC_SOURCE = "dumpsys";
private static final String METRIC_UNIT = "kb";
- // Prefixes of the lines in the output of "dumpsys meminfo -a" command that will be parsed
- private static final String NATIVE_HEAP_PREFIX = "Native Heap";
- private static final String DALVIK_HEAP_PREFIX = "Dalvik Heap";
- private static final String TOTAL_PREFIX = "TOTAL";
-
// The metric names corresponding to the columns in the output of "dumpsys meminfo -a" command
private static final String PSS_TOTAL = "pss_total";
private static final String SHARED_DIRTY = "shared_dirty";
private static final String PRIVATE_DIRTY = "private_dirty";
private static final String HEAP_SIZE = "heap_size";
private static final String HEAP_ALLOC = "heap_alloc";
- private static final String PSS = "pss";
-
- // Mapping from prefixes of lines to metric category names
- private static final Map<String, String> CATEGORIES =
- Stream.of(
- new String[][] {
- {NATIVE_HEAP_PREFIX, "native"},
- {DALVIK_HEAP_PREFIX, "dalvik"},
- {TOTAL_PREFIX, "total"},
- }).collect(Collectors.toMap(data -> data[0], data -> data[1]));
-
- // Mapping from metric keys to its column index (exclude prefix) in dumpsys meminfo output.
- // The index might change across different Android releases
- private static final Map<String, Integer> METRIC_POSITIONS =
- Stream.of(
- new Object[][] {
- {PSS_TOTAL, 0},
- {SHARED_DIRTY, 2},
- {PRIVATE_DIRTY, 3},
- {HEAP_SIZE, 7},
- {HEAP_ALLOC, 8},
- })
- .collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));
+
+ // Metric category names, which are the names of the heaps
+ private static final String NATIVE_HEAP = "native";
+ private static final String DALVIK_HEAP = "dalvik";
+ private static final String TOTAL_HEAP = "total";
private String[] mProcessNames = {};
- private UiDevice mUiDevice;
+ private UiAutomation mUiAutomation;
public void setUp(String... processNames) {
if (processNames == null) {
@@ -91,7 +70,7 @@ public class DumpsysMeminfoHelper implements ICollectorHelper<Long> {
@Override
public boolean startCollecting() {
- mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
return true;
}
@@ -99,7 +78,11 @@ public class DumpsysMeminfoHelper implements ICollectorHelper<Long> {
public Map<String, Long> getMetrics() {
Map<String, Long> metrics = new HashMap<>();
for (String processName : mProcessNames) {
- String rawOutput = getRawDumpsysMeminfo(processName);
+ byte[] rawOutput = getRawDumpsysMeminfo(processName);
+ if (rawOutput == null) {
+ Log.e(TAG, "Missing meminfo output for process " + processName);
+ continue;
+ }
metrics.putAll(parseMetrics(processName, rawOutput));
}
return metrics;
@@ -110,64 +93,103 @@ public class DumpsysMeminfoHelper implements ICollectorHelper<Long> {
return true;
}
- private String getRawDumpsysMeminfo(String processName) {
- if (isEmpty(processName)) {
- return "";
+ private byte[] getRawDumpsysMeminfo(String processName) {
+ if (processName == null || processName.isEmpty()) {
+ return null;
}
- try {
- String pidStr = mUiDevice.executeShellCommand(String.format(PIDOF_CMD, processName));
- if (isEmpty(pidStr)) {
- return "";
- }
- return mUiDevice.executeShellCommand(String.format(DUMPSYS_MEMINFO_CMD, pidStr));
+ final String cmd = String.format(DUMPSYS_MEMINFO_CMD, processName);
+ ParcelFileDescriptor pfd = mUiAutomation.executeShellCommand(cmd);
+ try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
+ return readInputStreamFully(fis);
} catch (IOException e) {
- Log.e(TAG, String.format("Failed to execute command. %s", e));
- return "";
+ Log.e(TAG, "Failed to execute command. " + cmd, e);
+ return null;
}
}
- private Map<String, Long> parseMetrics(String processName, String rawOutput) {
- String[] lines = rawOutput.split(LINE_SEPARATOR);
+ private Map<String, Long> parseMetrics(String processName, byte[] rawOutput) {
Map<String, Long> metrics = new HashMap<>();
- for (String line : lines) {
- String[] tokens = line.trim().split(SEPARATOR);
- if (tokens.length < 2) {
+ try {
+ MemInfoDumpProto memInfo = MemInfoDumpProto.parseFrom(rawOutput);
+ MemInfoDumpProto.ProcessMemory processMemory = findProcessMemory(memInfo, processName);
+ if (processMemory != null) {
+ putHeapMetrics(metrics, processMemory.nativeHeap, NATIVE_HEAP, processName);
+ putHeapMetrics(metrics, processMemory.dalvikHeap, DALVIK_HEAP, processName);
+ putHeapMetric(
+ metrics,
+ processMemory.totalHeap.memInfo.totalPssKb,
+ TOTAL_HEAP,
+ PSS_TOTAL,
+ processName);
+ }
+ } catch (InvalidProtocolBufferNanoException ex) {
+ Log.e(TAG, "Invalid protobuf obtained from `dumpsys meminfo --proto`", ex);
+ }
+ return metrics;
+ }
+
+ /** Find ProcessMemory by name. Looks in app and native process. Returns null on failure. */
+ private static MemInfoDumpProto.ProcessMemory findProcessMemory(
+ MemInfoDumpProto memInfo, String processName) {
+ // Look in app processes first.
+ for (MemInfoDumpProto.AppData appData : memInfo.appProcesses) {
+ if (appData.processMemory == null) {
continue;
}
- String firstToken = tokens[0];
- String firstTwoTokens = String.join(" ", tokens[0], tokens[1]);
- if (firstTwoTokens.equals(NATIVE_HEAP_PREFIX)
- || firstTwoTokens.equals(DALVIK_HEAP_PREFIX)) {
- if (tokens.length < 11) {
- continue;
- }
- int offset = 2;
- for (Map.Entry<String, Integer> metric : METRIC_POSITIONS.entrySet()) {
- metrics.put(
- MetricUtility.constructKey(
- METRIC_SOURCE,
- CATEGORIES.get(firstTwoTokens),
- metric.getKey(),
- METRIC_UNIT,
- processName),
- Long.parseLong(tokens[offset + metric.getValue()]));
- }
- } else if (firstToken.equals(TOTAL_PREFIX)) {
- int offset = 1;
- metrics.put(
- MetricUtility.constructKey(
- METRIC_SOURCE,
- CATEGORIES.get(firstToken),
- PSS_TOTAL,
- METRIC_UNIT,
- processName),
- Long.parseLong(tokens[offset + METRIC_POSITIONS.get(PSS_TOTAL)]));
+ if (processName.equals(appData.processMemory.processName)) {
+ return appData.processMemory;
}
}
- return metrics;
+ // If not found yet, then look in native processes.
+ for (MemInfoDumpProto.ProcessMemory procMem : memInfo.nativeProcesses) {
+ if (processName.equals(procMem.processName)) {
+ return procMem;
+ }
+ }
+ return null;
+ }
+
+ private static void putHeapMetrics(
+ Map<String, Long> metrics,
+ MemInfoDumpProto.ProcessMemory.HeapInfo heapInfo,
+ String heapName,
+ String processName) {
+ if (heapInfo == null || heapInfo.memInfo == null) {
+ return;
+ }
+ putHeapMetric(metrics, heapInfo.memInfo.totalPssKb, heapName, PSS_TOTAL, processName);
+ putHeapMetric(metrics, heapInfo.memInfo.sharedDirtyKb, heapName, SHARED_DIRTY, processName);
+ putHeapMetric(
+ metrics, heapInfo.memInfo.privateDirtyKb, heapName, PRIVATE_DIRTY, processName);
+ putHeapMetric(metrics, heapInfo.heapSizeKb, heapName, HEAP_SIZE, processName);
+ putHeapMetric(metrics, heapInfo.heapAllocKb, heapName, HEAP_ALLOC, processName);
+ }
+
+ private static void putHeapMetric(
+ Map<String, Long> metrics,
+ long value,
+ String heapName,
+ String metricName,
+ String processName) {
+ metrics.put(
+ MetricUtility.constructKey(
+ METRIC_SOURCE, heapName, metricName, METRIC_UNIT, processName),
+ value);
}
- private boolean isEmpty(String input) {
- return input == null || input.isEmpty();
+ /** Copied from {@link com.android.compatibility.common.util.FileUtils#readInputStreamFully}. */
+ private static byte[] readInputStreamFully(InputStream is) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ byte[] buffer = new byte[32768];
+ int count;
+ try {
+ while ((count = is.read(buffer)) != -1) {
+ os.write(buffer, 0, count);
+ }
+ is.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return os.toByteArray();
}
}
diff --git a/libraries/collectors-helper/memory/src/com/android/helpers/FreeMemHelper.java b/libraries/collectors-helper/memory/src/com/android/helpers/FreeMemHelper.java
index b2f1f8cb9..366aec69b 100644
--- a/libraries/collectors-helper/memory/src/com/android/helpers/FreeMemHelper.java
+++ b/libraries/collectors-helper/memory/src/com/android/helpers/FreeMemHelper.java
@@ -16,13 +16,17 @@
package com.android.helpers;
+import android.os.SystemClock;
import android.support.test.uiautomator.UiDevice;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -60,8 +64,10 @@ public class FreeMemHelper implements ICollectorHelper<Long> {
public static final String PROC_MEMINFO_MEM_AVAILABLE= "proc_meminfo_memavailable_bytes";
public static final String PROC_MEMINFO_MEM_FREE= "proc_meminfo_memfree_bytes";
public static final String DUMPSYS_CACHED_PROC_MEMORY= "dumpsys_cached_procs_memory_bytes";
+ public static final int DROPCACHE_WAIT_MSECS= 10000; // Wait for 10 secs after dropping cache
private UiDevice mUiDevice;
+ private boolean mDropCache = false;
@Override
public boolean startCollecting() {
@@ -76,6 +82,10 @@ public class FreeMemHelper implements ICollectorHelper<Long> {
@Override
public Map<String, Long> getMetrics() {
+ // Drop the cache and wait for 10 secs before collecting the metrics.
+ if (mDropCache) {
+ executeDropCachesImpl();
+ }
String memInfo;
try {
memInfo = mUiDevice.executeShellCommand(PROC_MEMINFO);
@@ -203,4 +213,42 @@ public class FreeMemHelper implements ICollectorHelper<Long> {
}
return cachedProcessList;
}
+
+ /**
+ * Drop the cache and wait for 10 secs before collecting the memory details.
+ */
+ private void executeDropCachesImpl() {
+ // Create a temporary file which contains the dropCaches command.
+ // Do this because we cannot write to /proc/sys/vm/drop_caches directly,
+ // as executeShellCommand parses the '>' character as a literal.
+ try {
+ File outputDir = InstrumentationRegistry.getInstrumentation().
+ getContext().getCacheDir();
+ File outputFile = File.createTempFile("drop_cache_script", ".sh", outputDir);
+ outputFile.setWritable(true);
+ outputFile.setExecutable(true, /*ownersOnly*/false);
+
+ String dropCacheScriptPath = outputFile.toString();
+
+ // If this works correctly, the next log-line will print 'Success'.
+ String str = "echo 3 > /proc/sys/vm/drop_caches && echo Success || echo Failure";
+ BufferedWriter writer = new BufferedWriter(new FileWriter(dropCacheScriptPath));
+ writer.write(str);
+ writer.close();
+
+ String result = mUiDevice.executeShellCommand(dropCacheScriptPath);
+ Log.v(TAG, "dropCaches output was: " + result);
+ outputFile.delete();
+ SystemClock.sleep(DROPCACHE_WAIT_MSECS);
+ } catch (IOException e) {
+ throw new AssertionError (e);
+ }
+ }
+
+ /**
+ * Enables the drop cache before taking the memory measurement.
+ */
+ public void setDropCache() {
+ mDropCache = true;
+ }
}
diff --git a/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ProcessShowmapHelperTest.java b/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ProcessShowmapHelperTest.java
index 9bf48be5c..3ad23da2e 100644
--- a/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ProcessShowmapHelperTest.java
+++ b/libraries/collectors-helper/memory/test/src/com/android/helpers/tests/ProcessShowmapHelperTest.java
@@ -35,7 +35,7 @@ import java.util.Map;
* Android Unit tests for {@link ProcessShowmapHelper}.
*
* To run:
- * atest CollectorsHelperTest:com.android.helpers.tests.ProcessShowmapHelper
+ * atest CollectorsHelperTest:com.android.helpers.tests.ProcessShowmapHelperTest
*/
@RunWith(AndroidJUnit4.class)
public class ProcessShowmapHelperTest {
diff --git a/libraries/collectors-helper/statsd/src/com/android/helpers/StatsdHelper.java b/libraries/collectors-helper/statsd/src/com/android/helpers/StatsdHelper.java
index 4d01473d2..5b6f07e94 100644
--- a/libraries/collectors-helper/statsd/src/com/android/helpers/StatsdHelper.java
+++ b/libraries/collectors-helper/statsd/src/com/android/helpers/StatsdHelper.java
@@ -59,7 +59,7 @@ public class StatsdHelper {
* Add simple event configurations using a list of atom ids.
*
* @param atomIdList uniquely identifies the information that we need to track by statsManager.
- * @return true if the configuration is added successfully other wise false.
+ * @return true if the configuration is added successfully, otherwise false.
*/
public boolean addEventConfig(List<Integer> atomIdList) {
long configId = System.currentTimeMillis();
@@ -105,6 +105,7 @@ public class StatsdHelper {
// Needed for collecting gauge metric based on trigger events.
statsConfigBuilder.addAtomMatcher(getSimpleAtomMatcher(appBreadCrumbUniqueId,
Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER));
+ statsConfigBuilder.addWhitelistedAtomIds(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER);
for (Integer atomId : atomIdList) {
int atomUniqueId = getUniqueId();
@@ -162,14 +163,19 @@ public class StatsdHelper {
* @return
*/
private static StatsdConfig.Builder getSimpleSources(long configId) {
- return StatsdConfig.newBuilder().setId(configId)
+ return StatsdConfig.newBuilder()
+ .setId(configId)
.addAllowedLogSource("AID_ROOT")
.addAllowedLogSource("AID_SYSTEM")
.addAllowedLogSource("AID_RADIO")
.addAllowedLogSource("AID_BLUETOOTH")
.addAllowedLogSource("AID_GRAPHICS")
.addAllowedLogSource("AID_STATSD")
- .addAllowedLogSource("AID_INCIENTD");
+ .addAllowedLogSource("AID_INCIENTD")
+ .addDefaultPullPackages("AID_SYSTEM")
+ .addDefaultPullPackages("AID_RADIO")
+ .addDefaultPullPackages("AID_STATSD")
+ .addDefaultPullPackages("AID_GPU_SERVICE");
}
/**
diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/FreeMemListener.java b/libraries/device-collectors/src/main/java/android/device/collectors/FreeMemListener.java
index 4b4bc51e2..5cf2b86be 100644
--- a/libraries/device-collectors/src/main/java/android/device/collectors/FreeMemListener.java
+++ b/libraries/device-collectors/src/main/java/android/device/collectors/FreeMemListener.java
@@ -28,13 +28,31 @@ import com.android.helpers.FreeMemHelper;
*/
@OptionClass(alias = "freemem-listener")
public class FreeMemListener extends BaseCollectionListener<Long> {
+ private static final String DROP_CACHE_ARG = "drop-cache";
+
+ private FreeMemHelper mFreeMemHelper = new FreeMemHelper();
public FreeMemListener() {
- createHelperInstance(new FreeMemHelper());
+ createHelperInstance(mFreeMemHelper);
}
@VisibleForTesting
public FreeMemListener(Bundle args, FreeMemHelper helper) {
super(args, helper);
}
+
+ /**
+ * Adds the options for free memory collector.
+ */
+ @Override
+ public void setupAdditionalArgs() {
+ Bundle args = getArgsBundle();
+ // By default set to false
+ boolean isDropCache = Boolean.parseBoolean(args.getString(DROP_CACHE_ARG));
+
+ // Set the flag to drop the cache before taking the memory measurement.
+ if (isDropCache) {
+ mFreeMemHelper.setDropCache();
+ }
+ }
}
diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java b/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java
index 69f708544..a1703ac1d 100644
--- a/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java
+++ b/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java
@@ -15,6 +15,8 @@
*/
package android.device.collectors;
+import static org.junit.Assert.assertNotNull;
+
import android.device.collectors.annotations.OptionClass;
import android.os.SystemClock;
import android.support.test.uiautomator.UiDevice;
@@ -24,6 +26,8 @@ import androidx.annotation.VisibleForTesting;
import java.io.IOException;
import java.io.File;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.HashMap;
@@ -38,17 +42,14 @@ import org.junit.runner.Description;
@OptionClass(alias = "screen-record-collector")
public class ScreenRecordCollector extends BaseMetricListener {
@VisibleForTesting static final int MAX_RECORDING_PARTS = 5;
- private static final long VIDEO_TAIL_BUFFER = 2000;
+ private static final long VIDEO_TAIL_BUFFER = 500;
static final String OUTPUT_DIR = "run_listeners/videos";
private UiDevice mDevice;
- private File mDestDir;
+ private static File mDestDir;
- // Tracks multiple parts to a single recording.
- private int mParts;
- // Avoid recording after the test is finished.
- private boolean mContinue;
+ private RecordingThread mCurrentThread;
// Tracks the test iterations to ensure that each failure gets unique filenames.
// Key: test description; value: number of iterations.
@@ -68,9 +69,8 @@ public class ScreenRecordCollector extends BaseMetricListener {
// Track the number of iteration for this test.
amendIterations(description);
// Start the screen recording operation.
- mParts = 1;
- mContinue = true;
- startScreenRecordThread(description);
+ mCurrentThread = new RecordingThread("test-screen-record", description);
+ mCurrentThread.start();
}
@Override
@@ -83,13 +83,19 @@ public class ScreenRecordCollector extends BaseMetricListener {
// Add some extra time to the video end.
SystemClock.sleep(getTailBuffer());
// Ctrl + C all screen record processes.
- mContinue = false;
- killScreenRecordProcesses();
+ mCurrentThread.cancel();
+ // Wait for the thread to completely die.
+ try {
+ mCurrentThread.join();
+ } catch (InterruptedException ex) {
+ Log.e(getTag(), "Interrupted when joining the recording thread.", ex);
+ }
// Add the output files to the data record.
- for (int i = 1; i < mParts; i++) {
- File output = getOutputFile(description, i);
- testData.addFileMetric(String.format("%s_%s", getTag(), output.getName()), output);
+ for (File recording : mCurrentThread.getRecordings()) {
+ Log.d(getTag(), String.format("Adding video part: #%s", recording.getName()));
+ testData.addFileMetric(
+ String.format("%s_%s", getTag(), recording.getName()), recording);
}
// TODO(b/144869954): Delete when tests pass.
@@ -102,6 +108,7 @@ public class ScreenRecordCollector extends BaseMetricListener {
mTestIterations.computeIfAbsent(testName, name -> 1);
}
+ /** Returns the recording's name for part {@code part} of test {@code description}. */
private File getOutputFile(Description description, int part) {
final String baseName =
String.format("%s.%s", description.getClassName(), description.getMethodName());
@@ -117,45 +124,6 @@ public class ScreenRecordCollector extends BaseMetricListener {
return Paths.get(mDestDir.getAbsolutePath(), fileName).toFile();
}
- /** Spawns a thread to start screen recording that will save to the provided {@code path}. */
- public void startScreenRecordThread(final Description description) {
- new Thread("test-screenrecord-thread") {
- @Override
- public void run() {
- try {
- for (int i = 0; i < MAX_RECORDING_PARTS && mContinue; i++) {
- String output = getOutputFile(description, mParts).getAbsolutePath();
- Log.d(getTag(), String.format("Recording screen to %s", output));
- // Make sure not to block on this background command so the test runs.
- getDevice().executeShellCommand(String.format("screenrecord %s", output));
- mParts++;
- }
- } catch (IOException e) {
- throw new RuntimeException("Caught exception while screen recording.");
- }
- }
- }.start();
- }
-
- /** Kills all screen recording processes that are actively running on the device. */
- public void killScreenRecordProcesses() {
- try {
- // Identify the screenrecord PIDs and send SIGINT 2 (Ctrl + C) to each.
- String[] pids = getDevice().executeShellCommand("pidof screenrecord").split(" ");
- for (String pid : pids) {
- // Avoid empty process ids, because of weird splitting behavior.
- if (pid.isEmpty()) {
- continue;
- }
-
- getDevice().executeShellCommand(String.format("kill -2 %s", pid));
- Log.d(getTag(), String.format("Sent SIGINT 2 to screenrecord process (%s)", pid));
- }
- } catch (IOException e) {
- throw new RuntimeException("Failed to kill screen recording process.");
- }
- }
-
/** Returns a buffer duration for the end of the video. */
@VisibleForTesting
public long getTailBuffer() {
@@ -169,4 +137,73 @@ public class ScreenRecordCollector extends BaseMetricListener {
}
return mDevice;
}
+
+ private class RecordingThread extends Thread {
+ private final Description mDescription;
+ private final List<File> mRecordings;
+
+ private boolean mContinue;
+
+ public RecordingThread(String name, Description description) {
+ super(name);
+
+ mContinue = true;
+ mRecordings = new ArrayList<>();
+
+ assertNotNull("No test description provided for recording.", description);
+ mDescription = description;
+ }
+
+ @Override
+ public void run() {
+ try {
+ // Start at i = 1 to encode parts as X.mp4, X2.mp4, X3.mp4, etc.
+ for (int i = 1; i <= MAX_RECORDING_PARTS && mContinue; i++) {
+ File output = getOutputFile(mDescription, i);
+ Log.d(
+ getTag(),
+ String.format("Recording screen to %s", output.getAbsolutePath()));
+ mRecordings.add(output);
+ // Make sure not to block on this background command in the main thread so
+ // that the test continues to run, but block in this thread so it does not
+ // trigger a new screen recording session before the prior one completes.
+ getDevice()
+ .executeShellCommand(
+ String.format("screenrecord %s", output.getAbsolutePath()));
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Caught exception while screen recording.");
+ }
+ }
+
+ public void cancel() {
+ mContinue = false;
+
+ // Identify the screenrecord PIDs and send SIGINT 2 (Ctrl + C) to each.
+ try {
+ String[] pids = getDevice().executeShellCommand("pidof screenrecord").split(" ");
+ for (String pid : pids) {
+ // Avoid empty process ids, because of weird splitting behavior.
+ if (pid.isEmpty()) {
+ continue;
+ }
+
+ getDevice().executeShellCommand(String.format("kill -2 %s", pid));
+ Log.d(
+ getTag(),
+ String.format("Sent SIGINT 2 to screenrecord process (%s)", pid));
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to kill screen recording process.");
+ }
+ }
+
+ public List<File> getRecordings() {
+ return mRecordings;
+ }
+
+ private String getTag() {
+ return RecordingThread.class.getName();
+ }
+ }
}
diff --git a/libraries/device-collectors/src/main/java/android/device/preparers/GarbageCollectionPreparer.java b/libraries/device-collectors/src/main/java/android/device/preparers/GarbageCollectionPreparer.java
index 797b2f671..96e1398a5 100644
--- a/libraries/device-collectors/src/main/java/android/device/preparers/GarbageCollectionPreparer.java
+++ b/libraries/device-collectors/src/main/java/android/device/preparers/GarbageCollectionPreparer.java
@@ -41,6 +41,7 @@ import org.junit.runner.Description;
* stabilize. Default is specified in {@link GarbageCollectionHelper}. This should be tuned based
* off noise in metric results (i.e. increase sleep if results are noisy, decrease if it's taking
* too long).
+ * -e garbagecollection-run-end [boolean] : whether to run GC on end of test. Default is true.
*/
@OptionClass(alias = "garbage-collection-preparer")
public final class GarbageCollectionPreparer extends BaseMetricListener {
@@ -51,11 +52,13 @@ public final class GarbageCollectionPreparer extends BaseMetricListener {
static final String PROCESS_NAMES_KEY = "garbagecollection-process-names";
@VisibleForTesting
static final String GC_WAIT_TIME_KEY = "garbagecollection-wait-time";
+ @VisibleForTesting static final String GC_RUN_END = "garbagecollection-run-end";
private final GarbageCollectionHelper mGcHelper;
// Whether the preparer successfully set up and initialized.
private boolean mSetUp;
private Long mWaitTime;
+ private boolean mRunEnd;
public GarbageCollectionPreparer() {
super();
@@ -90,6 +93,8 @@ public final class GarbageCollectionPreparer extends BaseMetricListener {
Log.e(TAG, "Unexpected wait time format. Using default time", e);
}
}
+ String gcRunEnd = args.getString(GC_RUN_END);
+ mRunEnd = gcRunEnd == null || Boolean.parseBoolean(gcRunEnd);
mSetUp = true;
}
@@ -100,7 +105,9 @@ public final class GarbageCollectionPreparer extends BaseMetricListener {
@Override
public void onTestEnd(DataRecord testData, Description description) {
- garbageCollect();
+ if (mRunEnd) {
+ garbageCollect();
+ }
}
private void garbageCollect() {
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/README.md
index a6bc18c42..d5aa4d502 100644
--- a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/README.md
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/README.md
@@ -30,14 +30,15 @@ section (and this section only) in the Android Metrics documentation to create a
2. Validate the config following the
[Validate and sent a changelist for review](http://go/westworld-modulefooding#validate-and-send-a-changelist-for-review)
section, but skip the sending CL for review part.
-2. Build the config parsing utility:
+3. Build the config parsing utility:
`blaze build -c opt java/com/google/wireless/android/stats/westworld:parse_definitions`
-3. Use the utility to create the binary config:
+4. Use the utility to create the binary config:
```
blaze-bin/java/com/google/wireless/android/stats/westworld/parse_definitions \
--action=WRITE_STATSD_CONFIG \
--definitions_dir=wireless/android/stats/platform/westworld/public/definitions/westworld/ \
--config_name=<You config's name defined in step 1> \
+--enable_string_hash=false \ # Output human-readable package names to the uid map in the report.
--allowed_sources=<Comma separated list of allowed log sources> \
--output_file=<Output path of your config>
```
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/app-start/app-start.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/app-start/app-start.pb
index f3ea66e0f..8297ee3df 100644
--- a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/app-start/app-start.pb
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/app-start/app-start.pb
Binary files differ
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/README.md
new file mode 100644
index 000000000..ef56f0f11
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/README.md
@@ -0,0 +1,3 @@
+# CPU Cluster Time Configs
+
+These configs are used to pull the process user time and system time at the start and end of tests or test run as defined in the CpuClusterTime atom. \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-run-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-run-level.pb
new file mode 100644
index 000000000..1477f34f0
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-run-level.pb
@@ -0,0 +1,3 @@
+ð乫ýŠÕå/*+ýŽäåáêŸÏ÷Òõ⢞ѥÒM0èHXÐ`€Óž¶¤¢Ÿ„2:Òõ⢞ѥÒM¡N:ꃂ÷œÇ”«/((:‚›Úï­§âÛ6/((:#€Óž¶¤¢Ÿ„2‚›Úï­§âÛ6ꃂ÷œÇ”«b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-test-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-test-level.pb
new file mode 100644
index 000000000..fe437879d
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-cluster-time/cpu-cluster-time-test-level.pb
@@ -0,0 +1,3 @@
+‰ßÈ•À÷°ªÉ*+Š†çÌ´°Ú¡¯Òõ⢞ѥÒM0èHXÐ`¾Ò°Þö¤¨ºi:Òõ⢞ѥÒM¡N:§óæëξ£²³/( (:ŸÓœÎ‚°¨µ„/( (:$¾Ò°Þö¤¨ºiŸÓœÎ‚°¨µ„§óæëξ£²³b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/README.md
new file mode 100644
index 000000000..dced6468a
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/README.md
@@ -0,0 +1,3 @@
+# CPU Time Per Frequency Configs
+
+These configs are used to pull the cpu time per frequency at the start and end of tests or test run as defined in the CpuTimePerFreq atom. \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-run-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-run-level.pb
new file mode 100644
index 000000000..5ef83960f
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-run-level.pb
@@ -0,0 +1,3 @@
+£À°Ð”È‚´*+´¯‘冿—¡½ ¤„¹®Ð§¨0èHXÐ`€Óž¶¤¢Ÿ„2:½ ¤„¹®Ð§¨˜N:ꃂ÷œÇ”«/((:‚›Úï­§âÛ6/((:#€Óž¶¤¢Ÿ„2‚›Úï­§âÛ6ꃂ÷œÇ”«b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-test-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-test-level.pb
new file mode 100644
index 000000000..7a2ae9e95
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-freq/cpu-time-per-freq-test-level.pb
@@ -0,0 +1,3 @@
+ʼۜ…‰ß\*,¦Ž‹À®¹á·Õ½ ¤„¹®Ð§¨0èHXÐ`¾Ò°Þö¤¨ºi:½ ¤„¹®Ð§¨˜N:§óæëξ£²³/( (:ŸÓœÎ‚°¨µ„/( (:$¾Ò°Þö¤¨ºiŸÓœÎ‚°¨µ„§óæëξ£²³b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/README.md
new file mode 100644
index 000000000..5bf55467e
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/README.md
@@ -0,0 +1,3 @@
+# CPU Time Per Thread Freq Configs
+
+These configs are used to pull CPU usage for each thread per frequency at the start and end of tests or test run as defined in the CpuTimePerThreadFreq atom. \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-run-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-run-level.pb
new file mode 100644
index 000000000..a245e44ae
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-run-level.pb
@@ -0,0 +1,3 @@
+ï”ÿۜ藸;*+¬¿þ𘎶ø®Öèùú¶¡“Ëx0èHXÐ`€Óž¶¤¢Ÿ„2:Öèùú¶¡“ËxµN:ꃂ÷œÇ”«/((:‚›Úï­§âÛ6/((:#€Óž¶¤¢Ÿ„2‚›Úï­§âÛ6ꃂ÷œÇ”«b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-test-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-test-level.pb
new file mode 100644
index 000000000..b59bf4d68
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-thread-freq/cpu-time-per-thread-freq-test-level.pb
@@ -0,0 +1,3 @@
+®ä‚渑Íöj**òˆË«ü¥ÙÚPÖèùú¶¡“Ëx0èHXÐ`¾Ò°Þö¤¨ºi:Öèùú¶¡“ËxµN:§óæëξ£²³/( (:ŸÓœÎ‚°¨µ„/( (:$¾Ò°Þö¤¨ºiŸÓœÎ‚°¨µ„§óæëξ£²³b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/README.md
new file mode 100644
index 000000000..c8137a757
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/README.md
@@ -0,0 +1,3 @@
+# CPU Time Per Uid Per Frequency Configs
+
+These configs are used to pull the cpu time per frequency at the start and end of tests or test run as defined in the CpuTimePerUidFreq atom. \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-run-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-run-level.pb
new file mode 100644
index 000000000..dad52359d
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-run-level.pb
@@ -0,0 +1,3 @@
+ίæ‚ëµ×Ú>*,ÔŠ›¹Æ…ßùÎéø›²Ö·ÔÈ0èHXÐ`€Óž¶¤¢Ÿ„2:éø›²Ö·ÔÈšN:ꃂ÷œÇ”«/((:‚›Úï­§âÛ6/((:#€Óž¶¤¢Ÿ„2‚›Úï­§âÛ6ꃂ÷œÇ”«b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-test-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-test-level.pb
new file mode 100644
index 000000000..f71026e48
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/cpu-time-per-uid-freq/cpu-time-per-uid-freq-test-level.pb
@@ -0,0 +1,3 @@
+ƒðÉÞŸŸ›î£*+¡öŽüŽõÝß3éø›²Ö·ÔÈ0èHXÐ`¾Ò°Þö¤¨ºi:éø›²Ö·ÔÈšN:§óæëξ£²³/( (:ŸÓœÎ‚°¨µ„/( (:$¾Ò°Þö¤¨ºiŸÓœÎ‚°¨µ„§óæëξ£²³b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/README.md
new file mode 100644
index 000000000..3ec669af1
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/README.md
@@ -0,0 +1,3 @@
+# Mobile Bytes Transfer Configs
+
+These configs are used to collect the bytes transferred via mobile networks(sum of foreground and background usage)on the device as defined in the MobileBytesTransfer atom at the start and end of tests or test run. \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-run-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-run-level.pb
new file mode 100644
index 000000000..8b79b6732
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-run-level.pb
@@ -0,0 +1,3 @@
+Ùº¼ï¾ ‹Â*+èøõÉ¢ŸÙøù¿å‰Í‚¼åŽi0èHXÐ`€Óž¶¤¢Ÿ„2:¿å‰Í‚¼åŽi’N:ꃂ÷œÇ”«/((:‚›Úï­§âÛ6/((:#€Óž¶¤¢Ÿ„2‚›Úï­§âÛ6ꃂ÷œÇ”«b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-test-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-test-level.pb
new file mode 100644
index 000000000..8b3314ae4
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/mobile-bytes-transfer/mobile-bytes-transfer-test-level.pb
@@ -0,0 +1,3 @@
+ôû¿®ÛŽ“·§*+—ùÕö àû„¹¿å‰Í‚¼åŽi0èHXÐ`¾Ò°Þö¤¨ºi:¿å‰Í‚¼åŽi’N:§óæëξ£²³/( (:ŸÓœÎ‚°¨µ„/( (:$¾Ò°Þö¤¨ºiŸÓœÎ‚°¨µ„§óæëξ£²³b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/README.md
new file mode 100644
index 000000000..4b2c6832d
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/README.md
@@ -0,0 +1,3 @@
+# Process CPU Time Configs
+
+These configs are used to collect the cpu stats at the start and end of tests or test run. \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-run-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-run-level.pb
new file mode 100644
index 000000000..b12538c12
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-run-level.pb
@@ -0,0 +1,3 @@
+¶Þé°§**Օ϶·€®çsë‚ÓÀÛÊüª:0èHXÐ`€Óž¶¤¢Ÿ„2:ë‚ÓÀÛÊüª:³N:ꃂ÷œÇ”«/((:‚›Úï­§âÛ6/((:#€Óž¶¤¢Ÿ„2‚›Úï­§âÛ6ꃂ÷œÇ”«b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-test-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-test-level.pb
new file mode 100644
index 000000000..5184548ca
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/process-cpu-time/process-cpu-time-test-level.pb
@@ -0,0 +1,3 @@
+€Ýˆœ—ë쀸*+àÕ¶ñÏÖª¤«ë‚ÓÀÛÊüª:0èHXÐ`¾Ò°Þö¤¨ºi:ë‚ÓÀÛÊüª:³N:§óæëξ£²³/( (:ŸÓœÎ‚°¨µ„/( (:$¾Ò°Þö¤¨ºiŸÓœÎ‚°¨µ„§óæëξ£²³b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/README.md b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/README.md
new file mode 100644
index 000000000..ab1ca9d1f
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/README.md
@@ -0,0 +1,3 @@
+# Subsytem sleep state Configs
+
+These configs are used to collect the subsystem sleep state on the device as defined in the SubsystemSleepState atom at the start and end of tests or test run.
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-run-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-run-level.pb
new file mode 100644
index 000000000..48f10b562
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-run-level.pb
@@ -0,0 +1,3 @@
+‡Ó²Ô…ë·÷ý*+ô냾À»ÿgåèÀÃòšª°Æ0èHXÐ`€Óž¶¤¢Ÿ„2:åèÀÃòšª°Æ•N:ꃂ÷œÇ”«/((:‚›Úï­§âÛ6/((:#€Óž¶¤¢Ÿ„2‚›Úï­§âÛ6ꃂ÷œÇ”«b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-test-level.pb b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-test-level.pb
new file mode 100644
index 000000000..5a2bc8ade
--- /dev/null
+++ b/libraries/device-collectors/src/main/platform-collectors/res/statsd-configs/subsystem-sleep-state/subsystem-sleep-state-test-level.pb
@@ -0,0 +1,3 @@
+Èà¢ýÌð¶ô*,¶­’í¥Ÿ±ŒåèÀÃòšª°Æ0èHXÐ`¾Ò°Þö¤¨ºi:åèÀÃòšª°Æ•N:§óæëξ£²³/( (:ŸÓœÎ‚°¨µ„/( (:$¾Ò°Þö¤¨ºiŸÓœÎ‚°¨µ„§óæëξ£²³b AID_GRAPHICSb AID_INCIDENTDb
+AID_STATSDb AID_RADIOb
+AID_SYSTEMbAID_ROOTb AID_BLUETOOTHÀ> \ No newline at end of file
diff --git a/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/StatsdListener.java b/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/StatsdListener.java
index 97f4719b8..b59d87600 100644
--- a/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/StatsdListener.java
+++ b/libraries/device-collectors/src/main/platform-collectors/src/android/device/collectors/StatsdListener.java
@@ -28,6 +28,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.test.InstrumentationRegistry;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto.Atom;
import com.android.os.StatsLog.ConfigMetricsReportList;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -178,6 +179,7 @@ public class StatsdListener extends BaseMetricListener {
long configId = getUniqueIdForConfig(configs.get(configName));
StatsdConfig newConfig = configs.get(configName).toBuilder().setId(configId).build();
try {
+ Log.i(LOG_TAG, String.format("Adding config %s with ID %d.", configName, configId));
addStatsConfig(configId, newConfig.toByteArray());
configIds.put(configName, configId);
} catch (StatsUnavailableException e) {
@@ -217,9 +219,21 @@ public class StatsdListener extends BaseMetricListener {
// Dump the metric report to external storage.
ConfigMetricsReportList reportList;
try {
+ Log.i(
+ LOG_TAG,
+ String.format(
+ "Pulling metrics for config %s with ID %d.",
+ configName, configIds.get(configName)));
reportList =
ConfigMetricsReportList.parseFrom(
getStatsReports(configIds.get(configName)));
+ Log.i(
+ LOG_TAG,
+ String.format(
+ "Found %d metric %s from config %s.",
+ reportList.getReportsCount(),
+ reportList.getReportsCount() == 1 ? "report" : "reports",
+ configName));
File reportFile =
new File(
saveDirectory,
@@ -249,6 +263,11 @@ public class StatsdListener extends BaseMetricListener {
// Remove the statsd config.
try {
+ Log.i(
+ LOG_TAG,
+ String.format(
+ "Removing config %s with ID %d.",
+ configName, configIds.get(configName)));
removeStatsConfig(configIds.get(configName));
} catch (StatsUnavailableException e) {
Log.e(
@@ -400,11 +419,11 @@ public class StatsdListener extends BaseMetricListener {
final AssetManager manager, String optionName, String configName) {
try (InputStream configStream = openConfigWithAssetManager(manager, configName)) {
try {
- return StatsdConfig.parseFrom(configStream);
+ return fixPermissions(StatsdConfig.parseFrom(configStream));
} catch (IOException e) {
throw new RuntimeException(
String.format(
- "Cannot parse profile %s in option %s.", configName, optionName),
+ "Cannot parse config %s in option %s.", configName, optionName),
e);
}
} catch (IOException e) {
@@ -458,4 +477,19 @@ public class StatsdListener extends BaseMetricListener {
protected boolean logStop(int label) {
return StatsLog.logStop(label);
}
+
+ /**
+ * Add a few permission-related options to the statsd config.
+ *
+ * <p>This is related to some new permission restrictions in RVC.
+ */
+ private StatsdConfig fixPermissions(StatsdConfig config) {
+ StatsdConfig.Builder builder = config.toBuilder();
+ // Allow system power stats to be pulled.
+ builder.addDefaultPullPackages("AID_SYSTEM");
+ // Gauge metrics rely on AppBreadcrumbReported as metric dump triggers.
+ builder.addWhitelistedAtomIds(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER);
+
+ return builder.build();
+ }
}
diff --git a/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java b/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java
index 8f45a7470..ceff8fd6f 100644
--- a/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java
+++ b/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java
@@ -17,7 +17,6 @@ package android.device.collectors;
import static org.junit.Assert.assertEquals;
import static org.mockito.AdditionalMatchers.not;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.endsWith;
import static org.mockito.ArgumentMatchers.eq;
@@ -111,9 +110,7 @@ public class ScreenRecordCollectorTest {
// Walk through a number of test cases to simulate behavior.
for (int i = 1; i <= NUM_TEST_CASE; i++) {
- // Verify a thread is started when the test starts.
mListener.testStarted(mTestDesc);
- verify(mListener, times(i)).startScreenRecordThread(any());
// Delay verification by 100 ms to ensure the thread was started.
SystemClock.sleep(100);
// Expect all recordings to be finished because of mocked commands.
@@ -131,7 +128,6 @@ public class ScreenRecordCollectorTest {
// Verify all processes are killed when the test ends.
mListener.testFinished(mTestDesc);
- verify(mListener, times(i)).killScreenRecordProcesses();
verify(mDevice, times(i)).executeShellCommand(eq("pidof screenrecord"));
verify(mDevice, times(i)).executeShellCommand(matches("kill -2 1234"));
}
diff --git a/libraries/device-collectors/src/test/java/android/device/preparers/GarbageCollectionPreparerTest.java b/libraries/device-collectors/src/test/java/android/device/preparers/GarbageCollectionPreparerTest.java
index 244926444..ee9097a17 100644
--- a/libraries/device-collectors/src/test/java/android/device/preparers/GarbageCollectionPreparerTest.java
+++ b/libraries/device-collectors/src/test/java/android/device/preparers/GarbageCollectionPreparerTest.java
@@ -16,6 +16,7 @@
package android.device.preparers;
+import static android.device.preparers.GarbageCollectionPreparer.GC_RUN_END;
import static android.device.preparers.GarbageCollectionPreparer.GC_WAIT_TIME_KEY;
import static android.device.preparers.GarbageCollectionPreparer.PROCESS_NAMES_KEY;
import static android.device.preparers.GarbageCollectionPreparer.PROCESS_SEPARATOR;
@@ -143,4 +144,32 @@ public class GarbageCollectionPreparerTest {
verify(mGcHelper, times(2)).garbageCollect(TEST_WAIT_TIME);
}
+
+ @Test
+ public void testHelperGcsNoRunEnd() throws Exception {
+ Bundle b = new Bundle();
+ b.putString(PROCESS_NAMES_KEY, TEST_PROCESS_NAME_1);
+ b.putString(GC_RUN_END, "false");
+ mPreparer = initPreparer(b);
+ mPreparer.testRunStarted(mRunDesc);
+
+ mPreparer.testStarted(mRunDesc);
+ mPreparer.testFinished(mRunDesc);
+
+ verify(mGcHelper, times(1)).garbageCollect();
+ }
+
+ @Test
+ public void testHelperGcsRunEnd() throws Exception {
+ Bundle b = new Bundle();
+ b.putString(PROCESS_NAMES_KEY, TEST_PROCESS_NAME_1);
+ b.putString(GC_RUN_END, "true");
+ mPreparer = initPreparer(b);
+ mPreparer.testRunStarted(mRunDesc);
+
+ mPreparer.testStarted(mRunDesc);
+ mPreparer.testFinished(mRunDesc);
+
+ verify(mGcHelper, times(2)).garbageCollect();
+ }
}
diff --git a/libraries/device-collectors/src/test/platform/Android.bp b/libraries/device-collectors/src/test/platform/Android.bp
index a6c93ec3d..14e3dcf96 100644
--- a/libraries/device-collectors/src/test/platform/Android.bp
+++ b/libraries/device-collectors/src/test/platform/Android.bp
@@ -30,5 +30,6 @@ android_test {
"ub-uiautomator",
],
platform_apis: true,
+ min_sdk_version: "26",
}
diff --git a/libraries/device-collectors/src/test/platform/android/device/collectors/StatsdListenerTest.java b/libraries/device-collectors/src/test/platform/android/device/collectors/StatsdListenerTest.java
index db8606d19..b134d179b 100644
--- a/libraries/device-collectors/src/test/platform/android/device/collectors/StatsdListenerTest.java
+++ b/libraries/device-collectors/src/test/platform/android/device/collectors/StatsdListenerTest.java
@@ -33,6 +33,7 @@ import android.content.res.AssetManager;
import android.os.Bundle;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto.Atom;
import com.android.os.StatsLog.ConfigMetricsReportList;
import com.android.os.StatsLog.ConfigMetricsReportList.ConfigKey;
import com.google.common.collect.ImmutableMap;
@@ -554,4 +555,32 @@ public class StatsdListenerTest {
&& Arrays.stream(moreComponents)
.allMatch(c -> f.getName().contains(c)));
}
+
+ /** Test that configs are parsed and applied with correct permission fixes. */
+ @Test
+ public void testConfigsHavePermissionFixes() throws Exception {
+ // Stub a config for testing.
+ ByteArrayInputStream configStream = new ByteArrayInputStream(CONFIG_1.toByteArray());
+ doReturn(configStream)
+ .when(mListener)
+ .openConfigWithAssetManager(any(AssetManager.class), eq(CONFIG_NAME_1));
+
+ Bundle args = new Bundle();
+ args.putString(StatsdListener.OPTION_CONFIGS_RUN_LEVEL, CONFIG_NAME_1);
+ doReturn(args).when(mListener).getArguments();
+
+ Map<String, StatsdConfig> configs =
+ mListener.getConfigsFromOption(StatsdListener.OPTION_CONFIGS_RUN_LEVEL);
+ Assert.assertTrue(configs.containsKey(CONFIG_NAME_1));
+ Assert.assertTrue(
+ configs.get(CONFIG_NAME_1)
+ .getWhitelistedAtomIdsList()
+ .stream()
+ .anyMatch(id -> id == Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER));
+ Assert.assertTrue(
+ configs.get(CONFIG_NAME_1)
+ .getDefaultPullPackagesList()
+ .stream()
+ .anyMatch(name -> "AID_SYSTEM".equals(name)));
+ }
}
diff --git a/libraries/flicker/src/com/android/server/wm/flicker/WindowManagerTrace.java b/libraries/flicker/src/com/android/server/wm/flicker/WindowManagerTrace.java
index 69b5fef02..1399a09e7 100644
--- a/libraries/flicker/src/com/android/server/wm/flicker/WindowManagerTrace.java
+++ b/libraries/flicker/src/com/android/server/wm/flicker/WindowManagerTrace.java
@@ -19,8 +19,7 @@ package com.android.server.wm.flicker;
import androidx.annotation.Nullable;
import com.android.server.wm.flicker.Assertions.Result;
-import com.android.server.wm.nano.AppWindowTokenProto;
-import com.android.server.wm.nano.StackProto;
+import com.android.server.wm.nano.ActivityRecordProto;
import com.android.server.wm.nano.TaskProto;
import com.android.server.wm.nano.WindowManagerTraceFileProto;
import com.android.server.wm.nano.WindowManagerTraceProto;
@@ -143,24 +142,33 @@ public class WindowManagerTrace {
/** Returns window title of the top most visible app window. */
private String getTopVisibleAppWindow() {
- StackProto[] stacks =
+ TaskProto[] tasks =
mProto.windowManagerService
.rootWindowContainer
.displays[DEFAULT_DISPLAY]
- .stacks;
- for (StackProto stack : stacks) {
- for (TaskProto task : stack.tasks) {
- for (AppWindowTokenProto token : task.appWindowTokens) {
- for (WindowStateProto windowState : token.windowToken.windows) {
- if (windowState.windowContainer.visible) {
- return task.appWindowTokens[0].name;
- }
- }
+ .tasks;
+ for (TaskProto rootTask : tasks) {
+ final String topVisible = getTopVisibleAppWindow(rootTask);
+ if (topVisible != null) return topVisible;
+ }
+
+ return "";
+ }
+
+ private String getTopVisibleAppWindow(TaskProto task) {
+ for (ActivityRecordProto activity : task.activities) {
+ for (WindowStateProto windowState : activity.windowToken.windows) {
+ if (windowState.windowContainer.visible) {
+ return task.activities[0].name;
}
}
}
- return "";
+ for (TaskProto childTask : task.tasks) {
+ final String topVisible = getTopVisibleAppWindow(childTask);
+ if (topVisible != null) return topVisible;
+ }
+ return null;
}
/** Checks if aboveAppWindow with {@code windowTitle} is visible. */
@@ -208,37 +216,49 @@ public class WindowManagerTrace {
/** Checks if app window with {@code windowTitle} is visible. */
public Result isAppWindowVisible(String windowTitle) {
final String assertionName = "isAppWindowVisible";
- boolean titleFound = false;
- StackProto[] stacks =
+ boolean[] titleFound = { false };
+ TaskProto[] tasks =
mProto.windowManagerService
.rootWindowContainer
.displays[DEFAULT_DISPLAY]
- .stacks;
- for (StackProto stack : stacks) {
- for (TaskProto task : stack.tasks) {
- for (AppWindowTokenProto token : task.appWindowTokens) {
- if (token.name.contains(windowTitle)) {
- titleFound = true;
- for (WindowStateProto windowState : token.windowToken.windows) {
- if (windowState.windowContainer.visible) {
- return new Result(
- true /* success */,
- getTimestamp(),
- assertionName,
- "Window " + token.name + "is visible");
- }
- }
- }
- }
- }
+ .tasks;
+ for (TaskProto task : tasks) {
+ final Result result = isAppWindowVisible(
+ windowTitle, assertionName, titleFound, task);
+ if (result != null) return result;
}
String reason;
- if (!titleFound) {
+ if (!titleFound[0]) {
reason = "Window " + windowTitle + " cannot be found";
} else {
reason = "Window " + windowTitle + " is invisible";
}
return new Result(false /* success */, getTimestamp(), assertionName, reason);
}
+
+ private Result isAppWindowVisible(String windowTitle, String assertionName,
+ boolean[] titleFound, TaskProto task) {
+ for (ActivityRecordProto activity : task.activities) {
+ if (activity.name.contains(windowTitle)) {
+ titleFound[0] = true;
+ for (WindowStateProto windowState : activity.windowToken.windows) {
+ if (windowState.windowContainer.visible) {
+ return new Result(
+ true /* success */,
+ getTimestamp(),
+ assertionName,
+ "Window " + activity.name + "is visible");
+ }
+ }
+ }
+ }
+
+ for (TaskProto childTask : task.tasks) {
+ final Result result = isAppWindowVisible(
+ windowTitle, assertionName, titleFound, childTask);
+ if (result != null) return result;
+ }
+ return null;
+ }
}
}
diff --git a/libraries/flicker/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java b/libraries/flicker/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
index 013093109..633ac84ad 100644
--- a/libraries/flicker/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
+++ b/libraries/flicker/src/com/android/server/wm/flicker/monitor/LayersTraceMonitor.java
@@ -26,6 +26,7 @@ import java.nio.file.Path;
public class LayersTraceMonitor extends TraceMonitor {
private static final String TRACE_FILE = "layers_trace.pb";
private IWindowManager mWm = WindowManagerGlobal.getWindowManagerService();
+ private static final int TRACE_FLAGS = 0x7; // TRACE_CRITICAL|TRACE_INPUT|TRACE_COMPOSITION
public LayersTraceMonitor() {
this(OUTPUT_DIR);
@@ -37,6 +38,11 @@ public class LayersTraceMonitor extends TraceMonitor {
@Override
public void start() {
+ try {
+ mWm.setLayerTracingFlags(TRACE_FLAGS);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
setEnabled(true);
}
diff --git a/libraries/health/composers/platform/src/android/platform/test/composer/Shuffle.java b/libraries/health/composers/platform/src/android/platform/test/composer/Shuffle.java
index 3b2a42968..e8321c781 100644
--- a/libraries/health/composers/platform/src/android/platform/test/composer/Shuffle.java
+++ b/libraries/health/composers/platform/src/android/platform/test/composer/Shuffle.java
@@ -36,8 +36,7 @@ public class Shuffle<U> extends ShuffleBase<Bundle, U> {
try {
return Long.parseLong(seed);
} catch (NumberFormatException e) {
- throw new RuntimeException(
- String.format("Failed to parse seed option: %s", seed, e));
+ throw new RuntimeException(String.format("Failed to parse seed option: %s", seed), e);
}
}
}
diff --git a/libraries/health/options/src/android/platform/test/options/BooleanOption.java b/libraries/health/options/src/android/platform/test/option/BooleanOption.java
index a8cb94829..a8cb94829 100644
--- a/libraries/health/options/src/android/platform/test/options/BooleanOption.java
+++ b/libraries/health/options/src/android/platform/test/option/BooleanOption.java
diff --git a/libraries/health/options/src/android/platform/test/options/DoubleOption.java b/libraries/health/options/src/android/platform/test/option/DoubleOption.java
index ccd389ce6..ccd389ce6 100644
--- a/libraries/health/options/src/android/platform/test/options/DoubleOption.java
+++ b/libraries/health/options/src/android/platform/test/option/DoubleOption.java
diff --git a/libraries/health/options/src/android/platform/test/options/IntegerOption.java b/libraries/health/options/src/android/platform/test/option/IntegerOption.java
index 63eeaf21f..63eeaf21f 100644
--- a/libraries/health/options/src/android/platform/test/options/IntegerOption.java
+++ b/libraries/health/options/src/android/platform/test/option/IntegerOption.java
diff --git a/libraries/health/options/src/android/platform/test/options/LongOption.java b/libraries/health/options/src/android/platform/test/option/LongOption.java
index 9fc704870..9fc704870 100644
--- a/libraries/health/options/src/android/platform/test/options/LongOption.java
+++ b/libraries/health/options/src/android/platform/test/option/LongOption.java
diff --git a/libraries/health/options/src/android/platform/test/options/StringOption.java b/libraries/health/options/src/android/platform/test/option/StringOption.java
index 5ac662331..5ac662331 100644
--- a/libraries/health/options/src/android/platform/test/options/StringOption.java
+++ b/libraries/health/options/src/android/platform/test/option/StringOption.java
diff --git a/libraries/health/options/src/android/platform/test/options/TestOption.java b/libraries/health/options/src/android/platform/test/option/TestOption.java
index b73264dd7..a556aac77 100644
--- a/libraries/health/options/src/android/platform/test/options/TestOption.java
+++ b/libraries/health/options/src/android/platform/test/option/TestOption.java
@@ -16,11 +16,11 @@
package android.platform.test.option;
import android.os.Bundle;
-import androidx.test.InstrumentationRegistry;
import androidx.annotation.VisibleForTesting;
+import androidx.test.InstrumentationRegistry;
-import org.junit.runner.Description;
import org.junit.rules.TestRule;
+import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
diff --git a/libraries/health/rules/src/android/platform/test/rule/CompilationFilterRule.java b/libraries/health/rules/src/android/platform/test/rule/CompilationFilterRule.java
index 049de6045..092aa8dbc 100644
--- a/libraries/health/rules/src/android/platform/test/rule/CompilationFilterRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/CompilationFilterRule.java
@@ -16,13 +16,13 @@
package android.platform.test.rule;
+import static java.util.stream.Collectors.joining;
+
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.google.common.collect.ImmutableList;
-import java.util.stream.Collectors;
-
import org.junit.runner.Description;
import org.junit.runners.model.InitializationError;
@@ -37,7 +37,7 @@ public class CompilationFilterRule extends TestWatcher {
@VisibleForTesting static final String COMPILE_FILTER_OPTION = "compilation-filter";
@VisibleForTesting static final String COMPILE_SUCCESS = "Success";
- private String[] mApplications;
+ private final String[] mApplications;
public CompilationFilterRule() throws InitializationError {
throw new InitializationError("Must supply an application to compile.");
@@ -56,7 +56,7 @@ public class CompilationFilterRule extends TestWatcher {
Log.d(LOG_TAG, "Skipping complation because filter option is unset.");
return;
} else if (!COMPILE_FILTER_LIST.contains(filter)) {
- String filterOptions = COMPILE_FILTER_LIST.stream().collect(Collectors.joining(", "));
+ String filterOptions = COMPILE_FILTER_LIST.stream().collect(joining(", "));
throw new IllegalArgumentException(
String.format(
"Unknown compiler filter: %s, not part of %s", filter, filterOptions));
diff --git a/libraries/health/rules/src/android/platform/test/rule/DropCachesRule.java b/libraries/health/rules/src/android/platform/test/rule/DropCachesRule.java
index b5a6bf70c..3ca70c08f 100644
--- a/libraries/health/rules/src/android/platform/test/rule/DropCachesRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/DropCachesRule.java
@@ -15,27 +15,28 @@
*/
package android.platform.test.rule;
-import android.support.test.uiautomator.UiDevice;
+import android.os.SystemClock;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.test.platform.app.InstrumentationRegistry;
-import org.junit.runner.Description;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
-import android.os.SystemClock;
-import android.util.Log;
+import org.junit.runner.Description;
/**
* This rule will drop caches before running each test method.
*/
public class DropCachesRule extends TestWatcher {
+
private static final String LOG_TAG = DropCachesRule.class.getSimpleName();
@VisibleForTesting static final String KEY_DROP_CACHE = "drop-cache";
- private static boolean mDropCache = true;
+
+ private String mDropCacheScriptPath;
/**
* Shell equivalent of $(echo 3 > /proc/sys/vm/drop_caches)
@@ -43,26 +44,30 @@ public class DropCachesRule extends TestWatcher {
* Clears out the system pagecache for files and inodes metadata.
*/
public static void executeDropCaches() {
+ new DropCachesRule().executeDropCachesImpl();
+ }
+
+ private void executeDropCachesImpl() {
// Create a temporary file which contains the dropCaches command.
// Do this because we cannot write to /proc/sys/vm/drop_caches directly,
// as executeShellCommand parses the '>' character as a literal.
try {
File outputDir =
InstrumentationRegistry.getInstrumentation().getContext().getCacheDir();
- File outputFile = File.createTempFile("drop_cache_script", "sh", outputDir);
+ File outputFile = File.createTempFile("drop_cache_script", ".sh", outputDir);
outputFile.setWritable(true);
outputFile.setExecutable(true, /*ownersOnly*/false);
- String outputFilePath = outputFile.toString();
+ mDropCacheScriptPath = outputFile.toString();
// If this works correctly, the next log-line will print 'Success'.
String str = "echo 3 > /proc/sys/vm/drop_caches && echo Success || echo Failure";
- BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilePath));
+ BufferedWriter writer = new BufferedWriter(new FileWriter(mDropCacheScriptPath));
writer.write(str);
writer.close();
- UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
- String result = device.executeShellCommand(outputFilePath);
+ String result = executeShellCommand(mDropCacheScriptPath);
+ // TODO: automatically report the output of shell commands to logcat?
Log.v(LOG_TAG, "dropCaches output was: " + result);
outputFile.delete();
} catch (IOException e) {
@@ -72,14 +77,18 @@ public class DropCachesRule extends TestWatcher {
@Override
protected void starting(Description description) {
- // Identify the filter option to use.
- mDropCache = Boolean.parseBoolean(getArguments().getString(KEY_DROP_CACHE, "true"));
- if (mDropCache == false) {
+ boolean dropCache = Boolean.parseBoolean(getArguments().getString(KEY_DROP_CACHE, "true"));
+ if (!dropCache) {
return;
}
- executeDropCaches();
+ executeDropCachesImpl();
// TODO: b/117868612 to identify the root cause for additional wait.
SystemClock.sleep(3000);
}
+
+ @VisibleForTesting
+ protected String getDropCacheScriptPath() {
+ return mDropCacheScriptPath;
+ }
}
diff --git a/libraries/health/rules/src/android/platform/test/rule/IorapCompilationRule.java b/libraries/health/rules/src/android/platform/test/rule/IorapCompilationRule.java
index 87a72895f..0bcf96184 100644
--- a/libraries/health/rules/src/android/platform/test/rule/IorapCompilationRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/IorapCompilationRule.java
@@ -17,7 +17,6 @@
package android.platform.test.rule;
import android.os.SystemClock;
-import android.platform.test.rule.DropCachesRule;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -47,7 +46,6 @@ public class IorapCompilationRule extends TestWatcher {
// Global static counter. Each junit instrument command must launch 1 package with
// 1 compiler filter.
private static int sIterationCounter = 0;
- private String mApplication;
private enum IorapStatus {
UNDEFINED,
@@ -62,6 +60,8 @@ public class IorapCompilationRule extends TestWatcher {
INSUFFICIENT_TRACES,
}
+ private final String mApplication;
+
@VisibleForTesting
protected static void resetState() {
sIorapStatus = IorapStatus.UNDEFINED;
@@ -105,8 +105,7 @@ public class IorapCompilationRule extends TestWatcher {
* If iorapd is already disabled and enable is false, does nothing.
*/
private void toggleIorapStatus(boolean enable) {
- boolean currentlyEnabled = false;
- Log.v(TAG, "toggleIorapStatus " + Boolean.toString(enable));
+ Log.v(TAG, "toggleIorapStatus " + enable);
// Do nothing if we are already enabled or disabled.
if (sIorapStatus == IorapStatus.ENABLED && enable) {
@@ -190,8 +189,8 @@ public class IorapCompilationRule extends TestWatcher {
// Compiled Status: Raw traces pending compilation (3)
if (line.contains("Compiled Status: Usable compiled trace")) {
return IorapCompilationStatus.COMPLETE;
- } else if (line.contains("Compiled Status: ") &&
- line.contains("more traces for compilation")) {
+ } else if (line.contains("Compiled Status: ")
+ && line.contains("more traces for compilation")) {
// Compiled Status: Need 1 more traces for compilation
// No amount of waiting will help here because there were
// insufficient traces made.
@@ -206,15 +205,15 @@ public class IorapCompilationRule extends TestWatcher {
/**
* The first {@code IORAP_TRIAL_LAUNCH_ITERATIONS} are used for collecting an iorap trace file.
*/
- private boolean isIorapTraceBeingCollected() {
+ private static boolean isIorapTraceBeingCollected() {
return sIterationCounter < IORAP_TRIAL_LAUNCH_ITERATIONS;
}
- private boolean isLastIorapTraceCollection() {
+ private static boolean isLastIorapTraceCollection() {
return sIterationCounter == IORAP_TRIAL_LAUNCH_ITERATIONS - 1;
}
- private boolean isFirstIorapTraceCollection() {
+ private static boolean isFirstIorapTraceCollection() {
return sIterationCounter == 0;
}
@@ -238,9 +237,9 @@ public class IorapCompilationRule extends TestWatcher {
Log.d(TAG, "Skipping iorapd toggling because 'iorapd-enabled' option is unset.");
return;
}
+
logStatus("starting");
// Compile each application in sequence.
- String app = mApplication;
toggleIorapStatus(enabled);
@@ -283,7 +282,10 @@ public class IorapCompilationRule extends TestWatcher {
}
private void logStatus(String status) {
- Log.v(TAG, String.format("%s iteration %s for app %s", status, sIterationCounter, mApplication));
+ Log.v(
+ TAG,
+ String.format(
+ "%s iteration %s for app %s", status, sIterationCounter, mApplication));
}
}
diff --git a/libraries/health/rules/src/android/platform/test/rule/KillAppsRule.java b/libraries/health/rules/src/android/platform/test/rule/KillAppsRule.java
index 6217836c1..cdfb79533 100644
--- a/libraries/health/rules/src/android/platform/test/rule/KillAppsRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/KillAppsRule.java
@@ -27,7 +27,6 @@ public class KillAppsRule extends TestWatcher {
@VisibleForTesting
static final String KILL_APP = "kill-app";
- private static boolean mKillApp;
public KillAppsRule() throws InitializationError {
throw new InitializationError("Must supply an application to kill.");
@@ -40,8 +39,8 @@ public class KillAppsRule extends TestWatcher {
@Override
protected void starting(Description description) {
// Check if killing the app after launch is selected or not.
- mKillApp = Boolean.parseBoolean(getArguments().getString(KILL_APP, "true"));
- if (!mKillApp) {
+ boolean killApp = Boolean.parseBoolean(getArguments().getString(KILL_APP, "true"));
+ if (!killApp) {
return;
}
diff --git a/libraries/health/rules/src/android/platform/test/rule/PressHomeRule.java b/libraries/health/rules/src/android/platform/test/rule/PressHomeRule.java
index 61a0cd153..3286bb13d 100644
--- a/libraries/health/rules/src/android/platform/test/rule/PressHomeRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/PressHomeRule.java
@@ -26,13 +26,12 @@ import org.junit.runner.Description;
public class PressHomeRule extends TestWatcher {
static final String GO_HOME = "press-home";
- private static boolean mGoHome;
@Override
protected void finished(Description description) {
// Navigate to home after the test method is executed.
- mGoHome = Boolean.parseBoolean(getArguments().getString(GO_HOME, "true"));
- if (!mGoHome) {
+ boolean goHome = Boolean.parseBoolean(getArguments().getString(GO_HOME, "true"));
+ if (!goHome) {
return;
}
diff --git a/libraries/health/rules/src/android/platform/test/rule/QuickstepPressureRule.java b/libraries/health/rules/src/android/platform/test/rule/QuickstepPressureRule.java
index b8d2e4a42..bcd977816 100644
--- a/libraries/health/rules/src/android/platform/test/rule/QuickstepPressureRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/QuickstepPressureRule.java
@@ -16,18 +16,19 @@
package android.platform.test.rule;
-import org.junit.runner.Description;
-
import android.os.SystemClock;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Until;
import androidx.annotation.VisibleForTesting;
+import org.junit.runner.Description;
+
/** This rule opens apps then goes to home before a test class. */
public class QuickstepPressureRule extends TestWatcher {
+ private static final long MIN_CRASH_WAIT_TIMEOUT = 2500;
+ private static final long UI_RESPONSE_TIMEOUT_MSECS = 3000;
+
private final String[] mPackages;
- private final long MIN_CRASH_WAIT_TIMEOUT = 2500;
- private final long UI_RESPONSE_TIMEOUT_MSECS = 3000;
public QuickstepPressureRule(String... packages) {
if (packages.length == 0) {
diff --git a/libraries/health/rules/src/android/platform/test/rule/StopwatchRule.java b/libraries/health/rules/src/android/platform/test/rule/StopwatchRule.java
index eed70715b..c4c696a17 100644
--- a/libraries/health/rules/src/android/platform/test/rule/StopwatchRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/StopwatchRule.java
@@ -16,6 +16,8 @@
package android.platform.test.rule;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
import android.app.Instrumentation;
import android.os.Bundle;
import androidx.annotation.VisibleForTesting;
@@ -24,8 +26,6 @@ import androidx.test.InstrumentationRegistry;
import org.junit.rules.Stopwatch;
import org.junit.runner.Description;
-import java.util.concurrent.TimeUnit;
-
/**
* The rule measures the test execution time by extending {@link org.junit.rules.Stopwatch}. It will
* report the test time as key value pair to the instrumentation. For now, the rule will only report
@@ -43,7 +43,7 @@ public class StopwatchRule extends Stopwatch {
@VisibleForTesting static final String METRIC_FORMAT = "duration_ms_%s#%s";
- private Bundle mResult = new Bundle();
+ private final Bundle mResult = new Bundle();
private Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
/**
@@ -56,7 +56,7 @@ public class StopwatchRule extends Stopwatch {
String metricKey =
String.format(
METRIC_FORMAT, description.getClassName(), description.getMethodName());
- long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
+ long millis = NANOSECONDS.toMillis(nanos);
mResult.putLong(metricKey, millis);
mInstrumentation.sendStatus(INST_STATUS_IN_PROGRESS, mResult);
}
diff --git a/libraries/health/rules/src/android/platform/test/rule/TracePointRule.java b/libraries/health/rules/src/android/platform/test/rule/TracePointRule.java
index 25e6b1261..26025bd86 100644
--- a/libraries/health/rules/src/android/platform/test/rule/TracePointRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/TracePointRule.java
@@ -17,6 +17,8 @@ package android.platform.test.rule;
import android.os.Trace;
+import com.google.common.base.Strings;
+
import org.junit.runner.Description;
/**
@@ -61,8 +63,8 @@ public class TracePointRule extends TestWatcher {
* Returns the section name used for the applied {@code TestWatcher}.
*/
protected String getSectionName(Description description) {
- if (mSectionTag == null || mSectionTag.isEmpty()) {
- return String.format("%s", description.getDisplayName());
+ if (Strings.isNullOrEmpty(mSectionTag)) {
+ return description.getDisplayName();
} else {
return mSectionTag;
}
diff --git a/libraries/health/rules/tests/src/android/platform/test/rule/DropCachesRuleTest.java b/libraries/health/rules/tests/src/android/platform/test/rule/DropCachesRuleTest.java
index d382e411e..e0c32eae9 100644
--- a/libraries/health/rules/tests/src/android/platform/test/rule/DropCachesRuleTest.java
+++ b/libraries/health/rules/tests/src/android/platform/test/rule/DropCachesRuleTest.java
@@ -42,7 +42,7 @@ public class DropCachesRuleTest {
rule.apply(rule.getTestStatement(), Description.createTestDescription("clzz", "mthd"))
.evaluate();
assertThat(rule.getOperations()).containsExactly(
- "echo 3 > /proc/sys/vm/drop_caches", "test")
+ rule.getDropCacheScriptPath(), "test")
.inOrder();
}
@@ -92,5 +92,10 @@ public class DropCachesRuleTest {
}
};
}
+
+ @Override
+ public String getDropCacheScriptPath() {
+ return super.getDropCacheScriptPath();
+ }
}
}
diff --git a/libraries/health/runners/longevity/host/src/android/host/test/longevity/LongevitySuite.java b/libraries/health/runners/longevity/host/src/android/host/test/longevity/LongevitySuite.java
index 2001a5625..e8868bfa8 100644
--- a/libraries/health/runners/longevity/host/src/android/host/test/longevity/LongevitySuite.java
+++ b/libraries/health/runners/longevity/host/src/android/host/test/longevity/LongevitySuite.java
@@ -15,10 +15,15 @@
*/
package android.host.test.longevity;
-import android.host.test.longevity.listener.ErrorTerminator;
-import android.host.test.longevity.listener.TimeoutTerminator;
import android.host.test.composer.Iterate;
import android.host.test.composer.Shuffle;
+import android.host.test.longevity.listener.ErrorTerminator;
+import android.host.test.longevity.listener.TimeoutTerminator;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
@@ -27,11 +32,6 @@ import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
-import java.util.List;
-import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.stream.Collectors;
-
/**
* Using the {@code LongevitySuite} as a runner allows you to run test sequences repeatedly and with
* shuffling in order to simulate longevity conditions and repeated stress or exercise. For examples
@@ -104,8 +104,9 @@ public class LongevitySuite extends Suite {
@Override
public void run(final RunNotifier notifier) {
// Add action terminators for custom runner logic.
- if (mArguments.containsKey(QUITTER_OPTION) ?
- Boolean.parseBoolean(mArguments.get(QUITTER_OPTION)) : QUITTER_DEFAULT) {
+ if (mArguments.containsKey(QUITTER_OPTION)
+ ? Boolean.parseBoolean(mArguments.get(QUITTER_OPTION))
+ : QUITTER_DEFAULT) {
notifier.addListener(getErrorTerminator(notifier));
}
notifier.addListener(getTimeoutTerminator(notifier));
@@ -114,8 +115,9 @@ public class LongevitySuite extends Suite {
super.run(notifier);
} catch (StoppedByUserException e) {
// Invalidate the test run if terminated early and the option is set.
- if (mArguments.containsKey(INVALIDATE_OPTION) ?
- Boolean.parseBoolean(mArguments.get(INVALIDATE_OPTION)) : INVALIDATE_DEFAULT) {
+ if (mArguments.containsKey(INVALIDATE_OPTION)
+ ? Boolean.parseBoolean(mArguments.get(INVALIDATE_OPTION))
+ : INVALIDATE_DEFAULT) {
throw e;
} else {
return;
diff --git a/libraries/health/runners/longevity/host/src/android/host/test/longevity/listener/TimeoutTerminator.java b/libraries/health/runners/longevity/host/src/android/host/test/longevity/listener/TimeoutTerminator.java
index 53c1d2566..5204e44ef 100644
--- a/libraries/health/runners/longevity/host/src/android/host/test/longevity/listener/TimeoutTerminator.java
+++ b/libraries/health/runners/longevity/host/src/android/host/test/longevity/listener/TimeoutTerminator.java
@@ -15,18 +15,19 @@
*/
package android.host.test.longevity.listener;
-import org.junit.runner.Description;
-import org.junit.runner.notification.RunNotifier;
+import static java.util.concurrent.TimeUnit.MINUTES;
import java.util.Map;
-import java.util.concurrent.TimeUnit;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
/**
* A {@link RunTerminator} for terminating early on test end due to long duration for host suites.
*/
public class TimeoutTerminator extends RunTerminator {
public static final String OPTION = "suite-timeout_msec";
- protected static final long DEFAULT = TimeUnit.MINUTES.toMillis(30L);
+ protected static final long DEFAULT = MINUTES.toMillis(30L);
protected static final long UNSET_TIMESTAMP = -1;
protected long mStartTimestamp = UNSET_TIMESTAMP;
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevityClassRunner.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevityClassRunner.java
index a94e27cfd..e565427e1 100644
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevityClassRunner.java
+++ b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevityClassRunner.java
@@ -51,7 +51,7 @@ public class LongevityClassRunner extends BlockJUnit4ClassRunner {
// A constant to indicate that the iteration number is not set.
@VisibleForTesting static final int ITERATION_NOT_SET = -1;
- private String[] mExcludedClasses;
+ private final String[] mExcludedClasses;
private String mIterationSep = ITERATION_SEP_DEFAULT;
private boolean mTestFailed = true;
@@ -116,7 +116,7 @@ public class LongevityClassRunner extends BlockJUnit4ClassRunner {
*/
@Override
protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
- List<FrameworkMethod> allBeforeMethods = new ArrayList<FrameworkMethod>();
+ List<FrameworkMethod> allBeforeMethods = new ArrayList<>();
allBeforeMethods.addAll(getTestClass().getAnnotatedMethods(BeforeClass.class));
allBeforeMethods.addAll(getTestClass().getAnnotatedMethods(Before.class));
return allBeforeMethods.isEmpty()
@@ -269,12 +269,16 @@ public class LongevityClassRunner extends BlockJUnit4ClassRunner {
*/
@Override
protected Description describeChild(FrameworkMethod method) {
- Description original = super.describeChild(method);
+ return addIterationIfEnabled(super.describeChild(method));
+ }
+
+ /** Rename the class name to add iterations if the renaming iteration option is enabled. */
+ protected Description addIterationIfEnabled(Description input) {
if (mIteration == ITERATION_NOT_SET) {
- return original;
+ return input;
}
return Description.createTestDescription(
- String.join(mIterationSep, original.getClassName(), String.valueOf(mIteration)),
- original.getMethodName());
+ String.join(mIterationSep, input.getClassName(), String.valueOf(mIteration)),
+ input.getMethodName());
}
}
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevitySuite.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevitySuite.java
index 74a22ab9f..ced687480 100644
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevitySuite.java
+++ b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/LongevitySuite.java
@@ -31,10 +31,11 @@ import androidx.annotation.VisibleForTesting;
import androidx.test.InstrumentationRegistry;
import java.lang.reflect.Field;
-import java.util.function.BiFunction;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.BiFunction;
import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Description;
@@ -53,21 +54,20 @@ public class LongevitySuite extends android.host.test.longevity.LongevitySuite {
private static final String LOG_TAG = LongevitySuite.class.getSimpleName();
public static final String RENAME_ITERATION_OPTION = "rename-iterations";
- private boolean mRenameIterations;
+ private final boolean mRenameIterations;
- private Instrumentation mInstrumentation;
private Context mContext;
// Cached {@link TimeoutTerminator} instance.
private TimeoutTerminator mTimeoutTerminator;
- private Map<Description, Integer> mIterations = new HashMap<>();
+ private final Map<Description, Integer> mIterations = new HashMap<>();
/**
* Takes a {@link Bundle} and maps all String K/V pairs into a {@link Map<String, String>}.
*
* @param bundle the input arguments to return in a {@link Map}
- * @return Map<String, String> all String-to-String key, value pairs in the {@link Bundle}
+ * @return a {@code Map<String, String>} of all key, value pairs in {@code bundle}.
*/
protected static final Map<String, String> toMap(Bundle bundle) {
Map<String, String> result = new HashMap<>();
@@ -87,42 +87,58 @@ public class LongevitySuite extends android.host.test.longevity.LongevitySuite {
*/
public LongevitySuite(Class<?> klass, RunnerBuilder builder)
throws InitializationError {
- this(klass, builder, InstrumentationRegistry.getInstrumentation(),
- InstrumentationRegistry.getContext(), InstrumentationRegistry.getArguments());
+ this(
+ klass,
+ builder,
+ new ArrayList<Runner>(),
+ InstrumentationRegistry.getInstrumentation(),
+ InstrumentationRegistry.getContext(),
+ InstrumentationRegistry.getArguments());
+ }
+
+ /** Used to dynamically pass in test classes to run as part of the suite in subclasses. */
+ public LongevitySuite(Class<?> klass, RunnerBuilder builder, List<Runner> additional)
+ throws InitializationError {
+ this(
+ klass,
+ builder,
+ additional,
+ InstrumentationRegistry.getInstrumentation(),
+ InstrumentationRegistry.getContext(),
+ InstrumentationRegistry.getArguments());
}
/**
- * Enables subclasses, e.g.{@link ProfileSuite}, to constuct a suite using its own list of
+ * Enables subclasses, e.g.{@link ProfileSuite}, to construct a suite using its own list of
* Runners.
*/
protected LongevitySuite(Class<?> klass, List<Runner> runners, Bundle args)
throws InitializationError {
super(klass, runners, toMap(args));
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = InstrumentationRegistry.getContext();
// Parse out additional options.
- mRenameIterations = Boolean.valueOf(args.getString(RENAME_ITERATION_OPTION));
+ mRenameIterations = Boolean.parseBoolean(args.getString(RENAME_ITERATION_OPTION));
}
- /**
- * Used to pass in mock-able Android features for testing.
- */
+ /** Used to pass in mock-able Android features for testing. */
@VisibleForTesting
- public LongevitySuite(Class<?> klass, RunnerBuilder builder,
- Instrumentation instrumentation, Context context, Bundle arguments)
+ public LongevitySuite(
+ Class<?> klass,
+ RunnerBuilder builder,
+ List<Runner> additional,
+ Instrumentation instrumentation,
+ Context context,
+ Bundle arguments)
throws InitializationError {
- this(klass, constructClassRunners(klass, builder, arguments), arguments);
+ this(klass, constructClassRunners(klass, additional, builder, arguments), arguments);
// Overwrite instrumentation and context here with the passed-in objects.
- mInstrumentation = instrumentation;
mContext = context;
}
- /**
- * Constructs the sequence of {@link Runner}s using platform composers.
- */
+ /** Constructs the sequence of {@link Runner}s using platform composers. */
private static List<Runner> constructClassRunners(
- Class<?> suite, RunnerBuilder builder, Bundle args)
+ Class<?> suite, List<Runner> additional, RunnerBuilder builder, Bundle args)
throws InitializationError {
// TODO(b/118340229): Refactor to share logic with base class. In the meanwhile, keep the
// logic here in sync with the base class.
@@ -153,10 +169,13 @@ public class LongevitySuite extends android.host.test.longevity.LongevitySuite {
runner.getClass(), runner.getDescription().getDisplayName()));
}
}
- // Construct and store custom runners for the full suite.
+ // Combine annotated runners and additional ones.
+ List<Runner> runners = builder.runners(suite, annotation.value());
+ runners.addAll(additional);
+ // Apply the modifiers to construct the full suite.
BiFunction<Bundle, List<Runner>, List<Runner>> modifier =
new Iterate<Runner>().andThen(new Shuffle<Runner>());
- return modifier.apply(args, builder.runners(suite, annotation.value()));
+ return modifier.apply(args, runners);
}
@Override
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/Profile.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/Profile.java
index b9812767c..d20fc9bcd 100644
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/Profile.java
+++ b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/Profile.java
@@ -15,6 +15,10 @@
*/
package android.platform.test.longevity;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.SystemClock;
@@ -25,16 +29,12 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.test.InstrumentationRegistry;
-import org.junit.runner.Description;
-import org.junit.runner.Runner;
-import org.junit.runner.notification.RunListener;
-
import java.io.File;
import java.io.FileInputStream;
-import java.io.InputStream;
import java.io.IOException;
-import java.text.SimpleDateFormat;
+import java.io.InputStream;
import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -42,7 +42,10 @@ import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.function.Function;
-import java.util.stream.Collectors;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunListener;
/** A profile composer for device-side testing. */
public class Profile extends RunListener {
@@ -63,15 +66,16 @@ public class Profile extends RunListener {
// constructed. Can be overridden by {@link setTestRunStartTimeMs}.
private long mRunStartTimeMs = SystemClock.elapsedRealtime();
// The profile configuration.
- private Configuration mConfiguration;
+ private final Configuration mConfiguration;
// The timestamp of the first scenario in milliseconds. All scenarios will be scheduled relative
// to this timestamp.
private long mFirstScenarioTimestampMs = 0;
- // Comparator for sorting timstamped CUJs.
+ // Comparator for sorting timestamped CUJs.
private static class ScenarioTimestampComparator implements Comparator<Scenario> {
+ @Override
public int compare(Scenario s1, Scenario s2) {
- if (! (s1.hasAt() && s2.hasAt())) {
+ if (!(s1.hasAt() && s2.hasAt())) {
throw new IllegalArgumentException(
"Scenarios in scheduled profiles must have timestamps.");
}
@@ -81,6 +85,7 @@ public class Profile extends RunListener {
// Comparator for sorting indexed CUJs.
private static class ScenarioIndexedComparator implements Comparator<Scenario> {
+ @Override
public int compare(Scenario s1, Scenario s2) {
if (!(s1.hasIndex() && s2.hasIndex())) {
throw new IllegalArgumentException(
@@ -92,7 +97,7 @@ public class Profile extends RunListener {
public Profile(Bundle args) {
super();
- // Set the timestamp parser to UTC to get test timstamps as "time elapsed since zero".
+ // Set the timestamp parser to UTC to get test timestamps as "time elapsed since zero".
TIMESTAMP_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
// Load configuration from arguments and stored the list of scenarios sorted according to
@@ -103,7 +108,7 @@ public class Profile extends RunListener {
if (mConfiguration == null) {
return;
}
- mOrderedScenariosList = new ArrayList<Scenario>(mConfiguration.getScenariosList());
+ mOrderedScenariosList = new ArrayList<>(mConfiguration.getScenariosList());
if (mOrderedScenariosList.isEmpty()) {
throw new IllegalArgumentException("Profile must have at least one scenario.");
}
@@ -134,34 +139,42 @@ public class Profile extends RunListener {
protected List<Runner> getTestSequenceFromConfiguration(
Configuration config, List<Runner> input) {
Map<String, Runner> nameToRunner =
- input.stream().collect(
- Collectors.toMap(
- r -> r.getDescription().getDisplayName(), Function.identity()));
- Log.i(LOG_TAG, String.format(
- "Available journeys: %s",
- nameToRunner.keySet().stream().collect(Collectors.joining(", "))));
- List<Runner> result = mOrderedScenariosList
- .stream()
- .map(Configuration.Scenario::getJourney)
- .map(
- journeyName -> {
- if (nameToRunner.containsKey(journeyName)) {
- return nameToRunner.get(journeyName);
- } else {
- throw new IllegalArgumentException(
- String.format(
+ input.stream()
+ .collect(
+ toMap(
+ r -> r.getDescription().getDisplayName(),
+ Function.identity()));
+ Log.i(
+ LOG_TAG,
+ String.format(
+ "Available journeys: %s",
+ nameToRunner.keySet().stream().collect(joining(", "))));
+ List<Runner> result =
+ mOrderedScenariosList
+ .stream()
+ .map(Configuration.Scenario::getJourney)
+ .map(
+ journeyName -> {
+ if (nameToRunner.containsKey(journeyName)) {
+ return nameToRunner.get(journeyName);
+ } else {
+ // Write error message here to trick the auto-formatter.
+ String errorFmtMessage =
"Journey %s in profile not found. "
- + "Check logcat to see available journeys.",
- journeyName));
- }
- })
- .collect(Collectors.toList());
- Log.i(LOG_TAG, String.format(
- "Returned runners: %s",
- result.stream()
- .map(Runner::getDescription)
- .map(Description::getDisplayName)
- .collect(Collectors.toList())));
+ + "Check logcat to see available journeys.";
+ throw new IllegalArgumentException(
+ String.format(errorFmtMessage, journeyName));
+ }
+ })
+ .collect(toList());
+ Log.i(
+ LOG_TAG,
+ String.format(
+ "Returned runners: %s",
+ result.stream()
+ .map(Runner::getDescription)
+ .map(Description::getDisplayName)
+ .collect(toList())));
return result;
}
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ProfileSuite.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ProfileSuite.java
index d557780d3..aa34a32f1 100644
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ProfileSuite.java
+++ b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ProfileSuite.java
@@ -20,6 +20,7 @@ import android.app.Instrumentation;
import android.content.Context;
import android.os.Bundle;
import android.platform.test.longevity.proto.Configuration.Scenario;
+import android.platform.test.longevity.proto.Configuration.Scenario.ExtraArg;
import androidx.annotation.VisibleForTesting;
import androidx.test.InstrumentationRegistry;
@@ -38,14 +39,9 @@ import org.junit.runners.model.RunnerBuilder;
* profile.
*/
public class ProfileSuite extends LongevitySuite {
- private static final String LOG_TAG = ProfileSuite.class.getSimpleName();
// Profile instance for scheduling tests.
- private Profile mProfile;
- // Suite timeout for timing out the last scenario.
- private long mSuiteTimeout;
- // Cached {@link android.host.test.longevity.listener.TimeoutTerminator} instance.
- private android.host.test.longevity.listener.TimeoutTerminator mTimeoutTerminator;
+ private final Profile mProfile;
/**
* Called reflectively on classes annotated with {@code @RunWith(LongevitySuite.class)}
@@ -118,10 +114,37 @@ public class ProfileSuite extends LongevitySuite {
super.run(notifier);
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The "extras" are injected here before the entire child test class is run to ensure that
+ * test options passed in as class-level rules still work.
+ */
@Override
protected void runChild(Runner runner, final RunNotifier notifier) {
+ // Fall back to LongevitySuite behavior if no profile is supplied.
+ if (mProfile.getConfiguration() == null) {
+ super.runChild(runner, notifier);
+ return;
+ }
+ Bundle existingArguments = InstrumentationRegistry.getArguments().deepCopy();
+ Bundle modifiedArguments = InstrumentationRegistry.getArguments().deepCopy();
+ for (ExtraArg argPair : mProfile.getCurrentScenario().getExtrasList()) {
+ if (!argPair.hasKey() || !argPair.hasValue()) {
+ throw new IllegalArgumentException(
+ String.format(
+ "Each extra arg entry in scenario must have both a key and a value,"
+ + " but scenario is %s.",
+ mProfile.getCurrentScenario()));
+ }
+ modifiedArguments.putString(argPair.getKey(), argPair.getValue());
+ }
+ // Swap the arguments, run the scenario, and then restore arguments.
+ InstrumentationRegistry.registerInstance(
+ InstrumentationRegistry.getInstrumentation(), modifiedArguments);
super.runChild(runner, notifier);
+ InstrumentationRegistry.registerInstance(
+ InstrumentationRegistry.getInstrumentation(), existingArguments);
}
/**
@@ -149,15 +172,15 @@ public class ProfileSuite extends LongevitySuite {
mProfile.hasNextScheduledScenario());
case INDEXED:
- return getIndexedRunner(
- (BlockJUnit4ClassRunner) runner, mProfile.getCurrentScenario());
-
- default:
- throw new RuntimeException(
- String.format(
- "Schedule type %s is not yet supported.",
- mProfile.getConfiguration().getSchedule().toString()));
+ // A LongevityClassRunner, which the superclass method already returns, is suitable
+ // for an indexed profile.
+ return super.getSuiteRunner(runner);
}
+
+ throw new RuntimeException(
+ String.format(
+ "Schedule type %s is not yet supported.",
+ mProfile.getConfiguration().getSchedule()));
}
/**
@@ -178,19 +201,4 @@ public class ProfileSuite extends LongevitySuite {
e);
}
}
-
- /** Replace a runner with {@link ScenarioRunner} for features specific to indexed profiles. */
- @VisibleForTesting
- protected ScenarioRunner getIndexedRunner(BlockJUnit4ClassRunner runner, Scenario scenario) {
- Class<?> testClass = runner.getTestClass().getJavaClass();
- try {
- return new ScenarioRunner(testClass, scenario);
- } catch (InitializationError e) {
- throw new RuntimeException(
- String.format(
- "Unable to run scenario %s with an indexed runner.",
- runner.getDescription().getDisplayName()),
- e);
- }
- }
}
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScenarioRunner.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScenarioRunner.java
deleted file mode 100644
index 33e4056c5..000000000
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScenarioRunner.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.platform.test.longevity;
-
-import android.os.Bundle;
-import android.platform.test.longevity.proto.Configuration.Scenario;
-import android.platform.test.longevity.proto.Configuration.Scenario.ExtraArg;
-import androidx.annotation.VisibleForTesting;
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-
-/** A {@link BlockJUnit4ClassRunner} that runs a test class with profile-specified options. */
-public class ScenarioRunner extends LongevityClassRunner {
- private final Scenario mScenario;
- private final Bundle mArguments;
-
- public ScenarioRunner(Class<?> klass, Scenario scenario) throws InitializationError {
- this(klass, scenario, InstrumentationRegistry.getArguments());
- }
-
- @VisibleForTesting
- ScenarioRunner(Class<?> klass, Scenario scenario, Bundle arguments) throws InitializationError {
- super(klass, arguments);
- mScenario = scenario;
- mArguments = arguments;
- }
-
- @Override
- protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
- // Keep a copy of the bundle arguments for restoring later.
- Bundle modifiedArguments = mArguments.deepCopy();
- for (ExtraArg argPair : mScenario.getExtrasList()) {
- if (argPair.getKey() == null || argPair.getValue() == null) {
- throw new IllegalArgumentException(
- String.format(
- "Each extra arg entry in scenario must have both a key and a value,"
- + " but scenario is %s.",
- mScenario.toString()));
- }
- modifiedArguments.putString(argPair.getKey(), argPair.getValue());
- }
- // Swap the arguments, run the scenario, and then restore arguments.
- InstrumentationRegistry.registerInstance(
- InstrumentationRegistry.getInstrumentation(), modifiedArguments);
- super.runChild(method, notifier);
- InstrumentationRegistry.registerInstance(
- InstrumentationRegistry.getInstrumentation(), mArguments);
- }
-}
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScheduledScenarioRunner.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScheduledScenarioRunner.java
index ffd54fee4..f757fe0b1 100644
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScheduledScenarioRunner.java
+++ b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/ScheduledScenarioRunner.java
@@ -17,6 +17,7 @@
package android.platform.test.longevity;
import static java.lang.Math.max;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -27,14 +28,12 @@ import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Process;
import android.platform.test.longevity.proto.Configuration.Scenario;
-import android.platform.test.longevity.proto.Configuration.Scenario.ExtraArg;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.test.InstrumentationRegistry;
import java.util.List;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
@@ -144,24 +143,7 @@ public class ScheduledScenarioRunner extends LongevityClassRunner {
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
mStartTimeMs = System.currentTimeMillis();
- // Keep a copy of the bundle arguments for restoring later.
- Bundle modifiedArguments = mArguments.deepCopy();
- for (ExtraArg argPair : mScenario.getExtrasList()) {
- if (argPair.getKey() == null || argPair.getValue() == null) {
- throw new IllegalArgumentException(
- String.format(
- "Each extra arg entry in scenario must have both a key and a value,"
- + " but scenario is %s.",
- mScenario.toString()));
- }
- modifiedArguments.putString(argPair.getKey(), argPair.getValue());
- }
- InstrumentationRegistry.registerInstance(
- InstrumentationRegistry.getInstrumentation(), modifiedArguments);
super.runChild(method, notifier);
- // Restore the arguments to the state prior to the scenario.
- InstrumentationRegistry.registerInstance(
- InstrumentationRegistry.getInstrumentation(), mArguments);
// If there are remaining scenarios, idle until the next one starts.
if (mShouldIdle) {
performIdleBeforeNextScenario(getTimeRemainingForScenario());
@@ -226,11 +208,8 @@ public class ScheduledScenarioRunner extends LongevityClassRunner {
String wakeUpAction =
String.format(
- "%s.%d.%d.ScheduledScenarioRunnerSleepWakeUp"
- .format(
- context.getPackageName(),
- Process.myPid(),
- Thread.currentThread().getId()));
+ "%s.%d.%d.ScheduledScenarioRunnerSleepWakeUp",
+ context.getPackageName(), Process.myPid(), Thread.currentThread().getId());
final CountDownLatch countDownLatch = new CountDownLatch(1);
IntentFilter wakeUpActionFilter = new IntentFilter(wakeUpAction);
@@ -253,7 +232,7 @@ public class ScheduledScenarioRunner extends LongevityClassRunner {
AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + durationMs, pendingIntent);
try {
- countDownLatch.await(countDownLatchTimeoutMs, TimeUnit.MILLISECONDS);
+ countDownLatch.await(countDownLatchTimeoutMs, MILLISECONDS);
Log.i(LOG_TAG, "Suspension-aware sleep ended.");
} catch (InterruptedException e) {
throw new RuntimeException(e);
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/BatteryTerminator.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/BatteryTerminator.java
index ec9831d64..f55763d60 100644
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/BatteryTerminator.java
+++ b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/BatteryTerminator.java
@@ -55,7 +55,7 @@ public final class BatteryTerminator extends RunTerminator {
if (level < 0 || scale <= 0) {
throw new RuntimeException("Failed to get proper battery levels.");
}
- return (double)level / (double)scale;
+ return (double) level / (double) scale;
}
@Override
diff --git a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/TimeoutTerminator.java b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/TimeoutTerminator.java
index 4773ce8a8..b2207687e 100644
--- a/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/TimeoutTerminator.java
+++ b/libraries/health/runners/longevity/platform/src/android/platform/test/longevity/listener/TimeoutTerminator.java
@@ -26,7 +26,8 @@ import org.junit.runner.notification.RunNotifier;
* A {@link RunTerminator} for terminating early on test end due to long duration for platform
* suites.
*/
-public final class TimeoutTerminator extends android.host.test.longevity.listener.TimeoutTerminator {
+public final class TimeoutTerminator
+ extends android.host.test.longevity.listener.TimeoutTerminator {
public TimeoutTerminator(RunNotifier notifier, Map<String, String> args) {
super(notifier, args);
}
diff --git a/libraries/health/runners/longevity/platform/tests/AndroidTest.xml b/libraries/health/runners/longevity/platform/tests/AndroidTest.xml
index 530392c0f..077136740 100644
--- a/libraries/health/runners/longevity/platform/tests/AndroidTest.xml
+++ b/libraries/health/runners/longevity/platform/tests/AndroidTest.xml
@@ -23,7 +23,9 @@
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.platform.test.longevity.tests" />
- <option name="exclude-filter" value="android.platform.test.longevity.samples.testing.SampleProfileSuite" />
+ <option name="exclude-filter" value="android.platform.test.longevity.samples.testing.SampleBasicProfileSuite" />
+ <option name="exclude-filter" value="android.platform.test.longevity.samples.testing.SampleExtraArgsSuite" />
+ <option name="exclude-filter" value="android.platform.test.longevity.samples.testing.SampleTimedProfileSuite" />
<option name="exclude-filter" value="android.platform.test.scenario" />
<option name="runtime-hint" value="1m30s" />
</test>
diff --git a/libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_registeredBeforeTest.textpb b/libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_registeredBeforeTest.textpb
new file mode 100644
index 000000000..b27488b09
--- /dev/null
+++ b/libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_registeredBeforeTest.textpb
@@ -0,0 +1,23 @@
+schedule: INDEXED
+scenarios [{
+ index: 1
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$ClassLevelExtraArgsScenario"
+ extras [{
+ key: "class-level-option"
+ value: "class-level-override"
+ }]
+}, {
+ index: 2
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$TestLevelExtraArgsScenario"
+ extras [{
+ key: "test-level-option"
+ value: "test-level-override"
+ }]
+}, {
+ index: 3
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$InTestExtraArgsScenario"
+ extras [{
+ key: "in-test-option"
+ value: "in-test-override"
+ }]
+}]
diff --git a/libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_unregisteredAfterTest.textpb b/libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_unregisteredAfterTest.textpb
new file mode 100644
index 000000000..87705ad5d
--- /dev/null
+++ b/libraries/health/runners/longevity/platform/tests/assets/testExtraArgs_unregisteredAfterTest.textpb
@@ -0,0 +1,44 @@
+schedule: INDEXED
+scenarios [{
+ index: 1
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$ClassLevelExtraArgsScenario"
+ extras [{
+ key: "class-level-option"
+ value: "class-level-override"
+ }]
+}, {
+ index: 2
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$NotInInstrumentationArgsTest"
+ extras [{
+ key: "arg-to-check"
+ value: "class-level-option"
+ }]
+}, {
+ index: 3
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$TestLevelExtraArgsScenario"
+ extras [{
+ key: "test-level-option"
+ value: "test-level-override"
+ }]
+}, {
+ index: 4
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$NotInInstrumentationArgsTest"
+ extras [{
+ key: "arg-to-check"
+ value: "test-level-option"
+ }]
+}, {
+ index: 5
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$InTestExtraArgsScenario"
+ extras [{
+ key: "in-test-option"
+ value: "in-test-override"
+ }]
+}, {
+ index: 6
+ journey: "android.platform.test.longevity.samples.testing.SampleExtraArgsSuite$NotInInstrumentationArgsTest"
+ extras [{
+ key: "arg-to-check"
+ value: "in-test-option"
+ }]
+}]
diff --git a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/LongevitySuiteTest.java b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/LongevitySuiteTest.java
index 4a53202d4..08c4c1a8a 100644
--- a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/LongevitySuiteTest.java
+++ b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/LongevitySuiteTest.java
@@ -74,6 +74,7 @@ public class LongevitySuiteTest {
new LongevitySuite(
TestSuite.class,
new AllDefaultPossibilitiesBuilder(true),
+ new ArrayList<Runner>(),
mInstrumentation,
mContext,
new Bundle());
@@ -92,6 +93,7 @@ public class LongevitySuiteTest {
new LongevitySuite(
TestSuite.class,
new AllDefaultPossibilitiesBuilder(true),
+ new ArrayList<Runner>(),
mInstrumentation,
mContext,
new Bundle());
@@ -111,6 +113,7 @@ public class LongevitySuiteTest {
new LongevitySuite(
IterationSuite.class,
new AllDefaultPossibilitiesBuilder(true),
+ new ArrayList<Runner>(),
mInstrumentation,
mContext,
new Bundle()));
@@ -146,6 +149,7 @@ public class LongevitySuiteTest {
new LongevitySuite(
IterationSuite.class,
new AllDefaultPossibilitiesBuilder(true),
+ new ArrayList<Runner>(),
mInstrumentation,
mContext,
args));
@@ -173,6 +177,55 @@ public class LongevitySuiteTest {
Assert.assertEquals(runners.get(2).getIteration(), 2);
}
+ /** Test that appending classes to a suite will properly append them and iterate on them. */
+ @Test
+ public void testAdditionalRunners() throws InitializationError {
+ Bundle args = new Bundle();
+ // TODO: Access the iterations option name directly.
+ args.putString("iterations", String.valueOf(2));
+ List<Runner> additions = new ArrayList<>();
+ additions.add(new BlockJUnit4ClassRunner(AdditionalTest.class));
+ additions.add(new BlockJUnit4ClassRunner(AdditionalTest.class));
+ // Construct the suite with additional classes to run.
+ mSuite =
+ Mockito.spy(
+ new LongevitySuite(
+ IterationSuite.class,
+ new AllDefaultPossibilitiesBuilder(true),
+ additions,
+ mInstrumentation,
+ mContext,
+ args));
+ // Store the runners that the tests are executing. Since these are object references,
+ // subsequent modifications to the runners (setting the iteration) will still be observable
+ // here.
+ List<LongevityClassRunner> runners = new ArrayList<>();
+ doAnswer(
+ invocation -> {
+ LongevityClassRunner runner =
+ (LongevityClassRunner) invocation.callRealMethod();
+ runners.add(runner);
+ return runner;
+ })
+ .when(mSuite)
+ .getSuiteRunner(any(Runner.class));
+ mSuite.run(mRunNotifier);
+ Assert.assertEquals(runners.size(), 10);
+ // Check the runners and their corresponding iterations.
+ Assert.assertTrue(runners.get(0).getDescription().getDisplayName().contains("TestOne"));
+ Assert.assertTrue(runners.get(1).getDescription().getDisplayName().contains("TestTwo"));
+ Assert.assertTrue(runners.get(2).getDescription().getDisplayName().contains("TestOne"));
+ Assert.assertTrue(
+ runners.get(3).getDescription().getDisplayName().contains("AdditionalTest"));
+ Assert.assertTrue(
+ runners.get(4).getDescription().getDisplayName().contains("AdditionalTest"));
+ // 5, 6, and 7 are repetitions of "TestOne", "TestTwo", and "TestOne".
+ Assert.assertTrue(
+ runners.get(8).getDescription().getDisplayName().contains("AdditionalTest"));
+ Assert.assertTrue(
+ runners.get(9).getDescription().getDisplayName().contains("AdditionalTest"));
+ }
+
/**
* Test that when a builder ends up being a {@link ErrorReportingRunner}, the underlying error
* is reported as an InitializationError.
@@ -193,6 +246,7 @@ public class LongevitySuiteTest {
new LongevitySuite(
IterationSuite.class,
builder,
+ new ArrayList<Runner>(),
mInstrumentation,
mContext,
new Bundle());
@@ -238,4 +292,11 @@ public class LongevitySuiteTest {
public void testNothing() {}
}
}
+
+ /** Additional test class to add to append to the longevity suite. */
+ // @RunWith(JUnit4.class)
+ public static class AdditionalTest {
+ @Test
+ public void testNothing() {}
+ }
}
diff --git a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ProfileSuiteTest.java b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ProfileSuiteTest.java
index 8d7237d3f..06fd46659 100644
--- a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ProfileSuiteTest.java
+++ b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ProfileSuiteTest.java
@@ -15,10 +15,12 @@
*/
package android.platform.test.longevity;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,9 +33,12 @@ import android.host.test.longevity.listener.TimeoutTerminator;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.longevity.samples.testing.SampleBasicProfileSuite;
+import android.platform.test.longevity.samples.testing.SampleExtraArgsSuite;
import android.platform.test.longevity.samples.testing.SampleTimedProfileSuite;
import android.platform.test.scenario.annotation.Scenario;
+import androidx.test.InstrumentationRegistry;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
@@ -52,6 +57,7 @@ import org.junit.runners.model.TestTimedOutException;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -71,10 +77,22 @@ public class ProfileSuiteTest {
// Threshold above which missing a schedule is considered a failure.
private static final long SCHEDULE_LEEWAY_MS = 500;
+ // Holds the state of the instrumentation args before each test for restoring after, as one test
+ // might affect the state of another otherwise.
+ // TODO(b/124239142): Avoid manipulating the instrumentation args here.
+ private Bundle mArgumentsBeforeTest;
+
@Before
public void setUpSuite() throws InitializationError {
initMocks(this);
mRunNotifier = spy(new RunNotifier());
+ mArgumentsBeforeTest = InstrumentationRegistry.getArguments();
+ }
+
+ @After
+ public void restoreSuite() {
+ InstrumentationRegistry.registerInstance(
+ InstrumentationRegistry.getInstrumentation(), mArgumentsBeforeTest);
}
/** Test that profile suites with classes that aren't scenarios are rejected. */
@@ -358,4 +376,68 @@ public class ProfileSuiteTest {
.equals(thirdScenarioName)),
argThat(notifier -> notifier.equals(mRunNotifier)));
}
+
+ /** Test that extra args for a scenario are registered before tests. */
+ @Test
+ public void testExtraArgs_registeredBeforeTest() throws Throwable {
+ // Arguments with the profile under test.
+ Bundle args = new Bundle();
+ args.putString(Profile.PROFILE_OPTION_NAME, "testExtraArgs_registeredBeforeTest");
+ ProfileSuite suite =
+ new ProfileSuite(
+ SampleExtraArgsSuite.class,
+ new AllDefaultPossibilitiesBuilder(true),
+ mInstrumentation,
+ mContext,
+ args);
+ // Run the suite, which is expected to pass.
+ suite.run(mRunNotifier);
+ // If it doesn't, fire what caused the tests within the suite to fail.
+ verifyForAssertionFailures(mRunNotifier);
+ }
+
+ /** Test that extra args for a scenario are unregistered after tests. */
+ @Test
+ public void testExtraArgs_unregisteredAfterTest() throws Throwable {
+ // Arguments with the profile under test.
+ Bundle args = new Bundle();
+ args.putString(Profile.PROFILE_OPTION_NAME, "testExtraArgs_unregisteredAfterTest");
+ ProfileSuite suite =
+ new ProfileSuite(
+ SampleExtraArgsSuite.class,
+ new AllDefaultPossibilitiesBuilder(true),
+ mInstrumentation,
+ mContext,
+ args);
+ // Run the suite, which is expected to pass.
+ suite.run(mRunNotifier);
+ // If it doesn't, fire what caused the tests within the suite to fail.
+ verifyForAssertionFailures(mRunNotifier);
+ }
+
+ /**
+ * Verify that no failures are fired to the test notifier. If the verification fails, check
+ * whether it's due to assertions made in a dummy test. If yes, throw that exception out;
+ * otherwise, throw the first exception.
+ */
+ private void verifyForAssertionFailures(final RunNotifier notifier) throws Throwable {
+ try {
+ verify(notifier, never()).fireTestFailure(any());
+ } catch (MockitoAssertionError e) {
+ ArgumentCaptor<Failure> failureCaptor = ArgumentCaptor.forClass(Failure.class);
+ verify(notifier, atLeastOnce()).fireTestFailure(failureCaptor.capture());
+ List<Failure> failures = failureCaptor.getAllValues();
+ // Go through the failures, look for an known failure case from the above exceptions
+ // and throw the exception in the first one out if any.
+ for (Failure failure : failures) {
+ if (failure.getException()
+ .getMessage()
+ .contains(SampleExtraArgsSuite.ASSERTION_FAILURE_MESSAGE)) {
+ throw failure.getException();
+ }
+ }
+ // Otherwise, throw the exception from the first failure reported.
+ throw failures.get(0).getException();
+ }
+ }
}
diff --git a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScenarioRunnerTest.java b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScenarioRunnerTest.java
deleted file mode 100644
index a6f3c5012..000000000
--- a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScenarioRunnerTest.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.platform.test.longevity;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.MockitoAnnotations.initMocks;
-
-import android.os.Bundle;
-import android.platform.test.longevity.proto.Configuration.Scenario;
-import android.platform.test.longevity.proto.Configuration.Scenario.ExtraArg;
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.Assert;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.JUnit4;
-import org.junit.runners.model.InitializationError;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.exceptions.base.MockitoAssertionError;
-
-import java.util.HashSet;
-import java.util.List;
-
-/** Unit tests for the {@link ScenarioRunner} runner. */
-@RunWith(JUnit4.class)
-public class ScenarioRunnerTest {
-
- @Mock private RunNotifier mRunNotifier;
-
- private static final String ASSERTION_FAILURE_MESSAGE = "Test assertion failed";
-
- public static class ArgumentTest {
- public static final String TEST_ARG = "test-arg-test-only";
- public static final String TEST_ARG_DEFAULT = "default";
- public static final String TEST_ARG_OVERRIDE = "not default";
-
- @Before
- public void setUp() {
- // The actual argument testing happens here as this is where instrumentation args are
- // parsed in the CUJs.
- String argValue =
- InstrumentationRegistry.getArguments().getString(TEST_ARG, TEST_ARG_DEFAULT);
- Assert.assertEquals(ASSERTION_FAILURE_MESSAGE, argValue, TEST_ARG_OVERRIDE);
- }
-
- @Test
- public void dummyTest() {
- // Does nothing; always passes.
- }
- }
-
- // Holds the state of the instrumentation args before each test for restoring after, as one test
- // might affect the state of another otherwise.
- // TODO(b/124239142): Avoid manipulating the instrumentation args here.
- private Bundle mArgumentsBeforeTest;
-
- @Before
- public void setUpSuite() throws InitializationError {
- initMocks(this);
- mArgumentsBeforeTest = InstrumentationRegistry.getArguments();
- }
-
- @After
- public void restoreSuite() {
- InstrumentationRegistry.registerInstance(
- InstrumentationRegistry.getInstrumentation(), mArgumentsBeforeTest);
- }
-
- /** Test that the "extras" in a scenario is properly registered before the test. */
- @Test
- public void testExtraArgs_registeredBeforeTest() throws Throwable {
- Scenario testScenario =
- Scenario.newBuilder()
- .setIndex(1)
- .setJourney(ArgumentTest.class.getName())
- .addExtras(
- ExtraArg.newBuilder()
- .setKey(ArgumentTest.TEST_ARG)
- .setValue(ArgumentTest.TEST_ARG_OVERRIDE))
- .build();
- ScenarioRunner runner = spy(new ScenarioRunner(ArgumentTest.class, testScenario));
- runner.run(mRunNotifier);
- verifyForAssertionFailures(mRunNotifier);
- }
-
- /** Test that the "extras" in a scenario is properly un-registered after the test. */
- @Test
- public void testExtraArgs_unregisteredAfterTest() throws Throwable {
- Bundle argsBeforeTest = InstrumentationRegistry.getArguments();
- Scenario testScenario =
- Scenario.newBuilder()
- .setIndex(1)
- .setJourney(ArgumentTest.class.getName())
- .addExtras(
- ExtraArg.newBuilder()
- .setKey(ArgumentTest.TEST_ARG)
- .setValue(ArgumentTest.TEST_ARG_OVERRIDE))
- .build();
- ScenarioRunner runner = spy(new ScenarioRunner(ArgumentTest.class, testScenario));
- runner.run(mRunNotifier);
- Bundle argsAfterTest = InstrumentationRegistry.getArguments();
- Assert.assertTrue(bundlesContainSameStringKeyValuePairs(argsBeforeTest, argsAfterTest));
- }
-
- /**
- * Verify that no test failure is fired because of an assertion failure in the stubbed methods.
- * If the verification fails, check whether it's due the injected assertions failing. If yes,
- * throw that exception out; otherwise, throw the first exception.
- */
- private void verifyForAssertionFailures(final RunNotifier notifier) throws Throwable {
- try {
- verify(notifier, never()).fireTestFailure(any());
- } catch (MockitoAssertionError e) {
- ArgumentCaptor<Failure> failureCaptor = ArgumentCaptor.forClass(Failure.class);
- verify(notifier, atLeastOnce()).fireTestFailure(failureCaptor.capture());
- List<Failure> failures = failureCaptor.getAllValues();
- // Go through the failures, look for an known failure case from the above exceptions
- // and throw the exception in the first one out if any.
- for (Failure failure : failures) {
- if (failure.getException().getMessage().contains(ASSERTION_FAILURE_MESSAGE)) {
- throw failure.getException();
- }
- }
- // Otherwise, throw the exception from the first failure reported.
- throw failures.get(0).getException();
- }
- }
-
- /**
- * Helper method to check whether two {@link Bundle}s are equal since the built-in {@code
- * equals} is not properly overridden.
- */
- private boolean bundlesContainSameStringKeyValuePairs(Bundle b1, Bundle b2) {
- if (b1.size() != b2.size()) {
- return false;
- }
- HashSet<String> allKeys = new HashSet<String>(b1.keySet());
- allKeys.addAll(b2.keySet());
- for (String key : allKeys) {
- if (b1.getString(key) != null) {
- // If key is in b1 and corresponds to a string, check whether this key corresponds
- // to the same value in b2.
- if (!b1.getString(key).equals(b2.getString(key))) {
- return false;
- }
- } else if (b2.getString(key) != null) {
- // Otherwise if b2 has a string at this key, return false since we know that b1 does
- // not have a string at this key.
- return false;
- }
- }
- return true;
- }
-}
diff --git a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScheduledScenarioRunnerTest.java b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScheduledScenarioRunnerTest.java
index 78bc467c1..1e4f48f34 100644
--- a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScheduledScenarioRunnerTest.java
+++ b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/ScheduledScenarioRunnerTest.java
@@ -30,7 +30,6 @@ import static java.lang.Math.abs;
import android.os.Bundle;
import android.platform.test.longevity.proto.Configuration.Scenario;
import android.platform.test.longevity.proto.Configuration.Scenario.AfterTest;
-import android.platform.test.longevity.proto.Configuration.Scenario.ExtraArg;
import android.platform.test.longevity.samples.testing.SampleTimedProfileSuite;
import androidx.test.InstrumentationRegistry;
@@ -47,9 +46,7 @@ import org.junit.runners.model.InitializationError;
import org.junit.runners.model.TestTimedOutException;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.exceptions.base.MockitoAssertionError;
-import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -61,26 +58,6 @@ public class ScheduledScenarioRunnerTest {
private static final String ASSERTION_FAILURE_MESSAGE = "Test assertion failed";
- public static class ArgumentTest {
- public static final String TEST_ARG = "test-arg-test-only";
- public static final String TEST_ARG_DEFAULT = "default";
- public static final String TEST_ARG_OVERRIDE = "not default";
-
- @Before
- public void setUp() {
- // The actual argument testing happens here as this is where instrumentation args are
- // parsed in the CUJs.
- String argValue =
- InstrumentationRegistry.getArguments().getString(TEST_ARG, TEST_ARG_DEFAULT);
- Assert.assertEquals(ASSERTION_FAILURE_MESSAGE, argValue, TEST_ARG_OVERRIDE);
- }
-
- @Test
- public void dummyTest() {
- // Does nothing; always passes.
- }
- }
-
// Threshold above which missing the expected timing is considered a failure.
private static final long TIMING_LEEWAY_MS = 500;
@@ -317,53 +294,6 @@ public class ScheduledScenarioRunnerTest {
verify(runner, never()).performIdleBeforeNextScenario(anyLong());
}
-
- /** Test that the "extras" in a scenario is properly registered before the test. */
- @Test
- public void testExtraArgs_registeredBeforeTest() throws Throwable {
- Scenario testScenario =
- Scenario.newBuilder()
- .setAt("00:00:00")
- .setJourney(ArgumentTest.class.getName())
- .setAfterTest(AfterTest.STAY_IN_APP)
- .addExtras(
- ExtraArg.newBuilder()
- .setKey(ArgumentTest.TEST_ARG)
- .setValue(ArgumentTest.TEST_ARG_OVERRIDE))
- .build();
- ScheduledScenarioRunner runner =
- spy(
- new ScheduledScenarioRunner(
- ArgumentTest.class,
- testScenario,
- TimeUnit.SECONDS.toMillis(6),
- false));
- runner.run(mRunNotifier);
- verifyForAssertionFailures(mRunNotifier);
- }
-
- /** Test that the "extras" in a scenario is properly un-registered after the test. */
- @Test
- public void testExtraArgs_unregisteredAfterTest() throws Throwable {
- Bundle argsBeforeTest = InstrumentationRegistry.getArguments();
- Scenario testScenario =
- Scenario.newBuilder()
- .setAt("00:00:00")
- .setJourney(ArgumentTest.class.getName())
- .setAfterTest(AfterTest.STAY_IN_APP)
- .addExtras(
- ExtraArg.newBuilder()
- .setKey(ArgumentTest.TEST_ARG)
- .setValue(ArgumentTest.TEST_ARG_OVERRIDE))
- .build();
- ScheduledScenarioRunner runner =
- new ScheduledScenarioRunner(
- ArgumentTest.class, testScenario, TimeUnit.SECONDS.toMillis(6), false);
- runner.run(mRunNotifier);
- Bundle argsAfterTest = InstrumentationRegistry.getArguments();
- Assert.assertTrue(bundlesContainSameStringKeyValuePairs(argsBeforeTest, argsAfterTest));
- }
-
/** Test that suspension-aware sleep will sleep for the expected duration. */
@Test
public void testSuspensionAwareSleep_sleepsForExpectedDuration() {
@@ -395,7 +325,7 @@ public class ScheduledScenarioRunnerTest {
ScheduledScenarioRunner.TEARDOWN_LEEWAY_OPTION, String.valueOf(leewayOverride));
ScheduledScenarioRunner runner =
new ScheduledScenarioRunner(
- ArgumentTest.class,
+ ScheduledScenarioRunnerTest.class,
Scenario.newBuilder().build(),
TimeUnit.SECONDS.toMillis(6),
false,
@@ -410,54 +340,4 @@ public class ScheduledScenarioRunnerTest {
private long getWithinMarginMatcher(long expected, long margin) {
return longThat(duration -> abs(duration - expected) <= margin);
}
-
- /**
- * Verify that no test failure is fired because of an assertion failure in the stubbed methods.
- * If the verification fails, check whether it's due the injected assertions failing. If yes,
- * throw that exception out; otherwise, throw the first exception.
- */
- private void verifyForAssertionFailures(final RunNotifier notifier) throws Throwable {
- try {
- verify(notifier, never()).fireTestFailure(any());
- } catch (MockitoAssertionError e) {
- ArgumentCaptor<Failure> failureCaptor = ArgumentCaptor.forClass(Failure.class);
- verify(notifier, atLeastOnce()).fireTestFailure(failureCaptor.capture());
- List<Failure> failures = failureCaptor.getAllValues();
- // Go through the failures, look for an known failure case from the above exceptions
- // and throw the exception in the first one out if any.
- for (Failure failure : failures) {
- if (failure.getException().getMessage().contains(ASSERTION_FAILURE_MESSAGE)) {
- throw failure.getException();
- }
- }
- // Otherwise, throw the exception from the first failure reported.
- throw failures.get(0).getException();
- }
- }
-
- /**
- * Helper method to check whether two {@link Bundle}s are equal since the built-in {@code
- * equals} is not properly overridden.
- */
- private boolean bundlesContainSameStringKeyValuePairs(Bundle b1, Bundle b2) {
- if (b1.size() != b2.size()) {
- return false;
- }
- HashSet<String> allKeys = new HashSet<String>(b1.keySet());
- allKeys.addAll(b2.keySet());
- for (String key : allKeys) {
- if (b1.getString(key) != null) {
- // If key is in b1 and corresponds to a string, check whether this key corresponds
- // to the same value in b2.
- if (!b1.getString(key).equals(b2.getString(key))) {
- return false;
- }
- } else if (b2.getString(key) != null) {
- // Otherwise if b2 has a string at this key, return false since we know that b1 does
- // not have a string at this key.
- return false;
- }
- }
- return true;
- }
}
diff --git a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleExtraArgsSuite.java b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleExtraArgsSuite.java
new file mode 100644
index 000000000..648666434
--- /dev/null
+++ b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleExtraArgsSuite.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.test.longevity.samples.testing;
+
+import android.platform.test.longevity.ProfileSuite;
+import android.platform.test.scenario.annotation.Scenario;
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.runners.Suite.SuiteClasses;
+import org.junit.runners.model.Statement;
+
+@RunWith(ProfileSuite.class)
+@SuiteClasses({
+ SampleExtraArgsSuite.ClassLevelExtraArgsScenario.class,
+ SampleExtraArgsSuite.TestLevelExtraArgsScenario.class,
+ SampleExtraArgsSuite.InTestExtraArgsScenario.class,
+ SampleExtraArgsSuite.NotInInstrumentationArgsTest.class
+})
+/** A sample test suite to verify that extra args are injected before the test class starts. */
+public class SampleExtraArgsSuite {
+
+ // A string to filter out expected assertion failures in the test.
+ public static final String ASSERTION_FAILURE_MESSAGE = "Test assertion failed";
+
+ /** This test simulates a test option that is used as a {@link ClassRule}. */
+ @Scenario
+ @RunWith(JUnit4.class)
+ public static class ClassLevelExtraArgsScenario {
+ public static final String CLASS_LEVEL_OPTION = "class-level-option";
+ public static final String CLASS_LEVEL_DEFAULT = "class-level-default";
+ public static final String CLASS_LEVEL_OVERRIDE = "class-level-override";
+
+ @ClassRule
+ public static TestRule classLevelOption =
+ new TestRule() {
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ Assert.assertEquals(
+ ASSERTION_FAILURE_MESSAGE,
+ CLASS_LEVEL_OVERRIDE,
+ InstrumentationRegistry.getArguments()
+ .getString(
+ CLASS_LEVEL_OPTION, CLASS_LEVEL_DEFAULT));
+ base.evaluate();
+ }
+ };
+ }
+ };
+
+ @Test
+ public void test() {}
+ }
+
+ /** This test simulates a test option that is used as a {@link Rule}. */
+ @Scenario
+ @RunWith(JUnit4.class)
+ public static class TestLevelExtraArgsScenario {
+ public static final String TEST_LEVEL_OPTION = "test-level-option";
+ public static final String TEST_LEVEL_DEFAULT = "test-level-default";
+ public static final String TEST_LEVEL_OVERRIDE = "test-level-override";
+
+ @Rule
+ public TestRule classLevelOption =
+ new TestRule() {
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ Assert.assertEquals(
+ ASSERTION_FAILURE_MESSAGE,
+ TEST_LEVEL_OVERRIDE,
+ InstrumentationRegistry.getArguments()
+ .getString(TEST_LEVEL_OPTION, TEST_LEVEL_DEFAULT));
+ base.evaluate();
+ }
+ };
+ }
+ };
+
+ @Test
+ public void test() {}
+ }
+
+ /** This test simulates an argument that is read within a test. */
+ @Scenario
+ @RunWith(JUnit4.class)
+ public static class InTestExtraArgsScenario {
+ public static final String IN_TEST_ARG = "in-test-option";
+ public static final String IN_TEST_DEFAULT = "in-test-default";
+ public static final String IN_TEST_OVERRIDE = "in-test-override";
+
+ @Test
+ public void testArgOverride() {
+ Assert.assertEquals(
+ ASSERTION_FAILURE_MESSAGE,
+ IN_TEST_OVERRIDE,
+ InstrumentationRegistry.getArguments().getString(IN_TEST_ARG, IN_TEST_DEFAULT));
+ }
+ }
+
+ /** Tests that a particular argument is not in instrumentation args. */
+ @Scenario
+ @RunWith(JUnit4.class)
+ public static class NotInInstrumentationArgsTest {
+ public static final String ARG_TO_CHECK_OPTION = "arg-to-check";
+
+ @Test
+ public void testArgIsAbsent() {
+ String argToCheck =
+ InstrumentationRegistry.getArguments().getString(ARG_TO_CHECK_OPTION);
+ Assert.assertNotNull(ASSERTION_FAILURE_MESSAGE, argToCheck);
+ Assert.assertNull(
+ ASSERTION_FAILURE_MESSAGE,
+ InstrumentationRegistry.getArguments().getString(argToCheck));
+ }
+ }
+}
diff --git a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleTimedProfileSuite.java b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleTimedProfileSuite.java
index 16686ee95..7aefe8549 100644
--- a/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleTimedProfileSuite.java
+++ b/libraries/health/runners/longevity/platform/tests/src/android/platform/test/longevity/samples/testing/SampleTimedProfileSuite.java
@@ -20,6 +20,8 @@ import android.os.SystemClock;
import android.platform.test.longevity.ProfileSuite;
import android.platform.test.scenario.annotation.Scenario;
+import java.util.concurrent.TimeUnit;
+
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
@@ -27,8 +29,6 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.Suite.SuiteClasses;
-import java.util.concurrent.TimeUnit;
-
@RunWith(ProfileSuite.class)
@SuiteClasses({
SampleTimedProfileSuite.LongIdleTest.class,
diff --git a/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java
index fa76c10c7..78a03e8d8 100644
--- a/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java
+++ b/libraries/health/runners/microbenchmark/src/android/platform/test/microbenchmark/Microbenchmark.java
@@ -21,7 +21,6 @@ import android.platform.test.rule.TracePointRule;
import androidx.annotation.VisibleForTesting;
import androidx.test.InstrumentationRegistry;
-
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -31,13 +30,18 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.junit.internal.AssumptionViolatedException;
+import org.junit.internal.runners.model.EachTestNotifier;
+import org.junit.internal.runners.model.ReflectiveCallable;
+import org.junit.internal.runners.statements.RunAfters;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.InitializationError;
import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
+import org.junit.rules.RunRules;
/**
* The {@code Microbenchmark} runner allows you to run test methods repeatedly and with {@link
@@ -45,18 +49,22 @@ import org.junit.runners.model.Statement;
* soon to follow.
*/
public class Microbenchmark extends BlockJUnit4ClassRunner {
- private Bundle mArguments;
@VisibleForTesting static final String ITERATION_SEP_OPTION = "iteration-separator";
@VisibleForTesting static final String ITERATION_SEP_DEFAULT = "$";
// A constant to indicate that the iteration number is not set.
@VisibleForTesting static final int ITERATION_NOT_SET = -1;
public static final String RENAME_ITERATION_OPTION = "rename-iterations";
+ private static final Statement EMPTY =
+ new Statement() {
+ @Override
+ public void evaluate() throws Throwable {}
+ };
- private String mIterationSep = ITERATION_SEP_DEFAULT;
-
- private boolean mRenameIterations;
- private Map<Description, Integer> mIterations = new HashMap<>();
+ private final String mIterationSep;
+ private final Bundle mArguments;
+ private final boolean mRenameIterations;
+ private final Map<Description, Integer> mIterations = new HashMap<>();
/**
* Called reflectively on classes annotated with {@code @RunWith(Microbenchmark.class)}.
@@ -73,11 +81,11 @@ public class Microbenchmark extends BlockJUnit4ClassRunner {
super(klass);
mArguments = arguments;
// Parse out additional options.
- mRenameIterations = Boolean.valueOf(arguments.getString(RENAME_ITERATION_OPTION));
+ mRenameIterations = Boolean.parseBoolean(arguments.getString(RENAME_ITERATION_OPTION));
mIterationSep =
arguments.containsKey(ITERATION_SEP_OPTION)
? arguments.getString(ITERATION_SEP_OPTION)
- : mIterationSep;
+ : ITERATION_SEP_DEFAULT;
}
/**
@@ -136,7 +144,7 @@ public class Microbenchmark extends BlockJUnit4ClassRunner {
* tests, where collection is isolated to just the method under test. This is important for when
* {@link Before} and {@link After} methods will obscure signal reliability.
*
- * <p> Currently these are only registered from inside a test class as follows, but should soon
+ * <p>Currently these are only registered from inside a test class as follows, but should soon
* be extended for command-line support.
*
* ```
@@ -145,15 +153,32 @@ public class Microbenchmark extends BlockJUnit4ClassRunner {
* @TightMethodRule
* public ExampleRule exampleRule = new ExampleRule();
*
- * @Test
- * ...
+ * @Test ...
* }
* ```
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
- public @interface TightMethodRule { }
+ public @interface TightMethodRule {}
+ /**
+ * A temporary annotation that acts like the {@code @Before} but is excluded from metric
+ * collection.
+ *
+ * <p>This should be removed as soon as possible. Do not use this unless explicitly instructed
+ * to do so. You'll regret it!
+ *
+ * <p>Note that all {@code TestOption}s must be instantiated as {@code @ClassRule}s to work
+ * inside these annotations.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.FIELD, ElementType.METHOD})
+ public @interface NoMetricBefore {}
+
+ /** A temporary annotation, same as the above, but for replacing {@code @After} methods. */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.FIELD, ElementType.METHOD})
+ public @interface NoMetricAfter {}
/**
* Rename the child class name to add iterations if the renaming iteration option is enabled.
@@ -176,17 +201,100 @@ public class Microbenchmark extends BlockJUnit4ClassRunner {
String.valueOf(mIterations.get(original))), original.getMethodName());
}
+ /** Re-implement the private rules wrapper from {@link BlockJUnit4ClassRunner} in JUnit 4.12. */
+ private Statement withRules(FrameworkMethod method, Object target, Statement statement) {
+ Statement result = statement;
+ List<TestRule> testRules = getTestRules(target);
+ // Apply legacy MethodRules, if they don't overlap with TestRules.
+ for (org.junit.rules.MethodRule each : rules(target)) {
+ if (!testRules.contains(each)) {
+ result = each.apply(result, method, target);
+ }
+ }
+ // Apply modern, method-level TestRules in outer statements.
+ result =
+ testRules.isEmpty()
+ ? statement
+ : new RunRules(result, testRules, describeChild(method));
+ return result;
+ }
+
/**
- * Keep track of the number of iterations for a particular method and
- * set the current iteration count for changing the current description.
+ * Combine the {@code #runChild}, {@code #methodBlock}, and final {@code #runLeaf} methods to
+ * implement the specific {@code Microbenchmark} test behavior. In particular, (1) keep track of
+ * the number of iterations for a particular method description, and (2) run {@code
+ * NoMetricBefore} and {@code NoMetricAfter} methods outside of the {@code RunListener} test
+ * wrapping methods.
*/
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
+ // Update the number of iterations this method has been run.
if (mRenameIterations) {
Description original = super.describeChild(method);
mIterations.computeIfPresent(original, (k, v) -> v + 1);
mIterations.computeIfAbsent(original, k -> 1);
}
- super.runChild(method, notifier);
+
+ Description description = describeChild(method);
+ if (isIgnored(method)) {
+ notifier.fireTestIgnored(description);
+ } else {
+ EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
+
+ Object test;
+ try {
+ // Fail fast if the test is not successfully created.
+ test =
+ new ReflectiveCallable() {
+ @Override
+ protected Object runReflectiveCall() throws Throwable {
+ return createTest();
+ }
+ }.run();
+
+ // Run {@code NoMetricBefore} methods first. Fail fast if they fail.
+ for (FrameworkMethod noMetricBefore :
+ getTestClass().getAnnotatedMethods(NoMetricBefore.class)) {
+ noMetricBefore.invokeExplosively(test);
+ }
+ } catch (Throwable e) {
+ eachNotifier.fireTestStarted();
+ eachNotifier.addFailure(e);
+ eachNotifier.fireTestFinished();
+ return;
+ }
+
+ Statement statement = methodInvoker(method, test);
+ statement = possiblyExpectingExceptions(method, test, statement);
+ statement = withPotentialTimeout(method, test, statement);
+ statement = withBefores(method, test, statement);
+ statement = withAfters(method, test, statement);
+ statement = withRules(method, test, statement);
+
+ // Fire test events from inside to exclude "no metric" methods.
+ eachNotifier.fireTestStarted();
+ try {
+ statement.evaluate();
+ } catch (AssumptionViolatedException e) {
+ eachNotifier.addFailedAssumption(e);
+ } catch (Throwable e) {
+ eachNotifier.addFailure(e);
+ } finally {
+ eachNotifier.fireTestFinished();
+ }
+
+ try {
+ // Run {@code NoMetricAfter} methods last, reporting all errors.
+ List<FrameworkMethod> afters =
+ getTestClass().getAnnotatedMethods(NoMetricAfter.class);
+ if (!afters.isEmpty()) {
+ new RunAfters(EMPTY, afters, test).evaluate();
+ }
+ } catch (AssumptionViolatedException e) {
+ eachNotifier.addFailedAssumption(e);
+ } catch (Throwable e) {
+ eachNotifier.addFailure(e);
+ }
+ }
}
}
diff --git a/libraries/health/utils/src/android/platform/test/util/HealthRunnerBuilder.java b/libraries/health/utils/src/android/platform/test/util/HealthRunnerBuilder.java
index 76a23c460..ba0b3b0fc 100644
--- a/libraries/health/utils/src/android/platform/test/util/HealthRunnerBuilder.java
+++ b/libraries/health/utils/src/android/platform/test/util/HealthRunnerBuilder.java
@@ -19,12 +19,12 @@ import android.os.Bundle;
import androidx.annotation.VisibleForTesting;
import androidx.test.InstrumentationRegistry;
-import org.junit.runners.JUnit4;
+import java.lang.reflect.Constructor;
+
import org.junit.runner.Runner;
+import org.junit.runners.JUnit4;
import org.junit.runners.model.RunnerBuilder;
-import java.lang.reflect.Constructor;
-
/**
* A {@link RunnerBuilder} that enables using a specified runner to run tests in a suite.
*
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/AutoLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/AutoLauncherStrategy.java
index 869d87019..cdcd388dc 100644
--- a/libraries/launcher-helper/src/android/support/test/launcherhelper/AutoLauncherStrategy.java
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/AutoLauncherStrategy.java
@@ -42,15 +42,17 @@ public class AutoLauncherStrategy implements IAutoLauncherStrategy {
private static final String DIAL_PACKAGE = "com.android.car.dialer";
private static final String ASSISTANT_PACKAGE = "com.google.android.googlequicksearchbox";
private static final String SETTINGS_PACKAGE = "com.android.car.settings";
- private static final String APP_SWITCH_ID = "app_switch_container";
+ private static final String APP_SWITCH_ID = "car_ui_toolbar_menu_item_icon_container";
private static final String APP_LIST_ID = "apps_grid";
- private static final long APP_LAUNCH_TIMEOUT = 10000;
+ private static final long APP_LAUNCH_TIMEOUT = 30000;
private static final long UI_WAIT_TIMEOUT = 5000;
private static final long POLL_INTERVAL = 100;
- private static final BySelector UP_BTN = By.res(Pattern.compile(".*:id/page_up"));
- private static final BySelector DOWN_BTN = By.res(Pattern.compile(".*:id/page_down"));
+ private static final BySelector UP_BTN =
+ By.res(Pattern.compile(".*:id/car_ui_scrollbar_page_up"));
+ private static final BySelector DOWN_BTN =
+ By.res(Pattern.compile(".*:id/car_ui_scrollbar_page_down"));
private static final BySelector APP_SWITCH = By.res(Pattern.compile(".*:id/" + APP_SWITCH_ID));
private static final BySelector APP_LIST = By.res(Pattern.compile(".*:id/" + APP_LIST_ID));
private static final BySelector SCROLLABLE_APP_LIST =
@@ -88,7 +90,7 @@ public class AutoLauncherStrategy implements IAutoLauncherStrategy {
protected UiDevice mDevice;
private Instrumentation mInstrumentation;
- private CommandsHelper mCommandsHelper;
+ protected CommandsHelper mCommandsHelper;
/**
* {@inheritDoc}
@@ -155,7 +157,15 @@ public class AutoLauncherStrategy implements IAutoLauncherStrategy {
openMediaFacet();
// Click on app switch to open app list.
- UiObject2 appSwitch = mDevice.wait(Until.findObject(APP_SWITCH), APP_LAUNCH_TIMEOUT);
+ List<UiObject2> buttons = mDevice.wait(
+ Until.findObjects(APP_SWITCH), APP_LAUNCH_TIMEOUT);
+ int lastIndex = buttons.size() - 1;
+ /*
+ * On some media app page, there are two buttons with the same ID,
+ * while on other media app page, only the app switch button presents.
+ * The app switch button is always the last button if not the only button.
+ */
+ UiObject2 appSwitch = buttons.get(lastIndex);
if (appSwitch == null) {
throw new RuntimeException("Failed to find app switch.");
}
@@ -206,15 +216,13 @@ public class AutoLauncherStrategy implements IAutoLauncherStrategy {
/** {@inheritDoc} */
@Override
public void openNotifications() {
- String cmd = "cmd statusbar expand-notifications";
- mCommandsHelper.executeShellCommand(cmd);
+ openNotificationFacet();
}
/** {@inheritDoc} */
@Override
public void pressHome() {
- String cmd = "input keyevent KEYCODE_HOME";
- mCommandsHelper.executeShellCommand(cmd);
+ openHomeFacet();
}
/** {@inheritDoc} */
@@ -352,6 +360,12 @@ public class AutoLauncherStrategy implements IAutoLauncherStrategy {
}
}
+ @Override
+ public void openGooglePlayStore() {
+ openApp("Play Store");
+ SystemClock.sleep(APP_LAUNCH_TIMEOUT);
+ }
+
private UiObject2 findApplication(String appName) {
BySelector appSelector = By.clickable(true).hasDescendant(By.text(appName));
if (mDevice.hasObject(SCROLLABLE_APP_LIST)) {
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/IAutoLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/IAutoLauncherStrategy.java
index 731d39cfa..6c97079d6 100644
--- a/libraries/launcher-helper/src/android/support/test/launcherhelper/IAutoLauncherStrategy.java
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/IAutoLauncherStrategy.java
@@ -68,6 +68,9 @@ public interface IAutoLauncherStrategy extends ILauncherStrategy {
/** This method is to open Bluetooth Audio application */
void openBluetoothAudioApp();
+ /** This method is to open Google Play Store application */
+ void openGooglePlayStore();
+
/** Open Quick Settings. */
void openQuickSettings();
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/VolvoLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/VolvoLauncherStrategy.java
index 695a9b26c..d0cac6148 100644
--- a/libraries/launcher-helper/src/android/support/test/launcherhelper/VolvoLauncherStrategy.java
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/VolvoLauncherStrategy.java
@@ -22,6 +22,7 @@ import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
+import android.system.helpers.CommandsHelper;
import java.util.Map;
import java.util.stream.Collectors;
@@ -59,6 +60,7 @@ public class VolvoLauncherStrategy extends AutoLauncherStrategy {
protected UiDevice mDevice;
private Instrumentation mInstrumentation;
+ private CommandsHelper mCommandsHelper;
@Override
public String getSupportedLauncherPackage() {
@@ -74,6 +76,7 @@ public class VolvoLauncherStrategy extends AutoLauncherStrategy {
public void setInstrumentation(Instrumentation instrumentation) {
super.setInstrumentation(instrumentation);
mInstrumentation = instrumentation;
+ mCommandsHelper = CommandsHelper.getInstance(mInstrumentation);
}
@Override
@@ -100,6 +103,17 @@ public class VolvoLauncherStrategy extends AutoLauncherStrategy {
}
@Override
+ public void openGooglePlayStore() {
+ mDevice.pressHome();
+ mDevice.waitForIdle();
+ mCommandsHelper.executeShellCommand(
+ "am start -a android.intent.action.MAIN "
+ + "-c android.intent.category.LAUNCHER "
+ + "-n com.android.vending/"
+ + "com.google.android.finsky.carmainactivity.MainActivity");
+ }
+
+ @Override
public boolean checkApplicationExists(String appName) {
openAppGridFacet();
UiObject2 app = findApplication(appName);
@@ -151,4 +165,18 @@ public class VolvoLauncherStrategy extends AutoLauncherStrategy {
BySelector appSelector = By.clickable(true).hasDescendant(By.text(appName));
return mDevice.findObject(appSelector);
}
+
+ /** {@inheritDoc} */
+ @Override
+ public void openNotifications() {
+ String cmd = "cmd statusbar expand-notifications";
+ mCommandsHelper.executeShellCommand(cmd);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void pressHome() {
+ String cmd = "input keyevent KEYCODE_HOME";
+ mCommandsHelper.executeShellCommand(cmd);
+ }
}
diff --git a/libraries/system-helpers/OWNERS b/libraries/system-helpers/OWNERS
new file mode 100644
index 000000000..48b311359
--- /dev/null
+++ b/libraries/system-helpers/OWNERS
@@ -0,0 +1,2 @@
+#SystemUI
+include platform/frameworks/base:/packages/SystemUI/OWNERS
diff --git a/libraries/system-helpers/settings-helper/src/android/system/helpers/SettingsHelper.java b/libraries/system-helpers/settings-helper/src/android/system/helpers/SettingsHelper.java
index f8fb83a73..68fa85856 100644
--- a/libraries/system-helpers/settings-helper/src/android/system/helpers/SettingsHelper.java
+++ b/libraries/system-helpers/settings-helper/src/android/system/helpers/SettingsHelper.java
@@ -52,6 +52,7 @@ public class SettingsHelper {
private static final String TAG = SettingsHelper.class.getSimpleName();
private static final String ANDROID_PACKAGE = "android";
private static final String SETTINGS_PACKAGE = "com.android.settings";
+ private static final String SETTINGS_PKG_SEARCH = "com.google.android.settings.intelligence";
private static final String SETTINGS_APP = "Settings";
private static final String SWITCH_WIDGET = "switch_widget";
private static final String WIFI = "Wi-Fi";
@@ -67,7 +68,8 @@ public class SettingsHelper {
private static final String ACTION_SEARCH = "com.android.settings.action.SETTINGS_SEARCH";
private static final String NO_RESULT_QUERY = "no_result_query";
private static final String RES_ID_SEARCH_UI_TEXT_BOX = "search_src_text";
- private static final String RES_ID_SEARCH_UI_NO_RESULT_IMAGE = "no_result_layout";
+ private static final String RES_ID_SEARCH_UI_EDIT_TEXT_BOX = "open_search_view_edit_text";
+ private static final String RES_ID_SEARCH_UI_NO_RESULT_IMAGE = "no_results_layout_v2";
private static final UiSelector LIST_ITEM_VALUE =
new UiSelector().className(TextView.class);
@@ -109,12 +111,19 @@ public class SettingsHelper {
public void performNoResultQuery() {
final String randomQuery = NO_RESULT_QUERY + new Random().nextInt();
- mDevice.wait(Until.findObject(By.res(ANDROID_PACKAGE, RES_ID_SEARCH_UI_TEXT_BOX)), TIMEOUT)
+ mDevice.wait(
+ Until.findObject(
+ By.res(SETTINGS_PKG_SEARCH, RES_ID_SEARCH_UI_EDIT_TEXT_BOX)),
+ TIMEOUT)
.setText(randomQuery);
- mDevice.wait(Until.hasObject(By.res(RES_ID_SEARCH_UI_NO_RESULT_IMAGE)),
+ mDevice.wait(
+ Until.hasObject(By.res(SETTINGS_PKG_SEARCH, RES_ID_SEARCH_UI_NO_RESULT_IMAGE)),
TIMEOUT);
- mDevice.wait(Until.findObject(By.res(ANDROID_PACKAGE, RES_ID_SEARCH_UI_TEXT_BOX)), TIMEOUT)
+ mDevice.wait(
+ Until.findObject(
+ By.res(SETTINGS_PKG_SEARCH, RES_ID_SEARCH_UI_EDIT_TEXT_BOX)),
+ TIMEOUT)
.clear();
}
diff --git a/scripts/perf-setup/angler-setup.sh b/scripts/perf-setup/angler-setup.sh
deleted file mode 100755
index cd0118461..000000000
--- a/scripts/perf-setup/angler-setup.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-if [[ "`id -u`" -ne "0" ]]; then
- echo "WARNING: running as non-root, proceeding anyways..."
-fi
-
-stop thermal-engine
-stop perfd
-
-cpubase=/sys/devices/system/cpu
-gov=cpufreq/scaling_governor
-
-cpu=0
-S=960000
-while [ $((cpu < 4)) -eq 1 ]; do
- echo 1 > $cpubase/cpu${cpu}/online
- echo userspace > $cpubase/cpu${cpu}/$gov
- echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_max_freq
- echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_min_freq
- echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_setspeed
- cpu=$(($cpu + 1))
-done
-
-echo -n 0 > /sys/devices/system/cpu/cpu4/online
-echo -n 0 > /sys/devices/system/cpu/cpu5/online
-echo -n 0 > /sys/devices/system/cpu/cpu6/online
-echo -n 0 > /sys/devices/system/cpu/cpu7/online
-
-echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split
-echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on
-echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer
-
-echo 11863 > /sys/class/devfreq/qcom,gpubw.70/min_freq
-
-echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor
-echo 305000000 > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
-echo 305000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
-
-echo 4 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel
-echo 4 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
-
diff --git a/scripts/perf-setup/b1c1-setup.sh b/scripts/perf-setup/b1c1-setup.sh
index 77c3ae2b6..aa57d857a 100755
--- a/scripts/perf-setup/b1c1-setup.sh
+++ b/scripts/perf-setup/b1c1-setup.sh
@@ -18,6 +18,7 @@
stop vendor.thermal-engine
setprop vendor.powerhal.init 0
+setprop ctl.restart vendor.power-hal-aidl
setprop ctl.interface_restart android.hardware.power@1.0::IPower/default
cpubase=/sys/devices/system/cpu
diff --git a/scripts/perf-setup/b4s4-setup.sh b/scripts/perf-setup/b4s4-setup.sh
index c7498e48c..a1aab6bd1 100755
--- a/scripts/perf-setup/b4s4-setup.sh
+++ b/scripts/perf-setup/b4s4-setup.sh
@@ -18,6 +18,7 @@
stop vendor.thermal-engine
setprop vendor.powerhal.init 0
+setprop ctl.restart vendor.power-hal-aidl
setprop ctl.interface_restart android.hardware.power@1.0::IPower/default
cpubase=/sys/devices/system/cpu
diff --git a/scripts/perf-setup/bullhead-setup.sh b/scripts/perf-setup/bullhead-setup.sh
deleted file mode 100644
index dfecb7df4..000000000
--- a/scripts/perf-setup/bullhead-setup.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-if [[ "`id -u`" -ne "0" ]]; then
- echo "WARNING: running as non-root, proceeding anyways..."
-fi
-
-stop thermal-engine
-stop perfd
-
-cpubase=/sys/devices/system/cpu
-gov=cpufreq/scaling_governor
-
-cpu=0
-S=960000
-while [ $((cpu < 4)) -eq 1 ]; do
- echo 1 > $cpubase/cpu${cpu}/online
- echo userspace > $cpubase/cpu${cpu}/$gov
- echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_max_freq
- echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_min_freq
- echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_setspeed
- cpu=$(($cpu + 1))
-done
-
-echo -n 0 > /sys/devices/system/cpu/cpu4/online
-echo -n 0 > /sys/devices/system/cpu/cpu5/online
-
-echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split
-echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on
-echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer
-
-echo 7102 > /sys/class/devfreq/qcom,gpubw.19/min_freq
-
-echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor
-echo 300000000 > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
-echo 300000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
-
-echo 4 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel
-echo 4 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
diff --git a/scripts/perf-setup/c2f2-setup.sh b/scripts/perf-setup/c2f2-setup.sh
index d83cef4ed..13a3ca488 100755
--- a/scripts/perf-setup/c2f2-setup.sh
+++ b/scripts/perf-setup/c2f2-setup.sh
@@ -18,6 +18,7 @@
stop vendor.thermal-engine
setprop vendor.powerhal.init 0
+setprop ctl.restart vendor.power-hal-aidl
setprop ctl.interface_restart android.hardware.power@1.0::IPower/default
cpubase=/sys/devices/system/cpu
diff --git a/scripts/perf-setup/dragon-setup.sh b/scripts/perf-setup/dragon-setup.sh
deleted file mode 100755
index 7a50a1620..000000000
--- a/scripts/perf-setup/dragon-setup.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-# performance testing setup script for dragon device
-
-if [[ "`id -u`" -ne "0" ]]; then
- echo "WARNING: running as non-root, proceeding anyways..."
-fi
-
-# locking CPU frequency
-
-# note: locking cpu0 is sufficent to cover other cores as well
-echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
-echo 1530000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
-echo 1530000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
-echo 1530000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
-
-# locking GPU frequency
-
-# note: frequency choices can be found in:
-# cat /sys/class/drm/card0/device/pstate
-
-# select 768 MHz
-# 0a: core 768 MHz emc 1600 MHz
-echo 0a > /sys/class/drm/card0/device/pstate
diff --git a/scripts/perf-setup/sailin-setup.sh b/scripts/perf-setup/sailin-setup.sh
deleted file mode 100644
index 4a7a33ddf..000000000
--- a/scripts/perf-setup/sailin-setup.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#Setup for newer devices
-
-if [[ "`id -u`" -ne "0" ]]; then
- echo "WARNING: running as non-root, proceeding anyways..."
-fi
-
-stop thermal-engine
-stop perfd
-stop vendor.thermal-engine
-stop vendor.perfd
-
-echo 0 > /sys/devices/system/cpu/cpu0/online
-echo 0 > /sys/devices/system/cpu/cpu1/online
-
-echo performance > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor
-echo 2150400 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq
-
-echo 13763 > /sys/class/devfreq/soc:qcom,gpubw/max_freq
-echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor
-echo -n 624000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
diff --git a/scripts/perfetto-setup/Android.mk b/scripts/perfetto-setup/Android.mk
index a742eea8d..ab478ecbb 100644
--- a/scripts/perfetto-setup/Android.mk
+++ b/scripts/perfetto-setup/Android.mk
@@ -46,3 +46,13 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp
LOCAL_PREBUILT_MODULE_FILE := prebuilts/tools/linux-x86_64/perfetto/configs/trace_config_experimental.textproto
include $(BUILD_PREBUILT)
+include $(CLEAR_VARS)
+LOCAL_MODULE := perfetto_trace_processor_shell
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp
+LOCAL_CHECK_ELF_FILES := false
+LOCAL_PREBUILT_MODULE_FILE := prebuilts/tools/linux-x86_64/perfetto/trace_processor_shell
+include $(BUILD_PREBUILT)
+
+
diff --git a/tests/functional/devicehealthchecks/Android.bp b/tests/functional/devicehealthchecks/Android.bp
index 295b5ec11..c407d96e4 100644
--- a/tests/functional/devicehealthchecks/Android.bp
+++ b/tests/functional/devicehealthchecks/Android.bp
@@ -21,7 +21,8 @@ android_test {
sdk_version: "current",
certificate: "platform",
static_libs: [
- "android-support-test",
+ "androidx.test.rules",
+ "androidx.test.runner",
"platform-test-annotations",
],
diff --git a/tests/functional/devicehealthchecks/AndroidManifest.xml b/tests/functional/devicehealthchecks/AndroidManifest.xml
index 597bc2156..1a57e13ea 100644
--- a/tests/functional/devicehealthchecks/AndroidManifest.xml
+++ b/tests/functional/devicehealthchecks/AndroidManifest.xml
@@ -16,18 +16,16 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.devicehealthchecks"
- android:sharedUserId="com.android.devicehealthchecks"
+ android:sharedUserId="android.uid.system"
android:versionCode="1"
android:versionName="1.0" >
- <uses-permission android:name="android.permission.READ_LOGS" />
-
<uses-sdk
android:minSdkVersion="22"
android:targetSdkVersion="25" />
<instrumentation
- android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.devicehealthchecks" />
<application>
diff --git a/tests/functional/devicehealthchecks/AndroidTest.xml b/tests/functional/devicehealthchecks/AndroidTest.xml
index 594a510e9..e3a211a0a 100644
--- a/tests/functional/devicehealthchecks/AndroidTest.xml
+++ b/tests/functional/devicehealthchecks/AndroidTest.xml
@@ -21,6 +21,5 @@
<option name="test-tag" value="DeviceHealthChecks" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.devicehealthchecks" />
- <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
</test>
</configuration>
diff --git a/tests/functional/devicehealthchecks/assets/bug_map b/tests/functional/devicehealthchecks/assets/bug_map
new file mode 100644
index 000000000..b6173492b
--- /dev/null
+++ b/tests/functional/devicehealthchecks/assets/bug_map
@@ -0,0 +1,21 @@
+<test_name> <regex.no.spaces> <only_bug_number>
+system_app_anr com.google.android.googlequicksearchbox:search 151164399
+system_app_anr com.google.oslo/.service.OsloService 159025912
+system_app_anr com.google.android.as/com.google.android.apps.miphone.aiai.common.superpacks.impl.AiAiSuperpacksService 159058706
+system_app_anr act=android.telephony.action.CARRIER_CONFIG_CHANGED 159921750
+system_app_crash -1\|android\|26\|null\|1000 155073214
+system_app_crash -1\|android\|32\|null\|1000 155073214
+system_app_crash android.database.sqlite.SQLiteCantOpenDatabaseException: 150248286
+system_app_crash com.android.vending:download_service 153462682
+system_app_crash pzd.a.:com.google.android.gms@ 145798275
+system_app_crash com.android.service.ims.RcsService.registerImsCallbacksAndSetAssociatedSubscription 156402275
+system_app_crash com.google.android.inputmethod.latin 157051520
+system_app_crash com.android.vending/com.google.android.finsky.verifier.impl.PackageVerificationService 156670156
+system_app_crash com.google.android.apps.youtube.music.mediabrowser.MusicBrowserService.a 157917208
+system_app_crash android.database.sqlite.SQLiteCloseable.acquireReference 159658068
+system_app_native_crash com.google.android.apps.safetyhub 154358781
+system_app_native_crash com.google.android.providers.media.module 154416156
+system_server_crash void.com.android.server.location.gnss.GnssBatchingProvider.enable 159504970
+SYSTEM_TOMBSTONE android.hardware.vibrator-service.drv2624 151884322
+SYSTEM_TOMBSTONE /vendor/bin/hw/android.hardware.gnss@1.0-service-qti 129282808
+SYSTEM_TOMBSTONE /system/product/priv-app/SafetyHubLprPrebuilt/SafetyHubLprPrebuilt.apk 158504050
diff --git a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheckBase.java b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheckBase.java
index e020da3dd..69119bee1 100644
--- a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheckBase.java
+++ b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheckBase.java
@@ -17,12 +17,23 @@ package com.android.devicehealthchecks;
import android.content.Context;
import android.os.DropBoxManager;
-import android.support.test.InstrumentationRegistry;
+import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
+import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Assert;
import org.junit.Before;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
abstract class CrashCheckBase {
private static final int MAX_DROPBOX_READ = 4096; // read up to 4K from a dropbox entry
@@ -32,15 +43,19 @@ abstract class CrashCheckBase {
private Context mContext;
private KnownFailures mKnownFailures = new KnownFailures();
/** whether known failures should be reported anyways, useful for bug investigation */
- private boolean mIncludeKnownFailures;
+ private boolean mIncludeKnownFailures = false;
+ private List<String> failures = new ArrayList<>();
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
- mIncludeKnownFailures = InstrumentationRegistry.getArguments().getBoolean(
- INCLUDE_KNOWN_FAILURES, false);
-
+ Bundle bundle = InstrumentationRegistry.getArguments();
+ mIncludeKnownFailures = TextUtils.equals("true", bundle.getString(INCLUDE_KNOWN_FAILURES));
+ if (!mIncludeKnownFailures) {
+ Log.i(LOG_TAG, "Will ignore known failures, populating known failure list");
+ populateKnownFailures();
+ }
}
/**
@@ -64,9 +79,11 @@ abstract class CrashCheckBase {
}
KnownFailureItem k = mKnownFailures.findMatchedKnownFailure(label, dropboxSnippet);
if (k != null && !mIncludeKnownFailures) {
- Log.i(LOG_TAG, String.format(
- "Ignored a known failure, type: %s, pattern: %s, bug: %s",
- label, k.failurePattern, k.bugNumber));
+ Log.i(
+ LOG_TAG,
+ String.format(
+ "Ignored a known failure, type: %s, pattern: %s, bug: b/%s",
+ label, k.failurePattern, k.bugNumber));
} else {
crashCount++;
errorDetails.append(label);
@@ -100,4 +117,44 @@ abstract class CrashCheckBase {
}
return ret.toString();
}
+
+ /** Parse known failure file and add to the list of known failures */
+ private void populateKnownFailures() {
+
+ try {
+ BufferedReader reader =
+ new BufferedReader(
+ new InputStreamReader(
+ mContext.getAssets().open("bug_map"), StandardCharsets.UTF_8));
+ while (reader.ready()) {
+ failures = Arrays.asList(reader.readLine());
+
+ for (String bug : failures) {
+ Log.i(LOG_TAG, String.format("ParsedFile: %s", bug));
+
+ List<String> split_bug = Arrays.asList(bug.split(" "));
+
+ if (split_bug.size() != 3) {
+ Log.e(
+ LOG_TAG,
+ String.format(
+ "bug_map file splits lines using space, please correct: %s",
+ bug));
+ } else {
+ String dropbox_label = split_bug.get(0);
+ Pattern pattern = Pattern.compile(split_bug.get(1), Pattern.MULTILINE);
+ String bug_id = split_bug.get(2);
+ Log.i(
+ LOG_TAG,
+ String.format(
+ "Adding failure b/%s to test: %s", bug_id, dropbox_label));
+
+ mKnownFailures.addKnownFailure(dropbox_label, pattern, bug_id);
+ }
+ }
+ }
+ } catch (IOException | NullPointerException e) {
+ e.printStackTrace();
+ }
+ }
}
diff --git a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/KnownFailures.java b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/KnownFailures.java
index 8a7039dde..efd25247c 100644
--- a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/KnownFailures.java
+++ b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/KnownFailures.java
@@ -28,23 +28,6 @@ import java.util.regex.Pattern;
public class KnownFailures {
private Map<String, List<KnownFailureItem>> mKnownFailures = new HashMap<>();
- {
- // add known failures per dropbox label below:
- // Example:
- // addKnownFailure(
- // "system_app_anr", // dropbox label
- // Pattern.compile("^.*Process:.*com\\.google\\.android\\.googlequicksearchbox"
- // + ":search.*$", Pattern.MULTILINE), // regex pattern
- // "73254069"); // bug number
- // add known failures for additional dropbox labels here
- // It's recommended to use multiline matching and a snippet will be matched if it's found
- // to contain the pattern described by regex
- addKnownFailure(
- "system_app_crash", // dropbox label
- Pattern.compile("^.*Process:.*com\\.android\\.vending.*$",
- Pattern.MULTILINE), // regex pattern
- "77533385"); // bug number
- }
/**
* Convenience method to add a known failure to list
@@ -53,6 +36,14 @@ public class KnownFailures {
* @param bugNumber
*/
public void addKnownFailure(String dropboxLabel, Pattern pattern, String bugNumber) {
+ // Example:
+ // addKnownFailure(
+ // "system_app_anr", // dropbox label
+ // Pattern.compile("^.*Process:.*com\\.google\\.android\\.googlequicksearchbox"
+ // + ":search.*$", Pattern.MULTILINE), // regex pattern
+ // "73254069"); // bug number
+ // It's recommended to use multiline matching and a snippet will be matched if it's found
+ // to contain the pattern described by regex
List<KnownFailureItem> knownFailures = mKnownFailures.get(dropboxLabel);
if (knownFailures == null) {
knownFailures = new ArrayList<>();
diff --git a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/MediaBootCheck.java b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/MediaBootCheck.java
new file mode 100644
index 000000000..419f18cf7
--- /dev/null
+++ b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/MediaBootCheck.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.devicehealthchecks;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/*
+ * Tests used for basic media validation after the device boot is completed.
+ * This test is used for global presubmit.
+ */
+// TODO: @GlobalPresubmit
+public class MediaBootCheck {
+ /*
+ * Test if codecs are listed and instantiable.
+ */
+ @Test
+ public void checkCodecList() throws Exception {
+ /*
+ * This is a simple test that checks the following:
+ * 1) MediaCodecList is not empty
+ * 2) The codecs listed can be created
+ */
+ MediaCodecList list = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ MediaCodecInfo[] infos = list.getCodecInfos();
+ Assert.assertTrue("MediaCodecList should not be empty", infos.length > 0);
+ for (MediaCodecInfo info : infos) {
+ MediaCodec codec = null;
+ try {
+ codec = MediaCodec.createByCodecName(info.getName());
+ // Basic checks.
+ Assert.assertEquals(codec.getName(), info.getName());
+ Assert.assertEquals(codec.getCanonicalName(), info.getCanonicalName());
+ } finally {
+ if (codec != null) {
+ codec.release();
+ }
+ }
+ }
+ }
+}
diff --git a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SensorsBootCheck.java b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SensorsBootCheck.java
index 93a623fe8..c4c1a617d 100644
--- a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SensorsBootCheck.java
+++ b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SensorsBootCheck.java
@@ -20,11 +20,11 @@ import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.platform.test.annotations.GlobalPresubmit;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
import org.junit.Assert;
import org.junit.Before;
-import org.junit.runner.RunWith;
import org.junit.Test;
/*
diff --git a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SystemAppCheck.java b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SystemAppCheck.java
new file mode 100644
index 000000000..78a8a7409
--- /dev/null
+++ b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SystemAppCheck.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.devicehealthchecks;
+
+import android.platform.test.annotations.GlobalPresubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests used for basic device system app health validation after the device boot is completed. This
+ * test class can be used to add more tests in the future for additional basic device system app
+ * health validation after the device boot is completed. This test is used for global presubmit, any
+ * dropbox label checked showing failures must be resolved immediately, or have corresponding tests
+ * filtered out.
+ */
+@GlobalPresubmit
+@RunWith(AndroidJUnit4.class)
+public class SystemAppCheck extends CrashCheckBase {
+
+ @Test
+ public void system_app_crash() {
+ checkCrash("system_app_crash");
+ }
+
+ @Test
+ public void system_app_native_crash() {
+ checkCrash("system_app_native_crash");
+ }
+
+ @Test
+ public void system_app_anr() {
+ checkCrash("system_app_anr");
+ }
+}
diff --git a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheck.java b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SystemCheck.java
index 286033801..5637216c3 100644
--- a/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/CrashCheck.java
+++ b/tests/functional/devicehealthchecks/src/com/android/devicehealthchecks/SystemCheck.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,23 @@
package com.android.devicehealthchecks;
import android.platform.test.annotations.GlobalPresubmit;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
+import org.junit.Ignore;
import org.junit.runner.RunWith;
/**
- * Tests used for basic device health validation after the device boot is completed. This test class
- * can be used to add more tests in the future for additional basic device health validation after
- * the device boot is completed. This test is used for global presubmit, any dropbox label checked
- * showing failures must be resolved immediately, or have corresponding tests filtered out. */
+ * Tests used for basic device system health validation after the device boot is completed. This
+ * test class can be used to add more tests in the future for additional basic device system health
+ * validation after the device boot is completed. This test is used for global presubmit, any
+ * dropbox label checked showing failures must be resolved immediately, or have corresponding tests
+ * filtered out.
+ */
@GlobalPresubmit
@RunWith(AndroidJUnit4.class)
-public class CrashCheck extends CrashCheckBase {
+public class SystemCheck extends CrashCheckBase {
@Test
public void system_server_crash() {
@@ -46,21 +50,6 @@ public class CrashCheck extends CrashCheckBase {
}
@Test
- public void system_app_crash() {
- checkCrash("system_app_crash");
- }
-
- @Test
- public void system_app_native_crash() {
- checkCrash("system_app_native_crash");
- }
-
- @Test
- public void system_app_anr() {
- checkCrash("system_app_anr");
- }
-
- @Test
public void system_tombstone() {
checkCrash("SYSTEM_TOMBSTONE");
}
diff --git a/tests/functional/notificationtests/src/com/android/notification/functional/HeadsUpNotificationTests.java b/tests/functional/notificationtests/src/com/android/notification/functional/HeadsUpNotificationTests.java
index 45be5f838..75054c9ad 100644
--- a/tests/functional/notificationtests/src/com/android/notification/functional/HeadsUpNotificationTests.java
+++ b/tests/functional/notificationtests/src/com/android/notification/functional/HeadsUpNotificationTests.java
@@ -86,6 +86,22 @@ public class HeadsUpNotificationTests extends InstrumentationTestCase {
}
@MediumTest
+ public void testHeadsUpNotificationUpdate() throws Exception {
+ // GIVEN a HeadsUp notification is posted and
+ mHelper.sendNotificationsWithInlineReply(NOTIFICATION_ID_1, true);
+
+ // WHEN the HUN is immediately updated multiple times
+ mHelper.sendNotificationsWithInlineReply(NOTIFICATION_ID_1, true);
+ mHelper.sendNotificationsWithInlineReply(NOTIFICATION_ID_1, true);
+ mHelper.sendNotificationsWithInlineReply(NOTIFICATION_ID_1, true);
+
+ // THEN we still see the HUN
+ UiObject2 obj =
+ mDevice.wait(Until.findObject(By.text(NOTIFICATION_CONTENT_TEXT)), LONG_TIMEOUT);
+ assertNotNull(String.format("Notification %s did not HUN", NOTIFICATION_ID_1), obj);
+ }
+
+ @MediumTest
public void testHeadsUpNotificationManualDismiss() throws Exception {
mHelper.sendNotificationsWithInlineReply(NOTIFICATION_ID_1, true);
Thread.sleep(SHORT_TIMEOUT);
@@ -100,10 +116,18 @@ public class HeadsUpNotificationTests extends InstrumentationTestCase {
@LargeTest
public void testHeadsUpNotificationAutoDismiss() throws Exception {
+ // WHEN a HUN is posted
mHelper.sendNotificationsWithInlineReply(NOTIFICATION_ID_1, true);
- Thread.sleep(LONG_TIMEOUT * 3);
+
+ // THEN we see the HUN
+ Thread.sleep(SHORT_TIMEOUT);
UiObject2 obj = mDevice.wait(Until.findObject(By.text(NOTIFICATION_CONTENT_TEXT)),
LONG_TIMEOUT);
+ assertNotNull(String.format("Notification %s did not HUN", NOTIFICATION_ID_1), obj);
+
+ // THEN we see the HUN auto dismissed
+ Thread.sleep(LONG_TIMEOUT * 3);
+ obj = mDevice.wait(Until.findObject(By.text(NOTIFICATION_CONTENT_TEXT)), SHORT_TIMEOUT);
assertNull(String.format("Notification %s has not been auto dismissed", NOTIFICATION_ID_1),
obj);
}
@@ -125,10 +149,7 @@ public class HeadsUpNotificationTests extends InstrumentationTestCase {
Thread.sleep(LONG_TIMEOUT);
UiObject2 obj = mDevice.wait(Until.findObject(By.text(NOTIFICATION_CONTENT_TEXT)),
LONG_TIMEOUT);
- if (obj == null) {
- assertNull(String.format("Notification %s can not be found", NOTIFICATION_ID_1),
- obj);
- }
+ assertNotNull(String.format("Notification %s can not be found", NOTIFICATION_ID_1), obj);
}
@LargeTest
@@ -137,7 +158,7 @@ public class HeadsUpNotificationTests extends InstrumentationTestCase {
setAlarmNow();
UiObject2 obj = mDevice.wait(Until.findObject(By.text("test")), 60000);
if (obj == null) {
- fail("Alarm heads up notifcation is not working");
+ fail("Alarm heads up notification is not working");
}
} finally {
mDevice.wait(Until.findObject(By.text("Dismiss")), LONG_TIMEOUT).click();
diff --git a/tests/health/scenarios/Android.bp b/tests/health/scenarios/Android.bp
index a20135e45..bdab489eb 100644
--- a/tests/health/scenarios/Android.bp
+++ b/tests/health/scenarios/Android.bp
@@ -20,7 +20,6 @@ java_library_static {
"androidx.test.runner",
"app-helpers-handheld-interfaces",
"handheld-app-helpers",
- "junit",
"platform-test-options",
"platform-test-rules",
"ub-uiautomator",
diff --git a/tests/health/scenarios/src/android/platform/test/scenario/annotation/FixedApp.java b/tests/health/scenarios/src/android/platform/test/scenario/annotation/FixedApp.java
new file mode 100644
index 000000000..f12c1f96a
--- /dev/null
+++ b/tests/health/scenarios/src/android/platform/test/scenario/annotation/FixedApp.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.test.scenario.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Identifies a scenario for use with fixed apps. */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface FixedApp {}
diff --git a/tests/health/scenarios/src/android/platform/test/scenario/sample/PrintListener.java b/tests/health/scenarios/src/android/platform/test/scenario/sample/PrintListener.java
new file mode 100644
index 000000000..442972871
--- /dev/null
+++ b/tests/health/scenarios/src/android/platform/test/scenario/sample/PrintListener.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.platform.test.scenario.sample;
+
+import android.util.Log;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+/** A {@link RunListener} that prints the methods it executes. */
+public class PrintListener extends RunListener {
+
+ private static final String LOG_TAG = SampleTest.LOG_TAG;
+
+ @Override
+ public void testRunStarted(Description description) throws Exception {
+ Log.d(LOG_TAG, "RunListener#testRunStarted");
+ }
+
+ @Override
+ public void testRunFinished(Result result) throws Exception {
+ Log.d(LOG_TAG, "RunListener#testRunFinished");
+ }
+
+ @Override
+ public void testStarted(Description description) throws Exception {
+ Log.d(LOG_TAG, "RunListener#testStarted");
+ }
+
+ @Override
+ public void testFinished(Description description) throws Exception {
+ Log.d(LOG_TAG, "RunListener#testFinished");
+ }
+
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ Log.d(LOG_TAG, "RunListener#testFailure");
+ }
+
+ @Override
+ public void testAssumptionFailure(Failure failure) {
+ Log.d(LOG_TAG, "RunListener#testAssumptionFailure");
+ }
+
+ @Override
+ public void testIgnored(Description description) throws Exception {
+ Log.d(LOG_TAG, "RunListener#testIgnored");
+ }
+}
diff --git a/tests/health/scenarios/src/android/platform/test/scenario/sample/SampleTest.java b/tests/health/scenarios/src/android/platform/test/scenario/sample/SampleTest.java
new file mode 100644
index 000000000..03e8a0725
--- /dev/null
+++ b/tests/health/scenarios/src/android/platform/test/scenario/sample/SampleTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.platform.test.scenario.sample;
+
+import android.util.Log;
+import android.platform.test.option.BooleanOption;
+import android.platform.test.rule.TestWatcher;
+import android.platform.test.scenario.annotation.Scenario;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * A test showcasing the order of execution for different components of standard JUnit 4 test.
+ *
+ * <p>Run this test with the listener alongside, {@link PrintListener}, to see how they interact.
+ */
+@Scenario
+@RunWith(JUnit4.class)
+public class SampleTest {
+
+ public static final String LOG_TAG = SampleTest.class.getSimpleName();
+
+ // Class-level rules
+ @ClassRule
+ public static RuleChain atClassRules =
+ RuleChain.outerRule(new PrintRule("@ClassRule #1"))
+ .around(new PrintRule("@ClassRule #2"))
+ .around(new PrintRule("@ClassRule #3"));
+
+ // Method-level rules
+ @Rule
+ public RuleChain atRules =
+ RuleChain.outerRule(new PrintRule("@Rule #1"))
+ .around(new PrintRule("@Rule #2"))
+ .around(new PrintRule("@Rule #3"));
+
+ @ClassRule
+ public static BooleanOption failBeforeClass =
+ new BooleanOption("fail-before-class").setRequired(false).setDefault(false);
+
+ @Rule
+ public BooleanOption failBefore =
+ new BooleanOption("fail-before").setRequired(false).setDefault(false);
+
+ @Rule
+ public BooleanOption failTest =
+ new BooleanOption("fail-test").setRequired(false).setDefault(false);
+
+ @Rule
+ public BooleanOption failAfter =
+ new BooleanOption("fail-after").setRequired(false).setDefault(false);
+
+ @ClassRule
+ public static BooleanOption failAfterClass =
+ new BooleanOption("fail-after-class").setRequired(false).setDefault(false);
+
+ @BeforeClass
+ public static void beforeClassMethod() {
+ failIfRequested(failBeforeClass, "@BeforeClass");
+ Log.d(LOG_TAG, "@BeforeClass");
+ }
+
+ @Before
+ public void beforeMethod() {
+ failIfRequested(failBefore, "@Before");
+ Log.d(LOG_TAG, "@Before");
+ }
+
+ @Test
+ public void testMethod() {
+ failIfRequested(failTest, "@Test");
+ Log.d(LOG_TAG, "@Test");
+ }
+
+ @After
+ public void afterMethod() {
+ failIfRequested(failAfter, "@After");
+ Log.d(LOG_TAG, "@After");
+ }
+
+ @AfterClass
+ public static void afterClassMethod() {
+ failIfRequested(failAfterClass, "@AfterClass");
+ Log.d(LOG_TAG, "@AfterClass");
+ }
+
+ /** Log and throw a failure if the provided {@code option} is set. */
+ public static void failIfRequested(BooleanOption option, String location) {
+ if (option.get()) {
+ String message = String.format("Failed %s", location);
+ Log.d(LOG_TAG, message);
+ throw new RuntimeException(message);
+ }
+ }
+
+ /** A {@link TestWatcher} that prints the methods it executes. */
+ private static class PrintRule extends TestWatcher {
+
+ private String mTag;
+
+ public PrintRule(String tag) {
+ mTag = tag;
+ }
+
+ @Override
+ protected void starting(Description description) {
+ Log.d(LOG_TAG, String.format("%s#starting", mTag));
+ }
+
+ @Override
+ protected void finished(Description description) {
+ Log.d(LOG_TAG, String.format("%s#finished.", mTag));
+ }
+ }
+}
diff --git a/tests/health/scenarios/tests/src/android/platform/test/scenario/sample/SampleMicrobenchmark.java b/tests/health/scenarios/tests/src/android/platform/test/scenario/sample/SampleMicrobenchmark.java
new file mode 100644
index 000000000..60ab12862
--- /dev/null
+++ b/tests/health/scenarios/tests/src/android/platform/test/scenario/sample/SampleMicrobenchmark.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.platform.test.scenario.sample;
+
+import android.platform.test.microbenchmark.Microbenchmark;
+import android.platform.test.microbenchmark.Microbenchmark.NoMetricAfter;
+import android.platform.test.microbenchmark.Microbenchmark.NoMetricBefore;
+import android.platform.test.option.BooleanOption;
+import android.util.Log;
+
+import org.junit.ClassRule;
+import org.junit.runner.RunWith;
+
+/**
+ * A test showcasing the order of execution for different components of a microbenchmark.
+ *
+ * <p>Run this test with the listener alongside, {@link PrintListener}, to see how they interact.
+ */
+@RunWith(Microbenchmark.class)
+public class SampleMicrobenchmark extends SampleTest {
+
+ @ClassRule
+ public static BooleanOption failNoMetricBefore =
+ new BooleanOption("fail-no-metric-before").setRequired(false).setDefault(false);
+
+ @ClassRule
+ public static BooleanOption failNoMetricAfter =
+ new BooleanOption("fail-no-metric-after").setRequired(false).setDefault(false);
+
+ @NoMetricBefore
+ public void noMetricBefore() {
+ SampleTest.failIfRequested(failNoMetricBefore, "@NoMetricBefore");
+ Log.d(SampleTest.LOG_TAG, "@NoMetricBefore");
+ }
+
+ @NoMetricAfter
+ public void noMetricAfter() {
+ SampleTest.failIfRequested(failNoMetricAfter, "@NoMetricAfter");
+ Log.d(SampleTest.LOG_TAG, "@NoMetricAfter");
+ }
+}
diff --git a/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/LauncherJankTests.java b/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/LauncherJankTests.java
index b946cfa4b..c8509a0e4 100644
--- a/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/LauncherJankTests.java
+++ b/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/LauncherJankTests.java
@@ -16,6 +16,7 @@
package android.platform.systemui.tests.jank;
+import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.RemoteException;
@@ -25,8 +26,10 @@ import android.support.test.jank.JankTestBase;
import android.support.test.launcherhelper.ILauncherStrategy;
import android.support.test.launcherhelper.LauncherStrategyFactory;
import android.support.test.timeresulthelper.TimeResultLogger;
+import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.Until;
import android.system.helpers.OverviewHelper;
import com.android.launcher3.tapl.AllApps;
@@ -218,4 +221,35 @@ public class LauncherJankTests extends JankTestBase {
mLauncher.pressHome();
}
}
+
+ private void startAppFast(String packageName) {
+ final android.app.Instrumentation instrumentation = getInstrumentation();
+ final Intent intent =
+ instrumentation
+ .getContext()
+ .getPackageManager()
+ .getLaunchIntentForPackage(packageName);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ instrumentation.getTargetContext().startActivity(intent);
+ assertTrue(
+ packageName + " didn't start",
+ mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), 60000));
+ }
+
+ /**
+ * Fast-opens the Messages app repeatedly and goes to home, measuring jank for going from app to
+ * home.
+ */
+ @JankTest(
+ beforeTest = "beforeOpenCloseMessagesApp",
+ afterTest = "afterOpenCloseMessagesApp",
+ expectedFrames = 90)
+ @GfxMonitor(processName = "#getLauncherPackage")
+ public void testAppToHome() throws Exception {
+ for (int i = 0; i < INNER_LOOP; i++) {
+ startAppFast("com.google.android.apps.messaging");
+ mLauncher.pressHome();
+ }
+ }
}
diff --git a/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/SystemUiJankTests.java b/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/SystemUiJankTests.java
index c5b919243..c50451718 100644
--- a/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/SystemUiJankTests.java
+++ b/tests/jank/UbSystemUiJankTests/src/android/platform/systemui/tests/jank/SystemUiJankTests.java
@@ -626,11 +626,13 @@ public class SystemUiJankTests extends JankTestBase {
}
public void beforeChangeBrightness() throws Exception {
- mDevice.openQuickSettings();
+ prepareNotifications(GROUP_MODE_UNGROUPED);
+ mDevice.openNotification();
// Wait until animation is starting.
SystemClock.sleep(200);
mDevice.waitForIdle();
+
TimeResultLogger.writeTimeStampLogStart(String.format("%s-%s",
getClass().getSimpleName(), getName()), TIMESTAMP_FILE);
}
@@ -653,6 +655,8 @@ public class SystemUiJankTests extends JankTestBase {
afterTest = "afterChangeBrightness")
@GfxMonitor(processName = SYSTEMUI_PACKAGE)
public void testChangeBrightness() throws Exception {
+ swipeDown();
+ mDevice.waitForIdle();
UiObject2 brightness = mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "slider"));
Rect bounds = brightness.getVisibleBounds();
for (int i = 0; i < INNER_LOOP; i++) {
diff --git a/tests/jank/androidtvjanktests/Android.bp b/tests/jank/androidtvjanktests/Android.bp
index 78f90184c..45e303ed5 100644
--- a/tests/jank/androidtvjanktests/Android.bp
+++ b/tests/jank/androidtvjanktests/Android.bp
@@ -17,13 +17,13 @@ android_test {
srcs: ["src/**/*.java"],
static_libs: [
- "ub-janktesthelper",
+ "androidx.test.janktesthelper",
"ub-uiautomator",
"timeresult-helper-lib",
"dpad-util",
],
- sdk_version: "21",
+ sdk_version: "23",
test_suites: ["device-tests"],
}
diff --git a/tests/jank/androidtvjanktests/AndroidManifest.xml b/tests/jank/androidtvjanktests/AndroidManifest.xml
index bdd303995..50987ca83 100644
--- a/tests/jank/androidtvjanktests/AndroidManifest.xml
+++ b/tests/jank/androidtvjanktests/AndroidManifest.xml
@@ -21,11 +21,11 @@
<uses-library android:name="android.test.runner" />
</application>
- <uses-sdk android:minSdkVersion="19"
+ <uses-sdk android:minSdkVersion="23"
android:targetSdkVersion="23"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<instrumentation
- android:name="android.test.InstrumentationTestRunner"
+ android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.androidtv.janktests"
android:label="Platform Android TV Jank Tests" />
</manifest>
diff --git a/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemAppJankTests.java b/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemAppJankTests.java
index f6747d066..db70cd9f5 100644
--- a/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemAppJankTests.java
+++ b/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemAppJankTests.java
@@ -20,9 +20,9 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.SystemClock;
-import android.support.test.jank.GfxMonitor;
-import android.support.test.jank.JankTest;
-import android.support.test.jank.JankTestBase;
+import androidx.test.jank.GfxMonitor;
+import androidx.test.jank.JankTest;
+import androidx.test.jank.JankTestBase;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
@@ -32,6 +32,7 @@ import android.support.test.uiautomator.Until;
import java.io.IOException;
/*
+ * These Tests are Ignored as frames cannot be rendered in Youtube App.
* This class contains the tests for key system apps on Android TV jank.
*/
public class SystemAppJankTests extends JankTestBase {
@@ -67,14 +68,14 @@ public class SystemAppJankTests extends JankTestBase {
}
// Measures jank while scrolling down the Youtube Navigation Bar
- @JankTest(expectedFrames=100, beforeTest = "launchYoutube",
- afterTest="afterTestSystemApp")
- @GfxMonitor(processName=YOUTUBE_PACKAGE)
- public void testYoutubeGuideNavigation() throws UiObjectNotFoundException {
- // As of launching Youtube, we're already at the screen where
- // the navigation bar is in focus, so we only need to scroll.
- navigateDownAndUpCurrentScreen();
- }
+/* @JankTest(expectedFrames=100, beforeTest = "launchYoutube",
+ * afterTest="afterTestSystemApp")
+ * @GfxMonitor(processName=YOUTUBE_PACKAGE)
+ * public void testYoutubeGuideNavigation() throws UiObjectNotFoundException {
+ * // As of launching Youtube, we're already at the screen where
+ * // the navigation bar is in focus, so we only need to scroll.
+ * navigateDownAndUpCurrentScreen();
+ } */
public void goToYoutubeContainer() throws UiObjectNotFoundException {
launchYoutube();
@@ -87,14 +88,14 @@ public class SystemAppJankTests extends JankTestBase {
}
// Measures jank while scrolling down the Youtube Navigation Bar
- @JankTest(expectedFrames=100, beforeTest = "goToYoutubeContainer",
- afterTest="afterTestSystemApp")
- @GfxMonitor(processName=YOUTUBE_PACKAGE)
- public void testYoutubeContainerListNavigation() throws UiObjectNotFoundException {
- // The gotoYouTubeContainer method confirms that the focus is
- // on the content, so we only need to scroll.
- navigateDownAndUpCurrentScreen();
- }
+/* @JankTest(expectedFrames=100, beforeTest = "goToYoutubeContainer",
+ * afterTest="afterTestSystemApp")
+ * @GfxMonitor(processName=YOUTUBE_PACKAGE)
+ * public void testYoutubeContainerListNavigation() throws UiObjectNotFoundException {
+ * // The gotoYouTubeContainer method confirms that the focus is
+ * // on the content, so we only need to scroll.
+ * navigateDownAndUpCurrentScreen();
+ } */
public void navigateDownAndUpCurrentScreen() {
for (int i = 0; i < INNER_LOOP; i++) {
@@ -114,4 +115,4 @@ public class SystemAppJankTests extends JankTestBase {
getInstrumentation().getContext().startActivity(appIntent);
SystemClock.sleep(LONG_TIMEOUT);
}
-} \ No newline at end of file
+}
diff --git a/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemUiJankTests.java b/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemUiJankTests.java
index 6868b7682..8609e322d 100644
--- a/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemUiJankTests.java
+++ b/tests/jank/androidtvjanktests/src/com/android/androidtv/janktests/SystemUiJankTests.java
@@ -18,9 +18,9 @@ package com.android.androidtv.janktests;
import android.os.Bundle;
import android.platform.test.utils.DPadUtil;
-import android.support.test.jank.GfxMonitor;
-import android.support.test.jank.JankTest;
-import android.support.test.jank.JankTestBase;
+import androidx.test.jank.GfxMonitor;
+import androidx.test.jank.JankTest;
+import androidx.test.jank.JankTestBase;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.Direction;
@@ -41,8 +41,9 @@ public class SystemUiJankTests extends JankTestBase {
private static final String TAG = SystemUiJankTests.class.getSimpleName();
private static final int SHORT_TIMEOUT = 1000;
- private static final int INNER_LOOP = 4;
+ private static final int INNER_LOOP = 8;
private static final int INNER_LOOP_SETTINGS = 8;
+ private static final int LOOP_SETTINGS_PREFERENCE = 4;
private static final String TVLAUNCHER_PACKAGE = "com.google.android.tvlauncher";
private static final String SETTINGS_PACKAGE = "com.android.tv.settings";
private static final BySelector SELECTOR_TOP_ROW = By.res(TVLAUNCHER_PACKAGE, "top_row");
@@ -107,7 +108,7 @@ public class SystemUiJankTests extends JankTestBase {
afterTest="afterTestSettings")
@GfxMonitor(processName=SETTINGS_PACKAGE)
public void testNavigateToSettings() throws UiObjectNotFoundException {
- for (int i = 0; i < INNER_LOOP * 10; i++) {
+ for (int i = 0; i < INNER_LOOP * 5; i++) {
// Press DPad center button to navigate to settings.
mDPadUtil.pressDPadCenter();
mDevice.wait(Until.hasObject(
@@ -135,15 +136,20 @@ public class SystemUiJankTests extends JankTestBase {
public void testSettingsScreenNavigation() throws UiObjectNotFoundException {
navigateDownAndUpCurrentScreen(INNER_LOOP_SETTINGS);
}
-
+
+ /*Increased the loop count to LOOP_SETTINGS_PREFERENCE
+ *since there is fewer Options in Settings Panel screen
+ */
public void navigateDownAndUpCurrentScreen(int iterations) {
- for (int i = 0; i < iterations; i++) {
+ for(int j = 0; j < LOOP_SETTINGS_PREFERENCE; j++){
+ for (int i = 0; i < iterations; i++) {
// Press DPad button down eight times in succession
mDPadUtil.pressDPadDown();
- }
- for (int i = 0; i < iterations; i++) {
+ }
+ for (int i = 0; i < iterations; i++) {
// Press DPad button up eight times in succession.
mDPadUtil.pressDPadUp();
+ }
}
}
diff --git a/tests/microbenchmarks/uibench/AndroidManifest.xml b/tests/microbenchmarks/uibench/AndroidManifest.xml
index 074f0d85a..e176dd606 100644
--- a/tests/microbenchmarks/uibench/AndroidManifest.xml
+++ b/tests/microbenchmarks/uibench/AndroidManifest.xml
@@ -20,6 +20,7 @@
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-sdk android:targetSdkVersion="28" />
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/IUiBenchJankHelper.java b/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/IUiBenchJankHelper.java
index ee0ea3205..d3699ee9d 100644
--- a/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/IUiBenchJankHelper.java
+++ b/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/IUiBenchJankHelper.java
@@ -85,6 +85,8 @@ public interface IUiBenchJankHelper extends IAppHelper {
void openResizeHWLayer();
+ void openWindowInsetsController();
+
void scrollDownAndUp(int count);
void slowSingleFlingDown();
diff --git a/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchJankHelper.java b/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchJankHelper.java
index 3180d6ddf..d64da15de 100644
--- a/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchJankHelper.java
+++ b/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchJankHelper.java
@@ -56,7 +56,7 @@ public class UiBenchJankHelper extends AbstractStandardAppHelper implements IUiB
private static final int SLOW_FLING_SPEED = 3000; // compare to UiObject2#DEFAULT_FLING_SPEED
// Main UiObject2 exercised by the test.
- private UiObject2 mContents;
+ private UiObject2 mContents, mNavigation;
public UiBenchJankHelper(Instrumentation instr) {
super(instr);
@@ -107,6 +107,15 @@ public class UiBenchJankHelper extends AbstractStandardAppHelper implements IUiB
Assert.assertNotNull(activityName + " isn't found", mContents);
}
+ int getEdgeSensitivity() {
+ int resId =
+ mInstrumentation
+ .getContext()
+ .getResources()
+ .getIdentifier("config_backGestureInset", "dimen", "android");
+ return mInstrumentation.getContext().getResources().getDimensionPixelSize(resId) + 1;
+ }
+
/** To perform the fling down and up on given content for flingCount number of times */
@Override
public void flingUpDown(int flingCount) {
@@ -119,6 +128,7 @@ public class UiBenchJankHelper extends AbstractStandardAppHelper implements IUiB
}
void flingUpDown(int flingCount, boolean reverse) {
+ mContents.setGestureMargin(getEdgeSensitivity());
for (int count = 0; count < flingCount; count++) {
SystemClock.sleep(SHORT_TIMEOUT);
mContents.fling(reverse ? Direction.UP : Direction.DOWN);
@@ -130,9 +140,13 @@ public class UiBenchJankHelper extends AbstractStandardAppHelper implements IUiB
/** To perform the swipe right and left on given content for swipeCount number of times */
@Override
public void swipeRightLeft(int swipeCount) {
+ mNavigation =
+ mDevice.wait(
+ Until.findObject(By.desc("Open navigation drawer")), FIND_OBJECT_TIMEOUT);
+ mContents.setGestureMargin(getEdgeSensitivity());
for (int count = 0; count < swipeCount; count++) {
SystemClock.sleep(SHORT_TIMEOUT);
- mContents.swipe(Direction.RIGHT, 1);
+ mNavigation.click();
SystemClock.sleep(SHORT_TIMEOUT);
mContents.swipe(Direction.LEFT, 1);
}
@@ -143,6 +157,7 @@ public class UiBenchJankHelper extends AbstractStandardAppHelper implements IUiB
SystemClock.sleep(SHORT_TIMEOUT);
Context context = mInstrumentation.getContext();
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
+ mContents.setGestureMargin(getEdgeSensitivity());
mContents.fling(Direction.DOWN, (int) (SLOW_FLING_SPEED * displayMetrics.density));
mDevice.waitForIdle();
}
@@ -323,6 +338,11 @@ public class UiBenchJankHelper extends AbstractStandardAppHelper implements IUiB
launchActivity("ActivityTransition", "Transitions/Activity Transition");
}
+ @Override
+ public void openWindowInsetsController() {
+ launchActivityAndAssert("WindowInsetsControllerActivity", "WindowInsetsControllerActivity");
+ }
+
// Get the image to click
@Override
public void clickImage(String imageName) {
diff --git a/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchWindowInsetsControllerMicrobenchmark.java b/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchWindowInsetsControllerMicrobenchmark.java
new file mode 100644
index 000000000..216ff30a5
--- /dev/null
+++ b/tests/microbenchmarks/uibench/src/com/android/uibench/microbenchmark/UiBenchWindowInsetsControllerMicrobenchmark.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.uibench.microbenchmark;
+
+import static com.android.uibench.microbenchmark.UiBenchJankHelper.FIND_OBJECT_TIMEOUT;
+import static com.android.uibench.microbenchmark.UiBenchJankHelper.SHORT_TIMEOUT;
+
+import android.os.SystemClock;
+import android.platform.helpers.HelperAccessor;
+import android.platform.test.microbenchmark.Microbenchmark;
+import android.platform.test.rule.NaturalOrientationRule;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(Microbenchmark.class)
+public class UiBenchWindowInsetsControllerMicrobenchmark {
+ @ClassRule public static NaturalOrientationRule orientationRule = new NaturalOrientationRule();
+
+ private static HelperAccessor<IUiBenchJankHelper> sHelper =
+ new HelperAccessor<>(IUiBenchJankHelper.class);
+
+ private static UiObject2 sEditText;
+ private static UiDevice sDevice;
+
+ @BeforeClass
+ public static void openApp() {
+ sHelper.get().openWindowInsetsController();
+ sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ sEditText = sDevice.wait(Until.findObject(By.text("WindowInsetsController")),
+ FIND_OBJECT_TIMEOUT);
+ }
+
+ @Test
+ public void testOpenIme() {
+ sEditText.click();
+ SystemClock.sleep(SHORT_TIMEOUT);
+ sDevice.pressBack();
+ }
+
+ @AfterClass
+ public static void closeApp() {
+ sHelper.get().exit();
+ }
+}