summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-08-30 19:00:56 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-08-30 19:00:56 +0000
commit63f5219215bf88e8f35d5007f40a6d78759e7165 (patch)
tree3682fbf937c017315bf722b1f3a47694c1560312
parent2253213e34c276b2f4a75a771b840ebe44dd4809 (diff)
parent13fab2ee3012aead0feb56d4ace52b74d2e22edd (diff)
downloadcts-aml_res_341110000.tar.gz
Snap for 10737070 from 13fab2ee3012aead0feb56d4ace52b74d2e22edd to mainline-resolv-releaseaml_res_341110000
Change-Id: Iaebe3f4f82b10aae7463387cdf3ad57f13c18035
-rw-r--r--apps/CameraITS/tests/scene6/test_low_latency_zoom.py28
-rw-r--r--apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py14
-rw-r--r--apps/CameraITS/tests/scene6/test_zoom.py21
-rw-r--r--apps/CameraITS/tests/scene_extensions/scene_hdr/test_hdr_extension.py2
-rw-r--r--apps/CameraITS/tests/scene_extensions/scene_night/test_night_extension.py181
-rw-r--r--apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py4
-rw-r--r--apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py4
-rw-r--r--apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py4
-rw-r--r--apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py4
-rw-r--r--apps/CameraITS/utils/opencv_processing_utils.py64
-rw-r--r--apps/CameraITS/utils/video_processing_utils.py35
-rw-r--r--apps/CtsVerifier/jni/midi/MidiTestManager.cpp2
-rw-r--r--apps/CtsVerifier/res/values/strings.xml7
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java9
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java54
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java66
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java42
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/midilib/JavaMidiTestModule.java2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java23
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java12
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/qstiles/InteractiveVerifierActivity.java8
-rwxr-xr-xcommon/device-side/bedstead/btest/btest6
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireHasDefaultBrowser.java37
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/FactoryResetProtection.java6
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedInputMethods.java2
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedSystemInputMethods.java39
-rw-r--r--common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java12
-rw-r--r--common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java7
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java117
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/RoleContext.java23
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java17
-rw-r--r--common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java7
-rw-r--r--common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConnectivityDeviceInfo.java20
-rw-r--r--common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GnssDeviceInfo.java7
-rw-r--r--common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MediaDrmDeviceInfo.java82
-rw-r--r--common/device-side/interactive/src/main/java/com/android/interactive/Step.java28
-rw-r--r--common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndConfirmStep.java1
-rw-r--r--common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndWaitStep.java1
-rw-r--r--common/device-side/interactive/src/main/java/com/android/interactive/steps/MultipleChoiceStep.java1
-rw-r--r--common/device-side/interactive/src/main/java/com/android/interactive/steps/YesNoStep.java1
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils2.java2
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/UserHelper.java4
-rw-r--r--common/device-side/util/jni/android_cts_CpuFeatures.cpp5
-rw-r--r--hostsidetests/abioverride/AndroidTest.xml2
-rw-r--r--hostsidetests/accounts/AndroidTest.xml2
-rw-r--r--hostsidetests/adbmanager/AndroidTest.xml2
-rw-r--r--hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/AppCompatOverridesServiceTest.java3
-rw-r--r--hostsidetests/appsecurity/Android.bp3
-rw-r--r--hostsidetests/appsecurity/AndroidTest.xml2
-rw-r--r--hostsidetests/appsecurity/OWNERS9
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java223
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java68
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java32
-rw-r--r--hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java122
-rw-r--r--hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp1
-rw-r--r--hostsidetests/art/host/AndroidTest.xml2
-rw-r--r--hostsidetests/calllog/AndroidTest.xml2
-rw-r--r--hostsidetests/car/src/android/car/cts/CarUserManagerHostTest.java34
-rw-r--r--hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java5
-rw-r--r--hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java10
-rw-r--r--hostsidetests/classloaders/splits/AndroidTest.xml2
-rw-r--r--hostsidetests/classloaders/useslibrary/AndroidTest.xml2
-rw-r--r--hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java42
-rw-r--r--hostsidetests/compilation/status_checker_app/src/android/compilation/cts/statuscheckerapp/StatusCheckerAppTest.java35
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java1
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java2
-rw-r--r--hostsidetests/incrementalinstall/AndroidTest.xml2
-rw-r--r--hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java18
-rw-r--r--hostsidetests/install/AndroidTest.xml2
-rw-r--r--hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java87
-rw-r--r--hostsidetests/numberblocking/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/domainverification/device/multiuser/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/domainverification/host/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/dynamicmime/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/extractnativelibs/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/installedloadingprogess/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/multiuser/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/packagesetting/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/packagesetting/app/AndroidManifest.xml2
-rw-r--r--hostsidetests/packagemanager/packagesetting/app/src/com/android/tests/packagesetting/app/PackageSettingDeviceTest.java10
-rw-r--r--hostsidetests/packagemanager/packagesetting/src/com/android/tests/packagesetting/host/PackageSettingTest.java48
-rw-r--r--hostsidetests/packagemanager/parsing/host/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/preferredactivity/AndroidTest.xml2
-rw-r--r--hostsidetests/packagemanager/stats/AndroidTest.xml2
-rw-r--r--hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java53
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java52
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java139
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java35
-rw-r--r--hostsidetests/scopedstorage/res/raw/fuzzer.heicbin0 -> 4407744 bytes
-rw-r--r--hostsidetests/seccomp/AndroidTest.xml2
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java69
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21144.java58
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml24
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java67
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/DeviceTest.java7
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/PocService.java12
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21144/Android.bp39
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21144/AndroidManifest.xml38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21144/res/values/strings.xml32
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/DeviceTest.java197
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/PocListenerService.java34
-rw-r--r--hostsidetests/silentupdate/AndroidTest.xml2
-rw-r--r--hostsidetests/stagedinstall/AndroidTest.xml2
-rw-r--r--hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/DisplayWakeReportedTests.java2
-rw-r--r--hostsidetests/systemui/src/android/host/systemui/TileServiceTest.java15
-rw-r--r--hostsidetests/usb/AndroidTest.xml2
-rw-r--r--hostsidetests/wifibroadcasts/AndroidTest.xml2
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java4
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java13
-rw-r--r--tests/accessibilityservice/res/layout/accessibility_embedded_hierarchy_test_host_side.xml4
-rw-r--r--tests/accessibilityservice/res/values/dimens.xml6
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java17
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java248
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java11
-rw-r--r--tests/app/BroadcastsTest/src/android/app/cts/broadcasts/BroadcastDeliveryGroupTest.java14
-rw-r--r--tests/app/WallpaperTest/AndroidTest.xml2
-rw-r--r--tests/app/WallpaperTest/testsdk33/AndroidTest.xml2
-rw-r--r--tests/app/src/android/app/cts/SystemFeaturesTest.java18
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java26
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java1151
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java13
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java32
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java43
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java23
-rw-r--r--tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java252
-rw-r--r--tests/filesystem/src/android/filesystem/cts/RandomRWTest.java7
-rw-r--r--tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java7
-rw-r--r--tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java15
-rw-r--r--tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceThemeActivity.java1
-rw-r--r--tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenStyleThemeActivity.java1
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingPlaceholderTests.java13
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingTestBase.java9
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/SplitAttributesCalculatorTest.java9
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java23
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java1
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/CompatScaleTests.java4
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/DisplayShapeTests.java33
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java51
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java5
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java10
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java30
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java3
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java16
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java11
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java22
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java4
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java55
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java3
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java4
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/InputMethodInfoTest.java4
-rw-r--r--tests/media/AndroidTest.xml2
-rw-r--r--tests/media/DynamicConfig.xml2
-rw-r--r--tests/media/README.md2
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java14
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java118
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/HDRDecoderTestBase.java54
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java86
-rwxr-xr-xtests/media/copy_media.sh2
-rw-r--r--tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java5
-rw-r--r--tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java50
-rw-r--r--tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java13
-rw-r--r--tests/media/src/android/mediav2/cts/ExtractorTest.java4
-rw-r--r--tests/media/src/android/mediav2/cts/WorkDir.java2
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/Utils.java41
-rw-r--r--tests/mediapc/src/android/mediapc/cts/CodecTestBase.java1
-rw-r--r--tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java143
-rw-r--r--tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java10
-rw-r--r--tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java6
-rw-r--r--tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java32
-rw-r--r--tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java10
-rw-r--r--tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java4
-rw-r--r--tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java86
-rw-r--r--tests/mocking/AndroidTest.xml2
-rw-r--r--tests/mocking/debuggable/AndroidTest.xml2
-rw-r--r--tests/mocking/inline/AndroidTest.xml2
-rw-r--r--tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java2
-rw-r--r--tests/signature/intent-check/AndroidTest.xml2
-rw-r--r--tests/storageaccess/Android.bp50
-rw-r--r--tests/storageaccess/AndroidManifest.xml40
-rw-r--r--tests/storageaccess/AndroidTest.xml58
-rw-r--r--tests/storageaccess/OWNERS11
-rw-r--r--tests/storageaccess/src/android/storageaccess/cts/ActivityScenarioExt.kt36
-rw-r--r--tests/storageaccess/src/android/storageaccess/cts/ClientActivity.kt68
-rw-r--r--tests/storageaccess/src/android/storageaccess/cts/Constants.kt21
-rw-r--r--tests/storageaccess/src/android/storageaccess/cts/LogUtils.kt24
-rw-r--r--tests/storageaccess/src/android/storageaccess/cts/tests/ScopedDirectoryAccessClientTest.kt115
-rw-r--r--tests/storageaccess/src/android/storageaccess/cts/tests/TestBase.kt68
-rw-r--r--tests/suspendapps/permission/AndroidTest.xml2
-rw-r--r--tests/suspendapps/tests/AndroidTest.xml2
-rw-r--r--tests/tests/app/AndroidTest.xml2
-rw-r--r--tests/tests/appcomponentfactory/AndroidTest.xml2
-rw-r--r--tests/tests/appenumeration/AndroidTest.xml2
-rw-r--r--tests/tests/car/src/android/car/cts/CarInputTest.java2
-rw-r--r--tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java9
-rw-r--r--tests/tests/classloaderfactory/test-memcl/AndroidTest.xml2
-rw-r--r--tests/tests/classloaderfactory/test-pathcl/AndroidTest.xml2
-rw-r--r--tests/tests/content/AndroidTest.xml2
-rw-r--r--tests/tests/content/TEST_MAPPING2
-rw-r--r--tests/tests/content/pm/SecureFrp/AndroidTest.xml2
-rw-r--r--tests/tests/content/src/android/content/cts/AvailableIntentsTest.java3
-rw-r--r--tests/tests/display/src/android/display/cts/DisplayManagerTest.java20
-rw-r--r--tests/tests/gesture/AndroidTest.xml2
-rw-r--r--tests/tests/instantapp/AndroidTest.xml2
-rw-r--r--tests/tests/libnativehelper/AndroidTest.xml2
-rw-r--r--tests/tests/match_flags/AndroidTest.xml2
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/RingtoneManagerTest.java6
-rw-r--r--tests/tests/media/misc/AndroidTest.xml2
-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/MediaMetadataRetrieverTest.java42
-rw-r--r--tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java2
-rw-r--r--tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java7
-rw-r--r--tests/tests/notification/NotificationTrampolineBase/src/com/android/test/notificationtrampoline/NotificationTrampolineTestService.java34
-rw-r--r--tests/tests/os/src/android/os/cts/SeccompTest.java5
-rw-r--r--tests/tests/packageinstaller/adminpackageinstaller/Android.bp2
-rw-r--r--tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml9
-rw-r--r--tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/BasePackageInstallTest.java71
-rw-r--r--tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/InstallReasonTest.java16
-rw-r--r--tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java58
-rw-r--r--tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SilentPackageInstallTest.java33
-rw-r--r--tests/tests/packageinstaller/atomicinstall/AndroidTest.xml10
-rw-r--r--tests/tests/packageinstaller/contentprovider/AndroidTestNoVisibility.xml2
-rw-r--r--tests/tests/packageinstaller/contentprovider/AndroidTestVisibility.xml2
-rw-r--r--tests/tests/packageinstaller/install/AndroidTest.xml2
-rw-r--r--tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt24
-rw-r--r--tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PreapprovalInstallTest.kt147
-rw-r--r--tests/tests/packageinstaller/install_appop_default/AndroidTest.xml2
-rw-r--r--tests/tests/packageinstaller/install_appop_denied/AndroidTest.xml2
-rw-r--r--tests/tests/packageinstaller/packagescheme/AndroidTestNoVisibility.xml2
-rw-r--r--tests/tests/packageinstaller/packagescheme/AndroidTestVisibility.xml2
-rw-r--r--tests/tests/packageinstaller/tapjacking/AndroidTest.xml2
-rw-r--r--tests/tests/packageinstaller/uninstall/AndroidTest.xml2
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt4
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/LocationProviderInterceptDialogTest.kt6
-rw-r--r--tests/tests/provider/src/android/provider/cts/settings/Settings_MemoryUsageTest.java2
-rw-r--r--tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java13
-rw-r--r--tests/tests/resolverservice/AndroidTest.xml2
-rw-r--r--tests/tests/security/AndroidManifest.xml3
-rw-r--r--tests/tests/security/res/layout/cve_2023_21143.xml27
-rw-r--r--tests/tests/security/res/raw/cve_2023_21143.pngbin0 -> 99729 bytes
-rw-r--r--tests/tests/security/res/values/strings_CVE_2023_21143.xml27
-rw-r--r--tests/tests/security/src/android/security/cts/ActivityManagerTest.java35
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2023_21143.java131
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2023_40119.java67
-rw-r--r--tests/tests/security/src/android/security/cts/CertificateData.java69
-rw-r--r--tests/tests/security/src/android/security/cts/CertificateTest.java3
-rw-r--r--tests/tests/sharesheet/AndroidTest.xml2
-rw-r--r--tests/tests/soundtrigger/AndroidTest.xml2
-rw-r--r--tests/tests/telecom/AndroidManifest.xml8
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java4
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java4
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/CtsSimCallManagerConnectionService.java360
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/EmergencyCallOnSimCallManagerTest.java14
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java8
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java151
-rw-r--r--tests/tests/toastlegacy/OWNERS2
-rw-r--r--tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java4
-rw-r--r--tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java3
-rw-r--r--tests/tests/usb/AndroidTest.xml2
-rw-r--r--tests/tests/view/res/layout-round/using_views_layout.xml78
-rw-r--r--tests/tests/view/src/android/view/cts/AutoHandwritingTest.java8
-rw-r--r--tests/tests/view/src/android/view/cts/ViewGroupTest.java12
-rw-r--r--tests/tests/voiceinteraction/Android.bp1
-rw-r--r--tests/tests/voiceinteraction/AndroidTest.xml2
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/AlwaysOnHotwordDetectorNoHdsTest.java340
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java2
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/services/CtsBasicVoiceInteractionService.java49
-rw-r--r--tests/tests/widget/src/android/widget/cts/TextViewHandwritingGestureTest.java15
-rw-r--r--tests/tests/wifi/AndroidManifest.xml2
-rw-r--r--tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java3
-rw-r--r--tools/cts-device-info/Android.bp1
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml8
-rw-r--r--tools/cts-tradefed/res/config/cts-validation-exclude.xml12
-rw-r--r--tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java3
277 files changed, 5898 insertions, 2249 deletions
diff --git a/apps/CameraITS/tests/scene6/test_low_latency_zoom.py b/apps/CameraITS/tests/scene6/test_low_latency_zoom.py
index 96b4181a3f7..11b0106379c 100644
--- a/apps/CameraITS/tests/scene6/test_low_latency_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_low_latency_zoom.py
@@ -31,6 +31,7 @@ import zoom_capture_utils
_CIRCLE_COLOR = 0 # [0: black, 255: white]
_CIRCLE_AR_RTOL = 0.15 # contour width vs height (aspect ratio)
_CIRCLISH_RTOL = 0.05 # contour area vs ideal circle area pi*((w+h)/4)**2
+_CONTINUOUS_PICTURE_MODE = 4 # continuous picture AF mode
_MIN_AREA_RATIO = 0.00015 # based on 2000/(4000x3000) pixels
_MIN_CIRCLE_PTS = 25
_NAME = os.path.splitext(os.path.basename(__file__))[0]
@@ -63,14 +64,15 @@ class LowLatencyZoomTest(its_base_test.ItsBaseTest):
its_session_utils.load_scene(
cam, props, self.scene, self.tablet, self.chart_distance)
+ # Determine test zoom range
z_range = props['android.control.zoomRatioRange']
- logging.debug('testing zoomRatioRange: %s', str(z_range))
debug = self.debug_mode
-
z_min, z_max = float(z_range[0]), float(z_range[1])
camera_properties_utils.skip_unless(z_max >= z_min * _ZOOM_MIN_THRESH)
- z_list = np.arange(z_min, z_max, float(z_max - z_min) / (_NUM_STEPS - 1))
+ z_max = min(z_max, zoom_capture_utils.ZOOM_MAX_THRESH * z_min)
+ z_list = np.arange(z_min, z_max, (z_max - z_min) / (_NUM_STEPS - 1))
z_list = np.append(z_list, z_max)
+ logging.debug('Testing zoom range: %s', str(z_list))
# set TOLs based on camera and test rig params
if camera_properties_utils.logical_multi_camera(props):
@@ -90,13 +92,18 @@ class LowLatencyZoomTest(its_base_test.ItsBaseTest):
# do auto captures over zoom range and find circles with cv2
img_name_stem = f'{os.path.join(self.log_path, _NAME)}'
logging.debug('Using auto capture request')
- cam.do_3a()
+ cam.do_3a(zoom_ratio=z_min)
test_failed = False
fmt = 'yuv'
test_data = {}
reqs = []
req = capture_request_utils.auto_capture_request()
- req['android.control.settingsOverride'] = camera_properties_utils.SETTINGS_OVERRIDE_ZOOM
+ req['android.control.settingsOverride'] = (
+ camera_properties_utils.SETTINGS_OVERRIDE_ZOOM
+ )
+ req['android.control.enableZsl'] = False
+ if not camera_properties_utils.fixed_focus(props):
+ req['android.control.afMode'] = _CONTINUOUS_PICTURE_MODE
for z in z_list:
logging.debug('zoom ratio: %.2f', z)
req_for_zoom = req.copy()
@@ -110,8 +117,10 @@ class LowLatencyZoomTest(its_base_test.ItsBaseTest):
# Check low latency zoom outputs match result metadata
for i, cap in enumerate(caps):
z_result = cap['metadata']['android.control.zoomRatio']
+ af_state = cap['metadata']['android.control.afState']
scaled_zoom = min(z_list[i], z_result)
- logging.debug('zoom ratio in result: %.2f', z_result)
+ logging.debug('Result[%d]: zoom ratio %.2f, afState %d',
+ i, z_result, af_state)
img = image_processing_utils.convert_capture_to_rgb_image(
cap, props=props)
img_name = f'{img_name_stem}_{fmt}_{i}_{round(z_result, 2)}.jpg'
@@ -147,6 +156,13 @@ class LowLatencyZoomTest(its_base_test.ItsBaseTest):
test_data[i] = {'z': z_result, 'circle': circle, 'r_tol': radius_tol,
'o_tol': offset_tol, 'fl': cap_fl}
+ # Since we are zooming in, settings_override may change the minimum zoom
+ # value in the result metadata.
+ # This is because zoom values like: [1., 2., 3., ..., 10.] may be applied
+ # as: [4., 4., 4., .... 9., 10., 10.].
+ # If we were zooming out, we would need to change the z_max.
+ z_min = test_data[min(test_data.keys())]['z']
+
if not zoom_capture_utils.verify_zoom_results(
test_data, size, z_max, z_min):
test_failed = True
diff --git a/apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py b/apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py
index c1ff7e71bef..acfef156b52 100644
--- a/apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py
+++ b/apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py
@@ -277,7 +277,19 @@ class PreviewVideoZoomTest(its_base_test.ItsBaseTest):
# Opencv expects a numpy array but np.flip generates a 'view' which
# doesn't work with opencv. ndarray.copy forces copy instead of view
if props['android.lens.facing'] == _LENS_FACING_FRONT:
- preview_img = np.ndarray.copy(np.flip(preview_img, 0))
+ # Preview are flipped on device's natural orientation
+ # so for sensor orientation 90 or 270, it is up or down
+ # Sensor orientation 0 or 180 is left or right
+ if props['android.sensor.orientation'] in (90, 270):
+ preview_img = np.ndarray.copy(np.flipud(preview_img))
+ logging.debug(
+ 'Found sensor orientation %d, flipping up down',
+ props['android.sensor.orientation'])
+ else:
+ preview_img = np.ndarray.copy(np.fliplr(preview_img))
+ logging.debug(
+ 'Found sensor orientation %d, flipping left right',
+ props['android.sensor.orientation'])
# Find the center circle in preview img
preview_img_name = (f'Preview_zoomRatio_{z}_{size}_circle.png')
diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py
index 78d555c7e2c..2e34320bc5f 100644
--- a/apps/CameraITS/tests/scene6/test_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_zoom.py
@@ -58,13 +58,15 @@ class ZoomTest(its_base_test.ItsBaseTest):
its_session_utils.load_scene(
cam, props, self.scene, self.tablet, self.chart_distance)
+ # Determine test zoom range
z_range = props['android.control.zoomRatioRange']
- logging.debug('testing zoomRatioRange: %s', str(z_range))
debug = self.debug_mode
-
z_min, z_max = float(z_range[0]), float(z_range[1])
- z_list = np.arange(z_min, z_max, float(z_max - z_min) / (_NUM_STEPS - 1))
+ camera_properties_utils.skip_unless(z_max >= z_min * _ZOOM_MIN_THRESH)
+ z_max = min(z_max, zoom_capture_utils.ZOOM_MAX_THRESH * z_min)
+ z_list = np.arange(z_min, z_max, (z_max - z_min) / (_NUM_STEPS - 1))
z_list = np.append(z_list, z_max)
+ logging.debug('Testing zoom range: %s', str(z_list))
# Check media performance class
media_performance_class = its_session_utils.get_media_performance_class(
@@ -81,8 +83,6 @@ class ZoomTest(its_base_test.ItsBaseTest):
f'Found media performance class {media_performance_class} '
f'and minimum zoom {z_min}.')
- camera_properties_utils.skip_unless(z_max >= z_min * _ZOOM_MIN_THRESH)
-
# set TOLs based on camera and test rig params
if camera_properties_utils.logical_multi_camera(props):
test_tols, size = zoom_capture_utils.get_test_tols_and_cap_size(
@@ -106,21 +106,14 @@ class ZoomTest(its_base_test.ItsBaseTest):
# do captures over zoom range and find circles with cv2
img_name_stem = f'{os.path.join(self.log_path, _NAME)}'
- if camera_properties_utils.manual_sensor(props):
- logging.debug('Manual sensor, using manual capture request')
- s, e, _, _, f_d = cam.do_3a(get_results=True)
- req = capture_request_utils.manual_capture_request(
- s, e, f_distance=f_d)
- else:
- logging.debug('Using auto capture request')
- cam.do_3a()
- req = capture_request_utils.auto_capture_request()
+ req = capture_request_utils.auto_capture_request()
test_failed = False
for fmt in test_formats:
logging.debug('testing %s format', fmt)
test_data = {}
for i, z in enumerate(z_list):
req['android.control.zoomRatio'] = z
+ cam.do_3a(zoom_ratio=z)
cap = cam.do_capture(
req, {'format': fmt, 'width': size[0], 'height': size[1]})
diff --git a/apps/CameraITS/tests/scene_extensions/scene_hdr/test_hdr_extension.py b/apps/CameraITS/tests/scene_extensions/scene_hdr/test_hdr_extension.py
index 9bb99ecf278..7ff6cd8e9b9 100644
--- a/apps/CameraITS/tests/scene_extensions/scene_hdr/test_hdr_extension.py
+++ b/apps/CameraITS/tests/scene_extensions/scene_hdr/test_hdr_extension.py
@@ -214,7 +214,7 @@ class HdrExtensionTest(its_base_test.ItsBaseTest):
its_session_utils.load_scene(
cam, props, self.scene, self.tablet, self.chart_distance,
- log_path=self.log_path)
+ lighting_check=False, log_path=self.log_path)
file_stem = f'{test_name}_{_FMT_NAME}_{_WIDTH}x{_HEIGHT}'
diff --git a/apps/CameraITS/tests/scene_extensions/scene_night/test_night_extension.py b/apps/CameraITS/tests/scene_extensions/scene_night/test_night_extension.py
index 676679a2fd4..c883d6fdd53 100644
--- a/apps/CameraITS/tests/scene_extensions/scene_night/test_night_extension.py
+++ b/apps/CameraITS/tests/scene_extensions/scene_night/test_night_extension.py
@@ -30,6 +30,7 @@ import lighting_control_utils
import opencv_processing_utils
_NAME = os.path.splitext(os.path.basename(__file__))[0]
+_DEFAULT_TABLET_BRIGHTNESS_SCALING = 0.04 # 4% of default brightness
_EXTENSION_NIGHT = 4 # CameraExtensionCharacteristics.EXTENSION_NIGHT
_TAP_COORDINATES = (500, 500) # Location to tap tablet screen via adb
_TEST_REQUIRED_MPC = 34
@@ -41,9 +42,8 @@ _IMAGE_FORMAT_YUV_420_888_INT = 35
_DOT_INTENSITY_DIFF_TOL = 20 # Min diff between dot/circle intensities [0:255]
_DURATION_DIFF_TOL = 0.5 # Night mode ON captures must take 0.5 seconds longer
-_EDGE_NOISE_WIDTH = 0.1 # Edge is left 10% of image and right 10% of image
-_EDGE_NOISE_IMPROVEMENT_TOL = 1.5 # Edge noise must be reduced by at least 67%
_INTENSITY_IMPROVEMENT_TOL = 1.1 # Night mode ON captures must be 10% brighter
+_IDEAL_INTENSITY_IMPROVEMENT = 2.5 # Skip noise check if images 2.5x brighter
_R_STRING = 'r'
_X_STRING = 'x'
@@ -86,60 +86,85 @@ def _convert_captures(cap, file_stem=None):
return y, image_processing_utils.convert_image_to_uint8(img)
-def _get_left_patch(y):
- """Return the left edge of a y plane according to _EDGE_NOISE_WIDTH.
-
- Args:
- y: y_plane from a capture.
- Returns:
- Cropped y_plane on the left edge of the capture.
- """
- return image_processing_utils.get_image_patch(
- y, 0, 0, _EDGE_NOISE_WIDTH, 1)
+def _check_dot_intensity_diff(night_img, night_y, no_night_img, no_night_y):
+ """Checks the difference between circle and dot intensities with Night ON.
-
-def _get_right_patch(y):
- """Return the right edge of a y plane according to _EDGE_NOISE_WIDTH.
-
- Args:
- y: y_plane from a capture.
- Returns:
- Cropped y_plane on the right edge of the capture.
- """
- return image_processing_utils.get_image_patch(
- y, 1 - _EDGE_NOISE_WIDTH, 0, _EDGE_NOISE_WIDTH, 1)
-
-
-def _get_edge_noise(night_y, no_night_y):
- """Computes the left and right edge noise in the y plane.
+ The performance with Night OFF is logged for debugging purposes.
+ This is an optional check, and a successful result can replace the
+ overall intensity check.
Args:
+ night_img: numpy image from a capture with night mode ON.
night_y: y_plane from a capture with night mode ON.
+ no_night_img: numpy image from a capture with night mode OFF.
no_night_y: y_plane from a capture with night mode OFF.
+
Returns:
- float; ratio of left edge noise, float; ratio of right edge noise.
+ True if diff between circle and dot intensities is significant.
"""
- night_left_patch_std = np.std(_get_left_patch(night_y), axis=(0, 1))
- no_night_left_patch_std = np.std(_get_left_patch(no_night_y), axis=(0, 1))
- night_right_patch_std = np.std(_get_right_patch(night_y), axis=(0, 1))
- no_night_right_patch_std = np.std(_get_right_patch(no_night_y), axis=(0, 1))
- logging.debug('Night mode ON left patch noise: %.2f', night_left_patch_std)
- logging.debug('Night mode OFF left patch noise: %.2f',
- no_night_left_patch_std)
- logging.debug('Night mode ON right patch noise: %.2f', night_right_patch_std)
- logging.debug('Night mode OFF right patch noise: %.2f',
- no_night_right_patch_std)
- left_patch_ratio = no_night_left_patch_std / night_left_patch_std
- right_patch_ratio = no_night_right_patch_std / night_right_patch_std
- return left_patch_ratio, right_patch_ratio
+ night_circle = opencv_processing_utils.find_circle(
+ night_img,
+ 'night_dot_intensity_check.png',
+ _MIN_AREA,
+ _WHITE,
+ )
+ night_circle_center_mean = np.mean(
+ night_img[night_circle[_Y_STRING], night_circle[_X_STRING]])
+ night_dots = _get_dots_from_circle(night_circle)
+
+ no_night_circle = opencv_processing_utils.find_circle(
+ no_night_img,
+ 'no_night_dot_intensity_check.png',
+ _MIN_AREA,
+ _WHITE,
+ )
+ no_night_circle_center_mean = np.mean(
+ no_night_img[no_night_circle[_Y_STRING], no_night_circle[_X_STRING]])
+ no_night_dots = _get_dots_from_circle(no_night_circle)
+
+ # Skip the first dot, which is of a different intensity
+ night_light_gray_dots_mean = np.mean(
+ [
+ night_y[night_dots[i][_Y_STRING], night_dots[i][_X_STRING]]
+ for i in range(1, len(night_dots))
+ ]
+ )
+ no_night_light_gray_dots_mean = np.mean(
+ [
+ no_night_y[no_night_dots[i][_Y_STRING], no_night_dots[i][_X_STRING]]
+ for i in range(1, len(no_night_dots))
+ ]
+ )
+
+ night_dot_intensity_diff = (
+ night_circle_center_mean -
+ night_light_gray_dots_mean
+ )
+ no_night_dot_intensity_diff = (
+ no_night_circle_center_mean -
+ no_night_light_gray_dots_mean
+ )
+ logging.debug('With night extension ON, the difference between white '
+ 'circle intensity and non-orientation dot intensity was %.2f.',
+ night_dot_intensity_diff)
+ logging.debug('With night extension OFF, the difference between white '
+ 'circle intensity and non-orientation dot intensity was %.2f.',
+ no_night_dot_intensity_diff)
+ return night_dot_intensity_diff > _DOT_INTENSITY_DIFF_TOL
def _check_overall_intensity(night_img, no_night_img):
"""Checks that overall intensity significantly improves with night mode ON.
+ All implementations must result in an increase in intensity of at least
+ _INTENSITY_IMPROVEMENT_TOL. _IDEAL_INTENSITY_IMPROVEMENT is the minimum
+ improvement to waive the edge noise check.
+
Args:
night_img: numpy image taken with night mode ON
no_night_img: numpy image taken with night mode OFF
+ Returns:
+ True if intensity has increased enough to waive the edge noise check.
"""
night_mean = np.mean(night_img)
no_night_mean = np.mean(no_night_img)
@@ -151,34 +176,7 @@ def _check_overall_intensity(night_img, no_night_img):
'intense than night mode OFF image! '
f'Ratio: {overall_intensity_ratio:.2f}, '
f'Expected: {_INTENSITY_IMPROVEMENT_TOL}')
-
-
-def _check_edge_noise(night_y, no_night_y):
- """Checks that noise at the edges significantly improves with night mode ON.
-
- Args:
- night_y: y_plane from a capture with night mode ON.
- no_night_y: y_plane from a capture with night mode OFF.
- """
- # Normalize both y planes to [0, 255]
- night_y *= 255
- no_night_y *= 255
- left_patch_ratio, right_patch_ratio = _get_edge_noise(
- night_y, no_night_y)
- logging.debug('Left edge of night mode OFF capture was %.2f times '
- 'as noisy as night mode ON', left_patch_ratio)
- logging.debug('Right edge of night mode OFF capture was %.2f times '
- 'as noisy as night mode ON', right_patch_ratio)
- if left_patch_ratio < _EDGE_NOISE_IMPROVEMENT_TOL:
- raise AssertionError('Left edge of night mode OFF capture was only '
- f'{float(left_patch_ratio):.2f} as noisy as '
- 'night mode OFF, expected to be '
- f'at least {_EDGE_NOISE_IMPROVEMENT_TOL}')
- if right_patch_ratio < _EDGE_NOISE_IMPROVEMENT_TOL:
- raise AssertionError('Right edge of night mode OFF capture was only '
- f'{float(right_patch_ratio):.2f} as noisy as '
- 'night mode OFF, expected to be '
- f'at least {_EDGE_NOISE_IMPROVEMENT_TOL}')
+ return overall_intensity_ratio > _IDEAL_INTENSITY_IMPROVEMENT
class NightExtensionTest(its_base_test.ItsBaseTest):
@@ -190,8 +188,7 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
3. Takes capture with night extension OFF using an auto capture request.
Verifies that the capture with night mode ON:
* takes longer
- * is brighter
- * contains less edge noise
+ * is brighter OR improves appearance of scene artifacts
"""
def find_tablet_brightness(self, cam, default_brightness, file_stem,
@@ -255,8 +252,12 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
except AssertionError:
logging.debug('Unable to find circle with brightness %d', brightness)
max_brightness = brightness
- if not final_brightness:
- raise AssertionError('Unable to find a valid brightness for the tablet')
+ if final_brightness is None:
+ logging.debug('Unable to find orientation dot at any brightness, '
+ 'defaulting to %.2f of current tablet brightness.',
+ _DEFAULT_TABLET_BRIGHTNESS_SCALING)
+ return int(_DEFAULT_TABLET_BRIGHTNESS_SCALING *
+ self.tablet_screen_brightness)
return final_brightness
def _time_and_take_captures(self, cam, req, out_surfaces,
@@ -365,19 +366,7 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
extension_capture_sizes.reverse()
logging.debug('Capture sizes: %s', capture_sizes)
logging.debug('Extension capture sizes: %s', extension_capture_sizes)
-
- for capture_size, extension_capture_size in zip(
- capture_sizes, extension_capture_sizes):
- if capture_size == extension_capture_size:
- width, height = capture_size
- break
- else:
- raise AssertionError(
- 'No matching sizes for non-extension and extension captures! '
- f'Camera ID {self.camera_id}, '
- f'extension {_EXTENSION_NIGHT}, and '
- f'format {_IMAGE_FORMAT_YUV_420_888_INT}'
- )
+ width, height = extension_capture_sizes[0]
# Set tablet brightness to darken scene
file_stem = f'{test_name}_{_FMT_NAME}_{width}x{height}'
@@ -420,12 +409,20 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
f'Difference: {duration_diff:.2f}, '
f'Expected: {_DURATION_DIFF_TOL}')
- logging.debug('Comparing overall intensity of capture with '
- 'night mode ON/OFF')
- _check_overall_intensity(night_img, no_night_img)
-
- logging.debug('Comparing edge noise of capture with night mode ON/OFF')
- _check_edge_noise(night_y, no_night_y)
+ logging.debug('Checking that dot intensities with Night ON match the '
+ 'expected values from the scene')
+ # Normalize y planes to [0:255]
+ dot_intensities_acceptable = _check_dot_intensity_diff(
+ night_img, night_y * 255, no_night_img, no_night_y * 255)
+
+ if not dot_intensities_acceptable:
+ logging.debug('Comparing overall intensity of capture with '
+ 'night mode ON/OFF')
+ much_higher_intensity = _check_overall_intensity(
+ night_img, no_night_img)
+ if not much_higher_intensity:
+ logging.warning(
+ 'Improvement in intensity was smaller than expected.')
if __name__ == '__main__':
test_runner.main()
diff --git a/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py b/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
index 149ad2aea2c..c27b192c8b6 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
@@ -15,8 +15,8 @@
import logging
-import multiprocessing
import os
+import threading
import time
import cv2
@@ -181,7 +181,7 @@ class MultiCameraFrameSyncTest(its_base_test.ItsBaseTest):
sensor_fusion_utils.ARDUINO_STRING)
# send test cmd to Arduino until cmd returns properly
sensor_fusion_utils.establish_serial_comm(serial_port)
- p = multiprocessing.Process(
+ p = threading.Thread(
target=sensor_fusion_utils.rotation_rig,
args=(
rot_rig['cntl'],
diff --git a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
index 1d99d643932..d860b37d5f1 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
@@ -14,8 +14,8 @@
"""Verify preview is stable during phone movement."""
import logging
-import multiprocessing
import os
+import threading
import time
from mobly import test_runner
@@ -74,7 +74,7 @@ def _collect_data(cam, tablet_device, video_size, rot_rig):
servo_speed = _TABLET_SERVO_SPEED
else:
servo_speed = _ARDUINO_SERVO_SPEED
- p = multiprocessing.Process(
+ p = threading.Thread(
target=sensor_fusion_utils.rotation_rig,
args=(
rot_rig['cntl'],
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index c925d5c81b9..c68789afc7e 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -17,9 +17,9 @@
import json
import logging
import math
-import multiprocessing
import os
import sys
+import threading
import time
from matplotlib import pylab
@@ -105,7 +105,7 @@ def _collect_data(cam, fps, w, h, test_length, rot_rig, chart_dist,
sensor_fusion_utils.ARDUINO_STRING)
# send test cmd to Arduino until cmd returns properly
sensor_fusion_utils.establish_serial_comm(serial_port)
- p = multiprocessing.Process(
+ p = threading.Thread(
target=sensor_fusion_utils.rotation_rig,
args=(
rot_rig['cntl'],
diff --git a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
index ecdcc21359b..3f069073551 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
@@ -15,8 +15,8 @@
import logging
import math
-import multiprocessing
import os
+import threading
import time
from mobly import test_runner
@@ -84,7 +84,7 @@ def _collect_data(cam, tablet_device, video_profile, video_quality, rot_rig):
else:
servo_speed = _ARDUINO_SERVO_SPEED
- p = multiprocessing.Process(
+ p = threading.Thread(
target=sensor_fusion_utils.rotation_rig,
args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,
_ARDUINO_ANGLES, servo_speed, _ARDUINO_MOVE_TIME, serial_port))
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index 62bfda93fa9..fd3d5e0dbd7 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -20,6 +20,7 @@ import os
import pathlib
import cv2
import numpy
+from scipy import spatial
import capture_request_utils
import error_util
@@ -46,9 +47,12 @@ CIRCLISH_LOW_RES_ATOL = 0.15 # loosen for low res images
CIRCLE_MIN_PTS = 20
CIRCLE_RADIUS_NUMPTS_THRESH = 2 # contour num_pts/radius: empirically ~3x
CIRCLE_COLOR_ATOL = 0.05 # circle color fill tolerance
+CIRCLE_LOCATION_VARIATION_RTOL = 0.05 # tolerance to remove similar circles
CV2_LINE_THICKNESS = 3 # line thickness for drawing on images
CV2_RED = (255, 0, 0) # color in cv2 to draw lines
+CV2_THRESHOLD_BLOCK_SIZE = 11
+CV2_THRESHOLD_CONSTANT = 2
CV2_HOME_DIRECTORY = os.path.dirname(cv2.__file__)
CV2_ALTERNATE_DIRECTORY = pathlib.Path(CV2_HOME_DIRECTORY).parents[3]
@@ -466,7 +470,7 @@ def find_circle_fill_metric(shape, img_bw, color):
return matching / total
-def find_circle(img, img_name, min_area, color):
+def find_circle(img, img_name, min_area, color, use_adaptive_threshold=False):
"""Find the circle in the test image.
Args:
@@ -474,6 +478,7 @@ def find_circle(img, img_name, min_area, color):
img_name: string with image info of format and size.
min_area: float of minimum area of circle to find
color: int of [0 or 255] 0 is black, 255 is white
+ use_adaptive_threshold: True if binarization should use adaptive threshold.
Returns:
circle = {'x', 'y', 'r', 'w', 'h', 'x_offset', 'y_offset'}
@@ -485,11 +490,15 @@ def find_circle(img, img_name, min_area, color):
else:
circlish_atol = CIRCLISH_LOW_RES_ATOL
- # convert to gray-scale image
- img_gray = convert_to_gray(img)
-
- # otsu threshold to binarize the image
- img_bw = binarize_image(img_gray)
+ # convert to gray-scale image and binarize using adaptive/global threshold
+ if use_adaptive_threshold:
+ img_gray = cv2.cvtColor(img.astype(numpy.uint8), cv2.COLOR_BGR2GRAY)
+ img_bw = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
+ cv2.THRESH_BINARY, CV2_THRESHOLD_BLOCK_SIZE,
+ CV2_THRESHOLD_CONSTANT)
+ else:
+ img_gray = convert_to_gray(img)
+ img_bw = binarize_image(img_gray)
# find contours
contours = find_all_contours(255-img_bw)
@@ -517,6 +526,35 @@ def find_circle(img, img_name, min_area, color):
math.isclose(1.0, aspect_ratio, abs_tol=CIRCLE_AR_ATOL) and
num_pts/radius >= CIRCLE_RADIUS_NUMPTS_THRESH and
math.isclose(1.0, fill, abs_tol=CIRCLE_COLOR_ATOL)):
+ # spatial.distance.euclidean can handle nested numpy arrays
+ radii = [
+ spatial.distance.euclidean((shape['ctx'], shape['cty']), point)
+ for point in contour
+ ]
+ minimum_radius, maximum_radius = min(radii), max(radii)
+ logging.debug('Minimum radius: %.2f, maximum radius: %.2f',
+ minimum_radius, maximum_radius)
+ if circle:
+ old_circle_center = (circle['x'], circle['y'])
+ new_circle_center = (shape['ctx'], shape['cty'])
+ # Based on image height
+ center_distance_atol = img_size[0]*CIRCLE_LOCATION_VARIATION_RTOL
+ if math.isclose(
+ spatial.distance.euclidean(old_circle_center, new_circle_center),
+ 0,
+ abs_tol=center_distance_atol
+ ) and maximum_radius - minimum_radius < circle['radius_spread']:
+ logging.debug('Replacing the previously found circle. '
+ 'Circle located at %s has a smaller radius spread '
+ 'than the previously found circle at %s. '
+ 'Current radius spread: %.2f, '
+ 'previous radius spread: %.2f',
+ new_circle_center, old_circle_center,
+ maximum_radius - minimum_radius,
+ circle['radius_spread'])
+ circle_contours.pop()
+ circle = {}
+ num_circles -= 1
circle_contours.append(contour)
# Populate circle dictionary
@@ -527,6 +565,7 @@ def find_circle(img, img_name, min_area, color):
circle['h'] = float(shape['height'])
circle['x_offset'] = (shape['ctx'] - img_size[1]//2) / circle['w']
circle['y_offset'] = (shape['cty'] - img_size[0]//2) / circle['h']
+ circle['radius_spread'] = maximum_radius - minimum_radius
logging.debug('Num pts: %d', num_pts)
logging.debug('Aspect ratio: %.3f', aspect_ratio)
logging.debug('Circlish value: %.3f', circlish)
@@ -541,8 +580,12 @@ def find_circle(img, img_name, min_area, color):
if num_circles == 0:
image_processing_utils.write_image(img/255, img_name, True)
- raise AssertionError('No black circle detected. '
- 'Please take pictures according to instructions.')
+ if not use_adaptive_threshold:
+ return find_circle(
+ img, img_name, min_area, color, use_adaptive_threshold=True)
+ else:
+ raise AssertionError('No circle detected. '
+ 'Please take pictures according to instructions.')
if num_circles > 1:
image_processing_utils.write_image(img/255, img_name, True)
@@ -551,7 +594,10 @@ def find_circle(img, img_name, min_area, color):
img_name_parts = img_name.split('.')
image_processing_utils.write_image(
img/255, f'{img_name_parts[0]}_contours.{img_name_parts[1]}', True)
- raise AssertionError('More than 1 black circle detected. '
+ if not use_adaptive_threshold:
+ return find_circle(
+ img, img_name, min_area, color, use_adaptive_threshold=True)
+ raise AssertionError('More than 1 circle detected. '
'Background of scene may be too complex.')
return circle
diff --git a/apps/CameraITS/utils/video_processing_utils.py b/apps/CameraITS/utils/video_processing_utils.py
index 1665dbf8e57..3045d1f9811 100644
--- a/apps/CameraITS/utils/video_processing_utils.py
+++ b/apps/CameraITS/utils/video_processing_utils.py
@@ -247,14 +247,13 @@ def get_average_frame_rate(video_file_name_with_path):
Float. average frames per second.
"""
- cmd = ['ffmpeg',
- '-i',
- video_file_name_with_path,
- '-vf',
- 'vfrdet',
- '-f',
- 'null',
- '-',
+ cmd = ['ffprobe',
+ '-v',
+ 'quiet',
+ '-show_streams',
+ '-select_streams',
+ 'v:0', # first video stream
+ video_file_name_with_path
]
logging.debug('Getting frame rate')
raw_output = ''
@@ -266,18 +265,16 @@ def get_average_frame_rate(video_file_name_with_path):
raise AssertionError(str(e.output)) from e
if raw_output:
output = str(raw_output.decode('utf-8')).strip()
- logging.debug('FFmpeg command %s output: %s', ' '.join(cmd), output)
- fps_data = output.splitlines()[-3] # frames printed on third to last line
- frames = int(re.search(r'frame= *([0-9]+)', fps_data).group(1))
- duration = re.search(r'time= *([0-9][0-9:\.]*)', fps_data).group(1)
- time_parts = [float(t) for t in duration.split(':')]
- seconds = time_parts[0] * HR_TO_SEC + time_parts[
- 1] * MIN_TO_SEC + time_parts[2]
- logging.debug('Average FPS: %d / %d = %.4f',
- frames, seconds, frames / seconds)
- return frames / seconds
+ logging.debug('ffprobe command %s output: %s', ' '.join(cmd), output)
+ average_frame_rate_data = (
+ re.search(r'avg_frame_rate=*([0-9]+/[0-9]+)', output).group(1)
+ )
+ average_frame_rate = (int(average_frame_rate_data.split('/')[0]) /
+ int(average_frame_rate_data.split('/')[1]))
+ logging.debug('Average FPS: %.4f', average_frame_rate)
+ return average_frame_rate
else:
- raise AssertionError('ffmpeg failed to provide frame rate data')
+ raise AssertionError('ffprobe failed to provide frame rate data')
def get_frame_deltas(video_file_name_with_path, timestamp_type='pts'):
diff --git a/apps/CtsVerifier/jni/midi/MidiTestManager.cpp b/apps/CtsVerifier/jni/midi/MidiTestManager.cpp
index 80d40b781d2..939fe39b888 100644
--- a/apps/CtsVerifier/jni/midi/MidiTestManager.cpp
+++ b/apps/CtsVerifier/jni/midi/MidiTestManager.cpp
@@ -257,7 +257,7 @@ int MidiTestManager::matchStream(uint8_t* bytes, int count) {
return matchedByteCount;
}
-#define THROTTLE_PERIOD_MS 10
+#define THROTTLE_PERIOD_MS 20
#define THROTTLE_MAX_PACKET_SIZE 15
int portSend(AMidiInputPort* sendPort, uint8_t* msg, int length, bool throttle) {
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index e38d57b22e2..17749a75145 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -2554,7 +2554,7 @@
\nPull down the notification shade and look for the NotifPrivacyTest notification.
\nFail the test if it can be found without unlocking the device.
\n\nGo back when ready to Pass/Fail the step.</string>
- <string name="np_public_version_text">NotifPrivacyTefst: REDACTED</string>
+ <string name="np_public_version_text">NotifPrivacyTest: REDACTED</string>
<string name="np_private_version_text">NotifPrivacyTest: EXPOSED</string>
<string name="notif_privacy_test">Notification Privacy Test</string>
<string name="notif_privacy_info">This test checks that Notification privacy is correctly
@@ -4462,7 +4462,7 @@ You should be prompted to select credentials; choose the ones you just installed
Set \'%s\' user restriction by turning on the switch below.
</string>
<string name="disallow_add_user">Disallow add user</string>
- <string name="disallow_add_user_action">Adding a new user</string>
+ <string name="disallow_add_user_action">Accessing the multiple users settings page, or if the device allows access to the page, then attempting to add a new user </string>
<string name="disallow_adjust_volume">Disallow adjust volume</string>
<string name="disallow_adjust_volume_action">Adjusting the volume\n
NOTE: If the device does not support volume adjustment in Settings app please skip this test and mark it as passing.\n</string>
@@ -5717,7 +5717,8 @@ You should be prompted to select credentials; choose the ones you just installed
<string name="audio_loopback_results_text">Results...</string>
<string name="audio_loopback_test_all_paths">Please test all supported paths.</string>
<string name="audio_loopback_test_not_required">Test not required for this device.</string>
- <string name="audio_loopback_test_non_handheld">This device is not a handheld. Test can pass.</string>
+ <string name="audio_loopback_test_non_handheld">This device is not a phone. Test can pass.</string>
+ <string name="audio_loopback_test_internal_devices">Speaker/Mic</string>
<string name="audio_loopback_speakermicpath_instructions">Place the DUT flat on a table
in a quiet room. Press the Start button and allow the test to proceed.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
index bb0f87956ba..872590e9121 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
@@ -92,7 +92,7 @@ public abstract class AbstractTestListActivity extends ListActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((getResources().getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK)
- == Configuration.UI_MODE_TYPE_TELEVISION) {
+ == Configuration.UI_MODE_TYPE_TELEVISION) {
getWindow().requestFeature(Window.FEATURE_OPTIONS_PANEL);
}
setContentView(R.layout.list_content);
@@ -114,10 +114,11 @@ public abstract class AbstractTestListActivity extends ListActivity {
mEndTime = System.currentTimeMillis();
}
TestResult testResult = TestResult.fromActivityResult(resultCode, data);
- // Set the same result in both folded and unfolded mode if the test pass mode is set to
- // either_mode.
+ // Set the same result in both folded and unfolded mode if the device is foldable
+ // and the test pass mode is set to either_mode.
TestListItem testListItem = mAdapter.getItemByName(testResult.getName());
- if (testListItem != null && testListItem.passInEitherMode) {
+ if (mAdapter.isFoldableDevice() && testListItem != null
+ && testListItem.passInEitherMode) {
setTestResult(TestResult.fromActivityResultWithDisplayMode(
resultCode, data, DisplayMode.FOLDED.toString()));
setTestResult(TestResult.fromActivityResultWithDisplayMode(
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
index 5857b484c59..43dd4cbf4eb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
@@ -117,7 +117,29 @@ public class PassFailButtons {
void setTestResultAndFinish(boolean passed);
/**
+ * @return true if the test module will write a ReportLog entry
+ *
+ * Note that in order to obtain a non-null CtsVerifierReportLog object from
+ * the getReportLog() method, the activity must override this method to return true
+ * and should implement the getReportFileName(), getReportSectionName() and
+ * recordTestResults() methods.
+ *
+ * If this method returns true and the user did not setup up CtsVerifier correctly
+ * with respect to accessing local data on the DUT;
+ * <code>
+ * adb shell appops set com.android.cts.verifier android:read_device_identifiers allow
+ * adb shell appops set com.android.cts.verifier MANAGE_EXTERNAL_STORAGE 0
+ * </code>
+ * a warning dialog will be displayed when invoking that test.
+ */
+ public boolean requiresReportLog();
+
+ /**
* @return The name of the file to store the (suite of) ReportLog information.
+ *
+ * If a test uses the CtsVerifierReportLog, it should implement this method to provide
+ * a file name for the (JSON) report log data. This does not need to be unique to the
+ * test, perhaps specific to a set of related tests.
*/
public String getReportFileName();
@@ -125,16 +147,29 @@ public class PassFailButtons {
* @return A unique name to serve as a section header in the CtsVerifierReportLog file.
* Tests need to conform to the underscore_delineated_name standard for use with
* the protobuff/json ReportLog parsing in Google3
+ *
+ * If the test implements this method, it should also implement the requiresReportLog()
+ * method to return true and the getReportFileName() and recordTestResults() methods.
*/
public String getReportSectionName();
/**
* Test subclasses can override this to record their CtsVerifierReportLogs.
- * This is called when the test is exited
+ * This is called when the test is exited.
+ *
+ * NOTE: If the test gathers reportLog data, the test class should implement
+ * the requiresReportLog() to return true, and implement the getReportFileName() and
+ * getReportSectionName() methods.
*/
void recordTestResults();
- /** @return A {@link ReportLog} that is used to record test metric data. */
+ /**
+ * @return A {@link ReportLog} that is used to record test metric data or null.
+ *
+ * If a test calls this method it must implement the requiresReportLog() to return true,
+ * and implement the getReportFileName() and getReportSectionName() methods, otherwise
+ * this method will return null.
+ */
CtsVerifierReportLog getReportLog();
/**
@@ -222,10 +257,7 @@ public class PassFailButtons {
getReportFileName(), getReportSectionName());
}
- /**
- * Specifies if the test module will write a ReportLog entry
- * @return true if the test module will write a ReportLog entry
- */
+ @Override
public boolean requiresReportLog() {
return false;
}
@@ -329,6 +361,11 @@ public class PassFailButtons {
}
@Override
+ public boolean requiresReportLog() {
+ return false;
+ }
+
+ @Override
public CtsVerifierReportLog getReportLog() {
return mReportLog;
}
@@ -422,6 +459,11 @@ public class PassFailButtons {
}
@Override
+ public boolean requiresReportLog() {
+ return false;
+ }
+
+ @Override
public CtsVerifierReportLog getReportLog() {
return mReportLog;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
index 03aec7a0beb..d4007f9edea 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
@@ -25,6 +25,7 @@ import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
+import android.hardware.devicestate.DeviceStateManager;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
@@ -44,10 +45,13 @@ import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
/**
* {@link BaseAdapter} that handles loading, refreshing, and setting test results. What tests are
@@ -442,12 +446,12 @@ public abstract class TestListAdapter extends BaseAdapter {
histories.merge(null, mHistories.get(name));
new SetTestResultTask(
- name,
- testResult.getResult(),
- testResult.getDetails(),
- testResult.getReportLog(),
- histories,
- mScreenshotsMetadata.get(name))
+ name,
+ testResult.getResult(),
+ testResult.getDetails(),
+ testResult.getReportLog(),
+ histories,
+ mScreenshotsMetadata.get(name))
.execute();
}
@@ -522,13 +526,13 @@ public abstract class TestListAdapter extends BaseAdapter {
protected abstract List<TestListItem> getRows();
static final String[] REFRESH_PROJECTION = {
- TestResultsProvider._ID,
- TestResultsProvider.COLUMN_TEST_NAME,
- TestResultsProvider.COLUMN_TEST_RESULT,
- TestResultsProvider.COLUMN_TEST_DETAILS,
- TestResultsProvider.COLUMN_TEST_METRICS,
- TestResultsProvider.COLUMN_TEST_RESULT_HISTORY,
- TestResultsProvider.COLUMN_TEST_SCREENSHOTS_METADATA,
+ TestResultsProvider._ID,
+ TestResultsProvider.COLUMN_TEST_NAME,
+ TestResultsProvider.COLUMN_TEST_RESULT,
+ TestResultsProvider.COLUMN_TEST_DETAILS,
+ TestResultsProvider.COLUMN_TEST_METRICS,
+ TestResultsProvider.COLUMN_TEST_RESULT_HISTORY,
+ TestResultsProvider.COLUMN_TEST_SCREENSHOTS_METADATA,
};
RefreshResult getRefreshResults(List<TestListItem> items) {
@@ -635,12 +639,12 @@ public abstract class TestListAdapter extends BaseAdapter {
ContentResolver resolver = mContext.getContentResolver();
try (Cursor cursor =
- resolver.query(
- TestResultsProvider.getTestNameUri(mContext, mTestName),
- new String[] {TestResultsProvider.COLUMN_TEST_RESULT_HISTORY},
- null,
- null,
- null)) {
+ resolver.query(
+ TestResultsProvider.getTestNameUri(mContext, mTestName),
+ new String[] {TestResultsProvider.COLUMN_TEST_RESULT_HISTORY},
+ null,
+ null,
+ null)) {
if (cursor.moveToFirst()) {
do {
TestResultHistoryCollection historyCollection =
@@ -848,8 +852,8 @@ public abstract class TestListAdapter extends BaseAdapter {
for (TestListItem item : mRows) {
if (item != null && item.isTest()
&& (!mTestResults.containsKey(item.testName)
- || (mTestResults.get(item.testName)
- != TestResult.TEST_RESULT_PASSED))) {
+ || (mTestResults.get(item.testName)
+ != TestResult.TEST_RESULT_PASSED))) {
return false;
}
}
@@ -907,6 +911,26 @@ public abstract class TestListAdapter extends BaseAdapter {
return textView;
}
+ /**
+ * Uses {@link DeviceStateManager} to determine if the device is foldable or not. It relies on
+ * the OEM exposing supported states, and setting
+ * com.android.internal.R.array.config_foldedDeviceStates correctly with the folded states.
+ *
+ * @return true if the device is foldable, false otherwise
+ */
+ public boolean isFoldableDevice() {
+ DeviceStateManager deviceStateManager = mContext.getSystemService(DeviceStateManager.class);
+ if (deviceStateManager == null) {
+ return false;
+ }
+ Set<Integer> supportedStates = Arrays.stream(
+ deviceStateManager.getSupportedStates()).boxed().collect(Collectors.toSet());
+ int identifier = mContext.getResources().getIdentifier(
+ "config_foldedDeviceStates", "array", "android");
+ int[] foldedDeviceStates = mContext.getResources().getIntArray(identifier);
+ return Arrays.stream(foldedDeviceStates).anyMatch(supportedStates::contains);
+ }
+
private int getLayout(int position) {
int viewType = getItemViewType(position);
switch (viewType) {
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 00c5e6e2790..24e9ac46ba3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
@@ -106,6 +106,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
private boolean mIsTV;
private boolean mIsAutomobile;
private boolean mIsHandheld;
+ private int mSpeakerDeviceId = AudioDeviceInfo.TYPE_UNKNOWN;
+ private int mMicDeviceId = AudioDeviceInfo.TYPE_UNKNOWN;
// Peripheral(s)
private static final int NUM_TEST_ROUTES = 3;
@@ -371,8 +373,7 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
mTestInstructions = (TextView) findViewById(R.id.audio_loopback_instructions);
mAudioManager = getSystemService(AudioManager.class);
-
- mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
+ scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
connectLoopbackUI();
@@ -384,6 +385,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
enableStartButtons(false);
}
+ mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
+
showTestInstructions();
handleTestCompletion(false);
}
@@ -459,19 +462,19 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
clearDeviceIds();
clearDeviceConnected();
+ mSpeakerDeviceId = AudioDeviceInfo.TYPE_UNKNOWN;
+ mMicDeviceId = AudioDeviceInfo.TYPE_UNKNOWN;
for (AudioDeviceInfo devInfo : devices) {
switch (devInfo.getType()) {
// TESTROUTE_DEVICE (i.e. Speaker & Mic)
+ // This needs to be handled differently. The other devices can be assumed
+ // to contain both input & output devices in the same type.
+ // For built-in we need to see both TYPES to be sure to have both input & output.
case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
+ mSpeakerDeviceId = devInfo.getId();
+ break;
case AudioDeviceInfo.TYPE_BUILTIN_MIC:
- if (devInfo.isSink()) {
- mTestSpecs[TESTROUTE_DEVICE].mOutputDeviceId = devInfo.getId();
- } else if (devInfo.isSource()) {
- mTestSpecs[TESTROUTE_DEVICE].mInputDeviceId = devInfo.getId();
- }
- mTestSpecs[TESTROUTE_DEVICE].mRouteAvailable = true;
- mTestSpecs[TESTROUTE_DEVICE].mRouteConnected = true;
- mTestSpecs[TESTROUTE_DEVICE].mDeviceName = devInfo.getProductName().toString();
+ mMicDeviceId = devInfo.getId();
break;
// TESTROUTE_ANALOG_JACK
@@ -500,9 +503,19 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
mTestSpecs[TESTROUTE_USB].mRouteConnected = true;
mTestSpecs[TESTROUTE_USB].mDeviceName = devInfo.getProductName().toString();
}
+ }
- enableStartButtons(mustRunTest());
+ // do we have BOTH a Speaker and Mic?
+ if (hasInternalPath()) {
+ mTestSpecs[TESTROUTE_DEVICE].mOutputDeviceId = mSpeakerDeviceId;
+ mTestSpecs[TESTROUTE_DEVICE].mInputDeviceId = mMicDeviceId;
+ mTestSpecs[TESTROUTE_DEVICE].mRouteAvailable = true;
+ mTestSpecs[TESTROUTE_DEVICE].mRouteConnected = true;
+ mTestSpecs[TESTROUTE_DEVICE].mDeviceName =
+ getResources().getString(R.string.audio_loopback_test_internal_devices);
}
+
+ enableStartButtons(mustRunTest());
}
private class ConnectListener extends AudioDeviceCallback {
@@ -737,7 +750,12 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
}
private boolean mustRunTest() {
- return mIsHandheld;
+ return mIsHandheld && hasInternalPath();
+ }
+
+ boolean hasInternalPath() {
+ return mSpeakerDeviceId != AudioDeviceInfo.TYPE_UNKNOWN
+ && mMicDeviceId != AudioDeviceInfo.TYPE_UNKNOWN;
}
private boolean calcPass(LoopbackLatencyRequirements requirements) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/midilib/JavaMidiTestModule.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/midilib/JavaMidiTestModule.java
index 7a3056c51b9..384b25f336f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/midilib/JavaMidiTestModule.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/midilib/JavaMidiTestModule.java
@@ -55,7 +55,7 @@ public abstract class JavaMidiTestModule extends MidiTestModule {
// the bandwidth, resulting in lost data. In this case, slow the data stream
// down.
private static final int THROTTLE_MAX_PACKET_SIZE = 15;
- private static final int THROTTLE_PERIOD_MS = 10;
+ private static final int THROTTLE_PERIOD_MS = 20;
private static final int MESSAGE_MAX_BYTES = 4096;
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 11e1cfe60f4..d1c44ec4051 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
@@ -1717,15 +1717,22 @@ public class ItsService extends Service implements SensorEventListener {
mSocketRunnableObj.sendResponse("camera1080pJpegCaptureMs", Double.toString(jpegCaptureMs));
}
- private static long getReaderUsage(int format) {
+ private static long getReaderUsage(int format, boolean has10bitOutput) {
// Private image format camera readers will default to ZSL usage unless
// explicitly configured to use a common consumer such as display.
- return (format == ImageFormat.PRIVATE) ? HardwareBuffer.USAGE_COMPOSER_OVERLAY :
- HardwareBuffer.USAGE_CPU_READ_OFTEN;
+ // We don't support the ZSL use case within the 10-bit use case.
+ return (format == ImageFormat.PRIVATE && has10bitOutput) ?
+ HardwareBuffer.USAGE_COMPOSER_OVERLAY : HardwareBuffer.USAGE_CPU_READ_OFTEN;
}
private void prepareImageReaders(Size[] outputSizes, int[] outputFormats, Size inputSize,
int inputFormat, int maxInputBuffers) {
+ prepareImageReaders(outputSizes, outputFormats, inputSize,
+ inputFormat, maxInputBuffers, /*has10bitOutput*/ false);
+ }
+
+ private void prepareImageReaders(Size[] outputSizes, int[] outputFormats, Size inputSize,
+ int inputFormat, int maxInputBuffers, boolean has10bitOutput) {
closeImageReaders();
mOutputImageReaders = new ImageReader[outputSizes.length];
for (int i = 0; i < outputSizes.length; i++) {
@@ -1734,18 +1741,19 @@ public class ItsService extends Service implements SensorEventListener {
mOutputImageReaders[i] = ImageReader.newInstance(outputSizes[i].getWidth(),
outputSizes[i].getHeight(), outputFormats[i],
MAX_CONCURRENT_READER_BUFFERS + maxInputBuffers,
- getReaderUsage(outputFormats[i]));
+ getReaderUsage(outputFormats[i], has10bitOutput));
mInputImageReader = mOutputImageReaders[i];
} else {
mOutputImageReaders[i] = ImageReader.newInstance(outputSizes[i].getWidth(),
outputSizes[i].getHeight(), outputFormats[i],
- MAX_CONCURRENT_READER_BUFFERS, getReaderUsage(outputFormats[i]));
+ MAX_CONCURRENT_READER_BUFFERS, getReaderUsage(outputFormats[i],
+ has10bitOutput));
}
}
if (inputSize != null && mInputImageReader == null) {
mInputImageReader = ImageReader.newInstance(inputSize.getWidth(), inputSize.getHeight(),
- inputFormat, maxInputBuffers, getReaderUsage(inputFormat));
+ inputFormat, maxInputBuffers, getReaderUsage(inputFormat, has10bitOutput));
}
}
@@ -2269,7 +2277,8 @@ public class ItsService extends Service implements SensorEventListener {
}
}
- prepareImageReaders(outputSizes, outputFormats, inputSize, inputFormat, maxInputBuffers);
+ prepareImageReaders(outputSizes, outputFormats, inputSize, inputFormat, maxInputBuffers,
+ is10bitOutputPresent);
return is10bitOutputPresent;
}
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 ca76b72f807..c31bc414ca2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -71,6 +71,7 @@ public class ByodFlowTestActivity extends DialogTestListActivity {
private static final int REQUEST_INTENT_FILTERS_STATUS = 2;
private static final int REQUEST_CHECK_DISK_ENCRYPTION = 3;
private static final int REQUEST_SET_LOCK_FOR_ENCRYPTION = 4;
+ private static final int REQUEST_DELETE_MANAGED_PROFILE = 5;
private static final String PROVISIONING_PREFERENCES = "provisioning_preferences";
private static final String PREFERENCE_PROVISIONING_COMPLETE_STATUS =
@@ -236,6 +237,10 @@ public class ByodFlowTestActivity extends DialogTestListActivity {
// Called after checkIntentFilters()
handleIntentFiltersStatus(resultCode);
break;
+ case REQUEST_DELETE_MANAGED_PROFILE:
+ // Called during finish()
+ finishAfterProfileDeleted();
+ break;
default:
super.handleActivityResult(requestCode, resultCode, data);
}
@@ -252,6 +257,13 @@ public class ByodFlowTestActivity extends DialogTestListActivity {
public void finish() {
// Pass and fail buttons are known to call finish() when clicked, and this is when we want to
// clean up the provisioned profile.
+ Intent intent = new Intent(ByodHelperActivity.ACTION_REMOVE_MANAGED_PROFILE);
+ // Wait until the managed profile is deleted before returning to the previous
+ // activity, to ensure the deletion is not interrupted.
+ startActivityForResult(intent, REQUEST_DELETE_MANAGED_PROFILE);
+ }
+
+ private void finishAfterProfileDeleted() {
mByodFlowTestHelper.tearDown();
super.finish();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
index b0cc3ac89df..cf32cb77704 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -34,7 +34,6 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.MediaStore;
import android.util.Log;
@@ -258,6 +257,7 @@ public class ByodHelperActivity extends Activity
mDevicePolicyManager.clearCrossProfileIntentFilters(mAdminReceiverComponent);
mDevicePolicyManager.wipeData(0);
showToast(R.string.provisioning_byod_profile_deleted);
+ setResult(RESULT_OK);
}
} else if (action.equals(ACTION_CHECK_DISK_ENCRYPTION)) {
final int status = mDevicePolicyManager.getStorageEncryptionStatus();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/qstiles/InteractiveVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/qstiles/InteractiveVerifierActivity.java
index 44f2f28d641..e33a9dfb78d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/qstiles/InteractiveVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/qstiles/InteractiveVerifierActivity.java
@@ -189,8 +189,8 @@ public abstract class InteractiveVerifierActivity extends PassFailButtons.Activi
}
@Override
- protected void onResume() {
- super.onResume();
+ protected void onStart() {
+ super.onStart();
//To avoid NPE during onResume,before start to iterate next test order
if (mCurrentTest != null && mCurrentTest.autoStart()) {
mCurrentTest.status = READY;
@@ -201,8 +201,8 @@ public abstract class InteractiveVerifierActivity extends PassFailButtons.Activi
}
@Override
- protected void onPause() {
- super.onPause();
+ protected void onStop() {
+ super.onStop();
// Makes sure that the tile is removed when test is not running
setTileState(false);
}
diff --git a/common/device-side/bedstead/btest/btest b/common/device-side/bedstead/btest/btest
index 1432189f2f8..2b7b322a323 100755
--- a/common/device-side/bedstead/btest/btest
+++ b/common/device-side/bedstead/btest/btest
@@ -283,6 +283,7 @@ STATE_CODES = {
DEFAULT_STATES = "csywal"
SHORT_PACKAGE_PREFIXES = {
+ "a.d.c.t": "android.devicepolicy.cts.telephony",
"a.d.c": "android.devicepolicy.cts",
"a.d.g": "android.devicepolicy.gts",
"a.m.c": "android.multiuser.cts",
@@ -299,6 +300,11 @@ supported_modules = {
"runner": "androidx.test.runner.AndroidJUnitRunner",
"states": [RUN_ON_SYSTEM_USER, RUN_ON_WORK_PROFILE, RUN_ON_SECONDARY_USER, RUN_ON_ADDITIONAL_USER, RUN_ON_CLONE_PROFILE]
},
+ "CtsDevicePolicySimTestCases": {
+ "package": "android.devicepolicy.cts.telephony",
+ "runner": "androidx.test.runner.AndroidJUnitRunner",
+ "states": [RUN_ON_SYSTEM_USER, RUN_ON_WORK_PROFILE, RUN_ON_SECONDARY_USER, RUN_ON_ADDITIONAL_USER, RUN_ON_CLONE_PROFILE]
+ },
"GtsDevicePolicyTestCases": {
"package": "android.devicepolicy.gts",
"runner": "androidx.test.runner.AndroidJUnitRunner",
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireHasDefaultBrowser.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireHasDefaultBrowser.java
new file mode 100644
index 00000000000..853776454aa
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireHasDefaultBrowser.java
@@ -0,0 +1,37 @@
+/*
+ * 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 static com.android.bedstead.harrier.UserType.INSTRUMENTED_USER;
+
+import com.android.bedstead.harrier.UserType;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Requires the user has a default browser
+ */
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface RequireHasDefaultBrowser {
+ /** Which user type should we check the browser for. */
+ UserType forUser() default INSTRUMENTED_USER;
+
+ FailureMode failureMode() default FailureMode.SKIP;
+}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/FactoryResetProtection.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/FactoryResetProtection.java
index 37786e50b99..45c6a9f930c 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/FactoryResetProtection.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/FactoryResetProtection.java
@@ -30,9 +30,7 @@ import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
* {@code DevicePolicyManager#getFactoryResetProtection}.
*/
@EnterprisePolicy(dpc =
- APPLIED_BY_DEVICE_OWNER | APPLIED_BY_ORGANIZATION_OWNED_PROFILE_OWNER_PROFILE |
- APPLIED_BY_DPM_ROLE_HOLDER | APPLIES_GLOBALLY | CANNOT_BE_APPLIED_BY_ROLE_HOLDER,
- permissions =
- @EnterprisePolicy.Permission(appliedWith = MANAGE_DEVICE_POLICY_FACTORY_RESET, appliesTo = APPLIES_GLOBALLY))
+ APPLIED_BY_DEVICE_OWNER | APPLIED_BY_ORGANIZATION_OWNED_PROFILE_OWNER_PROFILE
+ | APPLIES_GLOBALLY | CANNOT_BE_APPLIED_BY_ROLE_HOLDER)
public final class FactoryResetProtection {
}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedInputMethods.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedInputMethods.java
index bf4f3c0b048..3b5179b73bb 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedInputMethods.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedInputMethods.java
@@ -32,7 +32,7 @@ import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
* <p>See {@code DevicePolicyManager#setPermittedInputMethods(ComponentName, List<String>)}
* for more detail.
*/ // APPLIED_BY_DPM_ROLE_HOLDER
-@EnterprisePolicy(dpc = APPLIED_BY_DEVICE_OWNER | APPLIED_BY_PROFILE_OWNER | APPLIED_BY_PARENT_INSTANCE_OF_ORGANIZATIONAL_OWNED_PROFILE_OWNER_PROFILE | APPLIES_TO_OWN_USER
+@EnterprisePolicy(dpc = APPLIED_BY_DEVICE_OWNER | APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER
| CANNOT_BE_APPLIED_BY_ROLE_HOLDER | INHERITABLE,
permissions = @EnterprisePolicy.Permission(appliedWith = MANAGE_DEVICE_POLICY_INPUT_METHODS,
appliesTo = APPLIES_TO_OWN_USER))
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedSystemInputMethods.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedSystemInputMethods.java
new file mode 100644
index 00000000000..1b372a2a5bf
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/PermittedSystemInputMethods.java
@@ -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 com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PARENT_INSTANCE_OF_ORGANIZATIONAL_OWNED_PROFILE_OWNER_PROFILE;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PROFILE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.CANNOT_BE_APPLIED_BY_ROLE_HOLDER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.INHERITABLE;
+import static com.android.bedstead.nene.permissions.CommonPermissions.MANAGE_DEVICE_POLICY_INPUT_METHODS;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/**
+ * Policy for setting permitted input methods - with the restriction that it only permits setting
+ * either system apps enabled or all apps enabled (with no option to specify particular apps).
+ *
+ * <p>See {@code DevicePolicyManager#setPermittedInputMethods(ComponentName, List<String>)}
+ * for more detail.
+ */
+@EnterprisePolicy(dpc = APPLIED_BY_PARENT_INSTANCE_OF_ORGANIZATIONAL_OWNED_PROFILE_OWNER_PROFILE | APPLIES_TO_OWN_USER
+ | CANNOT_BE_APPLIED_BY_ROLE_HOLDER | INHERITABLE)
+public class PermittedSystemInputMethods {
+}
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 99648fbfb08..7a7990d594f 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
@@ -17,6 +17,7 @@
package com.android.bedstead.harrier;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.app.role.RoleManager.ROLE_BROWSER;
import static android.content.pm.PackageManager.FEATURE_MANAGED_USERS;
import static android.os.Build.VERSION.SDK_INT;
@@ -75,6 +76,7 @@ import com.android.bedstead.harrier.annotations.EnsureHasAccountAuthenticator;
import com.android.bedstead.harrier.annotations.EnsureHasAccounts;
import com.android.bedstead.harrier.annotations.EnsureHasAdditionalUser;
import com.android.bedstead.harrier.annotations.EnsureHasAppOp;
+import com.android.bedstead.harrier.annotations.RequireHasDefaultBrowser;
import com.android.bedstead.harrier.annotations.EnsureHasNoAccounts;
import com.android.bedstead.harrier.annotations.EnsureHasNoAdditionalUser;
import com.android.bedstead.harrier.annotations.EnsureHasPermission;
@@ -1290,6 +1292,16 @@ public final class DeviceState extends HarrierRule {
requireQuickSettingsSupport.failureMode());
continue;
}
+ if (annotation instanceof RequireHasDefaultBrowser) {
+ RequireHasDefaultBrowser requireHasDefaultBrowser =
+ (RequireHasDefaultBrowser) annotation;
+ UserReference user =
+ resolveUserTypeToUser(requireHasDefaultBrowser.forUser());
+ checkFailOrSkip("User: " + user + " does not have a default browser",
+ !TestApis.roles().getRoleHoldersAsUser(ROLE_BROWSER, user).isEmpty(),
+ requireHasDefaultBrowser.failureMode());
+ continue;
+ }
if (annotation instanceof RequireTelephonySupport) {
RequireTelephonySupport requireTelephonySupport =
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
index 1606b6e510c..5fed6b470fa 100644
--- a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
@@ -54,6 +54,7 @@ import static org.testng.Assert.assertThrows;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.contentsuggestions.ContentSuggestionsManager;
+import android.app.role.RoleManager;
import android.os.Build;
import android.os.Bundle;
import android.os.UserManager;
@@ -108,6 +109,7 @@ import com.android.bedstead.harrier.annotations.RequireFeatureFlagEnabled;
import com.android.bedstead.harrier.annotations.RequireFeatureFlagNotEnabled;
import com.android.bedstead.harrier.annotations.RequireFeatureFlagValue;
import com.android.bedstead.harrier.annotations.RequireGmsBuild;
+import com.android.bedstead.harrier.annotations.RequireHasDefaultBrowser;
import com.android.bedstead.harrier.annotations.RequireHeadlessSystemUserMode;
import com.android.bedstead.harrier.annotations.RequireInstantApp;
import com.android.bedstead.harrier.annotations.RequireLowRamDevice;
@@ -1636,4 +1638,9 @@ public class DeviceStateTest {
assertThat(TestApis.content().suggestions().defaultServiceEnabled(sDeviceState.additionalUser())).isTrue();
}
+ @Test
+ @RequireHasDefaultBrowser
+ public void requireHasDefaultBrowser_onDifferentUser_defaultContentSuggestionsServiceIsEnabled() {
+ assertThat(TestApis.roles().getRoleHolders(RoleManager.ROLE_BROWSER)).isNotEmpty();
+ }
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
index 0383d3096f7..79492ec86bb 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
@@ -66,6 +66,7 @@ import com.android.bedstead.nene.permissions.Permissions;
import com.android.bedstead.nene.roles.RoleContext;
import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.utils.Poll;
+import com.android.bedstead.nene.utils.Retry;
import com.android.bedstead.nene.utils.ShellCommand;
import com.android.bedstead.nene.utils.ShellCommandUtils;
import com.android.bedstead.nene.utils.Versions;
@@ -718,13 +719,15 @@ public final class Package {
// In most cases this should work first time, however if a user restriction has been
// recently removed we may need to retry
+ int previousPid = runningProcess().pid();
Poll.forValue("Application flag", () -> {
userActivityManager.forceStopPackage(mPackageName);
return userPackageManager.getPackageInfo(mPackageName, PackageManager.GET_META_DATA)
.applicationInfo.flags;
})
- .toMeet(flag -> (flag & FLAG_STOPPED) == FLAG_STOPPED)
+ .toMeet(flag ->(flag & FLAG_STOPPED) == FLAG_STOPPED
+ || previousPid != runningProcess().pid())
.errorOnFail("Expected application flags to contain FLAG_STOPPED ("
+ FLAG_STOPPED + ")")
.await();
@@ -952,24 +955,48 @@ public final class Package {
public RoleContext setAsRoleHolder(String role, UserReference user) {
try (PermissionContext p = TestApis.permissions().withPermission(
MANAGE_ROLE_HOLDERS, INTERACT_ACROSS_USERS_FULL)) {
- DefaultBlockingCallback<Boolean> blockingCallback = new DefaultBlockingCallback<>();
-
- sRoleManager.addRoleHolderAsUser(
- role,
- mPackageName,
- /* flags= */ 0,
- user.userHandle(),
- TestApis.context().instrumentedContext().getMainExecutor(),
- blockingCallback::triggerCallback);
-
- boolean success = blockingCallback.await();
- if (!success) {
- fail("Could not set role holder of " + role + ".");
- }
+
+ Retry.logic(() -> {
+ TestApis.logcat().clear();
+ DefaultBlockingCallback<Boolean> blockingCallback = new DefaultBlockingCallback<>();
+
+ sRoleManager.addRoleHolderAsUser(
+ role,
+ mPackageName,
+ /* flags= */ 0,
+ user.userHandle(),
+ TestApis.context().instrumentedContext().getMainExecutor(),
+ blockingCallback::triggerCallback);
+
+ boolean success = blockingCallback.await();
+ if (!success) {
+ fail("Could not set role holder of " + role + "." + " Relevant logcat: "
+ + TestApis.logcat().dump((line) -> line.contains(role)));
+ }
+ if (!TestApis.roles().getRoleHoldersAsUser(role, user).contains(packageName())) {
+ fail("addRoleHolderAsUser returned true but did not add role holder. "
+ + "Relevant logcat: " + TestApis.logcat().dump(
+ (line) -> line.contains(role)));
+ }
+ }).terminalException(e -> {
+ // Terminal unless we see logcat output indicating it might be temporary
+ var logcat = TestApis.logcat()
+ .dump(l -> l.contains("Error calling onAddRoleHolder()"));
+ if (!logcat.isEmpty()) {
+ // On low end devices - this can happen when the broadcast queue is full
+ try {
+ Thread.sleep(10_000);
+ } catch (InterruptedException ex) {
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }).runAndWrapException();
return new RoleContext(role, this, user);
- } catch (InterruptedException e) {
- throw new NeneException("Error waiting for setting role holder callback " + role, e);
}
}
@@ -988,23 +1015,45 @@ public final class Package {
public void removeAsRoleHolder(String role, UserReference user) {
try (PermissionContext p = TestApis.permissions().withPermission(
MANAGE_ROLE_HOLDERS)) {
- DefaultBlockingCallback<Boolean> blockingCallback = new DefaultBlockingCallback<>();
- sRoleManager.removeRoleHolderAsUser(
- role,
- mPackageName,
- /* flags= */ 0,
- user.userHandle(),
- TestApis.context().instrumentedContext().getMainExecutor(),
- blockingCallback::triggerCallback);
- TestApis.roles().setBypassingRoleQualification(false);
-
- boolean success = blockingCallback.await();
- if (!success) {
- fail("Failed to clear the role holder of "
- + role + ".");
- }
- } catch (InterruptedException e) {
- throw new NeneException("Error while clearing role holder " + role, e);
+ Retry.logic(() -> {
+ TestApis.logcat().clear();
+ DefaultBlockingCallback<Boolean> blockingCallback = new DefaultBlockingCallback<>();
+ sRoleManager.removeRoleHolderAsUser(
+ role,
+ mPackageName,
+ /* flags= */ 0,
+ user.userHandle(),
+ TestApis.context().instrumentedContext().getMainExecutor(),
+ blockingCallback::triggerCallback);
+ TestApis.roles().setBypassingRoleQualification(false);
+
+ boolean success = blockingCallback.await();
+ if (!success) {
+ fail("Failed to clear the role holder of "
+ + role + ".");
+ }
+ if (TestApis.roles().getRoleHoldersAsUser(role, user).contains(packageName())) {
+ fail("removeRoleHolderAsUser returned true but did not remove role holder. "
+ + "Relevant logcat: " + TestApis.logcat().dump(
+ (line) -> line.contains(role)));
+ }
+ }).terminalException(e -> {
+ // Terminal unless we see logcat output indicating it might be temporary
+ var logcat = TestApis.logcat()
+ .dump(l -> l.contains("Error calling onRemoveRoleHolder()"));
+ if (!logcat.isEmpty()) {
+ // On low end devices - this can happen when the broadcast queue is full
+ try {
+ Thread.sleep(10_000);
+ } catch (InterruptedException ex) {
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }).runAndWrapException();
}
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/RoleContext.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/RoleContext.java
index 714fc130532..98e38bd173b 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/RoleContext.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/RoleContext.java
@@ -16,9 +16,15 @@
package com.android.bedstead.nene.roles;
+import static com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL;
+
+import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.packages.Package;
+import com.android.bedstead.nene.permissions.PermissionContext;
import com.android.bedstead.nene.users.UserReference;
+import java.util.Set;
+
/**
* A context that, when closed, will remove the package from the role.
*/
@@ -27,15 +33,30 @@ public final class RoleContext implements AutoCloseable {
private final String mRole;
private final Package mPackage;
private final UserReference mUser;
+ private final Set<String> mPreviousRoleHolders;
public RoleContext(String role, Package pkg, UserReference user) {
mRole = role;
mPackage = pkg;
mUser = user;
+ mPreviousRoleHolders = TestApis.roles().getRoleHoldersAsUser(role, user);
}
@Override
public void close() {
- mPackage.removeAsRoleHolder(mRole, mUser);
+ try (PermissionContext p = TestApis.permissions().withPermission(
+ INTERACT_ACROSS_USERS_FULL)) {
+ mPackage.removeAsRoleHolder(mRole, mUser);
+
+ Set<String> currentRoleHolders = TestApis.roles().getRoleHoldersAsUser(mRole, mUser);
+ // Re-adding previous role holder just for exclusive role as we would have overridden
+ // the previous role holder in this case, for non exclusive roles it's not a problem
+ // as we just add as one of the role holder so just removing them is fine.
+ if (currentRoleHolders.isEmpty() && mPreviousRoleHolders.size() == 1) {
+ Package roleHolderPackage = Package.of(
+ mPreviousRoleHolders.stream().toList().get(0));
+ roleHolderPackage.setAsRoleHolder(mRole, mUser);
+ }
+ }
}
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java
index 72c90b6ac24..a6378d38902 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java
@@ -17,6 +17,7 @@
package com.android.bedstead.nene.roles;
import static com.android.bedstead.nene.permissions.CommonPermissions.BYPASS_ROLE_QUALIFICATION;
+import static com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL;
import static com.android.bedstead.nene.permissions.CommonPermissions.MANAGE_ROLE_HOLDERS;
import static com.android.bedstead.nene.utils.Versions.T;
@@ -24,15 +25,16 @@ import android.annotation.TargetApi;
import android.app.role.RoleManager;
import android.content.Context;
import android.os.Build;
+import android.os.UserHandle;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.annotations.Experimental;
import com.android.bedstead.nene.packages.Package;
import com.android.bedstead.nene.permissions.PermissionContext;
+import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.utils.Versions;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
/**
@@ -74,4 +76,17 @@ public class Roles {
return new HashSet<>(sContext.getSystemService(RoleManager.class).getRoleHolders(role));
}
}
+
+ /**
+ * @see RoleManager#getRoleHoldersAsUser(String, UserHandle)
+ */
+ @Experimental
+ public Set<String> getRoleHoldersAsUser(String role, UserReference user) {
+ try (PermissionContext p = TestApis.permissions().withPermission(
+ MANAGE_ROLE_HOLDERS).withPermission(INTERACT_ACROSS_USERS_FULL)) {
+ return new HashSet<>(
+ sContext.getSystemService(RoleManager.class).getRoleHoldersAsUser(role,
+ user.userHandle()));
+ }
+ }
}
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java
index a2a41920115..7998334ebb1 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java
@@ -357,6 +357,13 @@ public class PackageTest {
}
@Test
+ public void forceStop_whenRestartableApp_doesNotLoopEndlessly() {
+ final int previousId = TestApis.packages().launcher().runningProcess().pid();
+ TestApis.packages().launcher().forceStop();
+ assertThat(TestApis.packages().launcher().runningProcess().pid()).isNotEqualTo(previousId);
+ }
+
+ @Test
@EnsureHasSecondaryUser
@RequireRunNotOnSecondaryUser
public void installedOnUsers_doesNotIncludeUserWithoutPackageInstalled() throws Exception {
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConnectivityDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConnectivityDeviceInfo.java
index 45726b8690c..c99d9a250e5 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConnectivityDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/ConnectivityDeviceInfo.java
@@ -15,9 +15,13 @@
*/
package com.android.compatibility.common.deviceinfo;
+import android.content.pm.PackageManager;
+
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
+import android.os.Build;
+
import android.util.Log;
import com.android.compatibility.common.util.DeviceInfoStore;
@@ -63,12 +67,20 @@ public final class ConnectivityDeviceInfo extends DeviceInfo {
return "";
}
+ private boolean hasWifi() {
+ return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
+ }
+
@Override
protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
- try {
- collectWifiStandards(store);
- } catch (IOException e) {
- Log.w(LOG_TAG, "Failed to collect WiFi standards", e);
+ if (hasWifi()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ try {
+ collectWifiStandards(store);
+ } catch (IOException e) {
+ Log.w(LOG_TAG, "Failed to collect WiFi standards", e);
+ }
+ }
}
}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GnssDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GnssDeviceInfo.java
index 8ab6b5e755a..4100c97fdf8 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GnssDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GnssDeviceInfo.java
@@ -51,7 +51,9 @@ public final class GnssDeviceInfo extends DeviceInfo {
return;
}
collectGnssHardwareModelName(store, locationManager);
- collectGnssCapabilities(store, locationManager.getGnssCapabilities());
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
+ collectGnssCapabilities(store, locationManager.getGnssCapabilities());
+ }
collectAccumulatedDeltaRangeMeasurements(store, locationManager);
}
@@ -79,9 +81,6 @@ public final class GnssDeviceInfo extends DeviceInfo {
/** collect info for gnss capabilities into a group */
private void collectGnssCapabilities(DeviceInfoStore store, GnssCapabilities gnssCapabilities)
throws IOException {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
- return;
- }
store.startGroup("gnss_capabilities");
store.addResult("has_low_power_mode", gnssCapabilities.hasLowPowerMode());
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MediaDrmDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MediaDrmDeviceInfo.java
new file mode 100644
index 00000000000..28d49395b5b
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/MediaDrmDeviceInfo.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 Google LLC.
+ *
+ * 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.compatibility.common.deviceinfo;
+
+import android.annotation.TargetApi;
+import android.media.MediaDrm;
+import android.os.Build;
+import android.util.Log;
+
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
+import com.android.compatibility.common.util.DeviceInfoStore;
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Collects Media Drm related properties in WVTS tests.
+ */
+public class MediaDrmDeviceInfo extends DeviceInfo {
+ private static final String TAG = MediaDrmDeviceInfo.class.getSimpleName();
+
+ @Override
+ @TargetApi(Build.VERSION_CODES.R)
+ protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
+ List<UUID> supportedCryptoSchemes = MediaDrm.getSupportedCryptoSchemes();
+
+ store.startArray("media_drm_info");
+ for (UUID scheme : supportedCryptoSchemes) {
+ Log.i(TAG, scheme.toString());
+ store.startGroup();
+ store.addResult("scheme_uuid ", scheme.toString());
+ try (MediaDrm mediaDrm = new MediaDrm(scheme)) {
+ for (String key : new String[]{MediaDrm.PROPERTY_VENDOR, MediaDrm.PROPERTY_VERSION,
+ MediaDrm.PROPERTY_DESCRIPTION}) {
+ try {
+ String value = mediaDrm.getPropertyString(key);
+ Log.i(TAG, String.format("key %s, value %s", key, value));
+ store.addResult(key, value);
+ } catch (Exception e) {
+ // leave value blank
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to collect device info", e);
+ Log.e(TAG + "scheme", String.valueOf(scheme));
+ }
+ store.endGroup();
+ }
+ store.endArray();
+
+ try {
+ String output = SystemUtil.runShellCommand("pgrep -fl android.hardware.drm");
+ ArrayList<String> list = new ArrayList<>(Arrays.asList(output.split("\n")));
+ for (int i = list.size() - 1; i >= 0; i--) {
+ String drmHal = list.remove(i);
+ int n = drmHal.indexOf("/");
+ list.add(drmHal.substring(n, drmHal.length()));
+ }
+ store.addListResult("media_drm_hal", list);
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+}
diff --git a/common/device-side/interactive/src/main/java/com/android/interactive/Step.java b/common/device-side/interactive/src/main/java/com/android/interactive/Step.java
index 07d0f036b82..abe25f18aac 100644
--- a/common/device-side/interactive/src/main/java/com/android/interactive/Step.java
+++ b/common/device-side/interactive/src/main/java/com/android/interactive/Step.java
@@ -256,6 +256,21 @@ public abstract class Step<E> {
}
/**
+ * Adds small button with a single up/down arrow, used for moving the text box to the
+ * bottom of the screen in case it covers some critical area of the app
+ */
+
+ protected void addSwapButton() {
+ Button btn = new Button(TestApis.context().instrumentedContext());
+ // up/down arrow
+ btn.setText("\u21F5");
+ btn.setOnClickListener(v -> swap());
+
+ GridLayout layout = mInstructionView.findViewById(R.id.buttons);
+ layout.addView(btn);
+ }
+
+ /**
* Adds a button to immediately mark the test as failed and request the tester to provide the
* reason for failure.
*/
@@ -296,6 +311,19 @@ public abstract class Step<E> {
});
}
+ /**
+ * Swaps the prompt from the top to the bottom of the user screen
+ */
+ protected void swap() {
+ WindowManager.LayoutParams params = (WindowManager.LayoutParams) mInstructionView.getLayoutParams();
+ if (params.gravity == Gravity.TOP) {
+ params.gravity = Gravity.BOTTOM;
+ } else {
+ params.gravity = Gravity.TOP;
+ }
+ sWindowManager.updateViewLayout(mInstructionView, params);
+ }
+
protected void close() {
if (mInstructionView != null) {
TestApis.context().instrumentationContext().getMainExecutor().execute(() -> {
diff --git a/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndConfirmStep.java b/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndConfirmStep.java
index 1333a6ea504..9ce5549a5fd 100644
--- a/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndConfirmStep.java
+++ b/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndConfirmStep.java
@@ -36,5 +36,6 @@ public abstract class ActAndConfirmStep extends Step<Nothing> {
addButton("Done", this::pass);
addFailButton();
+ addSwapButton();
}
}
diff --git a/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndWaitStep.java b/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndWaitStep.java
index 22873cd82d0..944ec8cd1d4 100644
--- a/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndWaitStep.java
+++ b/common/device-side/interactive/src/main/java/com/android/interactive/steps/ActAndWaitStep.java
@@ -45,6 +45,7 @@ public abstract class ActAndWaitStep extends Step<Nothing> {
public void interact() {
show(mInstruction);
addFailButton();
+ addSwapButton();
}
@Override
diff --git a/common/device-side/interactive/src/main/java/com/android/interactive/steps/MultipleChoiceStep.java b/common/device-side/interactive/src/main/java/com/android/interactive/steps/MultipleChoiceStep.java
index 0f94ecf9081..56257810dfa 100644
--- a/common/device-side/interactive/src/main/java/com/android/interactive/steps/MultipleChoiceStep.java
+++ b/common/device-side/interactive/src/main/java/com/android/interactive/steps/MultipleChoiceStep.java
@@ -46,5 +46,6 @@ public abstract class MultipleChoiceStep extends Step<String> {
});
}
addFailButton();
+ addSwapButton();
}
}
diff --git a/common/device-side/interactive/src/main/java/com/android/interactive/steps/YesNoStep.java b/common/device-side/interactive/src/main/java/com/android/interactive/steps/YesNoStep.java
index 6f7887579b2..bd5cd7252a8 100644
--- a/common/device-side/interactive/src/main/java/com/android/interactive/steps/YesNoStep.java
+++ b/common/device-side/interactive/src/main/java/com/android/interactive/steps/YesNoStep.java
@@ -43,5 +43,6 @@ public abstract class YesNoStep extends Step<Boolean> {
close();
});
addFailButton();
+ addSwapButton();
}
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils2.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils2.java
index 64b11c1ee5e..6189ff60bac 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils2.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils2.java
@@ -172,7 +172,7 @@ public class UiAutomatorUtils2 {
if (scrollable != null && scrollable.exists()) {
final Rect scrollableBounds = scrollable.getVisibleBounds();
final int distanceToSwipe = collapsingToolbar.getVisibleBounds().height() / 2;
- getUiDevice().drag(scrollableBounds.centerX(), scrollableBounds.centerY(),
+ getUiDevice().swipe(scrollableBounds.centerX(), scrollableBounds.centerY(),
scrollableBounds.centerX(), scrollableBounds.centerY() - distanceToSwipe,
steps);
} else {
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UserHelper.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UserHelper.java
index a048fdee186..797743a3489 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UserHelper.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UserHelper.java
@@ -21,6 +21,7 @@ import static android.view.Display.INVALID_DISPLAY;
import android.app.ActivityOptions;
import android.content.Context;
+import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
@@ -31,7 +32,6 @@ import android.view.MotionEvent;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
-import com.android.modules.utils.build.SdkLevel;
import java.util.Objects;
import java.util.function.Function;
@@ -71,7 +71,7 @@ public final class UserHelper {
mUser = Objects.requireNonNull(context).getUser();
UserManager userManager = context.getSystemService(UserManager.class);
- if (!SdkLevel.isAtLeastU()) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
mVisibleBackgroundUsersSupported = false;
if (DEBUG) {
Log.d(TAG, "Pre-UDC constructor (mUser=" + mUser + "): setting "
diff --git a/common/device-side/util/jni/android_cts_CpuFeatures.cpp b/common/device-side/util/jni/android_cts_CpuFeatures.cpp
index 2f56a2fcab0..ac1f79b2069 100644
--- a/common/device-side/util/jni/android_cts_CpuFeatures.cpp
+++ b/common/device-side/util/jni/android_cts_CpuFeatures.cpp
@@ -17,6 +17,7 @@
#include <jni.h>
#include <string.h>
#include <sys/auxv.h>
+#include <sys/system_properties.h>
#include <sys/utsname.h>
#include <string>
@@ -73,6 +74,10 @@ jint android_cts_CpuFeatures_getHwCaps(JNIEnv*, jobject)
jboolean android_cts_CpuFeatures_isNativeBridgedCpu(JNIEnv* env, jobject thiz)
{
+#if defined(__arm__)
+ static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa.arm");
+ return pi != nullptr;
+#endif
#if defined(__arm__) || defined(__aarch64__)
// If the test is compiled for arm use uname() to check if host CPU is x86.
struct utsname uname_data;
diff --git a/hostsidetests/abioverride/AndroidTest.xml b/hostsidetests/abioverride/AndroidTest.xml
index edb3122595b..105b9232acb 100644
--- a/hostsidetests/abioverride/AndroidTest.xml
+++ b/hostsidetests/abioverride/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS AbiOverride host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="webview" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/accounts/AndroidTest.xml b/hostsidetests/accounts/AndroidTest.xml
index 2d752c49f3a..7b77b610939 100644
--- a/hostsidetests/accounts/AndroidTest.xml
+++ b/hostsidetests/accounts/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for the CTS accounts host tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="auth" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/hostsidetests/adbmanager/AndroidTest.xml b/hostsidetests/adbmanager/AndroidTest.xml
index 2194a4c574c..bb96507ed5a 100644
--- a/hostsidetests/adbmanager/AndroidTest.xml
+++ b/hostsidetests/adbmanager/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS AdbManager host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="devtools" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/AppCompatOverridesServiceTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/AppCompatOverridesServiceTest.java
index de1656568d3..61b4bf2899c 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/AppCompatOverridesServiceTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/AppCompatOverridesServiceTest.java
@@ -316,6 +316,9 @@ public class AppCompatOverridesServiceTest extends CompatChangeGatingTestCase {
}
private Change getChange(long changeId) throws Exception {
+ // Data put by device_config app_compat_overrides need some time to update the data
+ // for dumpsys platform_compat so adding some sleep time
+ Thread.sleep(WAIT_TIME_MS);
Change ctsChange = getOnDeviceChangeIdConfig(changeId);
assertWithMessage("CTS specific change %s not found on device", changeId)
.that(ctsChange).isNotNull();
diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp
index 4909cfc2377..100e5ede8b9 100644
--- a/hostsidetests/appsecurity/Android.bp
+++ b/hostsidetests/appsecurity/Android.bp
@@ -96,9 +96,6 @@ java_test_host {
":CtsStorageAppA",
":CtsStorageAppB",
":CtsNoAppDataStorageApp",
- ":CtsDocumentClient",
- ":CtsDocumentProvider",
- ":CtsStubIme",
":CtsInvalidRequiredSplitTypeSplitApp",
":CtsNeedSplitApp",
":CtsNeedSplitFeatureWarm",
diff --git a/hostsidetests/appsecurity/AndroidTest.xml b/hostsidetests/appsecurity/AndroidTest.xml
index 5633cce65b1..d7da6eb9757 100644
--- a/hostsidetests/appsecurity/AndroidTest.xml
+++ b/hostsidetests/appsecurity/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for the CTS App Security host tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/appsecurity/OWNERS b/hostsidetests/appsecurity/OWNERS
index a9fea40b80e..ca951166539 100644
--- a/hostsidetests/appsecurity/OWNERS
+++ b/hostsidetests/appsecurity/OWNERS
@@ -21,10 +21,6 @@
# Bug component: 46626 = per-file *Documents*
# Bug component: 46626 = per-file ScopedDirectoryAccessTest.java
-# DocsUI bug component
-# Bug component: 46626 = per-file *Documents*
-# Bug component: 46626 = per-file ScopedDirectoryAccessTest.java
-
patb@google.com
per-file AccessSerialNumberTest.java = ashfall@google.com
per-file ApexSignatureVerificationTest.java = dariofreni@google.com
@@ -71,11 +67,6 @@ per-file com.android.apex.cts.shim.*.apex = ioffe@google.com
per-file *Adoptable* = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
per-file *DirectBoot* = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
per-file *Storage* = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
-per-file *Documents* = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
-per-file ScopedDirectoryAccessTest.java = file:platform/frameworks/base:/core/java/android/os/storage/OWNERS
-
-per-file *Documents* = file:platform/packages/apps/DocumentsUI:/OWNERS
-per-file ScopedDirectoryAccessTest.java = file:platform/packages/apps/DocumentsUI:/OWNERS
# OTA
per-file *ResumeOnReboot* = file:platform/frameworks/base:/core/java/android/service/resumeonreboot/OWNERS
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
deleted file mode 100644
index b9ef7ad5376..00000000000
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2014 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.appsecurity.cts;
-
-import android.platform.test.annotations.AsbSecurityTest;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.compatibility.common.util.ApiLevelUtil;
-import com.android.tradefed.device.DeviceNotAvailableException;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Set of tests that verify behavior of
- * {@link android.provider.DocumentsContract} and related intents.
- */
-public class DocumentsTest extends DocumentsTestCase {
- private static final String PROVIDER_PKG = "com.android.cts.documentprovider";
- private static final String STUBIME_PKG = "com.android.cts.stubime";
- private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
- private static final String STUBIME_APK = "CtsStubIme.apk";
-
- private static final long RESTRICT_STORAGE_ACCESS_FRAMEWORK = 141600225L;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- getDevice().uninstallPackage(PROVIDER_PKG);
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- assertNull(getDevice().installPackage(buildHelper.getTestFile(PROVIDER_APK), false));
- assertNull(getDevice().installPackage(buildHelper.getTestFile(STUBIME_APK), false));
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(PROVIDER_PKG);
- getDevice().uninstallPackage(STUBIME_PKG);
- }
-
- public void testOpenSimple() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenSimple");
- }
-
- public void testOpenVirtual() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenVirtual");
- }
-
- public void testCreateNew() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateNew");
- }
-
- public void testCreateExisting() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateExisting");
- }
-
- public void testTree() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree");
- }
-
- public void testGetContent_rootsShowing() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testGetContent_rootsShowing");
- }
-
- public void testGetContentWithQuery_matchingFileShowing() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testGetContentWithQuery_matchingFileShowing");
- }
-
- public void testGetContent_returnsResultToCallingActivity() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testGetContent_returnsResultToCallingActivity");
- }
-
- public void testTransferDocument() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTransferDocument");
- }
-
- public void testFindDocumentPathInScopedAccess() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testFindDocumentPathInScopedAccess");
- }
-
- public void testOpenDocumentAtInitialLocation() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenDocumentAtInitialLocation");
- }
-
- public void testOpenDocumentTreeAtInitialLocation() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenDocumentTreeAtInitialLocation");
- }
-
- public void testOpenDocumentTreeWithScopedStorage() throws Exception {
- if (isAtLeastR()) {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testOpenDocumentTreeWithScopedStorage");
- }
- }
-
- public void testOpenRootWithoutRootIdAtInitialLocation() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testOpenRootWithoutRootIdAtInitialLocation");
- }
-
- public void testCreateDocumentAtInitialLocation() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateDocumentAtInitialLocation");
- }
-
- public void testCreateWebLink() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateWebLink");
- }
-
- public void testEject() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testEject");
- }
-
- public void testScopeStorageAtInitLocationRootWithDot_blockFromTree() throws Exception {
- if (isAtLeastT()) {
- // From BUILD.VERSION_CODES.S, scope storage is enabled in default
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testScopeStorageAtInitLocationRootWithDot_blockFromTree");
- }
- }
-
- public void testScopeStorageAtInitLocationAndroidData_blockFromTree() throws Exception {
- if (isAtLeastT()) {
- // From BUILD.VERSION_CODES.S, scope storage is enabled in default
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testScopeStorageAtInitLocationAndroidData_blockFromTree");
- }
- }
-
- public void testScopeStorageAtInitLocationAndroidObb_blockFromTree() throws Exception {
- if (isAtLeastT()) {
- // From BUILD.VERSION_CODES.S, scope storage is enabled in default
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testScopeStorageAtInitLocationAndroidObb_blockFromTree");
- }
- }
-
- public void testRestrictStorageAccessFrameworkEnabled_blockFromTree() throws Exception {
- if (isAtLeastR() && isSupportedHardware()) {
- runDeviceCompatTestReported(CLIENT_PKG, ".DocumentsClientTest",
- "testRestrictStorageAccessFrameworkEnabled_blockFromTree",
- /* enabledChanges= */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
- /* disabledChanges= */ ImmutableSet.of(),
- /* reportedEnabledChanges= */ ImmutableSet.of(),
- /* reportedDisabledChanges= */ ImmutableSet.of());
- }
- }
-
- public void testRestrictStorageAccessFrameworkDisabled_notBlockFromTree() throws Exception {
- // For S+, the flag will be force enabled, so we only run this test against R.
- if (isAtLeastR() && !isAtLeastS() && isSupportedHardware()) {
- runDeviceCompatTestReported(CLIENT_PKG, ".DocumentsClientTest",
- "testRestrictStorageAccessFrameworkDisabled_notBlockFromTree",
- /* enabledChanges */ ImmutableSet.of(),
- /* disabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
- /* reportedEnabledChanges= */ ImmutableSet.of(),
- /* reportedDisabledChanges= */ ImmutableSet.of());
- }
- }
-
- @AsbSecurityTest(cveBugId = 157474195)
- public void testAfterMoveDocumentInStorage_revokeUriPermission() throws Exception {
- if (isAtLeastS()) {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
- "testAfterMoveDocumentInStorage_revokeUriPermission");
- }
- }
-
- private boolean isAtLeastR() {
- try {
- return ApiLevelUtil.isAfter(getDevice(), 29 /* BUILD.VERSION_CODES.Q */);
- } catch (Exception e) {
- return false;
- }
- }
-
- private boolean isAtLeastS() {
- try {
- return ApiLevelUtil.isAfter(getDevice(), 30 /* BUILD.VERSION_CODES.R */)
- || ApiLevelUtil.codenameEquals(getDevice(), "S");
- } catch (Exception e) {
- return false;
- }
- }
-
- private boolean isAtLeastT() {
- try {
- return ApiLevelUtil.isAfter(getDevice(), 32 /* BUILD.VERSION_CODES.S_V2 */);
- } catch (Exception e) {
- return false;
- }
- }
-
- private boolean isSupportedHardware() {
- try {
- if (getDevice().hasFeature("feature:android.hardware.type.television")
- || getDevice().hasFeature("feature:android.hardware.type.watch")
- || getDevice().hasFeature("feature:android.hardware.type.automotive")) {
- return false;
- }
- } catch (DeviceNotAvailableException e) {
- return true;
- }
- return true;
- }
-}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
deleted file mode 100644
index d7a9ffc9f8c..00000000000
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 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.appsecurity.cts;
-
-import android.compat.cts.CompatChangeGatingTestCase;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-
-/**
- * Base class for {@link android.provider.DocumentsContract} and related test cases.
- */
-abstract class DocumentsTestCase extends CompatChangeGatingTestCase implements IAbiReceiver {
- protected static final String CLIENT_PKG = "com.android.cts.documentclient";
- protected static final String CLIENT_APK = "CtsDocumentClient.apk";
-
- protected IAbi mAbi;
-
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- Utils.prepareSingleUser(getDevice());
- assertNotNull(mAbi);
-
- reinstallClientPackage();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(CLIENT_PKG);
- }
-
- public void runDeviceTests(String packageName, String testClassName, String testMethodName)
- throws DeviceNotAvailableException {
- Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName,
- getDevice().getCurrentUser());
- }
-
- protected void reinstallClientPackage() throws Exception {
- getDevice().uninstallPackage(CLIENT_PKG);
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- assertNull(getDevice().installPackage(buildHelper.getTestFile(CLIENT_APK), false));
- }
-}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
deleted file mode 100644
index 552b2987f3d..00000000000
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2016 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.appsecurity.cts;
-
-/**
- * Set of tests that verify behavior of the deprecated Scoped Directory access API.
- */
-public class ScopedDirectoryAccessTest extends DocumentsTestCase {
-
- public void testInvalidPath() throws Exception {
- runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest", "testInvalidPath");
- }
-
- public void testActivityFailsForAllVolumesAndDirectories() throws Exception {
- runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest",
- "testActivityFailsForAllVolumesAndDirectories");
- }
-}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
deleted file mode 100644
index 8826c5bc863..00000000000
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2016 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.documentclient;
-
-import static android.os.Environment.DIRECTORY_ALARMS;
-import static android.os.Environment.DIRECTORY_DCIM;
-import static android.os.Environment.DIRECTORY_DOCUMENTS;
-import static android.os.Environment.DIRECTORY_DOWNLOADS;
-import static android.os.Environment.DIRECTORY_MOVIES;
-import static android.os.Environment.DIRECTORY_MUSIC;
-import static android.os.Environment.DIRECTORY_NOTIFICATIONS;
-import static android.os.Environment.DIRECTORY_PICTURES;
-import static android.os.Environment.DIRECTORY_PODCASTS;
-import static android.os.Environment.DIRECTORY_RINGTONES;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.storage.StorageManager;
-import android.os.storage.StorageVolume;
-
-import java.util.List;
-
-/**
- * Set of tests that verify behavior of the deprecated Scoped Directory Access API.
- */
-public class ScopedDirectoryAccessClientTest extends DocumentsClientTestCase {
- private static final String TAG = "ScopedDirectoryAccessClientTest";
-
- private static final String DIRECTORY_ROOT = null;
-
- private static final String[] STANDARD_DIRECTORIES = {
- DIRECTORY_MUSIC,
- DIRECTORY_PODCASTS,
- DIRECTORY_RINGTONES,
- DIRECTORY_ALARMS,
- DIRECTORY_NOTIFICATIONS,
- DIRECTORY_PICTURES,
- DIRECTORY_MOVIES,
- DIRECTORY_DOWNLOADS,
- DIRECTORY_DCIM,
- DIRECTORY_DOCUMENTS
- };
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
-
- // DocumentsUI caches some info like whether a user rejects a request, so we need to clear
- // its data before each test.
- clearDocumentsUi();
- }
-
- public void testInvalidPath() {
- if (!supportedHardwareForScopedDirectoryAccess()) return;
-
- for (StorageVolume volume : getVolumes()) {
- openExternalDirectoryInvalidPath(volume, "");
- openExternalDirectoryInvalidPath(volume, "/dev/null");
- openExternalDirectoryInvalidPath(volume, "/../");
- openExternalDirectoryInvalidPath(volume, "/HiddenStuff");
- }
- openExternalDirectoryInvalidPath(getPrimaryVolume(), DIRECTORY_ROOT);
- }
-
- public void testActivityFailsForAllVolumesAndDirectories() {
- if (!supportedHardwareForScopedDirectoryAccess()) return;
-
- for (StorageVolume volume : getVolumes()) {
- // Tests user clicking DENY button, for all valid directories.
- for (String dir : STANDARD_DIRECTORIES) {
- sendOpenExternalDirectoryIntent(volume, dir);
- assertActivityFailed();
- }
- if (!volume.isPrimary()) {
- // Also test root
- sendOpenExternalDirectoryIntent(volume, DIRECTORY_ROOT);
- assertActivityFailed();
- }
- }
- }
-
- private void openExternalDirectoryInvalidPath(StorageVolume volume, String directoryName) {
- final Intent intent = volume.createAccessIntent(directoryName);
- assertNull("should not get intent for volume '" + volume + "' and directory '"
- + directoryName + "'", intent);
- }
-
- private void sendOpenExternalDirectoryIntent(StorageVolume volume, String directoryName) {
- final Intent intent = volume.createAccessIntent(directoryName);
- assertNotNull("no intent for '" + volume + "' and directory " + directoryName, intent);
- mActivity.startActivityForResult(intent, REQUEST_CODE);
- mDevice.waitForIdle();
- }
-
- private List<StorageVolume> getVolumes() {
- final StorageManager sm = (StorageManager)
- getInstrumentation().getTargetContext().getSystemService(Context.STORAGE_SERVICE);
- final List<StorageVolume> volumes = sm.getStorageVolumes();
- assertTrue("empty volumes", !volumes.isEmpty());
- return volumes;
- }
-
- private StorageVolume getPrimaryVolume() {
- final StorageManager sm = (StorageManager)
- getInstrumentation().getTargetContext().getSystemService(Context.STORAGE_SERVICE);
- return sm.getPrimaryStorageVolume();
- }
-}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp
index 723d0632057..c29ae0553c5 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.bp
@@ -26,7 +26,6 @@ android_test_helper_app {
"androidx.test.rules",
"compatibility-device-util-axt",
"ctstestrunner-axt",
- "ub-uiautomator",
],
srcs: ["src/**/*.java"],
// tag this module as a cts test artifact
diff --git a/hostsidetests/art/host/AndroidTest.xml b/hostsidetests/art/host/AndroidTest.xml
index 95522880cf3..88b74d3e59e 100644
--- a/hostsidetests/art/host/AndroidTest.xml
+++ b/hostsidetests/art/host/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Host test for ThreadLocalRandom">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/calllog/AndroidTest.xml b/hostsidetests/calllog/AndroidTest.xml
index 3b0d124e617..fc09dc564b9 100644
--- a/hostsidetests/calllog/AndroidTest.xml
+++ b/hostsidetests/calllog/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS media host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="telecom" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<!-- These tests explicitly handle multiuser switching themselves. -->
diff --git a/hostsidetests/car/src/android/car/cts/CarUserManagerHostTest.java b/hostsidetests/car/src/android/car/cts/CarUserManagerHostTest.java
index 45f8a766b2f..73fb795dddc 100644
--- a/hostsidetests/car/src/android/car/cts/CarUserManagerHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/CarUserManagerHostTest.java
@@ -18,7 +18,6 @@ package android.car.cts;
import static com.google.common.truth.Truth.assertWithMessage;
-import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
@@ -56,18 +55,6 @@ public final class CarUserManagerHostTest extends CarHostJUnit4TestCase {
}
@Test
- public void testSwitchUserUxRestrictionFailure() throws Exception {
- executeCommand("cmd car_service emulate-driving-state drive");
- assertWithMessage("Waiting for driving state change").that(
- waitForDrivingStateChanged("Current Driving State: 2", TEST_TIMEOUT_MS)).isTrue();
-
- int newUserid = createFullUser("CarUserManagerHostTest_User");
- switchUser(newUserid, STATUS_UX_RESTRICTION_FAILURE);
-
- executeCommand("cmd car_service emulate-driving-state park");
- }
-
- @Test
public void testRemoveUser() throws Exception {
int newUserid = createFullUser("CarUserManagerHostTest_User");
@@ -99,25 +86,4 @@ public final class CarUserManagerHostTest extends CarHostJUnit4TestCase {
.max()
.orElse(0) + 1;
}
-
- private boolean waitForDrivingStateChanged(String expected, long timeout) {
- long start = System.currentTimeMillis();
- while (start + timeout > System.currentTimeMillis()) {
- try {
- String result = executeCommand(
- "dumpsys car_service --services CarDrivingStateService");
- if (result.contains(expected)) {
- return true;
- }
- Thread.sleep(TEST_WAIT_MS);
- } catch (InterruptedException e) {
- CLog.e(TAG, "Test interrupted: " + e);
- return false;
- } catch (Exception e) {
- CLog.e(TAG, "executeCommand failed: " + e);
- return false;
- }
- }
- return false;
- }
}
diff --git a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
index 14770d504d8..cb120a0744f 100644
--- a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
@@ -131,9 +131,6 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
teststep = "check the inital power policies";
testHelper = getTestHelper(testcase, stepNo++, teststep);
testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
- // power policy can be different from system_power_policy_all_on, save it to check
- // after device restart.
- String powerPolicyForOnState = testHelper.getCurrentPolicyId();
// save number of device power policies
int registeredPoliciesNumber = testHelper.getNumberOfRegisteredPolicies();
int expectedTotalPolicies = registeredPoliciesNumber;
@@ -210,7 +207,6 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
teststep = "reboot to clear added test power policies";
testHelper = getTestHelper(testcase, stepNo++, teststep);
testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
- testHelper.checkCurrentPolicy(powerPolicyForOnState);
testHelper.checkTotalRegisteredPolicies(registeredPoliciesNumber);
}
@@ -370,7 +366,6 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.INITIAL_ALL_ON);
testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.DEFAULT_ALL_ON);
- testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
}
private void defineAndCheckPolicyTest1(String testcase, int stepNo,
diff --git a/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java b/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
index d4835011329..b58078b01ef 100644
--- a/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
@@ -274,6 +274,16 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
for (int userId : userIds) {
getDevice().removeUser(userId);
}
+ int retryCount = 10;
+ while (retryCount > 0) {
+ String allUsers = getDevice().executeShellCommand("cmd user list --all -v");
+ if (allUsers.contains("(pre-created)")) {
+ retryCount--;
+ sleep(1000);
+ continue;
+ }
+ break;
+ }
}
private void convertPreCreatedUser(boolean isGuest, int expectedId) throws Exception {
diff --git a/hostsidetests/classloaders/splits/AndroidTest.xml b/hostsidetests/classloaders/splits/AndroidTest.xml
index 557b879b678..06b38f4e97b 100644
--- a/hostsidetests/classloaders/splits/AndroidTest.xml
+++ b/hostsidetests/classloaders/splits/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for the CTS Classloader Splits host tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
diff --git a/hostsidetests/classloaders/useslibrary/AndroidTest.xml b/hostsidetests/classloaders/useslibrary/AndroidTest.xml
index 0b94f35bca5..593435f3458 100644
--- a/hostsidetests/classloaders/useslibrary/AndroidTest.xml
+++ b/hostsidetests/classloaders/useslibrary/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for the CTS UsesLibrary host tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
diff --git a/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java b/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
index 2b62399eb73..00eb56f2c45 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
@@ -20,8 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
import android.compilation.cts.annotation.CtsTestCase;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.DeviceParameterizedRunner;
import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
import org.junit.After;
@@ -31,10 +31,12 @@ import org.junit.runner.RunWith;
import java.util.regex.Pattern;
+import junitparams.Parameters;
+
/**
* Compilation tests that don't require root access.
*/
-@RunWith(DeviceJUnit4ClassRunner.class)
+@RunWith(DeviceParameterizedRunner.class)
@CtsTestCase
public class CompilationTest extends BaseHostJUnit4Test {
private static final String STATUS_CHECKER_PKG = "android.compilation.cts.statuscheckerapp";
@@ -122,29 +124,48 @@ public class CompilationTest extends BaseHostJUnit4Test {
}
@Test
- public void testCompileSecondaryDex() throws Exception {
+ @Parameters({"secondary.jar", "secondary"})
+ public void testCompileSecondaryDex(String filename) throws Exception {
var options = new DeviceTestRunOptions(STATUS_CHECKER_PKG)
.setTestClassName(STATUS_CHECKER_CLASS)
- .setTestMethodName("createAndLoadSecondaryDex");
+ .setTestMethodName("createAndLoadSecondaryDex")
+ .addInstrumentationArg("secondary-dex-filename", filename);
assertThat(runDeviceTests(options)).isTrue();
// Verify that the secondary dex file is recorded.
String dump = mUtils.assertCommandSucceeds("dumpsys package " + STATUS_CHECKER_PKG);
- checkDexoptStatus(dump, "secondary\\.jar", ".*");
+ checkDexoptStatus(dump, Pattern.quote(filename), ".*?");
mUtils.assertCommandSucceeds(
"pm compile --secondary-dex -m speed -f " + STATUS_CHECKER_PKG);
dump = mUtils.assertCommandSucceeds("dumpsys package " + STATUS_CHECKER_PKG);
- checkDexoptStatus(dump, "secondary\\.jar", "speed");
+ checkDexoptStatus(dump, Pattern.quote(filename), "speed");
mUtils.assertCommandSucceeds(
"pm compile --secondary-dex -m verify -f " + STATUS_CHECKER_PKG);
dump = mUtils.assertCommandSucceeds("dumpsys package " + STATUS_CHECKER_PKG);
- checkDexoptStatus(dump, "secondary\\.jar", "verify");
+ checkDexoptStatus(dump, Pattern.quote(filename), "verify");
mUtils.assertCommandSucceeds("pm delete-dexopt " + STATUS_CHECKER_PKG);
dump = mUtils.assertCommandSucceeds("dumpsys package " + STATUS_CHECKER_PKG);
- checkDexoptStatus(dump, "secondary\\.jar", "run-from-apk");
+ checkDexoptStatus(dump, Pattern.quote(filename), "run-from-apk");
+ }
+
+ @Test
+ public void testSecondaryDexReporting() throws Exception {
+ var options = new DeviceTestRunOptions(STATUS_CHECKER_PKG)
+ .setTestClassName(STATUS_CHECKER_CLASS)
+ .setTestMethodName("testSecondaryDexReporting")
+ .setDisableHiddenApiCheck(true);
+ assertThat(runDeviceTests(options)).isTrue();
+
+ // Check that ART Service doesn't crash on various operations after invalid dex paths are
+ // reported.
+ mUtils.assertCommandSucceeds("dumpsys package " + STATUS_CHECKER_PKG);
+ mUtils.assertCommandSucceeds(
+ "pm compile --secondary-dex -m verify -f " + STATUS_CHECKER_PKG);
+ mUtils.assertCommandSucceeds("pm art clear-app-profiles " + STATUS_CHECKER_PKG);
+ mUtils.assertCommandSucceeds("pm art cleanup");
}
private void checkDexoptStatus(String dump, String dexfilePattern, String statusPattern) {
@@ -153,7 +174,8 @@ public class CompilationTest extends BaseHostJUnit4Test {
// x86_64: [status=speed] [reason=cmdline] [primary-abi]
// The pattern is intentionally minimized to be as forward compatible as possible.
// TODO(b/283447251): Use a machine-readable format.
- assertThat(dump).containsMatch(Pattern.compile(String.format(
- "\\b(%s)\\b[^\\n]*\\n[^\\n]*\\[status=(%s)\\]", dexfilePattern, statusPattern)));
+ assertThat(dump).containsMatch(
+ Pattern.compile(String.format("[\\s/](%s)(\\s[^\\n]*)?\\n[^\\n]*\\[status=(%s)\\]",
+ dexfilePattern, statusPattern)));
}
}
diff --git a/hostsidetests/compilation/status_checker_app/src/android/compilation/cts/statuscheckerapp/StatusCheckerAppTest.java b/hostsidetests/compilation/status_checker_app/src/android/compilation/cts/statuscheckerapp/StatusCheckerAppTest.java
index efc289aac8d..87357811e5d 100644
--- a/hostsidetests/compilation/status_checker_app/src/android/compilation/cts/statuscheckerapp/StatusCheckerAppTest.java
+++ b/hostsidetests/compilation/status_checker_app/src/android/compilation/cts/statuscheckerapp/StatusCheckerAppTest.java
@@ -29,6 +29,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import dalvik.system.ApplicationRuntime;
+import dalvik.system.BaseDexClassLoader;
import dalvik.system.PathClassLoader;
import com.google.common.io.ByteStreams;
@@ -41,6 +42,7 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Paths;
+import java.util.Map;
/**
* An instrumentation test that checks optimization status.
@@ -65,15 +67,46 @@ public class StatusCheckerAppTest {
@Test
public void createAndLoadSecondaryDex() throws Exception {
+ Bundle bundle = InstrumentationRegistry.getArguments();
+ String secondaryDexFilename = bundle.getString("secondary-dex-filename");
+ createAndLoadSecondaryDex(secondaryDexFilename);
+ }
+
+ private String createAndLoadSecondaryDex(String secondaryDexFilename) throws Exception {
Context context = ApplicationProvider.getApplicationContext();
String dataDir = context.getApplicationInfo().dataDir;
- File secondaryDexFile = Paths.get(dataDir, "secondary.jar").toFile();
+ File secondaryDexFile = Paths.get(dataDir, secondaryDexFilename).toFile();
if (secondaryDexFile.exists()) {
secondaryDexFile.delete();
}
copyResourceToFile(SECONDARY_DEX_RES, secondaryDexFile);
assertThat(secondaryDexFile.setReadOnly()).isTrue();
new PathClassLoader(secondaryDexFile.getAbsolutePath(), this.getClass().getClassLoader());
+ return secondaryDexFile.getAbsolutePath();
+ }
+
+ @Test
+ public void testSecondaryDexReporting() throws Exception {
+ String fooPath = createAndLoadSecondaryDex("foo.jar");
+ createAndLoadSecondaryDex("bar.jar");
+
+ var reporter =
+ (BaseDexClassLoader.Reporter) BaseDexClassLoader.class.getMethod("getReporter")
+ .invoke(null);
+
+ // Invalid dex paths. The binder calls should be rejected, though we won't see any failure
+ // on the client side because the calls are oneway.
+ reporter.report(Map.of("relative/path.apk", "PCL[]"));
+ reporter.report(Map.of("/non-normal/./path.apk", "PCL[]"));
+
+ // Invalid class loader contexts. The binder calls should be rejected too.
+ reporter.report(Map.of(fooPath, "ABC"));
+ reporter.report(Map.of(fooPath, "PCL[./bar.jar]"));
+
+ // Valid paths and class loader contexts.
+ reporter.report(Map.of("/absolute/path.apk", "PCL[]"));
+ reporter.report(Map.of(fooPath, "PCL[bar.jar]"));
+ reporter.report(Map.of(fooPath, "=UnsupportedClassLoaderContext="));
}
public File copyResourceToFile(String resourceName, File file) throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index a1ddafb0718..ea8c7dabcb1 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -429,6 +429,7 @@ public abstract class BaseDevicePolicyTest extends BaseHostJUnit4Test {
int retries = 10;
CLog.i("switching to user %d", userId);
executeShellCommand("am switch-user " + userId);
+ RunUtil.getDefault().sleep(USER_SWITCH_WAIT);
while (getDevice().getCurrentUser() != userId && (--retries) >= 0) {
// am switch-user can be ignored if a previous user-switching operation
// is still in progress. In this case, sleep a bit and then retry
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index 3e7616c3569..4f0ce17a01a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -475,7 +475,7 @@ public final class OrgOwnedProfileOwnerTest extends BaseDevicePolicyTest {
// Wait until IMS service is registered by the system.
waitForOutput("Failed waiting for IME to become available",
String.format("ime list --user %d -s -a", userId),
- s -> s.contains(imeComponent), 45 /* seconds */);
+ s -> s.contains(imeComponent), 100 /* seconds */);
executeShellCommand("ime enable " + imeComponent);
executeShellCommand("ime set " + imeComponent);
diff --git a/hostsidetests/incrementalinstall/AndroidTest.xml b/hostsidetests/incrementalinstall/AndroidTest.xml
index 4721e7a6aa1..3b25ebc1b30 100644
--- a/hostsidetests/incrementalinstall/AndroidTest.xml
+++ b/hostsidetests/incrementalinstall/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS adb incremental installer host test cases">
<option name="test-suite-tag" value="cts"/>
- <option name="config-descriptor:metadata" key="component" value="devtools"/>
+ <option name="config-descriptor:metadata" key="component" value="packagemanager"/>
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java
index 65b75f4f667..f3662880a01 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java
@@ -88,6 +88,9 @@ public class MultiUserTest extends BaseHostJUnit4Test {
*/
private ArrayList<Integer> mOriginalUsers;
+ /** Current user before the test runs. */
+ private int mInitialUserId;
+
/**
* Set up the test case
*/
@@ -96,6 +99,7 @@ public class MultiUserTest extends BaseHostJUnit4Test {
// Skip whole tests when DUT has no android.software.input_methods feature.
assumeTrue(hasDeviceFeature(ShellCommandUtils.FEATURE_INPUT_METHODS));
assumeTrue(getDevice().isMultiUserSupported());
+ mInitialUserId = getDevice().getCurrentUser();
mNeedsTearDown = true;
mOriginalUsers = new ArrayList<>(getDevice().listUsers());
@@ -111,8 +115,9 @@ public class MultiUserTest extends BaseHostJUnit4Test {
if (!mNeedsTearDown) {
return;
}
+ // Switch back to the initial user.
+ getDevice().switchUser(mInitialUserId);
- getDevice().switchUser(getDeviceMainUserId(getDevice()));
// We suspect that the optimization made for Bug 38143512 was a bit unstable. Let's see
// if adding a sleep improves the stability or not.
RunUtil.getDefault().sleep(WAIT_AFTER_USER_SWITCH);
@@ -305,9 +310,14 @@ public class MultiUserTest extends BaseHostJUnit4Test {
assertIme1NotCurrentInputMethodInfo(profileUserId);
}
- private static int getDeviceMainUserId(ITestDevice device) throws DeviceNotAvailableException {
- return device.isHeadlessSystemUserMode() ? device.getPrimaryUserId() :
- device.getMainUserId();
+ private int getDeviceMainUserId(ITestDevice device) throws Exception {
+ Integer userId = device.getMainUserId();
+
+ // Some headless surfaces like auto may not necessarily define a MAIN user.
+ if (userId == null) {
+ userId = mInitialUserId;
+ }
+ return userId;
}
private String shell(String command) {
diff --git a/hostsidetests/install/AndroidTest.xml b/hostsidetests/install/AndroidTest.xml
index 1eae5f6717c..62266669946 100644
--- a/hostsidetests/install/AndroidTest.xml
+++ b/hostsidetests/install/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Runs the install API tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<!-- Instant apps can't have INSTALL_PACKAGES permission. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
index 1c25b5a4537..60b671d9635 100644
--- a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
+++ b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
@@ -22,6 +22,8 @@ import static android.media.cts.MediaSessionTestHelperConstants.FLAG_SET_MEDIA_S
import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_APK;
import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_PKG;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import android.media.cts.BaseMultiUserTest;
import android.media.cts.MediaSessionTestHelperConstants;
import android.platform.test.annotations.AppModeFull;
@@ -30,6 +32,7 @@ import android.platform.test.annotations.RequiresDevice;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.RunUtil;
@@ -59,6 +62,12 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
private static final int TIMEOUT_MS = 1000;
+ /**
+ * Returned by {@link ITestDevice#getCurrentUser()} when there is an error retrieving the
+ * current user id.
+ */
+ private static final int INVALID_USER_ID = -10000;
+
private final List<Integer> mNotificationListeners = new ArrayList<>();
@Override
@@ -96,18 +105,21 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
}
private void testGetActiveSessions_primaryUser(boolean instant) throws Exception {
- int mainUserId = getDevice().getMainUserId();
+ int userIdForTesting = getUserIdForTesting();
- setAllowGetActiveSessionForTest(true, mainUserId);
- installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, mainUserId, instant);
+ setAllowGetActiveSessionForTest(true, userIdForTesting);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, instant);
runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
installAppAsUser(
- MEDIA_SESSION_TEST_HELPER_APK, MEDIA_SESSION_TEST_HELPER_PKG, mainUserId, false);
- sendControlCommand(mainUserId, FLAG_CREATE_MEDIA_SESSION);
+ MEDIA_SESSION_TEST_HELPER_APK,
+ MEDIA_SESSION_TEST_HELPER_PKG,
+ userIdForTesting,
+ false);
+ sendControlCommand(userIdForTesting, FLAG_CREATE_MEDIA_SESSION);
runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
- sendControlCommand(mainUserId, FLAG_SET_MEDIA_SESSION_ACTIVE);
+ sendControlCommand(userIdForTesting, FLAG_SET_MEDIA_SESSION_ACTIVE);
runTest("testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper");
}
@@ -210,7 +222,7 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
// Remove the created user first not to exceed system's user number limit.
// Managed profile's parent must not be the primary user (in the context of this test, we
// use the main user).
- int newUser = createAndStartManagedProfile(getDevice().getMainUserId());
+ int newUser = createAndStartManagedProfile(getUserIdForTesting());
installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, newUser, instant);
setAllowGetActiveSessionForTest(true, newUser);
runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
@@ -220,15 +232,18 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
@AppModeFull
@RequiresDevice
public void testGetActiveSessions_noSession2() throws Exception {
- int mainUserId = getDevice().getMainUserId();
+ int userIdForTesting = getUserIdForTesting();
- setAllowGetActiveSessionForTest(true, mainUserId);
- installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, mainUserId, false);
+ setAllowGetActiveSessionForTest(true, userIdForTesting);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false);
runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
installAppAsUser(
- MEDIA_SESSION_TEST_HELPER_APK, MEDIA_SESSION_TEST_HELPER_PKG, mainUserId, false);
- sendControlCommand(mainUserId, FLAG_CREATE_MEDIA_SESSION2);
+ MEDIA_SESSION_TEST_HELPER_APK,
+ MEDIA_SESSION_TEST_HELPER_PKG,
+ userIdForTesting,
+ false);
+ sendControlCommand(userIdForTesting, FLAG_CREATE_MEDIA_SESSION2);
// Wait for a second for framework to recognize media session2.
RunUtil.getDefault().sleep(TIMEOUT_MS);
@@ -238,16 +253,19 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
@AppModeFull
@RequiresDevice
public void testGetActiveSessions_withSession2() throws Exception {
- int mainUserId = getDevice().getMainUserId();
+ int userIdForTesting = getUserIdForTesting();
- setAllowGetActiveSessionForTest(true, mainUserId);
- installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, mainUserId, false);
+ setAllowGetActiveSessionForTest(true, userIdForTesting);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false);
runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
installAppAsUser(
- MEDIA_SESSION_TEST_HELPER_APK, MEDIA_SESSION_TEST_HELPER_PKG, mainUserId, false);
+ MEDIA_SESSION_TEST_HELPER_APK,
+ MEDIA_SESSION_TEST_HELPER_PKG,
+ userIdForTesting,
+ false);
sendControlCommand(
- mainUserId,
+ userIdForTesting,
FLAG_CREATE_MEDIA_SESSION
| FLAG_CREATE_MEDIA_SESSION2
| FLAG_SET_MEDIA_SESSION_ACTIVE);
@@ -261,20 +279,20 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
@AppModeFull
@RequiresDevice
public void testOnMediaKeyEventSessionChangedListener() throws Exception {
- int mainUserId = getDevice().getMainUserId();
+ int userIdForTesting = getUserIdForTesting();
- setAllowGetActiveSessionForTest(true, mainUserId);
- installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, mainUserId, false);
+ setAllowGetActiveSessionForTest(true, userIdForTesting);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false);
runTest("testOnMediaKeyEventSessionChangedListener");
}
@AppModeFull
@RequiresDevice
public void testOnMediaKeyEventSessionChangedListener_whenSessionIsReleased() throws Exception {
- int mainUserId = getDevice().getMainUserId();
+ int userIdForTesting = getUserIdForTesting();
- setAllowGetActiveSessionForTest(true, mainUserId);
- installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, mainUserId, false);
+ setAllowGetActiveSessionForTest(true, userIdForTesting);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, DEVICE_SIDE_TEST_PKG, userIdForTesting, false);
runTest("testOnMediaKeyEventSessionChangedListener_whenSessionIsReleased");
}
@@ -310,7 +328,7 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
}
private void runTest(String testMethodName) throws DeviceNotAvailableException {
- runTestAsUser(testMethodName, getDevice().getMainUserId());
+ runTestAsUser(testMethodName, getUserIdForTesting());
}
private void runTestAsUser(String testMethodName, int userId)
@@ -319,6 +337,27 @@ public class MediaSessionManagerHostTest extends BaseMultiUserTest {
}
/**
+ * If running headless system user mode, returns the current user. Otherwise, returns the main
+ * user.
+ *
+ * <p>Historically, some tests in this class would use the main user for running device-side
+ * tests. Headless surfaces (like Android Auto) do not have a main user. As a result, on
+ * headless surfaces, we use the current user in replacement of the missing main user.
+ */
+ private int getUserIdForTesting() throws DeviceNotAvailableException {
+ if (getDevice().isHeadlessSystemUserMode()) {
+ int currentUserId = getDevice().getCurrentUser();
+ assertWithMessage(
+ "Unable to fetch a valid current user id in headless system user mode.")
+ .that(currentUserId)
+ .isNotEqualTo(INVALID_USER_ID);
+ return currentUserId;
+ } else {
+ return getDevice().getMainUserId();
+ }
+ }
+
+ /**
* Sets to allow or disallow the {@link #DEVICE_SIDE_TEST_CLASS}
* to call {@link MediaSessionManager#getActiveSessions} for testing.
* <p>{@link MediaSessionManager#getActiveSessions} bypasses the permission check if the
diff --git a/hostsidetests/numberblocking/AndroidTest.xml b/hostsidetests/numberblocking/AndroidTest.xml
index 8a00fc3e2d7..4b028f70870 100644
--- a/hostsidetests/numberblocking/AndroidTest.xml
+++ b/hostsidetests/numberblocking/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS number blocking test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="abuse" />
+ <option name="config-descriptor:metadata" key="component" value="telecom" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/domainverification/device/multiuser/AndroidTest.xml b/hostsidetests/packagemanager/domainverification/device/multiuser/AndroidTest.xml
index 70b742eedaf..28ee4f9f278 100644
--- a/hostsidetests/packagemanager/domainverification/device/multiuser/AndroidTest.xml
+++ b/hostsidetests/packagemanager/domainverification/device/multiuser/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS domain verification multi user test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="multiuser" />
<!-- Instant apps can never be device admin / profile owner / device owner so positive tests
diff --git a/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml b/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml
index 95b86f5d0b2..752a5fee258 100644
--- a/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml
+++ b/hostsidetests/packagemanager/domainverification/device/standalone/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS domain verification device standalone test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/domainverification/host/AndroidTest.xml b/hostsidetests/packagemanager/domainverification/host/AndroidTest.xml
index cad7454fc0d..f0a14e40732 100644
--- a/hostsidetests/packagemanager/domainverification/host/AndroidTest.xml
+++ b/hostsidetests/packagemanager/domainverification/host/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for CTS package manager metrics host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/dynamicmime/AndroidTest.xml b/hostsidetests/packagemanager/dynamicmime/AndroidTest.xml
index 62f681e5a72..b5e0eabac71 100644
--- a/hostsidetests/packagemanager/dynamicmime/AndroidTest.xml
+++ b/hostsidetests/packagemanager/dynamicmime/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for the CTS dynamic MIME tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/extractnativelibs/AndroidTest.xml b/hostsidetests/packagemanager/extractnativelibs/AndroidTest.xml
index 1b6f8b0a95f..ef22f11f7d6 100644
--- a/hostsidetests/packagemanager/extractnativelibs/AndroidTest.xml
+++ b/hostsidetests/packagemanager/extractnativelibs/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS extract native libs host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/installedloadingprogess/AndroidTest.xml b/hostsidetests/packagemanager/installedloadingprogess/AndroidTest.xml
index 7c1850d2d1d..35fb6eb77e2 100644
--- a/hostsidetests/packagemanager/installedloadingprogess/AndroidTest.xml
+++ b/hostsidetests/packagemanager/installedloadingprogess/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config Package Manager InstalledLoadingProgress API test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/multiuser/AndroidTest.xml b/hostsidetests/packagemanager/multiuser/AndroidTest.xml
index 0e538397861..8069661f7e2 100644
--- a/hostsidetests/packagemanager/multiuser/AndroidTest.xml
+++ b/hostsidetests/packagemanager/multiuser/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for CTS package manager multi-user host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/packagesetting/AndroidTest.xml b/hostsidetests/packagemanager/packagesetting/AndroidTest.xml
index 92188534b1a..ae6d560d04d 100644
--- a/hostsidetests/packagemanager/packagesetting/AndroidTest.xml
+++ b/hostsidetests/packagemanager/packagesetting/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for CTS package installation code path host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/packagesetting/app/AndroidManifest.xml b/hostsidetests/packagemanager/packagesetting/app/AndroidManifest.xml
index 0072f743ad1..4c7f5174d4f 100644
--- a/hostsidetests/packagemanager/packagesetting/app/AndroidManifest.xml
+++ b/hostsidetests/packagemanager/packagesetting/app/AndroidManifest.xml
@@ -17,8 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.tests.packagesetting.app" >
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/hostsidetests/packagemanager/packagesetting/app/src/com/android/tests/packagesetting/app/PackageSettingDeviceTest.java b/hostsidetests/packagemanager/packagesetting/app/src/com/android/tests/packagesetting/app/PackageSettingDeviceTest.java
index ca3c4edccbd..6b5d2c6cae0 100644
--- a/hostsidetests/packagemanager/packagesetting/app/src/com/android/tests/packagesetting/app/PackageSettingDeviceTest.java
+++ b/hostsidetests/packagemanager/packagesetting/app/src/com/android/tests/packagesetting/app/PackageSettingDeviceTest.java
@@ -19,7 +19,6 @@ package com.android.tests.packagesetting.app;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -45,15 +44,12 @@ public class PackageSettingDeviceTest {
@Test
public void testFirstInstallTimeMatchesExpected() throws Exception {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
- String packageName =
- InstrumentationRegistry.getInstrumentation().getContext().getPackageName();
- String userIdStr = InstrumentationRegistry.getArguments().getString("userId");
+ String packageName = context.getPackageName();
String expectedFirstInstallTimeStr = InstrumentationRegistry.getArguments().getString(
"expectedFirstInstallTime");
- final int userId = Integer.parseInt(userIdStr);
final long expectedFirstInstallTime = Long.parseLong(expectedFirstInstallTimeStr);
- final Context contextAsUser = context.createContextAsUser(UserHandle.of(userId), 0);
- PackageInfo pi = contextAsUser.getPackageManager().getPackageInfo(packageName,
+ final PackageManager packageManager = context.getPackageManager();
+ PackageInfo pi = packageManager.getPackageInfo(packageName,
PackageManager.PackageInfoFlags.of(0));
Assert.assertTrue(Math.abs(expectedFirstInstallTime - pi.firstInstallTime) < 1000 /* ms */);
}
diff --git a/hostsidetests/packagemanager/packagesetting/src/com/android/tests/packagesetting/host/PackageSettingTest.java b/hostsidetests/packagemanager/packagesetting/src/com/android/tests/packagesetting/host/PackageSettingTest.java
index 93ab5a3bd30..6934c64a17b 100644
--- a/hostsidetests/packagemanager/packagesetting/src/com/android/tests/packagesetting/host/PackageSettingTest.java
+++ b/hostsidetests/packagemanager/packagesetting/src/com/android/tests/packagesetting/host/PackageSettingTest.java
@@ -25,7 +25,6 @@ import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
import org.junit.Assert;
-import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -41,16 +40,11 @@ public class PackageSettingTest extends BaseHostJUnit4Test {
private static final String TEST_CLASS = TEST_PACKAGE + "." + "PackageSettingDeviceTest";
private static final String CODE_PATH_ROOT = "/data/app";
private static final long DEFAULT_TIMEOUT = 10 * 60 * 1000L;
- private int mSecondUser = -1;
-
/** Uninstall apps after tests. */
@After
public void cleanUp() throws Exception {
uninstallPackage(getDevice(), TEST_PACKAGE);
Assert.assertFalse(isPackageInstalled(TEST_PACKAGE));
- if (mSecondUser != -1) {
- stopAndRemoveUser(mSecondUser);
- }
}
@Test
@@ -84,52 +78,16 @@ public class PackageSettingTest extends BaseHostJUnit4Test {
@Test
@AppModeFull
public void testFirstInstallTimeWithReboot() throws Exception {
- Assume.assumeTrue("device does not support multi-user",
- getDevice().getMaxNumberOfUsersSupported() > 1);
installPackage(TEST_APK);
final int currentUser = getDevice().getCurrentUser();
final String firstInstallTimeForCurrentUser = getFirstInstallTimeForUserFromDumpsys(
TEST_PACKAGE, currentUser);
Assert.assertNotNull(firstInstallTimeForCurrentUser);
- testFirstInstallTimeMatchesDumpsys(firstInstallTimeForCurrentUser, currentUser);
+ testFirstInstallTimeMatchesDumpsys(firstInstallTimeForCurrentUser);
// firstInstallTime should be the same after reboot
getDevice().reboot();
Assert.assertEquals(firstInstallTimeForCurrentUser,
getFirstInstallTimeForUserFromDumpsys(TEST_PACKAGE, currentUser));
-
- mSecondUser = createAndStartSecondUser();
- installPackageOnExistingUser(TEST_PACKAGE, mSecondUser);
- final String firstInstallTimeForSecondUser = getFirstInstallTimeForUserFromDumpsys(
- TEST_PACKAGE, mSecondUser);
- Assert.assertNotNull(firstInstallTimeForSecondUser);
- Assert.assertNotEquals(firstInstallTimeForCurrentUser, firstInstallTimeForSecondUser);
- testFirstInstallTimeMatchesDumpsys(firstInstallTimeForSecondUser, mSecondUser);
- getDevice().reboot();
- Assert.assertEquals(firstInstallTimeForSecondUser,
- getFirstInstallTimeForUserFromDumpsys(TEST_PACKAGE, mSecondUser));
- }
-
- private int createAndStartSecondUser() throws Exception {
- String output = getDevice().executeShellCommand("pm create-user SecondUser");
- Assert.assertTrue(output.startsWith("Success"));
- int userId = Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
- output = getDevice().executeShellCommand("am start-user -w " + userId);
- Assert.assertFalse(output.startsWith("Error"));
- output = getDevice().executeShellCommand("am get-started-user-state " + userId);
- Assert.assertTrue(output.contains("RUNNING_UNLOCKED"));
- return userId;
- }
-
- private void stopAndRemoveUser(int userId) throws Exception {
- getDevice().executeShellCommand("am stop-user -w -f " + userId);
- getDevice().executeShellCommand("pm remove-user " + userId);
- }
-
- private void installPackageOnExistingUser(String packageName, int userId) throws Exception {
- final String output = getDevice().executeShellCommand(
- String.format("pm install-existing --user %d %s", userId, packageName));
- Assert.assertEquals("Package " + packageName + " installed for user: " + userId + "\n",
- output);
}
private String getFirstInstallTimeForUserFromDumpsys(String packageName, int userId)
@@ -138,14 +96,13 @@ public class PackageSettingTest extends BaseHostJUnit4Test {
return packageInfo.getFirstInstallTime(userId);
}
- private void testFirstInstallTimeMatchesDumpsys(String firstInstallTime, int userId)
+ private void testFirstInstallTimeMatchesDumpsys(String firstInstallTime)
throws Exception {
final Map<String, String> testArgs = new HashMap<>();
// Notice the printed timestamp in dumpsys is formatted and has lost sub-second precision
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone(getDeviceTimezone()));
final long firstInstallTs = sdf.parse(firstInstallTime).getTime();
- testArgs.put("userId", String.valueOf(userId));
testArgs.put("expectedFirstInstallTime", String.valueOf(firstInstallTs));
runDeviceTests(getDevice(), null, TEST_PACKAGE, TEST_CLASS,
"testFirstInstallTimeMatchesExpected", null, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT,
@@ -159,5 +116,4 @@ public class PackageSettingTest extends BaseHostJUnit4Test {
}
return "GMT";
}
-
}
diff --git a/hostsidetests/packagemanager/parsing/host/AndroidTest.xml b/hostsidetests/packagemanager/parsing/host/AndroidTest.xml
index 30f994f81f7..e920dcb7733 100644
--- a/hostsidetests/packagemanager/parsing/host/AndroidTest.xml
+++ b/hostsidetests/packagemanager/parsing/host/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for CTS package manager metrics host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/preferredactivity/AndroidTest.xml b/hostsidetests/packagemanager/preferredactivity/AndroidTest.xml
index b978585c39b..9e7c4220c72 100644
--- a/hostsidetests/packagemanager/preferredactivity/AndroidTest.xml
+++ b/hostsidetests/packagemanager/preferredactivity/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for CTS package manager preferred activity host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/packagemanager/stats/AndroidTest.xml b/hostsidetests/packagemanager/stats/AndroidTest.xml
index 8a9081b46c9..ef351656323 100644
--- a/hostsidetests/packagemanager/stats/AndroidTest.xml
+++ b/hostsidetests/packagemanager/stats/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for CTS package manager metrics host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
index 9bdd2778982..4435e756274 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
@@ -39,6 +39,7 @@ import static android.scopedstorage.cts.lib.TestUtils.IS_URI_REDACTED_VIA_FILE_D
import static android.scopedstorage.cts.lib.TestUtils.OPEN_FILE_FOR_READ_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.OPEN_FILE_FOR_WRITE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.QUERY_MAX_ROW_ID;
+import static android.scopedstorage.cts.lib.TestUtils.QUERY_MEDIA_BY_URI_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.QUERY_MIN_ROW_ID;
import static android.scopedstorage.cts.lib.TestUtils.QUERY_OWNER_PACKAGE_NAMES;
import static android.scopedstorage.cts.lib.TestUtils.QUERY_TYPE;
@@ -48,6 +49,7 @@ import static android.scopedstorage.cts.lib.TestUtils.READDIR_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_PARAMS_SEPARATOR;
import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.SETATTR_QUERY;
+import static android.scopedstorage.cts.lib.TestUtils.UPDATE_MEDIA_BY_URI_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.canOpen;
import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.getFileRowIdFromDatabase;
@@ -131,6 +133,12 @@ public class ScopedStorageTestHelper extends Activity {
case DELETE_MEDIA_BY_URI_QUERY:
returnIntent = deleteMediaByUri(queryType);
break;
+ case UPDATE_MEDIA_BY_URI_QUERY:
+ returnIntent = updateMediaByUri(queryType);
+ break;
+ case QUERY_MEDIA_BY_URI_QUERY:
+ returnIntent = queryMediaByUri(queryType);
+ break;
case EXIF_METADATA_QUERY:
returnIntent = sendMetadata(queryType);
break;
@@ -244,6 +252,51 @@ public class ScopedStorageTestHelper extends Activity {
return intent;
}
+ private Intent updateMediaByUri(String queryType) {
+ final Intent intent = new Intent(queryType);
+ final Uri uri = getIntent().getParcelableExtra(INTENT_EXTRA_URI);
+ final Bundle attributes = getIntent().getBundleExtra(INTENT_EXTRA_ARGS);
+
+ final ContentValues values = new ContentValues();
+ for (String key : attributes.keySet()) {
+ values.put(key, attributes.getString(key));
+ }
+
+ try {
+ getContentResolver().update(uri, values, null, null);
+ intent.putExtra(queryType, true);
+ } catch (Exception e) {
+ intent.putExtra(INTENT_EXCEPTION, e);
+ }
+
+ return intent;
+ }
+
+ private Intent queryMediaByUri(String queryType) {
+ final Intent intent = new Intent(queryType);
+ final Uri uri = getIntent().getParcelableExtra(INTENT_EXTRA_URI);
+ final Bundle projection = getIntent().getBundleExtra(INTENT_EXTRA_ARGS);
+
+ try (Cursor c = getContentResolver()
+ .query(uri, projection.keySet().toArray(new String[0]), null, null)) {
+ final Bundle result = new Bundle();
+ if (c.getCount() == 1) {
+ c.moveToFirst();
+ for (String column : projection.keySet()) {
+ result.putString(column, c.getString(c.getColumnIndex(column)));
+ }
+ } else {
+ Log.d(TAG, String.format("Uri in QUERY_MEDIA_BY_URI_QUERY query points "
+ + "to %d media files", c.getCount()));
+ }
+ intent.putExtra(queryType, result);
+ } catch (Exception e) {
+ intent.putExtra(INTENT_EXCEPTION, e);
+ }
+
+ return intent;
+ }
+
private Intent queryWithArgs(String queryType) {
final Intent intent = new Intent(queryType);
final Uri uri = getIntent().getParcelableExtra(INTENT_EXTRA_URI);
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
index b23f945ae4d..8e653a1f14f 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
@@ -40,6 +40,7 @@ import static org.junit.Assert.assertEquals;
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 android.Manifest;
import android.content.ContentValues;
@@ -52,6 +53,7 @@ import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
+import android.system.Os;
import androidx.test.filters.SdkSuppress;
@@ -91,6 +93,9 @@ public class RedactUriDeviceTest extends ScopedStorageBaseDeviceTest {
static final String IMAGE_FILE_NAME = "ScopedStorageDeviceTest_file_" + NONCE + ".jpg";
+ static final String FUZZER_HEIC_FILE_NAME =
+ "ScopedStorageDeviceTest_file_fuzzer_" + NONCE + ".heic";
+
// An app with no permissions
private static final TestApp APP_B_NO_PERMS = new TestApp("TestAppB",
"android.scopedstorage.cts.testapp.B.noperms", 1, false,
@@ -465,7 +470,7 @@ public class RedactUriDeviceTest extends ScopedStorageBaseDeviceTest {
assertUriIsUnredacted(img);
try (ParcelFileDescriptor pfd =
- getContentResolver().openFileDescriptor(redactedUri, "r")) {
+ getContentResolver().openFileDescriptor(redactedUri, "r")) {
FileDescriptor fd = pfd.getFileDescriptor();
ExifInterface redactedExifInf = new ExifInterface(fd);
assertUriIsRedacted(redactedExifInf);
@@ -475,6 +480,26 @@ public class RedactUriDeviceTest extends ScopedStorageBaseDeviceTest {
}
}
+ @Test
+ public void testOpenOnRedactedUri_readFuzzer() throws Exception {
+ final File img = stageFuzzerImageFileWithMetadata(FUZZER_HEIC_FILE_NAME);
+ final Uri redactedUri = getRedactedUri(img);
+ try {
+ assertUriIsUnredacted(img);
+
+ try (ParcelFileDescriptor pfd =
+ getContentResolver().openFileDescriptor(redactedUri, "r")) {
+ FileDescriptor fd = pfd.getFileDescriptor();
+ int bufSize = 0x1000000;
+ byte[] data = new byte[bufSize];
+ int fileSize = Os.read(fd, data, 0, bufSize);
+ assertUriIsRedacted(data, fileSize);
+ }
+ } finally {
+ img.delete();
+ }
+ }
+
private void testRedactedUriCommon(Uri uri, Uri redactedUri) {
assertEquals(redactedUri.getAuthority(), uri.getAuthority());
assertEquals(redactedUri.getScheme(), uri.getScheme());
@@ -517,6 +542,19 @@ public class RedactUriDeviceTest extends ScopedStorageBaseDeviceTest {
assertEquals(latLong[1], 0.0, 0.0);
}
+ private void assertUriIsRedacted(byte[] data, int fileSize) {
+ // Data in redaction ranges should be zero.
+ int[] start = new int[]{50538, 712941, 712965, 712989, 713033, 713101};
+ int[] end = new int[]{711958, 712943, 712967, 712990, 713100, 713125};
+
+ assertTrue(fileSize == 4407744);
+ for (int index = 0; index < start.length && index < end.length; index++) {
+ for (int c = start[index]; c < end[index]; c++) {
+ assertTrue("It should be zero!", data[c] == (byte) 0);
+ }
+ }
+ }
+
private Cursor getRedactedCursor(Uri redactedUri) {
Cursor redactedUriCursor = getContentResolver().query(redactedUri, null, null, null);
assertNotNull(redactedUriCursor);
@@ -530,11 +568,19 @@ public class RedactUriDeviceTest extends ScopedStorageBaseDeviceTest {
}
private File stageImageFileWithMetadata(String name) throws Exception {
+ return stageImageFileWithMetadata(name, R.raw.img_with_metadata);
+ }
+
+ private File stageFuzzerImageFileWithMetadata(String name) throws Exception {
+ return stageImageFileWithMetadata(name, R.raw.fuzzer);
+ }
+
+ private File stageImageFileWithMetadata(String name, int sourceId) throws Exception {
final File img = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), name);
try (InputStream in =
- getContext().getResources().openRawResource(R.raw.img_with_metadata);
+ getContext().getResources().openRawResource(sourceId);
OutputStream out = new FileOutputStream(img)) {
// Dump the image we have to external storage
FileUtils.copy(in, out);
@@ -542,4 +588,4 @@ public class RedactUriDeviceTest extends ScopedStorageBaseDeviceTest {
return img;
}
-}
+} \ No newline at end of file
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 4bff21bbd54..8dd4f7a8211 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java
@@ -35,6 +35,8 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
+import android.net.Uri;
+import android.os.Bundle;
import android.provider.MediaStore;
import android.scopedstorage.cts.lib.TestUtils;
import android.util.Log;
@@ -54,7 +56,10 @@ import org.junit.runners.Parameterized.Parameter;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
@RunWith(Parameterized.class)
public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
@@ -66,9 +71,14 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
"android.scopedstorage.cts.testapp.filemanager", 1, false,
"CtsScopedStorageTestAppFileManager.apk");
+ private static final TestApp APP_NO_PERMS = new TestApp("TestAppB",
+ "android.scopedstorage.cts.testapp.B.noperms", 1, false,
+ "CtsScopedStorageTestAppB.apk");
private static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
permissionToOp(Manifest.permission.MANAGE_EXTERNAL_STORAGE);
+ private static final int MAX_MEDIA_FILES_COUNT_THRESHOLD = 1000;
+
private Context mContext;
private ContentResolver mContentResolver;
private UiDevice mDevice;
@@ -79,17 +89,23 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
/** Parameters data. */
@Parameterized.Parameters(name = "volume={0}")
public static Iterable<?> data() {
- return Arrays.asList(MediaStore.VOLUME_EXTERNAL_PRIMARY);
+ return Arrays.asList(MediaStore.VOLUME_EXTERNAL);
}
@Before
public void setUp() throws Exception {
super.setupExternalStorage(mVolumeName);
- Log.d(TAG, "Using volume : " + mVolumeName);
mContext = ApplicationProvider.getApplicationContext();
mContentResolver = mContext.getContentResolver();
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
mDevice = UiDevice.getInstance(inst);
+ final int mMediaFilesCount = TestUtils.queryWithArgsAs(APP_FM,
+ MediaStore.Files.getContentUri(mVolumeName), null);
+ Log.d(TAG, "Number of media files on device: " + mMediaFilesCount);
+
+ assumeTrue("The number of media files is too large; Skipping the test as it "
+ + "will take too much time to execute",
+ mMediaFilesCount <= MAX_MEDIA_FILES_COUNT_THRESHOLD);
}
@Test
@@ -99,6 +115,37 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
}
@Test
+ public void testAttributesRestoration() throws Exception {
+ Map<File, Uri> fileToUriMap = new HashMap<>();
+
+ try {
+ setFlag("persist.sys.fuse.backup.internal_db_backup", true);
+ setFlag("persist.sys.fuse.backup.external_volume_backup", true);
+
+ fileToUriMap = createFilesAsTestApp(APP_NO_PERMS, 5);
+ final Map<File, Bundle> fileToAttributesMapBeforeRestore = setAttributes(fileToUriMap);
+
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ final ContentResolver resolver = context.getContentResolver();
+ MediaStore.waitForIdle(resolver);
+ resolver.call(MediaStore.AUTHORITY, "idle_maintenance_for_stable_uris",
+ null, null);
+
+ // Clear MediaProvider package data to trigger DB recreation.
+ mDevice.executeShellCommand("pm clear " + getMediaProviderPackageName());
+
+ // Sleeping to make sure the db recovering is completed
+ Thread.sleep(20000);
+
+ verifyAttributes(fileToUriMap, fileToAttributesMapBeforeRestore);
+ } finally {
+ for (File file : fileToUriMap.keySet()) {
+ file.delete();
+ }
+ }
+ }
+
+ @Test
public void testUrisMapToNewIds_withNextRowIdBackup() throws Exception {
assumeTrue(getBoolean("persist.sys.fuse.backup.nextrowid_enabled", false));
testScenario(/* nextRowIdBackupEnabled */ true);
@@ -113,7 +160,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
0);
allowAppOpsToUid(fmUid, OPSTR_MANAGE_EXTERNAL_STORAGE);
- files = createFilesAsTestApp(APP_FM, 5);
+ files.addAll(createFilesAsTestApp(APP_FM, 5).keySet());
long maxRowIdOfInternalDbBeforeReset = readMaximumRowIdFromDatabaseAs(APP_FM,
MediaStore.Files.getContentUri(MediaStore.VOLUME_INTERNAL));
@@ -161,19 +208,95 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
}
}
- private List<File> createFilesAsTestApp(TestApp app, int count) throws Exception {
- List<File> files = new ArrayList<>();
+ private Map<File, Uri> createFilesAsTestApp(TestApp app, int count) throws Exception {
+ final Map<File, Uri> files = new HashMap<>();
for (int i = 1; i <= count; i++) {
final File file = new File(getPicturesDir(),
"Cts_" + System.currentTimeMillis() + ".jpg");
- TestUtils.createFileAs(app, file.getAbsolutePath());
- MediaStore.scanFile(mContentResolver, file);
- files.add(file);
+ final boolean isFileCreated = !file.exists()
+ && TestUtils.createFileAs(app, file.getAbsolutePath());
+
+ if (!isFileCreated) {
+ throw new RuntimeException(
+ "File was not created on path: " + file.getAbsolutePath());
+ }
+
+ final Uri uri = MediaStore.scanFile(mContentResolver, file);
+ if (uri == null) {
+ throw new RuntimeException("Scanning returned null uri for file "
+ + file.getAbsolutePath());
+ }
+ files.put(file, uri);
}
return files;
}
+ private void verifyAttributes(Map<File, Uri> fileToUriMap,
+ Map<File, Bundle> fileToAttributesMapBeforeRestore) throws Exception {
+ Log.d(TAG, "Started attributes verification after db restore");
+ for (Map.Entry<File, Uri> entry : fileToUriMap.entrySet()) {
+ final Bundle originalAttributes = fileToAttributesMapBeforeRestore.get(entry.getKey());
+ final Bundle attributesAfterRestore = TestUtils.queryMediaByUriAs(APP_NO_PERMS,
+ entry.getValue(), originalAttributes.keySet());
+
+ assertWithMessage("Uri doesn't point to a media file after db restore")
+ .that(attributesAfterRestore.isEmpty()).isFalse();
+
+ for (String attribute : originalAttributes.keySet()) {
+ final String afterRestore = attributesAfterRestore.getString(attribute);
+ final String beforeRestore = fileToAttributesMapBeforeRestore
+ .get(entry.getKey()).getString(attribute);
+
+ final String assertMessage = String.format("Expected values for %s attribute to be "
+ + "equal before and after DB restoration", attribute);
+ assertWithMessage(assertMessage)
+ .that(afterRestore).isEqualTo(beforeRestore);
+ }
+ }
+ Log.d(TAG, "Finished attributes verification after db restore");
+ }
+
+ private Map<File, Bundle> setAttributes(Map<File, Uri> fileToUriMap) throws Exception {
+ final Map<File, Bundle> fileToAttributes = new HashMap<>();
+ int seed = 0;
+ for (Map.Entry<File, Uri> entry : fileToUriMap.entrySet()) {
+ final Bundle attributes = generateAttributes(seed++);
+
+ TestUtils.updateMediaByUriAs(APP_NO_PERMS, entry.getValue(), attributes);
+
+ final Bundle autoGeneratedAttributes = TestUtils.queryMediaByUriAs(APP_NO_PERMS,
+ entry.getValue(), new HashSet<>(Arrays.asList(
+ MediaStore.MediaColumns._ID,
+ MediaStore.MediaColumns.DATE_EXPIRES,
+ MediaStore.MediaColumns.OWNER_PACKAGE_NAME)));
+
+ attributes.putAll(autoGeneratedAttributes);
+ fileToAttributes.put(entry.getKey(), attributes);
+ }
+ return fileToAttributes;
+ }
+
+ private Bundle generateAttributes(int seed) {
+ final Bundle attributes = new Bundle();
+ attributes.putString(MediaStore.MediaColumns.IS_FAVORITE, seed % 2 == 0 ? "1" : "0");
+ attributes.putString(MediaStore.MediaColumns.IS_PENDING, seed % 3 == 0 ? "1" : "0");
+ // Shouldn't set both IS_PENDING and IS_TRASHED
+ attributes.putString(MediaStore.MediaColumns.IS_TRASHED,
+ seed % 4 == 0 && seed % 3 != 0 ? "1" : "0");
+
+ return attributes;
+ }
+
+ private void setFlag(String flagName, boolean value) throws Exception {
+ mDevice.executeShellCommand(
+ "setprop " + flagName + " " + value);
+ final String newValue = mDevice.executeShellCommand("getprop " + flagName).trim();
+
+ assumeTrue("Not able to set flag: " + flagName,
+ String.valueOf(value).equals(newValue));
+ }
+
private static String getMediaProviderPackageName() {
final Instrumentation inst = androidx.test.InstrumentationRegistry.getInstrumentation();
final PackageManager packageManager = inst.getContext().getPackageManager();
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 6d17f4f9c15..a824a1558aa 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
@@ -93,6 +93,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -118,6 +119,10 @@ public class TestUtils {
public static final String DELETE_FILE_QUERY = "android.scopedstorage.cts.deletefile";
public static final String DELETE_MEDIA_BY_URI_QUERY =
"android.scopedstorage.cts.deletemediabyuri";
+ public static final String UPDATE_MEDIA_BY_URI_QUERY =
+ "android.scopedstorage.cts.update_media_by_uri";
+ public static final String QUERY_MEDIA_BY_URI_QUERY =
+ "android.scopedstorage.cts.query_media_by_uri";
public static final String DELETE_RECURSIVE_QUERY = "android.scopedstorage.cts.deleteRecursive";
public static final String CAN_OPEN_FILE_FOR_READ_QUERY =
"android.scopedstorage.cts.can_openfile_read";
@@ -413,6 +418,36 @@ public class TestUtils {
}
/**
+ * Makes the given {@code testApp} update the media rows for the given {@code uri} by
+ * updating values for the provided {@code attributes}.
+ *
+ * <p>This method drops shell permission identity.
+ */
+ public static boolean updateMediaByUriAs(TestApp testApp, Uri uri, Bundle attributes)
+ throws Exception {
+ final String actionName = UPDATE_MEDIA_BY_URI_QUERY;
+ return getFromTestApp(testApp, uri, actionName, attributes).getBoolean(actionName);
+ }
+
+ /**
+ * Makes the given {@code testApp} query media file by the given {@code uri}
+ * and {@code projection}. An empty result will be returned if {@code uri}
+ * indicates location of multiple files or no files at all.
+ *
+ * <p>This method drops shell permission identity.
+ */
+ public static Bundle queryMediaByUriAs(TestApp testApp, Uri uri, Set<String> projection)
+ throws Exception {
+ final String actionName = QUERY_MEDIA_BY_URI_QUERY;
+ final Bundle bundle = new Bundle();
+ for (String columnName : projection) {
+ bundle.putString(columnName, "");
+ }
+
+ return getFromTestApp(testApp, uri, actionName, bundle).getBundle(actionName);
+ }
+
+ /**
* Makes the given {@code testApp} delete a file.
*
* <p>This method drops shell permission identity.
diff --git a/hostsidetests/scopedstorage/res/raw/fuzzer.heic b/hostsidetests/scopedstorage/res/raw/fuzzer.heic
new file mode 100644
index 00000000000..32069afcce0
--- /dev/null
+++ b/hostsidetests/scopedstorage/res/raw/fuzzer.heic
Binary files differ
diff --git a/hostsidetests/seccomp/AndroidTest.xml b/hostsidetests/seccomp/AndroidTest.xml
index 49e19c552e4..669834114f2 100644
--- a/hostsidetests/seccomp/AndroidTest.xml
+++ b/hostsidetests/seccomp/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS Sseccomp host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="misc" />
+ <option name="config-descriptor:metadata" key="component" value="security" />
<!-- Run in instant_app mode as well, since application zygotes are available
even in that context -->
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
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 a5e655737b9..603292ab624 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29374.java
@@ -17,10 +17,12 @@
package android.security.cts;
import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.KernelVersionHost;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
@@ -36,6 +38,7 @@ public class CVE_2020_29374 extends NonRootSecurityTestCase {
@AsbSecurityTest(cveBugId = 174737879)
@Test
public void testPocCVE_2020_29374() throws Exception {
+ assumeTrue(KernelVersionHost.isKernelVersionGreaterThanEqualTo(getDevice(), "5.4.0"));
AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-29374", getDevice(),60);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java
index 69645d8d012..c12cf330d81 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -17,10 +17,10 @@
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.UserUtils;
import com.android.sts.common.tradefed.testtype.RootSecurityTestCase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -38,55 +38,28 @@ public class CVE_2022_20112 extends RootSecurityTestCase {
// Is play managed : No
@AsbSecurityTest(cveBugId = 206987762)
@Test
- public void testPocCVE_2022_20112() throws Exception {
- // This setting is not supported on automotive
- if (isAutomotive()) return;
-
- final String testPkg = "android.security.cts.CVE_2022_20112";
- ITestDevice device = null;
- int currentUser = -1;
- int newUser = -1;
+ public void testPocCVE_2022_20112() {
try {
- device = getDevice();
-
- // Device wakeup and unlock
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("wm dismiss-keyguard", device);
-
- // Get current user
- currentUser = device.getCurrentUser();
-
- // Create new guest user 'CTSUser' for test
- newUser = device.createUser("CTSUser", true, false);
-
- // Start new guest user 'CTSUser'
- assumeTrue("Unable to create new guest user", device.startUser(newUser, true));
-
- // Switch to new user 'CTSUser'
- assumeTrue("Unable to switch to guest user", device.switchUser(newUser));
-
- // Install PoC application
- installPackage("CVE-2022-20112.apk");
-
- runDeviceTests(testPkg, testPkg + ".DeviceTest", "testprivateDnsPreferenceController");
+ // This setting is not supported on automotive
+ if (isAutomotive()) return;
+
+ final ITestDevice device = getDevice();
+ try (AutoCloseable asGuestUser =
+ new UserUtils.SecondaryUser(device)
+ .name("CTSUser")
+ .guest()
+ .doSwitch()
+ .withUser()) {
+ // Install PoC application in guest user
+ installPackageAsUser(
+ "CVE-2022-20112.apk", false /* grantPermission */, device.getCurrentUser());
+
+ final String testPkg = "android.security.cts.CVE_2022_20112";
+ runDeviceTests(
+ testPkg, testPkg + ".DeviceTest", "testPrivateDnsPreferenceController");
+ }
} catch (Exception e) {
assumeNoException(e);
- } finally {
- try {
- if (currentUser != -1) {
- // Switch back to previous user
- device.switchUser(currentUser);
- }
- if (newUser != -1) {
- // Stop user 'CTSUser'
- device.stopUser(newUser);
-
- // Remove user 'CTSUser'
- device.removeUser(newUser);
- }
- } catch (Exception e) {
- // Ignore exception here
- }
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21144.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21144.java
new file mode 100644
index 00000000000..064cfbc3dcd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21144.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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_2023_21144 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 252766417)
+ @Test
+ public void testPocCVE_2023_21144() {
+ ITestDevice device = null;
+ try {
+ device = getDevice();
+ final String testPkg = "android.security.cts.CVE_2023_21144";
+ installPackage("CVE-2023-21144.apk", "-g");
+
+ // Allowing notification listener service for PocListenerService
+ device.executeShellCommand(
+ "cmd notification allow_listener " + testPkg + "/.PocListenerService");
+
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testPocCVE_2023_21144");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ // To undo the expanded notification panel
+ try {
+ device.executeShellCommand("input keyevent KEYCODE_HOME");
+ } catch (Exception ignore) {
+ // Ignore
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml
deleted file mode 100644
index af458479c47..00000000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml
+++ /dev/null
@@ -1,24 +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.
--->
-<resources>
- <string name="defaultSettingsPkg">com.android.settings</string>
- <string name="getAvailabilityStatusMethodName">getAvailabilityStatus</string>
- <string name="privateDnsPreferenceControllerClassName">.network.PrivateDnsPreferenceController
- </string>
- <string name="testFailMsg">Device is vulnerable to b/206987762!! Private DNS can be modified in
- guest mode</string>
-</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java
index 96cb205134f..731c5949c6d 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -17,10 +17,12 @@
package android.security.cts.CVE_2022_20112;
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.Instrumentation;
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
@@ -40,51 +42,64 @@ import java.lang.reflect.Method;
public class DeviceTest {
@Test
- public void testprivateDnsPreferenceController() {
- UiAutomation uiAutomation = null;
+ public void testPrivateDnsPreferenceController() {
try {
- Context context = getInstrumentation().getTargetContext();
+ final Instrumentation instrumentation = getInstrumentation();
+ final Context context = instrumentation.getContext();
// Retrieve settings package name dynamically
Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
ComponentName settingsComponent =
settingsIntent.resolveActivity(context.getPackageManager());
- String settingsPkgName = settingsComponent != null ? settingsComponent.getPackageName()
- : context.getString(R.string.defaultSettingsPkg);
+ String settingsPkgName =
+ settingsComponent != null
+ ? settingsComponent.getPackageName()
+ : "com.android.settings";
// Get vulnerable method 'getAvailabilityStatus' using reflection
- Context settingsContext = context.createPackageContext(settingsPkgName,
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ final Context settingsContext =
+ context.createPackageContext(
+ settingsPkgName,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
ClassLoader settingsClassLoader = settingsContext.getClassLoader();
Class<?> privateDnsPreferenceControllerClass =
- settingsClassLoader.loadClass(settingsPkgName
- + context.getString(R.string.privateDnsPreferenceControllerClassName));
+ settingsClassLoader.loadClass(
+ settingsPkgName + ".network.PrivateDnsPreferenceController");
Constructor<?> privateDnsPreferenceControllerCstr =
privateDnsPreferenceControllerClass.getConstructor(Context.class);
Object privateDnsPreferenceControllerObject =
privateDnsPreferenceControllerCstr.newInstance(settingsContext);
- Method getAvailabilityStatusMethod = privateDnsPreferenceControllerClass
- .getDeclaredMethod(context.getString(R.string.getAvailabilityStatusMethodName));
+ Method getAvailabilityStatusMethod =
+ privateDnsPreferenceControllerClass.getDeclaredMethod("getAvailabilityStatus");
getAvailabilityStatusMethod.setAccessible(true);
// Check if current user is guest user
- uiAutomation = getInstrumentation().getUiAutomation();
- uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.CREATE_USERS);
final UserManager userManager = context.getSystemService(UserManager.class);
- assumeTrue(userManager.isGuestUser());
-
- // Invoke vulnerable method 'getAvailabilityStatus'
- int status =
- (int) getAvailabilityStatusMethod.invoke(privateDnsPreferenceControllerObject);
- assertFalse(context.getString(R.string.testFailMsg), status == 0 /* AVAILABLE */);
+ try (AutoCloseable withAdoptShellPermissionIdentity =
+ withAdoptShellPermissionIdentity(
+ instrumentation, android.Manifest.permission.CREATE_USERS)) {
+ assumeTrue(userManager.isGuestUser());
+ // Invoke vulnerable method 'getAvailabilityStatus'
+ int status =
+ (int)
+ getAvailabilityStatusMethod.invoke(
+ privateDnsPreferenceControllerObject);
+ assertFalse(
+ "Device is vulnerable to b/206987762!! Private DNS can be modified in"
+ + " guest mode",
+ status == 0 /* AVAILABLE */);
+ }
} catch (Exception e) {
assumeNoException(e);
- } finally {
- try {
- uiAutomation.dropShellPermissionIdentity();
- } catch (Exception ignored) {
- // Ignore exception here
- }
}
}
+
+ private AutoCloseable withAdoptShellPermissionIdentity(
+ Instrumentation instrumentation, String permission) {
+ final UiAutomation uiAutomation = instrumentation.getUiAutomation();
+ uiAutomation.adoptShellPermissionIdentity(permission);
+
+ // Remove permissions
+ return () -> uiAutomation.dropShellPermissionIdentity();
+ }
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/DeviceTest.java
index 070a1d9f90b..d9dc035dc0f 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/DeviceTest.java
@@ -16,6 +16,8 @@
package android.security.cts.CVE_2023_21129;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertFalse;
@@ -30,6 +32,9 @@ import android.content.IntentFilter;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -75,7 +80,7 @@ public class DeviceTest {
// Check if bubble notifications are enabled or disabled on the device
assumeTrue(
context.getString(R.string.bubbleNotificDisabled),
- notificationManager.areBubblesAllowed());
+ notificationManager.getBubblePreference() == BUBBLE_PREFERENCE_ALL);
// Launching BubbleActivity
Intent intent = new Intent(context, BubbleActivity.class);
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/PocService.java
index 9fdacad1130..1406e8372aa 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/PocService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21129/src/android/security/cts/CVE_2023_21129/PocService.java
@@ -46,8 +46,16 @@ public class PocService extends Service {
PendingIntent.getActivity(
this,
mResources.getInteger(R.integer.requestCode),
+ new Intent(this, BubbleActivity.class),
+ PendingIntent.FLAG_MUTABLE /* flags */);
+
+ // Create a pending intent for fullscreen intent
+ PendingIntent pendingIntent =
+ PendingIntent.getActivity(
+ this,
+ mResources.getInteger(R.integer.requestCode),
new Intent(this, PocActivity.class),
- 0 /* flags */);
+ PendingIntent.FLAG_IMMUTABLE /* flags */);
// Create icon
Icon icon = createNotificationIcon();
@@ -102,7 +110,7 @@ public class PocService extends Service {
.setSmallIcon(icon)
.setShortcutId(shortcutId)
.setBubbleMetadata(bubbleData)
- .setFullScreenIntent(bubbleIntent, true /* high priority */)
+ .setFullScreenIntent(pendingIntent, true /* high priority */)
.setStyle(messagingStyle);
notificationManager.notify(
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/Android.bp
new file mode 100644
index 00000000000..a1132bb534c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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-2023-21144",
+ defaults: [
+ "cts_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/AndroidManifest.xml
new file mode 100644
index 00000000000..c0b27b711f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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_2023_21144">
+
+ <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <service android:name=".PocListenerService"
+ android:exported="true"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.NotificationListenerService" />
+ </intent-filter>
+ </service>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_21144" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/res/values/strings.xml
new file mode 100644
index 00000000000..d51c9b90445
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/res/values/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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="broadcastAction">CVE_2023_21144_action</string>
+ <string name="dataMimeType">image/png</string>
+ <string name="failMessage">Device is vulnerable to b/252766417 !!</string>
+ <string name="fileNotCreated">image file is not created</string>
+ <string name="imageFile">cve_2023_21144.png</string>
+ <string name="message">CVE_2023_21144_message</string>
+ <string name="notificationChannelId">CVE_2023_21144_notification_channel_id</string>
+ <string name="notificationChannelName">CVE_2023_21144_notification_channel_name</string>
+ <string name="notificationListenerNotConnected">notification listener not connected!!</string>
+ <string name="notificationText">CVE_2023_21144_notification_text</string>
+ <string name="resourceId">android:id/message_text</string>
+ <string name="systemUiPkgName">com.android.systemui</string>
+ <string name="username">CVE_2023_21144_username</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/DeviceTest.java
new file mode 100644
index 00000000000..e91c3ea9424
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/DeviceTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 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_2023_21144;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.app.Notification;
+import android.app.Notification.MessagingStyle;
+import android.app.Notification.MessagingStyle.Message;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Person;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.widget.ImageView;
+
+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.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testPocCVE_2023_21144() {
+ try {
+ Instrumentation instrumentation = getInstrumentation();
+ Context context = instrumentation.getContext();
+
+ try (AutoCloseable withTemporaryImage = withTemporaryImage(context)) {
+ // Prepare notification channel
+ NotificationChannel notificationChannel =
+ new NotificationChannel(
+ context.getString(R.string.notificationChannelId),
+ context.getString(R.string.notificationChannelName),
+ NotificationManager.IMPORTANCE_HIGH);
+ NotificationManager notificationManager =
+ context.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(notificationChannel);
+
+ // Prepare messaging style
+ Person person =
+ new Person.Builder().setName(context.getString(R.string.username)).build();
+ Message message =
+ new Message(context.getString(R.string.message), 0L /* timestamp */, person)
+ .setData(
+ context.getString(R.string.dataMimeType),
+ Uri.fromFile(getImageFile(context)));
+ MessagingStyle messagingStyle = new MessagingStyle(person).addMessage(message);
+
+ // Build notification
+ Notification notification =
+ new Notification.Builder(context, notificationChannel.getId())
+ .setContentText(context.getString(R.string.notificationText))
+ .setSmallIcon(
+ Icon.createWithData(
+ new byte[0] /* data */,
+ 0 /* offset */,
+ 0 /* length */))
+ .setStyle(messagingStyle)
+ .build();
+
+ // Register BroadcastReceiver
+ Semaphore broadcastReceived = new Semaphore(0);
+ BroadcastReceiver broadcastReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ broadcastReceived.release();
+ } catch (Exception ignore) {
+ // Ignore
+ }
+ }
+ };
+ IntentFilter broadcastFilter =
+ new IntentFilter(context.getString(R.string.broadcastAction));
+ context.registerReceiver(broadcastReceiver, broadcastFilter);
+
+ // Send notification and wait for broadcast to get received
+ notificationManager.notify(0 /* notification id */, notification);
+ final long timeout = 10_000L;
+ assumeTrue(
+ context.getString(R.string.notificationListenerNotConnected),
+ broadcastReceived.tryAcquire(timeout, TimeUnit.MILLISECONDS));
+
+ // With fix, the notification does not contain image. Hence, using uiautomator
+ // to detect the imageview to fail test
+ context.getSystemService(StatusBarManager.class).expandNotificationsPanel();
+ final UiDevice uiDevice = UiDevice.getInstance(instrumentation);
+ UiObject2 uiObject =
+ uiDevice.wait(
+ Until.findObject(
+ By.pkg(context.getString(R.string.systemUiPkgName))
+ .res(context.getString(R.string.resourceId))
+ .desc(context.getString(R.string.message))
+ .clazz(ImageView.class.getName())),
+ timeout);
+ assertNull(context.getString(R.string.failMessage), uiObject);
+ }
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ private AutoCloseable withTemporaryImage(Context context) throws Exception {
+ // Create a png file in a worker Thread.
+ CompletableFuture<Boolean> imageIsReady = new CompletableFuture<Boolean>();
+ final HandlerThread handlerThread = new HandlerThread(context.getPackageName());
+ handlerThread.start();
+ new Handler(handlerThread.getLooper())
+ .post(
+ () -> {
+ try {
+ // The dimension of 13000 x 17000 creates png image of size ~2mb
+ // which is sufficient to extend loading time of 100ms.
+ final int sufficientlyLargeWidth = 13000;
+ final int sufficientlyLargeHeight = 17000;
+ Bitmap bitmap =
+ Bitmap.createBitmap(
+ sufficientlyLargeWidth,
+ sufficientlyLargeHeight,
+ Bitmap.Config.ARGB_8888);
+ File imageFile = getImageFile(context);
+ imageFile.createNewFile();
+ FileOutputStream fileOutputStream = new FileOutputStream(imageFile);
+ bitmap.compress(
+ Bitmap.CompressFormat.PNG,
+ 100 /* quality */,
+ fileOutputStream);
+ fileOutputStream.flush();
+ fileOutputStream.close();
+ imageIsReady.complete(true);
+ } catch (Exception ignore) {
+ imageIsReady.complete(false);
+ }
+ });
+
+ // Wait until image gets created successfully
+ assumeTrue(
+ context.getString(R.string.fileNotCreated),
+ imageIsReady.get() && getImageFile(context).exists());
+
+ return () -> {
+ File imageFile = getImageFile(context);
+ if (imageFile.exists()) {
+ imageFile.delete();
+ }
+ };
+ }
+
+ private File getImageFile(Context context) {
+ return Environment.buildPath(
+ Environment.getExternalStorageDirectory(),
+ Environment.DIRECTORY_DOWNLOADS,
+ context.getString(R.string.imageFile));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/PocListenerService.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/PocListenerService.java
new file mode 100644
index 00000000000..77508a6a78f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21144/src/android/security/cts/CVE_2023_21144/PocListenerService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 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_2023_21144;
+
+import android.content.Intent;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+
+public class PocListenerService extends NotificationListenerService {
+
+ @Override
+ public void onNotificationPosted(StatusBarNotification sbn) {
+ try {
+ // Send broadcast when notification is posted
+ sendBroadcast(new Intent(getString(R.string.broadcastAction)));
+ } catch (Exception ignore) {
+ // Ignore as it causes assumptionFailure in DeviceTest
+ }
+ }
+}
diff --git a/hostsidetests/silentupdate/AndroidTest.xml b/hostsidetests/silentupdate/AndroidTest.xml
index 8cb9ca11258..2f23e0918f3 100644
--- a/hostsidetests/silentupdate/AndroidTest.xml
+++ b/hostsidetests/silentupdate/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Runs the silent update install tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/stagedinstall/AndroidTest.xml b/hostsidetests/stagedinstall/AndroidTest.xml
index a76052890eb..45ba6e1eb1f 100644
--- a/hostsidetests/stagedinstall/AndroidTest.xml
+++ b/hostsidetests/stagedinstall/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Runs the staged install API tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<!-- Instant apps can't have INSTALL_PACKAGES permission. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/DisplayWakeReportedTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/DisplayWakeReportedTests.java
index 95607c270d9..89d67c617f4 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/DisplayWakeReportedTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/DisplayWakeReportedTests.java
@@ -93,7 +93,7 @@ public class DisplayWakeReportedTests {
@Test
public void testWakeWithWakeUpApi() throws Exception {
ShellIdentityUtils.invokeWithShellPermissions(() ->
- mPowerManager.wakeUp(SystemClock.elapsedRealtime(),
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(),
PowerManager.WAKE_REASON_UNKNOWN,
TAG));
}
diff --git a/hostsidetests/systemui/src/android/host/systemui/TileServiceTest.java b/hostsidetests/systemui/src/android/host/systemui/TileServiceTest.java
index 7f5e74ea0fd..10d94271545 100644
--- a/hostsidetests/systemui/src/android/host/systemui/TileServiceTest.java
+++ b/hostsidetests/systemui/src/android/host/systemui/TileServiceTest.java
@@ -62,21 +62,6 @@ public class TileServiceTest extends BaseTileServiceTest {
remTile();
assertTrue(waitFor("onTileRemoved"));
}
-
- @ApiTest(apis = {"android.service.quicksettings.TileService#onStartListening",
- "android.service.quicksettings.TileService#onStopListening"})
- public void testListeningNotifications() throws Exception {
- if (!supported()) return;
- addTile();
-
- // Open the notification shade and make sure the tile gets a chance to listen.
- openNotifications();
- assertTrue(waitFor("onStartListening"));
- // Collapse the shade and make sure the listening ends.
- collapse();
- assertTrue(waitFor("onStopListening"));
- }
-
@ApiTest(apis = {"android.service.quicksettings.TileService#onStartListening",
"android.service.quicksettings.TileService#onStopListening"})
public void testListeningSettings() throws Exception {
diff --git a/hostsidetests/usb/AndroidTest.xml b/hostsidetests/usb/AndroidTest.xml
index 14f6b95e803..c217a2fbfe0 100644
--- a/hostsidetests/usb/AndroidTest.xml
+++ b/hostsidetests/usb/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS USB host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="misc" />
+ <option name="config-descriptor:metadata" key="component" value="systems" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/hostsidetests/wifibroadcasts/AndroidTest.xml b/hostsidetests/wifibroadcasts/AndroidTest.xml
index 79760f7b9e2..cc32b6f7dbf 100644
--- a/hostsidetests/wifibroadcasts/AndroidTest.xml
+++ b/hostsidetests/wifibroadcasts/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS WifiBroadcasts host test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="networking" />
+ <option name="config-descriptor:metadata" key="component" value="wifi" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
index cfcbddaae6b..dbb3ad7b353 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
@@ -51,6 +51,7 @@ import androidx.test.uiautomator.UiSelector;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;
@@ -149,6 +150,7 @@ public class ActionGetContentOnlyTest extends PhotoPickerBaseTest {
}
@Test
+ @Ignore("Tracking this in b/295151917")
public void testBrowse_multiSelect() throws Exception {
final int itemCount = 3;
List<Pair<Uri, String>> createdImagesData = createImagesAndGetUriAndPath(itemCount,
@@ -251,7 +253,7 @@ public class ActionGetContentOnlyTest extends PhotoPickerBaseTest {
assertWithMessage("Waiting for app list to appear in DocumentsUi").that(
new UiObject(appList).waitForExists(SHORT_TIMEOUT)).isTrue();
- String photoPickerAppName = "Media";
+ String photoPickerAppName = "Media picker";
UiObject mediaButton = sDevice.findObject(new UiSelector().text(photoPickerAppName));
assertWithMessage("Timed out waiting for " + photoPickerAppName + " app icon to appear")
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
index d0d2595ae05..afc33e11c7d 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
@@ -22,6 +22,7 @@ import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.Nullable;
@@ -91,11 +92,15 @@ public class PhotoPickerBaseTest {
protected static void setCloudProvider(@Nullable String authority) throws Exception {
if (authority == null) {
sDevice.executeShellCommand(
- "content call --uri content://media/ --method set_cloud_provider --extra"
+ "content call"
+ + " --user " + UserHandle.myUserId()
+ + " --uri content://media/ --method set_cloud_provider --extra"
+ " cloud_provider:n:null");
} else {
sDevice.executeShellCommand(
- "content call --uri content://media/ --method set_cloud_provider --extra"
+ "content call"
+ + " --user " + UserHandle.myUserId()
+ + " --uri content://media/ --method set_cloud_provider --extra"
+ " cloud_provider:s:"
+ authority);
}
@@ -104,7 +109,9 @@ public class PhotoPickerBaseTest {
protected static String getCurrentCloudProvider() throws IOException {
final String out =
sDevice.executeShellCommand(
- "content call --uri content://media/ --method get_cloud_provider");
+ "content call"
+ + " --user " + UserHandle.myUserId()
+ + " --uri content://media/ --method get_cloud_provider");
return extractCloudProvider(out);
}
diff --git a/tests/accessibilityservice/res/layout/accessibility_embedded_hierarchy_test_host_side.xml b/tests/accessibilityservice/res/layout/accessibility_embedded_hierarchy_test_host_side.xml
index 9c0976274df..4c52f05af5e 100644
--- a/tests/accessibilityservice/res/layout/accessibility_embedded_hierarchy_test_host_side.xml
+++ b/tests/accessibilityservice/res/layout/accessibility_embedded_hierarchy_test_host_side.xml
@@ -16,8 +16,8 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="200dp"
- android:layout_height="200dp"
+ android:layout_width="@dimen/embedded_hierarchy_host_layout_size"
+ android:layout_height="@dimen/embedded_hierarchy_host_layout_size"
android:orientation="vertical">
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/tests/accessibilityservice/res/values/dimens.xml b/tests/accessibilityservice/res/values/dimens.xml
index a50549c55ed..2f96ab30b89 100644
--- a/tests/accessibilityservice/res/values/dimens.xml
+++ b/tests/accessibilityservice/res/values/dimens.xml
@@ -18,4 +18,10 @@
<resources>
<dimen name="button_touchable_width_increment_amount">48dp</dimen>
+
+ <dimen name="embedded_hierarchy_host_layout_size">200dp</dimen>
+ <!-- Smaller than embedded_hierarchy_host_layout_size so it can be embedded inside. -->
+ <dimen name="embedded_hierarchy_embedded_layout_size">150dp</dimen>
+ <!-- Amount that the embedded layout can move while still remaining inside the host. -->
+ <dimen name="embedded_hierarchy_embedded_layout_movement_size">50dp</dimen>
</resources> \ No newline at end of file
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
index 13aacb032c0..ba7a0ddc6ab 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
@@ -177,8 +177,10 @@ public class AccessibilityEmbeddedHierarchyTest {
final Rect oldEmbeddedViewBoundsInScreen = new Rect();
target.getBoundsInScreen(oldEmbeddedViewBoundsInScreen);
- // Move Host SurfaceView from (0, 0) to (50, 50).
- mActivity.requestNewLayoutForTest(50, 50);
+ // Move the host's SurfaceView away from (0,0).
+ int moveAmountPx = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.embedded_hierarchy_embedded_layout_movement_size);
+ mActivity.moveSurfaceViewLayoutPosition(moveAmountPx, moveAmountPx);
target.refresh();
final AccessibilityNodeInfo parent = target.getParent();
@@ -207,7 +209,7 @@ public class AccessibilityEmbeddedHierarchyTest {
// Move Host SurfaceView out of screen
final Point screenSize = getScreenSize();
- mActivity.requestNewLayoutForTest(screenSize.x, screenSize.y);
+ mActivity.moveSurfaceViewLayoutPosition(screenSize.x, screenSize.y);
target.refresh();
assertWithMessage("Embedded view should be invisible after moving out of screen.").that(
@@ -248,9 +250,6 @@ public class AccessibilityEmbeddedHierarchyTest {
AccessibilityTestActivity implements SurfaceHolder.Callback {
private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
- private static final int DEFAULT_WIDTH = 150;
- private static final int DEFAULT_HEIGHT = 150;
-
private SurfaceView mSurfaceView;
private View mInputFocusableView;
private SurfaceControlViewHost mViewHost;
@@ -273,7 +272,9 @@ public class AccessibilityEmbeddedHierarchyTest {
View layout = getLayoutInflater().inflate(
R.layout.accessibility_embedded_hierarchy_test_embedded_side, null);
- mViewHost.setView(layout, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ final int viewSizePx = getResources().getDimensionPixelSize(
+ R.dimen.embedded_hierarchy_embedded_layout_size);
+ mViewHost.setView(layout, viewSizePx, viewSizePx);
mCountDownLatch.countDown();
}
@@ -296,7 +297,7 @@ public class AccessibilityEmbeddedHierarchyTest {
}
}
- public void requestNewLayoutForTest(int x, int y) throws TimeoutException {
+ public void moveSurfaceViewLayoutPosition(int x, int y) throws TimeoutException {
sUiAutomation.executeAndWaitForEvent(
() -> sInstrumentation.runOnMainSync(() -> {
mSurfaceView.setX(x);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
index 9f78f556b0e..e279e746e85 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
@@ -35,14 +35,11 @@ import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ADDED
import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_BOUNDS;
import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_CHILDREN;
import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_FOCUSED;
-import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_REMOVED;
import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_TITLE;
-import static junit.framework.TestCase.assertTrue;
+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;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeTrue;
import android.Manifest;
@@ -51,6 +48,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.cts.activities.AccessibilityWindowReportingActivity;
import android.accessibilityservice.cts.activities.NonDefaultDisplayActivity;
import android.accessibilityservice.cts.activities.NotTouchableWindowTestActivity;
+import android.accessibilityservice.cts.utils.ActivityLaunchUtils;
import android.accessibilityservice.cts.utils.DisplayUtils;
import android.accessibilityservice.cts.utils.WindowCreationUtils;
import android.app.Activity;
@@ -103,10 +101,10 @@ public class AccessibilityWindowReportingTest {
private Activity mActivity;
private CharSequence mActivityTitle;
- private ActivityTestRule<AccessibilityWindowReportingActivity> mActivityRule =
+ private final ActivityTestRule<AccessibilityWindowReportingActivity> mActivityRule =
new ActivityTestRule<>(AccessibilityWindowReportingActivity.class, false, false);
- private AccessibilityDumpOnFailureRule mDumpOnFailureRule =
+ private final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
new AccessibilityDumpOnFailureRule();
@Rule
@@ -124,7 +122,7 @@ public class AccessibilityWindowReportingTest {
}
@AfterClass
- public static void finalTearDown() throws Exception {
+ public static void finalTearDown() {
sUiAutomation.destroy();
}
@@ -145,8 +143,8 @@ public class AccessibilityWindowReportingTest {
public void testUpdatedWindowTitle_generatesEventAndIsReturnedByGetTitle() {
final String updatedTitle = "Updated Title";
try {
- sUiAutomation.executeAndWaitForEvent(() -> sInstrumentation.runOnMainSync(
- () -> mActivity.setTitle(updatedTitle)),
+ sUiAutomation.executeAndWaitForEvent(
+ () -> sInstrumentation.runOnMainSync(() -> mActivity.setTitle(updatedTitle)),
filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_TITLE),
TIMEOUT_ASYNC_PROCESSING);
} catch (TimeoutException exception) {
@@ -154,7 +152,8 @@ public class AccessibilityWindowReportingTest {
"Failed to get windows changed event for title update", exception);
}
final AccessibilityWindowInfo window = findWindowByTitle(sUiAutomation, updatedTitle);
- assertNotNull("Updated window title not reported to accessibility", window);
+ assertWithMessage("Updated window title not reported to accessibility")
+ .that(window).isNotNull();
window.recycle();
}
@@ -163,8 +162,8 @@ public class AccessibilityWindowReportingTest {
public void testWindowAddedMovedAndRemoved_generatesEventsForAllThree() throws Exception {
final WindowManager.LayoutParams paramsForTop =
WindowCreationUtils.layoutParamsForWindowOnTop(
- sInstrumentation, mActivity, TOP_WINDOW_TITLE);
- final WindowManager.LayoutParams paramsForBottom = layoutParmsForWindowOnBottom();
+ sInstrumentation, mActivity, TOP_WINDOW_TITLE);
+ final WindowManager.LayoutParams paramsForBottom = layoutParamsForWindowOnBottom();
final Button button = new Button(mActivity);
button.setText(R.string.button1);
@@ -212,7 +211,7 @@ public class AccessibilityWindowReportingTest {
numPictureInPictureWindows++;
}
}
- assertTrue(numPictureInPictureWindows >= 1);
+ assertThat(numPictureInPictureWindows).isAtLeast(1);
}
@Test
@@ -237,14 +236,15 @@ public class AccessibilityWindowReportingTest {
// Windows may have changed - refresh
activityWindow = findWindowByTitle(sUiAutomation, mActivityTitle);
- assertFalse(activityWindow.isActive());
- assertFalse(activityWindow.isFocused());
+ assertThat(activityWindow.isActive()).isFalse();
+ assertThat(activityWindow.isFocused()).isFalse();
// Find a focusable view in the main activity menu
final AccessibilityNodeInfo autoCompleteTextInfo = activityWindow.getRoot()
.findAccessibilityNodeInfosByViewId(
"android.accessibilityservice.cts:id/autoCompleteLayout")
.get(0);
+ assertThat(autoCompleteTextInfo).isNotNull();
// Remove the top window and focus on the main activity
sUiAutomation.executeAndWaitForEvent(
@@ -264,15 +264,15 @@ public class AccessibilityWindowReportingTest {
// Makes sure activityWindow on default display is focused
AccessibilityWindowInfo activityWindow = findWindowByTitle(sUiAutomation, mActivityTitle);
- assertTrue(activityWindow.isActive());
- assertTrue(activityWindow.isFocused());
+ assertThat(activityWindow.isActive()).isTrue();
+ assertThat(activityWindow.isFocused()).isTrue();
// Creates a virtual display.
try (VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
final int virtualDisplayId =
- displaySession.createDisplayWithDefaultDisplayMetricsAndWait(
- sInstrumentation.getContext(), false).getDisplayId();
- // Launchs an activity on virtual display.
+ displaySession.createDisplayWithDefaultDisplayMetricsAndWait(
+ sInstrumentation.getContext(), false).getDisplayId();
+ // Launches an activity on virtual display.
final Activity activityOnVirtualDisplay =
launchActivityOnSpecifiedDisplayAndWaitForItToBeOnscreen(sInstrumentation,
sUiAutomation,
@@ -286,44 +286,43 @@ public class AccessibilityWindowReportingTest {
// at virtual display needs to be touched then it becomes to be focused one. Adding this
// touch event on the activity window of the virtual display to pass this test case.
sUiAutomation.executeAndWaitForEvent(
- () -> {
- DisplayUtils.touchDisplay(sUiAutomation, virtualDisplayId, activityTitle);
- },
+ () -> DisplayUtils.touchDisplay(sUiAutomation, virtualDisplayId, activityTitle),
filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_FOCUSED |
WINDOWS_CHANGE_ACTIVE),
TIMEOUT_ASYNC_PROCESSING);
// Make sure activityWindow on virtual display is focused.
AccessibilityWindowInfo activityWindowOnVirtualDisplay =
- findWindowByTitleAndDisplay(sUiAutomation, activityTitle, virtualDisplayId);
+ findWindowByTitleAndDisplay(sUiAutomation, activityTitle, virtualDisplayId);
// Windows may have changed - refresh.
activityWindow = findWindowByTitle(sUiAutomation, mActivityTitle);
try {
if (!perDisplayFocusEnabled()) {
- assertFalse(activityWindow.isActive());
- assertFalse(activityWindow.isFocused());
+ assertThat(activityWindow.isActive()).isFalse();
+ assertThat(activityWindow.isFocused()).isFalse();
} else {
- assertTrue(activityWindow.isActive());
- assertTrue(activityWindow.isFocused());
+ assertThat(activityWindow.isActive()).isTrue();
+ assertThat(activityWindow.isFocused()).isTrue();
}
- assertTrue(activityWindowOnVirtualDisplay.isActive());
- assertTrue(activityWindowOnVirtualDisplay.isFocused());
+ assertThat(activityWindowOnVirtualDisplay.isActive()).isTrue();
+ assertThat(activityWindowOnVirtualDisplay.isFocused()).isTrue();
} finally {
sUiAutomation.executeAndWaitForEvent(
- () -> {
- sInstrumentation.runOnMainSync(
- () -> activityOnVirtualDisplay.finish());
- },
- filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_FOCUSED |
- WINDOWS_CHANGE_ACTIVE),
+ () -> sInstrumentation.runOnMainSync(activityOnVirtualDisplay::finish),
+ filterWaitForAll(
+ filterWindowsChangedWithChangeTypes(
+ WINDOWS_CHANGE_FOCUSED | WINDOWS_CHANGE_ACTIVE),
+ event -> {
+ // The focused window should be returned to activity at
+ // default display after
+ // the activity at virtual display is destroyed.
+ AccessibilityWindowInfo window = findWindowByTitle(
+ sUiAutomation, mActivityTitle);
+ return window.isActive() && window.isFocused();
+ }),
TIMEOUT_ASYNC_PROCESSING);
}
}
- // The focused window should be returned to activity at default display after
- // the activity at virtual display is destroyed.
- activityWindow = findWindowByTitle(sUiAutomation, mActivityTitle);
- assertTrue(activityWindow.isActive());
- assertTrue(activityWindow.isFocused());
}
@Test
@@ -369,20 +368,20 @@ public class AccessibilityWindowReportingTest {
@Test
public void testGetAnchorForDropDownForAutoCompleteTextView_returnsTextViewNode() {
final AutoCompleteTextView autoCompleteTextView =
- (AutoCompleteTextView) mActivity.findViewById(R.id.autoCompleteLayout);
+ mActivity.findViewById(R.id.autoCompleteLayout);
final AccessibilityNodeInfo autoCompleteTextInfo = sUiAutomation.getRootInActiveWindow()
.findAccessibilityNodeInfosByViewId(
"android.accessibilityservice.cts:id/autoCompleteLayout")
.get(0);
// For the drop-down
- final String[] COUNTRIES = new String[] {"Belgium", "France", "Italy", "Germany", "Spain"};
+ final String[] countries = new String[]{"Belgium", "France", "Italy", "Germany", "Spain"};
try {
sUiAutomation.executeAndWaitForEvent(() -> sInstrumentation.runOnMainSync(
() -> {
final ArrayAdapter<String> adapter = new ArrayAdapter<>(
- mActivity, android.R.layout.simple_dropdown_item_1line, COUNTRIES);
+ mActivity, android.R.layout.simple_dropdown_item_1line, countries);
autoCompleteTextView.setAdapter(adapter);
autoCompleteTextView.showDropDown();
}),
@@ -401,17 +400,18 @@ public class AccessibilityWindowReportingTest {
if (window.getAnchor() == null) {
continue;
}
- assertEquals(autoCompleteTextInfo, window.getAnchor());
- assertFalse("Found multiple pop-ups anchored to one text view", foundPopup);
+ assertThat(window.getAnchor()).isEqualTo(autoCompleteTextInfo);
+ assertWithMessage("Found multiple pop-ups anchored to one text view")
+ .that(foundPopup).isFalse();
foundPopup = true;
}
- assertTrue("Failed to find accessibility window for auto-complete pop-up", foundPopup);
+ assertWithMessage("Failed to find accessibility window for auto-complete pop-up")
+ .that(foundPopup).isTrue();
}
@AppModeFull
@Test
- public void showNotTouchableWindow_activityWindowIsNotVisible()
- throws TimeoutException {
+ public void showNotTouchableWindow_activityWindowIsNotVisible() throws TimeoutException {
try {
launchNotTouchableWindowTestActivityFromShell();
@@ -419,40 +419,29 @@ public class AccessibilityWindowReportingTest {
intent.setAction(NotTouchableWindowTestActivity.ADD_WINDOW);
intent.setPackage(sInstrumentation.getContext().getPackageName());
- try {
- // Waits for two events, whose order is nondeterministic:
- // (1) the test activity is covered by the untrusted non-touchable window.
- // (2) the untrusted non-touchable window is added.
- sendIntentAndWaitForEvent(intent,
- filterWaitForAll(
- event -> {
- final AccessibilityWindowInfo coveredWindow =
- findWindowByTitle(sUiAutomation,
- NotTouchableWindowTestActivity.TITLE);
- return coveredWindow == null;
- },
- filterWindowsChangeTypesAndWindowTitle(sUiAutomation,
- WINDOWS_CHANGE_ADDED,
- NotTouchableWindowTestActivity.NON_TOUCHABLE_WINDOW_TITLE)
- ));
- } finally {
- intent.setAction(NotTouchableWindowTestActivity.REMOVE_WINDOW);
- sendIntentAndWaitForEvent(intent,
- filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_REMOVED));
- }
- } finally {
- Intent intent = new Intent();
- intent.setAction(NotTouchableWindowTestActivity.FINISH_ACTIVITY);
- intent.setPackage(sInstrumentation.getContext().getPackageName());
+ // Waits for two events, whose order is nondeterministic:
+ // (1) the test activity is covered by the untrusted non-touchable window.
+ // (2) the untrusted non-touchable window is added.
sendIntentAndWaitForEvent(intent,
- filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_REMOVED));
+ filterWaitForAll(
+ event -> {
+ final AccessibilityWindowInfo coveredWindow =
+ findWindowByTitle(sUiAutomation,
+ NotTouchableWindowTestActivity.TITLE);
+ return coveredWindow == null;
+ },
+ filterWindowsChangeTypesAndWindowTitle(sUiAutomation,
+ WINDOWS_CHANGE_ADDED,
+ NotTouchableWindowTestActivity.NON_TOUCHABLE_WINDOW_TITLE)
+ ));
+ } finally {
+ closeNotTouchableWindowTestActivity();
}
}
@AppModeFull
@Test
- public void showNotTouchableTrustedWindow_activityWindowIsVisible()
- throws TimeoutException {
+ public void showNotTouchableTrustedWindow_activityWindowIsVisible() {
try {
launchNotTouchableWindowTestActivityFromShell();
@@ -460,31 +449,17 @@ public class AccessibilityWindowReportingTest {
intent.setAction(NotTouchableWindowTestActivity.ADD_TRUSTED_WINDOW);
intent.setPackage(sInstrumentation.getContext().getPackageName());
- try {
- SystemUtil.runWithShellPermissionIdentity(sUiAutomation, () -> {
- sendIntentAndWaitForEvent(intent,
+ SystemUtil.runWithShellPermissionIdentity(sUiAutomation,
+ () -> sendIntentAndWaitForEvent(intent,
filterWindowsChangeTypesAndWindowTitle(sUiAutomation,
WINDOWS_CHANGE_ADDED,
- NotTouchableWindowTestActivity.NON_TOUCHABLE_WINDOW_TITLE)
- );
- }, Manifest.permission.INTERNAL_SYSTEM_WINDOW);
-
- List<AccessibilityWindowInfo> windows = sUiAutomation.getWindows();
- assertNotNull(windows);
+ NotTouchableWindowTestActivity.NON_TOUCHABLE_WINDOW_TITLE)),
+ Manifest.permission.INTERNAL_SYSTEM_WINDOW);
- assertEquals(1, windows.stream().filter(
- w -> NotTouchableWindowTestActivity.TITLE.equals(w.getTitle())).count());
- } finally {
- intent.setAction(NotTouchableWindowTestActivity.REMOVE_WINDOW);
- sendIntentAndWaitForEvent(intent,
- filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_REMOVED));
- }
+ assertThat(findWindowByTitle(sUiAutomation, NotTouchableWindowTestActivity.TITLE))
+ .isNotNull();
} finally {
- Intent intent = new Intent();
- intent.setAction(NotTouchableWindowTestActivity.FINISH_ACTIVITY);
- intent.setPackage(sInstrumentation.getContext().getPackageName());
- sendIntentAndWaitForEvent(intent,
- filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_REMOVED));
+ closeNotTouchableWindowTestActivity();
}
}
@@ -493,31 +468,43 @@ public class AccessibilityWindowReportingTest {
// Use shell command instead of ActivityLaunchUtils to get INTERNAL_SYSTEM_WINDOW
// permission when the Session is created.
private void launchNotTouchableWindowTestActivityFromShell() {
- SystemUtil.runWithShellPermissionIdentity(sUiAutomation, () -> {
- sUiAutomation.executeAndWaitForEvent(
- () -> {
- final ComponentName componentName = new ComponentName(
- sInstrumentation.getContext(), NotTouchableWindowTestActivity.class);
-
- String command = "am start -n " + componentName.flattenToString();
- try {
- SystemUtil.runShellCommand(sInstrumentation, command);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- },
- (event) -> {
- final AccessibilityWindowInfo window =
- findWindowByTitleAndDisplay(sUiAutomation,
- NotTouchableWindowTestActivity.TITLE, 0);
- return window != null;
- }, TIMEOUT_ASYNC_PROCESSING);
- }, Manifest.permission.INTERNAL_SYSTEM_WINDOW);
+ SystemUtil.runWithShellPermissionIdentity(sUiAutomation,
+ () -> sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ final ComponentName componentName = new ComponentName(
+ sInstrumentation.getContext(),
+ NotTouchableWindowTestActivity.class);
+
+ String command = "am start -n " + componentName.flattenToString();
+ try {
+ SystemUtil.runShellCommand(sInstrumentation, command);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ },
+ (event) -> {
+ final AccessibilityWindowInfo window =
+ findWindowByTitleAndDisplay(sUiAutomation,
+ NotTouchableWindowTestActivity.TITLE, 0);
+ return window != null;
+ }, TIMEOUT_ASYNC_PROCESSING), Manifest.permission.INTERNAL_SYSTEM_WINDOW);
+ }
+
+ private void closeNotTouchableWindowTestActivity() {
+ final Intent intent = new Intent();
+ intent.setAction(NotTouchableWindowTestActivity.FINISH_ACTIVITY);
+ intent.setPackage(sInstrumentation.getContext().getPackageName());
+ // Call finish() on the window. This is required to launch more activities in any subsequent
+ // tests from this same app process.
+ sInstrumentation.runOnMainSync(() -> sInstrumentation.getContext().sendBroadcast(intent));
+ // Ensure we're at the home screen before continuing to other tests.
+ // finish() should do this, but sometimes takes longer than expected.
+ ActivityLaunchUtils.homeScreenOrBust(sInstrumentation.getContext(), sUiAutomation);
}
- /**
- * Test whether we can successfully enable and disable window animations.
- */
+ /**
+ * Test whether we can successfully enable and disable window animations.
+ */
@Test
public void testDisableWindowAnimations() {
setAndAssertAnimationScale(0.0f);
@@ -529,22 +516,23 @@ public class AccessibilityWindowReportingTest {
private void setAndAssertAnimationScale(float value) {
Context context = sInstrumentation.getContext();
sUiAutomation.setAnimationScale(value);
- assertEquals(value, getGlobalFloat(context, Settings.Global.WINDOW_ANIMATION_SCALE), 0.0f);
- assertEquals(
- value, getGlobalFloat(context, Settings.Global.TRANSITION_ANIMATION_SCALE), 0.0f);
- assertEquals(value, getGlobalFloat(context, Settings.Global.ANIMATOR_DURATION_SCALE), 0.0f);
+ assertThat(getGlobalFloat(context, Settings.Global.WINDOW_ANIMATION_SCALE))
+ .isEqualTo(value);
+ assertThat(getGlobalFloat(context, Settings.Global.TRANSITION_ANIMATION_SCALE))
+ .isEqualTo(value);
+ assertThat(getGlobalFloat(context, Settings.Global.ANIMATOR_DURATION_SCALE))
+ .isEqualTo(value);
}
/** Returns value of constants in Settings.Global. */
private static float getGlobalFloat(Context context, String constantName) {
- float value = Settings.Global.getFloat(context.getContentResolver(), constantName, -1);
- return value;
+ return Settings.Global.getFloat(context.getContentResolver(), constantName, -1);
}
private View showTopWindowAndWaitForItToShowUp() throws TimeoutException {
final WindowManager.LayoutParams paramsForTop =
WindowCreationUtils.layoutParamsForWindowOnTop(
- sInstrumentation, mActivity, TOP_WINDOW_TITLE);
+ sInstrumentation, mActivity, TOP_WINDOW_TITLE);
final Button button = new Button(mActivity);
button.setText(R.string.button1);
@@ -555,7 +543,7 @@ public class AccessibilityWindowReportingTest {
return button;
}
- private WindowManager.LayoutParams layoutParmsForWindowOnBottom() {
+ private WindowManager.LayoutParams layoutParamsForWindowOnBottom() {
final WindowManager.LayoutParams params = WindowCreationUtils.layoutParamsForTestWindow(
sInstrumentation, mActivity);
params.gravity = Gravity.BOTTOM;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java
index e2bd5c2c046..039b948399a 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/activities/NotTouchableWindowTestActivity.java
@@ -44,11 +44,6 @@ public class NotTouchableWindowTestActivity extends AccessibilityTestActivity {
context.getSystemService(WindowManager.class).addView(rootView, params);
break;
- case REMOVE_WINDOW:
- context.getSystemService(WindowManager.class).removeViewImmediate(rootView);
- rootView = null;
- break;
-
case ADD_TRUSTED_WINDOW:
if (rootView != null) {
throw new IllegalStateException("Window already exists");
@@ -60,9 +55,6 @@ public class NotTouchableWindowTestActivity extends AccessibilityTestActivity {
break;
case FINISH_ACTIVITY:
- if (rootView != null) {
- throw new IllegalStateException("Window still exists");
- }
finish();
}
}
@@ -78,8 +70,6 @@ public class NotTouchableWindowTestActivity extends AccessibilityTestActivity {
public static final String ADD_WINDOW =
"android.accessibilityservice.cts.ADD_WINDOW";
- public static final String REMOVE_WINDOW =
- "android.accessibilityservice.cts.REMOVE_WINDOW";
public static final String ADD_TRUSTED_WINDOW =
"android.accessibilityservice.cts.ADD_TRUSTED_WINDOW";
public static final String FINISH_ACTIVITY =
@@ -94,7 +84,6 @@ public class NotTouchableWindowTestActivity extends AccessibilityTestActivity {
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(ADD_WINDOW);
- filter.addAction(REMOVE_WINDOW);
filter.addAction(ADD_TRUSTED_WINDOW);
filter.addAction(FINISH_ACTIVITY);
this.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
diff --git a/tests/app/BroadcastsTest/src/android/app/cts/broadcasts/BroadcastDeliveryGroupTest.java b/tests/app/BroadcastsTest/src/android/app/cts/broadcasts/BroadcastDeliveryGroupTest.java
index dd7a45b83a6..3eca80428b4 100644
--- a/tests/app/BroadcastsTest/src/android/app/cts/broadcasts/BroadcastDeliveryGroupTest.java
+++ b/tests/app/BroadcastsTest/src/android/app/cts/broadcasts/BroadcastDeliveryGroupTest.java
@@ -76,6 +76,7 @@ public class BroadcastDeliveryGroupTest extends BaseBroadcastTest {
// Now force delay the broadcasts to make sure delivery group policies are
// applied as expected.
+ initializeQueue(HELPER_PKG2, cmdReceiver2);
forceDelayBroadcasts(HELPER_PKG2);
final Intent intent1 = new Intent(TEST_ACTION1)
@@ -142,6 +143,7 @@ public class BroadcastDeliveryGroupTest extends BaseBroadcastTest {
// Now force delay the broadcasts to make sure delivery group policies are
// applied as expected.
+ initializeQueue(HELPER_PKG2, cmdReceiver2);
forceDelayBroadcasts(HELPER_PKG2);
final Intent intent1 = new Intent(TEST_ACTION1)
@@ -163,4 +165,16 @@ public class BroadcastDeliveryGroupTest extends BaseBroadcastTest {
connection2.unbind();
}
}
+
+ private void initializeQueue(String pkg, ICommandReceiver cmdReceiver) throws Exception {
+ // TODO: b/294884478 - We can remove this method once forceDelayBroadcastDelivery() is
+ // updated to work in any state.
+ final String testAction = "com.android.app.cts.test";
+ final IntentFilter filter = new IntentFilter(testAction);
+ cmdReceiver.monitorBroadcasts(filter, testAction);
+
+ final Intent testIntent = new Intent(testAction)
+ .setPackage(pkg);
+ getContext().sendBroadcast(testIntent);
+ }
}
diff --git a/tests/app/WallpaperTest/AndroidTest.xml b/tests/app/WallpaperTest/AndroidTest.xml
index 096db14efb2..373f7067675 100644
--- a/tests/app/WallpaperTest/AndroidTest.xml
+++ b/tests/app/WallpaperTest/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS App test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="sysui" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/app/WallpaperTest/testsdk33/AndroidTest.xml b/tests/app/WallpaperTest/testsdk33/AndroidTest.xml
index 4955e5cecd5..7b37cef6c1c 100644
--- a/tests/app/WallpaperTest/testsdk33/AndroidTest.xml
+++ b/tests/app/WallpaperTest/testsdk33/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS App test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="sysui" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/app/src/android/app/cts/SystemFeaturesTest.java
index 182b2d65ffb..20151d17cb6 100644
--- a/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -70,6 +70,8 @@ import java.util.Set;
*/
@RunWith(JUnit4.class)
public class SystemFeaturesTest {
+ private static final String FEATURE_GOOGLE_BATTERYLESS_DEVICE =
+ "com.google.android.feature.batteryless_device";
private static final String FEATURE_GOOGLE_LARGE_DISPLAY =
"com.google.android.feature.large_display";
private static final String FEATURE_GOOGLE_OTHER_FORM_FACTOR =
@@ -174,6 +176,7 @@ public class SystemFeaturesTest {
boolean motionTracking = false;
boolean raw = false;
boolean hasFlash = false;
+ boolean hasAutofocus = false;
CameraCharacteristics[] cameraChars = new CameraCharacteristics[cameraIds.length];
for (String cameraId : cameraIds) {
CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
@@ -207,6 +210,11 @@ public class SystemFeaturesTest {
if (flashAvailable) {
hasFlash = true;
}
+ float minFocusDistance =
+ chars.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+ if (minFocusDistance > 0) {
+ hasAutofocus = true;
+ }
}
assertFeature(fullCamera, PackageManager.FEATURE_CAMERA_LEVEL_FULL);
assertFeature(manualSensor, PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR);
@@ -228,6 +236,7 @@ public class SystemFeaturesTest {
assertNotAvailable(PackageManager.FEATURE_CAMERA_AR);
}
assertFeature(hasFlash, PackageManager.FEATURE_CAMERA_FLASH);
+ assertFeature(hasAutofocus, PackageManager.FEATURE_CAMERA_AUTOFOCUS);
}
private void checkFrontCamera() {
@@ -264,19 +273,14 @@ public class SystemFeaturesTest {
Camera.Parameters params = camera.getParameters();
if (params.getSupportedFocusModes().contains(Parameters.FOCUS_MODE_AUTO)) {
assertAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
- } else {
- assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
}
if (params.getFlashMode() != null) {
assertAvailable(PackageManager.FEATURE_CAMERA_FLASH);
- } else {
- assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
}
+
} else {
assertNotAvailable(PackageManager.FEATURE_CAMERA);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
- assertNotAvailable(PackageManager.FEATURE_CAMERA_FLASH);
}
} finally {
if (camera != null) {
@@ -336,6 +340,8 @@ public class SystemFeaturesTest {
// Watches MAY support all FEATURE_NFC features when an NfcAdapter is available, but
// non-watches MUST support them both.
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ || (mPackageManager.hasSystemFeature(FEATURE_GOOGLE_BATTERYLESS_DEVICE)
+ && mPackageManager.hasSystemFeature(FEATURE_GOOGLE_OTHER_FORM_FACTOR))
|| (mPackageManager.hasSystemFeature(FEATURE_GOOGLE_LARGE_DISPLAY)
&& mPackageManager.hasSystemFeature(FEATURE_GOOGLE_OTHER_FORM_FACTOR))) {
assertOneAvailable(PackageManager.FEATURE_NFC,
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
index b904623d934..b8aa7ec4133 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
@@ -28,6 +28,8 @@ import android.app.appsearch.testutil.AppSearchEmail;
import org.junit.Test;
+import java.util.Collections;
+
public class AppSearchSchemaCtsTest {
@Test
public void testInvalidEnums() {
@@ -515,4 +517,28 @@ public class AppSearchSchemaCtsTest {
IllegalArgumentException.class,
() -> new LongPropertyConfig.Builder("timestamp").setIndexingType(-1).build());
}
+
+ @Test
+ public void testInvalidDocumentPropertyConfig_indexableNestedProperties() {
+ // Adding indexableNestedProperties with shouldIndexNestedProperties=true should fail.
+ AppSearchSchema.DocumentPropertyConfig.Builder builder =
+ new AppSearchSchema.DocumentPropertyConfig.Builder("prop1", "Schema1")
+ .setShouldIndexNestedProperties(true)
+ .addIndexableNestedProperties(Collections.singleton("prop1"));
+ IllegalArgumentException e =
+ assertThrows(IllegalArgumentException.class, () -> builder.build());
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ "DocumentIndexingConfig#shouldIndexNestedProperties is required to be false"
+ + " when one or more indexableNestedProperties are provided.");
+
+ builder.addIndexableNestedProperties(Collections.singleton("prop1.prop2"));
+ e = assertThrows(IllegalArgumentException.class, () -> builder.build());
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ "DocumentIndexingConfig#shouldIndexNestedProperties is required to be false"
+ + " when one or more indexableNestedProperties are provided.");
+ }
}
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 61bbd15b366..ba76489068d 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
@@ -6409,4 +6409,1155 @@ public abstract class AppSearchSessionCtsTestBase {
new SearchSuggestionResult.Builder().setSuggestedResult("bar subject:foo").build();
assertThat(suggestions).containsExactly(barSubjectFo, barSubjectFoo);
}
+
+ @Test
+ public void testGetSchema_parentTypes() throws Exception {
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+ AppSearchSchema emailSchema = new AppSearchSchema.Builder("Email").build();
+ AppSearchSchema messageSchema = new AppSearchSchema.Builder("Message").build();
+ AppSearchSchema emailMessageSchema =
+ new AppSearchSchema.Builder("EmailMessage")
+ .addProperty(
+ new StringPropertyConfig.Builder("sender")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("email")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("content")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .addParentType("Email")
+ .addParentType("Message")
+ .build();
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchemas(emailMessageSchema)
+ .addSchemas(emailSchema)
+ .addSchemas(messageSchema)
+ .build();
+
+ mDb1.setSchemaAsync(request).get();
+
+ Set<AppSearchSchema> actual = mDb1.getSchemaAsync().get().getSchemas();
+ assertThat(actual).hasSize(3);
+ assertThat(actual).isEqualTo(request.getSchemas());
+ }
+
+ @Test
+ public void testGetSchema_parentTypes_notSupported() throws Exception {
+ assumeFalse(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+ AppSearchSchema emailSchema = new AppSearchSchema.Builder("Email").build();
+ AppSearchSchema messageSchema = new AppSearchSchema.Builder("Message").build();
+ AppSearchSchema emailMessageSchema =
+ new AppSearchSchema.Builder("EmailMessage")
+ .addParentType("Email")
+ .addParentType("Message")
+ .build();
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchemas(emailMessageSchema)
+ .addSchemas(emailSchema)
+ .addSchemas(messageSchema)
+ .build();
+
+ UnsupportedOperationException e =
+ assertThrows(
+ UnsupportedOperationException.class,
+ () -> mDb1.setSchemaAsync(request).get());
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ Features.SCHEMA_ADD_PARENT_TYPE
+ + " is not available on this AppSearch implementation.");
+ }
+
+ @Test
+ public void testSetSchema_dataTypeIncompatibleWithParentTypes() throws Exception {
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+ AppSearchSchema messageSchema =
+ new AppSearchSchema.Builder("Message")
+ .addProperty(
+ new AppSearchSchema.LongPropertyConfig.Builder("sender")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .build();
+ AppSearchSchema emailSchema =
+ new AppSearchSchema.Builder("Email")
+ .addParentType("Message")
+ .addProperty(
+ new StringPropertyConfig.Builder("sender")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .build();
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchemas(messageSchema)
+ .addSchemas(emailSchema)
+ .build();
+
+ ExecutionException executionException =
+ assertThrows(ExecutionException.class, () -> mDb1.setSchemaAsync(request).get());
+ assertThat(executionException).hasCauseThat().isInstanceOf(AppSearchException.class);
+ AppSearchException exception = (AppSearchException) executionException.getCause();
+ assertThat(exception.getResultCode()).isEqualTo(RESULT_INVALID_ARGUMENT);
+ assertThat(exception)
+ .hasMessageThat()
+ .containsMatch(
+ "Property sender from child type .*\\$/Email is not compatible"
+ + " to the parent type .*\\$/Message.");
+ }
+
+ @Test
+ public void testSetSchema_documentTypeIncompatibleWithParentTypes() throws Exception {
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+ AppSearchSchema personSchema = new AppSearchSchema.Builder("Person").build();
+ AppSearchSchema artistSchema =
+ new AppSearchSchema.Builder("Artist").addParentType("Person").build();
+ AppSearchSchema messageSchema =
+ new AppSearchSchema.Builder("Message")
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "sender", "Artist")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .build();
+ AppSearchSchema emailSchema =
+ new AppSearchSchema.Builder("Email")
+ .addParentType("Message")
+ // "sender" is defined as an Artist in the parent type Message, which
+ // requires "sender"'s type here to be a subtype of Artist. Thus, this is
+ // incompatible because Person is not a subtype of Artist.
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "sender", "Person")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .build();
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema)
+ .addSchemas(artistSchema)
+ .addSchemas(messageSchema)
+ .addSchemas(emailSchema)
+ .build();
+
+ ExecutionException executionException =
+ assertThrows(ExecutionException.class, () -> mDb1.setSchemaAsync(request).get());
+ assertThat(executionException).hasCauseThat().isInstanceOf(AppSearchException.class);
+ AppSearchException exception = (AppSearchException) executionException.getCause();
+ assertThat(exception.getResultCode()).isEqualTo(RESULT_INVALID_ARGUMENT);
+ assertThat(exception)
+ .hasMessageThat()
+ .containsMatch(
+ "Property sender from child type .*\\$/Email is not compatible"
+ + " to the parent type .*\\$/Message.");
+ }
+
+ @Test
+ public void testSetSchema_compatibleWithParentTypes() throws Exception {
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+ AppSearchSchema personSchema = new AppSearchSchema.Builder("Person").build();
+ AppSearchSchema artistSchema =
+ new AppSearchSchema.Builder("Artist").addParentType("Person").build();
+ AppSearchSchema messageSchema =
+ new AppSearchSchema.Builder("Message")
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "sender", "Person")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("note")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
+ AppSearchSchema emailSchema =
+ new AppSearchSchema.Builder("Email")
+ .addParentType("Message")
+ .addProperty(
+ // Artist is a subtype of Person, so compatible
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "sender", "Artist")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("note")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ // A different indexing or tokenizer type is ok.
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(
+ StringPropertyConfig.TOKENIZER_TYPE_VERBATIM)
+ .build())
+ .build();
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema)
+ .addSchemas(artistSchema)
+ .addSchemas(messageSchema)
+ .addSchemas(emailSchema)
+ .build();
+
+ mDb1.setSchemaAsync(request).get();
+
+ Set<AppSearchSchema> actual = mDb1.getSchemaAsync().get().getSchemas();
+ assertThat(actual).hasSize(4);
+ assertThat(actual).isEqualTo(request.getSchemas());
+ }
+
+ @Test
+ public void testQuery_typeFilterWithPolymorphism() throws Exception {
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+
+ // Schema registration
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .build();
+ AppSearchSchema artistSchema =
+ new AppSearchSchema.Builder("Artist")
+ .addParentType("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .build();
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema)
+ .addSchemas(artistSchema)
+ .addSchemas(AppSearchEmail.SCHEMA)
+ .build())
+ .get();
+
+ // Index some documents
+ GenericDocument personDoc =
+ new GenericDocument.Builder<>("namespace", "id1", "Person")
+ .setPropertyString("name", "Foo")
+ .build();
+ GenericDocument artistDoc =
+ new GenericDocument.Builder<>("namespace", "id2", "Artist")
+ .setPropertyString("name", "Foo")
+ .build();
+ AppSearchEmail emailDoc =
+ new AppSearchEmail.Builder("namespace", "id3")
+ .setFrom("from@example.com")
+ .setTo("to1@example.com", "to2@example.com")
+ .setSubject("testPut example")
+ .setBody("Foo")
+ .build();
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(personDoc, artistDoc, emailDoc)
+ .build()));
+
+ // Query for the documents
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "Foo",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(3);
+ assertThat(documents).containsExactly(personDoc, artistDoc, emailDoc);
+
+ // Query with a filter for the "Person" type should also include the "Artist" type.
+ searchResults =
+ mDb1.search(
+ "Foo",
+ new SearchSpec.Builder()
+ .addFilterSchemas("Person")
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(2);
+ assertThat(documents).containsExactly(personDoc, artistDoc);
+
+ // Query with a filters for the "Artist" type should not include the "Person" type.
+ searchResults =
+ mDb1.search(
+ "Foo",
+ new SearchSpec.Builder()
+ .addFilterSchemas("Artist")
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents).containsExactly(artistDoc);
+ }
+
+ @Test
+ public void testQuery_projectionWithPolymorphism() throws Exception {
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+
+ // Schema registration
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("emailAddress")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .build();
+ AppSearchSchema artistSchema =
+ new AppSearchSchema.Builder("Artist")
+ .addParentType("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("emailAddress")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("company")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .build();
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema)
+ .addSchemas(artistSchema)
+ .build())
+ .get();
+
+ // Index two documents
+ GenericDocument personDoc =
+ new GenericDocument.Builder<>("namespace", "id1", "Person")
+ .setCreationTimestampMillis(1000)
+ .setPropertyString("name", "Foo Person")
+ .setPropertyString("emailAddress", "person@gmail.com")
+ .build();
+ GenericDocument artistDoc =
+ new GenericDocument.Builder<>("namespace", "id2", "Artist")
+ .setCreationTimestampMillis(1000)
+ .setPropertyString("name", "Foo Artist")
+ .setPropertyString("emailAddress", "artist@gmail.com")
+ .setPropertyString("company", "Company")
+ .build();
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(personDoc, artistDoc)
+ .build()));
+
+ // Query with type property paths {"Person", ["name"]}, {"Artist", ["emailAddress"]}
+ // This will be expanded to paths {"Person", ["name"]}, {"Artist", ["name", "emailAddress"]}
+ // via polymorphism.
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "Foo",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .addProjection("Person", ImmutableList.of("name"))
+ .addProjection("Artist", ImmutableList.of("emailAddress"))
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+
+ // The person document should have been returned with only the "name" property. The artist
+ // document should have been returned with all of its properties.
+ GenericDocument expectedPerson =
+ new GenericDocument.Builder<>("namespace", "id1", "Person")
+ .setCreationTimestampMillis(1000)
+ .setPropertyString("name", "Foo Person")
+ .build();
+ GenericDocument expectedArtist =
+ new GenericDocument.Builder<>("namespace", "id2", "Artist")
+ .setCreationTimestampMillis(1000)
+ .setPropertyString("name", "Foo Artist")
+ .setPropertyString("emailAddress", "artist@gmail.com")
+ .build();
+ assertThat(documents).containsExactly(expectedPerson, expectedArtist);
+ }
+
+ @Test
+ public void testQuery_indexBasedOnParentTypePolymorphism() throws Exception {
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SCHEMA_ADD_PARENT_TYPE));
+
+ // Schema registration
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .build();
+ AppSearchSchema artistSchema =
+ new AppSearchSchema.Builder("Artist")
+ .addParentType("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("company")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .build())
+ .build();
+ AppSearchSchema messageSchema =
+ new AppSearchSchema.Builder("Message")
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "sender", "Person")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setShouldIndexNestedProperties(true)
+ .build())
+ .build();
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema)
+ .addSchemas(artistSchema)
+ .addSchemas(messageSchema)
+ .build())
+ .get();
+
+ // Index some an artistDoc and a messageDoc
+ GenericDocument artistDoc =
+ new GenericDocument.Builder<>("namespace", "id1", "Artist")
+ .setPropertyString("name", "Foo")
+ .setPropertyString("company", "Bar")
+ .build();
+ GenericDocument messageDoc =
+ new GenericDocument.Builder<>("namespace", "id2", "Message")
+ // sender is defined as a Person, which accepts an Artist because Artist <:
+ // Person.
+ // However, indexing will be based on what's defined in Person, so the
+ // "company"
+ // property in artistDoc cannot be used to search this messageDoc.
+ .setPropertyDocument("sender", artistDoc)
+ .build();
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(artistDoc, messageDoc)
+ .build()));
+
+ // Query for the documents
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "Foo",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ List<GenericDocument> documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(2);
+ assertThat(documents).containsExactly(artistDoc, messageDoc);
+
+ // The "company" property in artistDoc cannot be used to search messageDoc.
+ searchResults =
+ mDb1.search(
+ "Bar",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ documents = convertSearchResultsToDocuments(searchResults);
+ assertThat(documents).hasSize(1);
+ assertThat(documents).containsExactly(artistDoc);
+ }
+
+ @Test
+ public void testSetSchema_indexableNestedPropsList() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(Features.SCHEMA_ADD_INDEXABLE_NESTED_PROPERTIES));
+
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "worksFor", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(false)
+ .addIndexableNestedProperties(Collections.singleton("name"))
+ .build())
+ .build();
+ AppSearchSchema organizationSchema =
+ new AppSearchSchema.Builder("Organization")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("notes")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
+
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema, organizationSchema)
+ .build())
+ .get();
+
+ // Test that properties in Person's indexable_nested_properties_list are indexed and
+ // searchable
+ GenericDocument org1 =
+ new GenericDocument.Builder<>("namespace", "org1", "Organization")
+ .setPropertyString("name", "Org1")
+ .setPropertyString("notes", "Some notes")
+ .build();
+ GenericDocument person1 =
+ new GenericDocument.Builder<>("namespace", "person1", "Person")
+ .setPropertyString("name", "Jane")
+ .setPropertyDocument("worksFor", org1)
+ .build();
+
+ AppSearchBatchResult<String, Void> putResult =
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(person1, org1)
+ .build()));
+ assertThat(putResult.getSuccesses()).containsExactly("person1", null, "org1", null);
+ assertThat(putResult.getFailures()).isEmpty();
+
+ GetByDocumentIdRequest getByDocumentIdRequest =
+ new GetByDocumentIdRequest.Builder("namespace").addIds("person1", "org1").build();
+ List<GenericDocument> outDocuments = doGet(mDb1, getByDocumentIdRequest);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(person1, org1);
+
+ // Both org1 and person should be returned for query "Org1"
+ // For org1 this matches the 'name' property and for person1 this matches the
+ // 'worksFor.name' property.
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "Org1",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(person1, org1);
+
+ // Only org1 should be returned for query "notes", since 'worksFor.notes' is not indexed
+ // for the Person-type.
+ searchResults =
+ mDb1.search(
+ "notes",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(org1);
+ }
+
+ @Test
+ public void testSetSchema_indexableNestedPropsList_notSupported() throws Exception {
+ assumeFalse(
+ mDb1.getFeatures()
+ .isFeatureSupported(Features.SCHEMA_ADD_INDEXABLE_NESTED_PROPERTIES));
+
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "worksFor", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(false)
+ .addIndexableNestedProperties(Collections.singleton("name"))
+ .build())
+ .build();
+ AppSearchSchema organizationSchema =
+ new AppSearchSchema.Builder("Organization")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("notes")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
+
+ SetSchemaRequest setSchemaRequest =
+ new SetSchemaRequest.Builder().addSchemas(personSchema, organizationSchema).build();
+ UnsupportedOperationException e =
+ assertThrows(
+ UnsupportedOperationException.class,
+ () -> mDb1.setSchemaAsync(setSchemaRequest).get());
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ "DocumentPropertyConfig.addIndexableNestedProperties is not supported on"
+ + " this AppSearch implementation.");
+ }
+
+ @Test
+ public void testSetSchema_indexableNestedPropsList_nonIndexableProp() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(Features.SCHEMA_ADD_INDEXABLE_NESTED_PROPERTIES));
+
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "worksFor", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(false)
+ .addIndexableNestedProperties(Collections.singleton("name"))
+ .build())
+ .build();
+ AppSearchSchema organizationSchema =
+ new AppSearchSchema.Builder("Organization")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("notes")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(StringPropertyConfig.INDEXING_TYPE_NONE)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_NONE)
+ .build())
+ .build();
+
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema, organizationSchema)
+ .build())
+ .get();
+
+ // Test that Person's nested properties are indexed correctly.
+ GenericDocument org1 =
+ new GenericDocument.Builder<>("namespace", "org1", "Organization")
+ .setPropertyString("name", "Org1")
+ .setPropertyString("notes", "Some notes")
+ .build();
+ GenericDocument person1 =
+ new GenericDocument.Builder<>("namespace", "person1", "Person")
+ .setPropertyString("name", "Jane")
+ .setPropertyDocument("worksFor", org1)
+ .build();
+
+ AppSearchBatchResult<String, Void> putResult =
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(person1, org1)
+ .build()));
+ assertThat(putResult.getSuccesses()).containsExactly("person1", null, "org1", null);
+ assertThat(putResult.getFailures()).isEmpty();
+
+ GetByDocumentIdRequest getByDocumentIdRequest =
+ new GetByDocumentIdRequest.Builder("namespace").addIds("person1", "org1").build();
+ List<GenericDocument> outDocuments = doGet(mDb1, getByDocumentIdRequest);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(person1, org1);
+
+ // Both org1 and person should be returned for query "Org1"
+ // For org1 this matches the 'name' property and for person1 this matches the
+ // 'worksFor.name' property.
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "Org1",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(person1, org1);
+
+ // No documents should match for "notes", since both 'Organization:notes'
+ // and 'Person:worksFor.notes' are non-indexable.
+ searchResults =
+ mDb1.search(
+ "notes",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(0);
+ }
+
+ @Test
+ public void testSetSchema_indexableNestedPropsList_multipleNestedLevels() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(Features.SCHEMA_ADD_INDEXABLE_NESTED_PROPERTIES));
+
+ AppSearchSchema emailSchema =
+ new AppSearchSchema.Builder("Email")
+ .addProperty(
+ new StringPropertyConfig.Builder("subject")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "sender", "Person")
+ .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+ .setShouldIndexNestedProperties(false)
+ .addIndexableNestedProperties(
+ Arrays.asList(
+ "name", "worksFor.name", "worksFor.notes"))
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "recipient", "Person")
+ .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+ .setShouldIndexNestedProperties(true)
+ .build())
+ .build();
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("age")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "worksFor", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(false)
+ .addIndexableNestedProperties(Arrays.asList("name", "id"))
+ .build())
+ .build();
+ AppSearchSchema organizationSchema =
+ new AppSearchSchema.Builder("Organization")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_REQUIRED)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("notes")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("id")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .build();
+
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(emailSchema, personSchema, organizationSchema)
+ .build())
+ .get();
+
+ // Test that Email and Person's nested properties are indexed correctly.
+ GenericDocument org1 =
+ new GenericDocument.Builder<>("namespace", "org1", "Organization")
+ .setPropertyString("name", "Org1")
+ .setPropertyString("notes", "Some notes")
+ .setPropertyString("id", "1234")
+ .build();
+ GenericDocument person1 =
+ new GenericDocument.Builder<>("namespace", "person1", "Person")
+ .setPropertyString("name", "Jane")
+ .setPropertyString("age", "20")
+ .setPropertyDocument("worksFor", org1)
+ .build();
+ GenericDocument person2 =
+ new GenericDocument.Builder<>("namespace", "person2", "Person")
+ .setPropertyString("name", "John")
+ .setPropertyString("age", "30")
+ .setPropertyDocument("worksFor", org1)
+ .build();
+ GenericDocument email1 =
+ new GenericDocument.Builder<>("namespace", "email1", "Email")
+ .setPropertyString("subject", "Greetings!")
+ .setPropertyDocument("sender", person1)
+ .setPropertyDocument("recipient", person2)
+ .build();
+ AppSearchBatchResult<String, Void> putResult =
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(person1, org1, person2, email1)
+ .build()));
+ assertThat(putResult.getSuccesses())
+ .containsExactly("person1", null, "org1", null, "person2", null, "email1", null);
+ assertThat(putResult.getFailures()).isEmpty();
+
+ GetByDocumentIdRequest getByDocumentIdRequest =
+ new GetByDocumentIdRequest.Builder("namespace")
+ .addIds("person1", "org1", "person2", "email1")
+ .build();
+ List<GenericDocument> outDocuments = doGet(mDb1, getByDocumentIdRequest);
+ assertThat(outDocuments).hasSize(4);
+ assertThat(outDocuments).containsExactly(person1, org1, person2, email1);
+
+ // Indexed properties:
+ // Email: 'subject', 'sender.name', 'sender.worksFor.name', 'sender.worksFor.notes',
+ // 'recipient.name', 'recipient.age', 'recipient.worksFor.name',
+ // 'recipient.worksFor.id'
+ // (Email:recipient sets index_nested_props=true, so it follows the same indexing
+ // configs as the next schema-type level (person))
+ // Person: 'name', 'age', 'worksFor.name', 'worksFor.id'
+ // Organization: 'name', 'notes', 'id'
+ //
+ // All documents should be returned for query 'Org1' because all schemaTypes index the
+ // 'Organization:name' property.
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "Org1",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(4);
+ assertThat(outDocuments).containsExactly(person1, org1, person2, email1);
+
+ // org1 and email1 should be returned for query 'notes'
+ searchResults =
+ mDb1.search(
+ "notes",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(org1, email1);
+
+ // all docs should be returned for query "1234"
+ searchResults =
+ mDb1.search(
+ "1234",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(4);
+ assertThat(outDocuments).containsExactly(person1, org1, person2, email1);
+
+ // email1 should be returned for query "30", but not for "20" since sender.age is not
+ // indexed, but recipient.age is.
+ // For query "30", person2 should also be returned
+ // For query "20, person1 should be returned.
+ searchResults =
+ mDb1.search(
+ "30",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(person2, email1);
+
+ searchResults =
+ mDb1.search(
+ "20",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(person1);
+ }
+
+ @Test
+ public void testSetSchema_indexableNestedPropsList_circularRefs() throws Exception {
+ assumeTrue(
+ mDb1.getFeatures()
+ .isFeatureSupported(Features.SCHEMA_ADD_INDEXABLE_NESTED_PROPERTIES));
+ assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SET_SCHEMA_CIRCULAR_REFERENCES));
+
+ // Create schema with valid cycle: Person -> Organization -> Person...
+ AppSearchSchema personSchema =
+ new AppSearchSchema.Builder("Person")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("address")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "worksFor", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(false)
+ .addIndexableNestedProperties(
+ Arrays.asList("name", "notes", "funder.name"))
+ .build())
+ .build();
+ AppSearchSchema organizationSchema =
+ new AppSearchSchema.Builder("Organization")
+ .addProperty(
+ new StringPropertyConfig.Builder("name")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new StringPropertyConfig.Builder("notes")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(
+ StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+ .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build())
+ .addProperty(
+ new AppSearchSchema.DocumentPropertyConfig.Builder(
+ "funder", "Person")
+ .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+ .setShouldIndexNestedProperties(false)
+ .addIndexableNestedProperties(
+ Arrays.asList(
+ "name",
+ "worksFor.name",
+ "worksFor.funder.address",
+ "worksFor.funder.worksFor.notes"))
+ .build())
+ .build();
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema, organizationSchema)
+ .build())
+ .get();
+
+ // Test that documents following the circular schema are indexed correctly, and that its
+ // sections are searchable
+ GenericDocument person1 =
+ new GenericDocument.Builder<>("namespace", "person1", "Person")
+ .setPropertyString("name", "Person1")
+ .setPropertyString("address", "someAddress")
+ .build();
+ GenericDocument org1 =
+ new GenericDocument.Builder<>("namespace", "org1", "Organization")
+ .setPropertyString("name", "Org1")
+ .setPropertyString("notes", "someNote")
+ .setPropertyDocument("funder", person1)
+ .build();
+ GenericDocument person2 =
+ new GenericDocument.Builder<>("namespace", "person2", "Person")
+ .setPropertyString("name", "Person2")
+ .setPropertyString("address", "anotherAddress")
+ .setPropertyDocument("worksFor", org1)
+ .build();
+ GenericDocument org2 =
+ new GenericDocument.Builder<>("namespace", "org2", "Organization")
+ .setPropertyString("name", "Org2")
+ .setPropertyString("notes", "anotherNote")
+ .setPropertyDocument("funder", person2)
+ .build();
+
+ AppSearchBatchResult<String, Void> putResult =
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(person1, org1, person2, org2)
+ .build()));
+ assertThat(putResult.getSuccesses())
+ .containsExactly("person1", null, "org1", null, "person2", null, "org2", null);
+ assertThat(putResult.getFailures()).isEmpty();
+
+ GetByDocumentIdRequest getByDocumentIdRequest =
+ new GetByDocumentIdRequest.Builder("namespace")
+ .addIds("person1", "person2", "org1", "org2")
+ .build();
+ List<GenericDocument> outDocuments = doGet(mDb1, getByDocumentIdRequest);
+ assertThat(outDocuments).hasSize(4);
+ assertThat(outDocuments).containsExactly(person1, person2, org1, org2);
+
+ // Indexed properties:
+ // Person: 'name', 'address', 'worksFor.name', 'worksFor.notes', 'worksFor.funder.name'
+ // Organization: 'name', 'notes', 'funder.name', 'funder.worksFor.name',
+ // 'funder.worksFor.funder.address', 'funder.worksFor.funder.worksFor.notes'
+ //
+ // "Person1" should match person1 (name), org1 (funder.name) and person2
+ // (worksFor.funder.name)
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "Person1",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(3);
+ assertThat(outDocuments).containsExactly(person1, org1, person2);
+
+ // "someAddress" should match person1 (address) and org2 (funder.worksFor.funder.address)
+ searchResults =
+ mDb1.search(
+ "someAddress",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(person1, org2);
+
+ // "Org1" should match org1 (name), person2 (worksFor.name) and org2 (funder.worksFor.name)
+ searchResults =
+ mDb1.search(
+ "Org1",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(3);
+ assertThat(outDocuments).containsExactly(org1, person2, org2);
+
+ // "someNote" should match org1 (notes) and person2 (worksFor.notes)
+ searchResults =
+ mDb1.search(
+ "someNote",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(org1, person2);
+
+ // "Person2" should match person2 (name), org2 (funder.name)
+ searchResults =
+ mDb1.search(
+ "Person2",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(2);
+ assertThat(outDocuments).containsExactly(person2, org2);
+
+ // "anotherAddress" should match only person2 (address)
+ searchResults =
+ mDb1.search(
+ "anotherAddress",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(person2);
+
+ // "Org2" and "anotherNote" should both match only org2 (name, notes)
+ searchResults =
+ mDb1.search(
+ "Org2",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(org2);
+
+ searchResults =
+ mDb1.search(
+ "anotherNote",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(org2);
+ }
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java
index a92dbb241fb..c9e1e6274bc 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/DisableAutofillTest.java
@@ -21,6 +21,7 @@ import static android.autofillservice.cts.testcore.Timeouts.CALLBACK_NOT_CALLED_
import static org.junit.Assume.assumeTrue;
+import android.app.Instrumentation;
import android.autofillservice.cts.activities.AbstractAutoFillActivity;
import android.autofillservice.cts.activities.PreSimpleSaveActivity;
import android.autofillservice.cts.activities.SimpleSaveActivity;
@@ -35,6 +36,9 @@ import android.platform.test.annotations.FlakyTest;
import android.platform.test.annotations.Presubmit;
import android.service.autofill.FillResponse;
import android.util.Log;
+import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.InstrumentationRegistry;
import com.android.compatibility.common.util.RetryableException;
@@ -49,6 +53,7 @@ import org.junit.Test;
public class DisableAutofillTest extends AutoFillServiceTestCase.ManualActivityLaunch {
private static final String TAG = "DisableAutofillTest";
+ private Instrumentation mInstrumentation;
/**
* Defines what to do after the activity being tested is launched.
@@ -101,6 +106,7 @@ public class DisableAutofillTest extends AutoFillServiceTestCase.ManualActivityL
}
+ final UiDevice device = UiDevice.getInstance(mInstrumentation);
final long before = SystemClock.elapsedRealtime();
final SimpleSaveActivity activity = startSimpleSaveActivity();
final MyAutofillCallback callback = activity.registerCallback();
@@ -111,7 +117,9 @@ public class DisableAutofillTest extends AutoFillServiceTestCase.ManualActivityL
if (action == PostLaunchAction.ASSERT_DISABLING) {
callback.assertUiUnavailableEvent(activity.mInput);
+ callback.assertNotCalled();
sReplier.getNextFillRequest();
+ device.waitForIdle();
// Make sure other fields are not triggered.
activity.syncRunOnUiThread(() -> activity.mPassword.requestFocus());
@@ -191,6 +199,11 @@ public class DisableAutofillTest extends AutoFillServiceTestCase.ManualActivityL
}
@Before
+ public void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ @Before
public void resetAutofillOptions() throws Exception {
// Reset AutofillOptions to avoid cts package was added to augmented autofill allowlist.
Helper.resetApplicationAutofillOptions(sContext);
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 88fd9bdb0e4..b2da36177ba 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -113,6 +113,8 @@ public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
private static final int ANTI_FLICKERING_60HZ = 2;
// 5 percent error margin for resulting crop regions
private static final float CROP_REGION_ERROR_PERCENT_DELTA = 0.05f;
+ private static final float ZOOM_RATIO_ERROR_PERCENT_DELTA = 0.05f;
+
// 1 percent error margin for centering the crop region
private static final float CROP_REGION_ERROR_PERCENT_CENTERED = 0.01f;
private static final float DYNAMIC_VS_FIXED_BLK_WH_LVL_ERROR_MARGIN = 0.25f;
@@ -3206,8 +3208,9 @@ public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
verifyCaptureResultForKey(CaptureResult.CONTROL_EXTENDED_SCENE_MODE,
mode, listener, NUM_FRAMES_VERIFIED);
+ float zoomRatioDelta = ZOOM_RATIO_ERROR_PERCENT_DELTA * ratio;
verifyCaptureResultForKey(CaptureResult.CONTROL_ZOOM_RATIO,
- ratio, listener, NUM_FRAMES_VERIFIED);
+ ratio, listener, NUM_FRAMES_VERIFIED, zoomRatioDelta);
}
}
}
@@ -3485,6 +3488,33 @@ public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
* @param requestMode The request mode for this result
* @param listener The capture listener to get capture results
* @param numFramesVerified The number of capture results to be verified
+ * @param threshold The threshold by which the request and result keys can differ
+ */
+ private void verifyCaptureResultForKey(CaptureResult.Key<Float> key, float requestMode,
+ SimpleCaptureCallback listener, int numFramesVerified, float threshold) {
+ for (int i = 0; i < numFramesVerified; i++) {
+ CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+ validatePipelineDepth(result);
+ float resultMode = getValueNotNull(result, key);
+ if (VERBOSE) {
+ Log.v(TAG, "Expect value: " + requestMode + " result value: "
+ + resultMode + " threshold " + threshold);
+ }
+ // Check that the request and result are within the given threshold of each other.
+ // (expectEquals isn't the most intuitive function name.)
+ mCollector.expectEquals("Key " + key.getName() + " request: " + requestMode +
+ " result: " + resultMode + " not within threshold " + threshold +
+ " of each other", requestMode, resultMode, threshold);
+ }
+ }
+
+ /**
+ * Basic verification for the control mode capture result.
+ *
+ * @param key The capture result key to be verified against
+ * @param requestMode The request mode for this result
+ * @param listener The capture listener to get capture results
+ * @param numFramesVerified The number of capture results to be verified
*/
private <T> void verifyCaptureResultForKey(CaptureResult.Key<T> key, T requestMode,
SimpleCaptureCallback listener, int numFramesVerified) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index e8194d2a21f..3ac79f928f1 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -1709,19 +1709,49 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
boolean supportsRemosaic = arrayContains(capabilities,
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING);
+ List<CaptureRequest.Key<?>> requestKeys = c.getAvailableCaptureRequestKeys();
+ boolean doesSupportSensorPixelMode =
+ requestKeys.contains(CaptureRequest.SENSOR_PIXEL_MODE);
+
+ if (!isUltraHighResolutionSensor && !doesSupportSensorPixelMode) {
+ Log.i(TAG, "Camera id " + cameraId + " not ultra high resolution / doesn't" +
+ " support sensor pixel mode. Skipping " +
+ "testUltraHighResolutionSensorCharacteristics");
+ continue;
+ }
+
+ // Test conditions applicable to both ULTRA_HIGH_RESOLUTION_SENSOR devices and those
+ // which support SENSOR_PIXEL_MODE.
+ StreamConfigurationMap configs =
+ c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION);
+ assertNotNull("Maximum resolution stream configuration map must not be null for ultra" +
+ " high resolution sensor camera " + cameraId, configs);
+
+ int[] outputFormats = configs.getOutputFormats();
+ boolean supportsRawOutput =
+ arrayContains(outputFormats, ImageFormat.RAW_SENSOR) ||
+ arrayContains(outputFormats, ImageFormat.RAW10) ||
+ arrayContains(outputFormats, ImageFormat.RAW_PRIVATE) ||
+ arrayContains(outputFormats, ImageFormat.RAW12);
+
+ if (supportsRawOutput) {
+ Size binningFactor = c.get(CameraCharacteristics.SENSOR_INFO_BINNING_FACTOR);
+ assertTrue("SENSOR_INFO_BINNING_FACTOR must be advertised by a sensor that " +
+ " supports ULTRA_HIGH_RESOLUTION_SENSOR / SENSOR_PIXEL_MODE with "
+ + " RAW outputs - camera id: " +
+ cameraId, binningFactor != null);
+ }
+
if (!isUltraHighResolutionSensor) {
- Log.i(TAG, "Camera id " + cameraId + " not ultra high resolution. Skipping " +
- "testUltraHighResolutionSensorCharacteristics");
continue;
}
+
+ // These conditions apply to ULTRA_HIGH_RESOLUTION_SENSOR devices.
assertArrayContains(
String.format("Ultra high resolution sensor, camera id %s" +
" must also have the RAW capability", cameraId), capabilities,
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW);
- StreamConfigurationMap configs =
- c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION);
- assertNotNull("Maximum resolution stream configuration map must not be null for ultra" +
- " high resolution sensor camera " + cameraId, configs);
+
Size uhrPixelArraySize = CameraTestUtils.getValueNotNull(
c, CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION);
long uhrSensorSize = uhrPixelArraySize.getHeight() * uhrPixelArraySize.getWidth();
@@ -1730,7 +1760,6 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
MIN_UHR_SENSOR_RESOLUTION + " pixels, is " + uhrSensorSize + ", for camera id "
+ cameraId, uhrSensorSize >= MIN_UHR_SENSOR_RESOLUTION);
- int[] outputFormats = configs.getOutputFormats();
assertArrayContains(String.format("No max res JPEG image format for ultra high" +
" resolution sensor: ID %s", cameraId), outputFormats, ImageFormat.JPEG);
assertArrayContains(String.format("No max res YUV_420_88 image format for ultra high" +
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java
index 35230061292..c62b526cc65 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java
@@ -48,10 +48,12 @@ import com.android.bedstead.harrier.annotations.EnsureHasPermission;
import com.android.bedstead.harrier.annotations.Postsubmit;
import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
import com.android.bedstead.harrier.annotations.enterprise.MostRestrictiveCoexistenceTest;
import com.android.bedstead.harrier.annotations.enterprise.PolicyAppliesTest;
import com.android.bedstead.harrier.annotations.enterprise.PolicyDoesNotApplyTest;
import com.android.bedstead.harrier.policies.PermittedInputMethods;
+import com.android.bedstead.harrier.policies.PermittedSystemInputMethods;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.inputmethods.InputMethod;
import com.android.bedstead.nene.packages.Package;
@@ -107,7 +109,7 @@ public final class PermitInputMethodsTest {
}
@Postsubmit(reason = "New test")
- @PolicyAppliesTest(policy = PermittedInputMethods.class)
+ @PolicyAppliesTest(policy = {PermittedInputMethods.class, PermittedSystemInputMethods.class})
@EnsureHasPermission({INTERACT_ACROSS_USERS_FULL, QUERY_ADMIN_POLICY})
public void setPermittedInputMethods_allPermitted() {
assertThat(sDeviceState.dpc().devicePolicyManager().setPermittedInputMethods(
@@ -120,7 +122,7 @@ public final class PermitInputMethodsTest {
}
@Postsubmit(reason = "New test")
- @CanSetPolicyTest(policy = PermittedInputMethods.class)
+ @CanSetPolicyTest(policy = {PermittedInputMethods.class, PermittedSystemInputMethods.class})
@EnsureHasPermission({INTERACT_ACROSS_USERS_FULL, QUERY_ADMIN_POLICY})
public void setPermittedInputMethods_doesNotThrowException() {
sDeviceState.dpc().devicePolicyManager().setPermittedInputMethods(
@@ -128,7 +130,8 @@ public final class PermitInputMethodsTest {
}
@Postsubmit(reason = "New test")
- @CannotSetPolicyTest(policy = PermittedInputMethods.class, includeNonDeviceAdminStates = false)
+ @CannotSetPolicyTest(policy = {PermittedInputMethods.class, PermittedSystemInputMethods.class},
+ includeNonDeviceAdminStates = false)
@EnsureHasPermission({INTERACT_ACROSS_USERS_FULL, QUERY_ADMIN_POLICY})
public void setPermittedInputMethods_canNotSet_throwsException() {
assertThrows(SecurityException.class, () -> {
@@ -138,6 +141,15 @@ public final class PermitInputMethodsTest {
}
@Postsubmit(reason = "New test")
+ @CanSetPolicyTest(policy = PermittedSystemInputMethods.class)
+ public void setPermittedInputMethods_nonEmptyList_throwsException() {
+ assertThrows(IllegalArgumentException.class, () -> {
+ sDeviceState.dpc().devicePolicyManager().setPermittedInputMethods(
+ sDeviceState.dpc().componentName(), /* packageNames= */ List.of("package"));
+ });
+ }
+
+ @Postsubmit(reason = "New test")
@PolicyDoesNotApplyTest(policy = PermittedInputMethods.class)
@EnsureHasPermission({INTERACT_ACROSS_USERS_FULL, QUERY_ADMIN_POLICY})
public void setPermittedInputMethods_policyDoesNotApply_isNotSet() {
@@ -183,7 +195,7 @@ public final class PermitInputMethodsTest {
}
@Postsubmit(reason = "New test")
- @CanSetPolicyTest(policy = PermittedInputMethods.class)
+ @CanSetPolicyTest(policy = {PermittedInputMethods.class, PermittedSystemInputMethods.class})
public void setPermittedInputMethods_packageNameTooLong_throwsException() {
// Invalid package name - too long
List<String> badMethods = List.of(new String(new char[1000]).replace('\0', 'A'));
@@ -225,7 +237,7 @@ public final class PermitInputMethodsTest {
@ApiTest(apis = {"android.app.admin.DevicePolicyManager#setPermittedInputMethods"})
// TODO: enable after adding the broadcast receiver to relevant test apps.
// @PolicyAppliesTest(policy = PermittedInputMethods.class)
- @com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner(isPrimary = true)
+ @EnsureHasDeviceOwner(isPrimary = true)
public void policyUpdateReceiver_setPermittedInputMethods_receivedPolicySetBroadcast() {
assumeFalse("A system input method is required",
SYSTEM_INPUT_METHODS_PACKAGES.isEmpty());
@@ -448,7 +460,6 @@ public final class PermitInputMethodsTest {
.containsExactlyElementsIn(permittedPlusSystem);
assertThat(policyState.getCurrentResolvedPolicy())
.containsExactlyElementsIn(enabledNonSystemImes);
-
} finally {
sDeviceState.dpc().devicePolicyManager().setPermittedInputMethods(
sDeviceState.dpc().componentName(), /* packageNames= */ null);
diff --git a/tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java b/tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java
index 60a6cb8bcf2..075cfc5e15a 100644
--- a/tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java
+++ b/tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java
@@ -23,14 +23,14 @@ import static android.Manifest.permission.READ_PHONE_NUMBERS;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.READ_SMS;
import static android.Manifest.permission.WRITE_CALL_LOG;
-import static android.app.role.RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP;
import static android.app.role.RoleManager.ROLE_SMS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static com.android.bedstead.harrier.UserType.WORK_PROFILE;
import static com.android.bedstead.nene.appops.CommonAppOps.OPSTR_CALL_PHONE;
-import static com.android.bedstead.nene.types.OptionalBoolean.TRUE;
+import static com.android.bedstead.nene.permissions.CommonPermissions.MODIFY_PHONE_STATE;
+import static com.android.bedstead.nene.permissions.CommonPermissions.READ_PRIVILEGED_PHONE_STATE;
import static com.android.eventlib.truth.EventLogsSubject.assertThat;
import static com.android.queryable.queries.ActivityQuery.activity;
import static com.android.queryable.queries.IntentFilterQuery.intentFilter;
@@ -54,7 +54,6 @@ import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
-import android.os.UserHandle;
import android.provider.CallLog;
import android.provider.Settings;
import android.provider.Telephony;
@@ -70,6 +69,8 @@ import android.text.TextUtils;
import com.android.activitycontext.ActivityContext;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.BeforeClass;
import com.android.bedstead.harrier.annotations.EnsureGlobalSettingSet;
import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
import com.android.bedstead.harrier.annotations.Postsubmit;
@@ -79,7 +80,9 @@ import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
import com.android.bedstead.nene.DefaultDialerContext;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.packages.ComponentReference;
+import com.android.bedstead.nene.permissions.CommonPermissions;
import com.android.bedstead.nene.permissions.PermissionContext;
+import com.android.bedstead.nene.roles.RoleContext;
import com.android.bedstead.nene.users.UserReference;
import com.android.bedstead.nene.utils.Poll;
import com.android.bedstead.testapp.TestApp;
@@ -87,10 +90,8 @@ import com.android.bedstead.testapp.TestAppActivityReference;
import com.android.bedstead.testapp.TestAppInstance;
import com.android.bedstead.testapp.TestInCallService;
import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.SystemUtil;
import com.android.eventlib.events.CustomEvent;
-import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
@@ -98,9 +99,7 @@ import org.junit.runner.RunWith;
import java.time.Duration;
import java.util.List;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@RequireFeature(FEATURE_TELEPHONY)
@@ -128,21 +127,30 @@ public final class WorkProfileTelephonyTest {
"enable_work_profile_telephony";
private static final String ENABLE_SWITCH_TO_MANAGED_PROFILE_FLAG =
"enable_switch_to_managed_profile_dialog";
+ private static final int DEFAULT_SIM_SLOT = 0;
+
+ private static final RoleManager sRoleManager = sContext.getSystemService(RoleManager.class);
+ private static final TelephonyManager sTelephonyManager = sContext.getSystemService(
+ TelephonyManager.class);
+ private static final SubscriptionManager sSubscriptionManager = sContext.getSystemService(
+ SubscriptionManager.class);
+
+ private static String sDestinationNumber;
+
+ @BeforeClass
+ public static void setupClass() {
+ try (PermissionContext p = TestApis.permissions().withPermission(READ_PHONE_NUMBERS,
+ MODIFY_PHONE_STATE)) {
+ int subId = SubscriptionManager.getSubscriptionId(DEFAULT_SIM_SLOT);
+ sDestinationNumber = sSubscriptionManager.getPhoneNumber(subId);
+ sSubscriptionManager.setDefaultSmsSubId(subId);
+ }
+ }
- private RoleManager mRoleManager;
- private TelephonyManager mTelephonyManager;
- private String mDestinationNumber;
-
- @Before
- public void setUp() {
- mTelephonyManager = sContext.getSystemService(TelephonyManager.class);
- mRoleManager = sContext.getSystemService(RoleManager.class);
-
- try (PermissionContext p = TestApis.permissions().withPermission(READ_PHONE_NUMBERS)) {
- SubscriptionManager subscriptionManager = sContext.getSystemService(
- SubscriptionManager.class);
- mDestinationNumber =
- subscriptionManager.getPhoneNumber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ @AfterClass
+ public static void teardownClass() {
+ try (PermissionContext p = TestApis.permissions().withPermission(MODIFY_PHONE_STATE)) {
+ sSubscriptionManager.setDefaultSmsSubId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
}
@@ -156,14 +164,13 @@ public final class WorkProfileTelephonyTest {
throws ExecutionException, InterruptedException, TimeoutException {
assumeSmsCapableDevice();
assertValidSimCardPresent();
- String previousDefaultSmsPackage = Telephony.Sms.getDefaultSmsPackage(sContext);
RemoteDevicePolicyManager dpm = sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager();
UserReference workProfileUser = sDeviceState.workProfile();
- try (TestAppInstance smsApp = sSmsApp.install(workProfileUser)) {
- dpm.setManagedSubscriptionsPolicy(new ManagedSubscriptionsPolicy(
- ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS));
- setPackageAsSmsRoleHolderForUser(smsApp.packageName(), workProfileUser.userHandle());
+ dpm.setManagedSubscriptionsPolicy(new ManagedSubscriptionsPolicy(
+ ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS));
+ try (TestAppInstance smsApp = sSmsApp.install(workProfileUser);
+ RoleContext c = smsApp.testApp().pkg().setAsRoleHolder(ROLE_SMS, workProfileUser)) {
Intent sentIntent = new Intent(SMS_SENT_INTENT_ACTION).setPackage(smsApp.packageName());
PendingIntent sentPendingIntent = PendingIntent.getBroadcast(
TestApis.context().instrumentedContext(), 0, sentIntent,
@@ -171,15 +178,13 @@ public final class WorkProfileTelephonyTest {
IntentFilter sentIntentFilter = new IntentFilter(SMS_SENT_INTENT_ACTION);
smsApp.registerReceiver(sentIntentFilter, Context.RECEIVER_EXPORTED_UNAUDITED);
- smsApp.smsManager().sendTextMessage(mDestinationNumber, null, "test", sentPendingIntent,
+ smsApp.smsManager().sendTextMessage(sDestinationNumber, null, "test", sentPendingIntent,
null);
assertThat(smsApp.events().broadcastReceived().whereIntent().action().isEqualTo(
SMS_SENT_INTENT_ACTION).whereResultCode().isEqualTo(
Activity.RESULT_OK)).eventOccurred();
} finally {
- dpm.setDefaultSmsApplication(sDeviceState.profileOwner(WORK_PROFILE).componentName(),
- previousDefaultSmsPackage);
sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
new ManagedSubscriptionsPolicy(
@@ -198,44 +203,54 @@ public final class WorkProfileTelephonyTest {
throws ExecutionException, InterruptedException, TimeoutException {
assumeSmsCapableDevice();
assertValidSimCardPresent();
- String previousDefaultSmsPackage = Telephony.Sms.getDefaultSmsPackage(sContext);
RemoteDevicePolicyManager dpm = sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager();
UserReference primaryUser = sDeviceState.primaryUser();
- try (TestAppInstance smsApp = sSmsApp.install(primaryUser)) {
- setPackageAsSmsRoleHolderForUser(smsApp.packageName(), primaryUser.userHandle());
+ UserReference workProfileUser = sDeviceState.workProfile();
+ try (TestAppInstance personalSmsApp = sSmsApp.install(primaryUser);
+ RoleContext c1 = personalSmsApp.testApp().pkg().setAsRoleHolder(ROLE_SMS,
+ primaryUser)) {
dpm.setManagedSubscriptionsPolicy(new ManagedSubscriptionsPolicy(
ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS));
- Intent sentIntent = new Intent(SMS_SENT_INTENT_ACTION).setPackage(smsApp.packageName());
- PendingIntent sentPendingIntent = PendingIntent.getBroadcast(
- TestApis.context().instrumentedContext(), 1, sentIntent,
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
- smsApp.registerReceiver(new IntentFilter(SMS_SENT_INTENT_ACTION),
- Context.RECEIVER_EXPORTED_UNAUDITED);
- TestAppActivityReference activityReference =
- smsApp.activities().query().whereActivity().exported().isTrue().get();
- // Launch an activity here to bring the default sms app to foreground, we only show the
- // switch to managed profile dialog for sms, when sms app is foreground.
- ActivityContext.runWithContext(activity -> {
- Intent intent = new Intent().addFlags(FLAG_ACTIVITY_NEW_TASK).setComponent(
- activityReference.component().componentName());
- activity.startActivity(intent, new Bundle());
- });
-
- smsApp.smsManager().sendTextMessage(mDestinationNumber, null, "test", sentPendingIntent,
- null);
-
- assertThat(smsApp.events().broadcastReceived().whereIntent().action().isEqualTo(
- SMS_SENT_INTENT_ACTION).whereResultCode().isEqualTo(
- SmsManager.RESULT_USER_NOT_ALLOWED)).eventOccurred();
- Poll.forValue("Foreground activity", () -> TestApis.activities().foregroundActivity())
- .toBeEqualTo(INTENT_FORWARDER_COMPONENT).errorOnFail().await();
- } finally {
- sDeviceState.profileOwner(
- WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
- new ManagedSubscriptionsPolicy(
- ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
- setPackageAsSmsRoleHolderForUser(previousDefaultSmsPackage, primaryUser.userHandle());
+ try (TestAppInstance workSmsApp = sSmsApp.install(workProfileUser);
+ RoleContext c2 = workSmsApp.testApp().pkg().setAsRoleHolder(ROLE_SMS,
+ workProfileUser)) {
+ Intent sentIntent = new Intent(SMS_SENT_INTENT_ACTION).setPackage(
+ personalSmsApp.packageName());
+ PendingIntent sentPendingIntent = PendingIntent.getBroadcast(
+ TestApis.context().instrumentedContext(), 1, sentIntent,
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ personalSmsApp.registerReceiver(new IntentFilter(SMS_SENT_INTENT_ACTION),
+ Context.RECEIVER_EXPORTED_UNAUDITED);
+ TestAppActivityReference activityReference = personalSmsApp.activities().query()
+ .whereActivity().exported().isTrue().get();
+ // Launch an activity here to bring the default sms app to foreground, we only
+ // show the
+ // switch to managed profile dialog for sms, when sms app is foreground.
+ ActivityContext.runWithContext(activity -> {
+ Intent intent = new Intent().addFlags(FLAG_ACTIVITY_NEW_TASK).setComponent(
+ activityReference.component().componentName());
+ activity.startActivity(intent, new Bundle());
+ });
+
+ personalSmsApp.smsManager().sendTextMessage(sDestinationNumber, null, "test",
+ sentPendingIntent,
+ null);
+
+ assertThat(
+ personalSmsApp.events().broadcastReceived()
+ .whereIntent().action().isEqualTo(SMS_SENT_INTENT_ACTION)
+ .whereResultCode().isEqualTo(SmsManager.RESULT_USER_NOT_ALLOWED))
+ .eventOccurred();
+ Poll.forValue("Foreground activity",
+ () -> TestApis.activities().foregroundActivity()).toBeEqualTo(
+ INTENT_FORWARDER_COMPONENT).errorOnFail().await();
+ } finally {
+ sDeviceState.profileOwner(
+ WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
+ new ManagedSubscriptionsPolicy(
+ ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
+ }
}
}
@@ -249,17 +264,15 @@ public final class WorkProfileTelephonyTest {
public void allManagedSubscriptions_accessWorkMessageFromPersonalProfile_fails() {
assumeSmsCapableDevice();
assertValidSimCardPresent();
- String previousDefaultSmsPackage = Telephony.Sms.getDefaultSmsPackage(sContext);
RemoteDevicePolicyManager dpm = sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager();
UserReference workProfileUser = sDeviceState.workProfile();
- try (TestAppInstance smsApp = sSmsApp.install(workProfileUser)) {
- dpm.setManagedSubscriptionsPolicy(new ManagedSubscriptionsPolicy(
- ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS));
- dpm.setDefaultSmsApplication(sDeviceState.profileOwner(WORK_PROFILE).componentName(),
- smsApp.packageName());
+ dpm.setManagedSubscriptionsPolicy(new ManagedSubscriptionsPolicy(
+ ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS));
+ try (TestAppInstance smsApp = sSmsApp.install(workProfileUser);
+ RoleContext c = smsApp.testApp().pkg().setAsRoleHolder(ROLE_SMS, workProfileUser)) {
ContentValues smsValues = new ContentValues();
- smsValues.put(Telephony.Sms.ADDRESS, mDestinationNumber);
+ smsValues.put(Telephony.Sms.ADDRESS, sDestinationNumber);
smsValues.put(Telephony.Sms.BODY, "This is a test message.");
Uri insertedSmsUri = null;
try {
@@ -280,8 +293,6 @@ public final class WorkProfileTelephonyTest {
}
}
} finally {
- dpm.setDefaultSmsApplication(sDeviceState.profileOwner(WORK_PROFILE).componentName(),
- previousDefaultSmsPackage);
sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
new ManagedSubscriptionsPolicy(
@@ -298,18 +309,17 @@ public final class WorkProfileTelephonyTest {
public void allManagedSubscriptions_accessWorkMessageFromWorkProfile_works()
throws ExecutionException, InterruptedException, TimeoutException {
assumeSmsCapableDevice();
- String previousDefaultSmsPackage = Telephony.Sms.getDefaultSmsPackage(sContext);
RemoteDevicePolicyManager dpm = sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager();
UserReference workProfileUser = sDeviceState.workProfile();
- try (TestAppInstance smsApp = sSmsApp.install(workProfileUser)) {
- dpm.setManagedSubscriptionsPolicy(new ManagedSubscriptionsPolicy(
- ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS));
- setPackageAsSmsRoleHolderForUser(smsApp.packageName(), workProfileUser.userHandle());
+ dpm.setManagedSubscriptionsPolicy(new ManagedSubscriptionsPolicy(
+ ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS));
+ try (TestAppInstance smsApp = sSmsApp.install(workProfileUser);
+ RoleContext c = smsApp.testApp().pkg().setAsRoleHolder(ROLE_SMS, workProfileUser)) {
String insertMessageBody =
"This is a test message with timestamp : " + System.currentTimeMillis();
ContentValues smsValues = new ContentValues();
- smsValues.put(Telephony.Sms.ADDRESS, mDestinationNumber);
+ smsValues.put(Telephony.Sms.ADDRESS, sDestinationNumber);
smsValues.put(Telephony.Sms.BODY, insertMessageBody);
Uri insertedSmsUri = null;
try {
@@ -333,8 +343,6 @@ public final class WorkProfileTelephonyTest {
}
}
} finally {
- dpm.setDefaultSmsApplication(sDeviceState.profileOwner(WORK_PROFILE).componentName(),
- previousDefaultSmsPackage);
sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
new ManagedSubscriptionsPolicy(
@@ -344,7 +352,7 @@ public final class WorkProfileTelephonyTest {
@EnsureGlobalSettingSet(key =
Settings.Global.ALLOW_WORK_PROFILE_TELEPHONY_FOR_NON_DPM_ROLE_HOLDERS, value = "1")
- @EnsureHasWorkProfile(isOrganizationOwned = true)
+ @RequireRunOnWorkProfile(isOrganizationOwned = true)
@Postsubmit(reason = "new test")
@Test
public void placeCall_fromWorkProfile_allManagedSubscriptions_works() throws Exception {
@@ -359,8 +367,9 @@ public final class WorkProfileTelephonyTest {
dialerApp.packageName());
PermissionContext p = dialerApp.permissions().withPermission(CALL_PHONE).withAppOp(
OPSTR_CALL_PHONE)) {
+ setDefaultSimForCallInWorkProfile();
- dialerApp.telecomManager().placeCall(Uri.fromParts("tel", mDestinationNumber, null),
+ dialerApp.telecomManager().placeCall(Uri.fromParts("tel", sDestinationNumber, null),
null);
customEvents(dialerApp.packageName(), dialerApp.user()).whereTag().isEqualTo(
TestInCallService.TAG).whereData().isEqualTo(
@@ -373,6 +382,7 @@ public final class WorkProfileTelephonyTest {
WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
new ManagedSubscriptionsPolicy(
ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
+ unsetDefaultSimForCallInWorkProfile();
}
}
@@ -396,7 +406,7 @@ public final class WorkProfileTelephonyTest {
DefaultDialerContext dc = TestApis.telecom().setDefaultDialerForAllUsers(
dialerApp.packageName())) {
- dialerApp.telecomManager().placeCall(Uri.fromParts("tel", mDestinationNumber, null),
+ dialerApp.telecomManager().placeCall(Uri.fromParts("tel", sDestinationNumber, null),
null);
Poll.forValue("Foreground activity",
@@ -489,16 +499,20 @@ public final class WorkProfileTelephonyTest {
dialerApp.packageName());
PermissionContext p = dialerApp.permissions().withPermission(CALL_PHONE).withAppOp(
OPSTR_CALL_PHONE)) {
+ setDefaultSimForCallInWorkProfile();
+
// This will create a call log in work profile
- dialerApp.telecomManager().placeCall(Uri.fromParts("tel", mDestinationNumber, null),
+ dialerApp.telecomManager().placeCall(Uri.fromParts("tel", sDestinationNumber, null),
null);
customEvents(dialerApp.packageName(), dialerApp.user()).whereTag().isEqualTo(
TestInCallService.TAG).whereData().isEqualTo(
"onStateChanged:" + Call.STATE_DISCONNECTED).poll();
- try (PermissionContext pc = TestApis.permissions().withPermission(READ_CALL_LOG)) {
- Poll.forValue(() -> numCallLogs()).timeout(Duration.ofSeconds(10)).toNotBeEqualTo(
- 0).errorOnFail().await();
+ try (PermissionContext pc = TestApis.permissions().withPermission(READ_CALL_LOG,
+ INTERACT_ACROSS_USERS_FULL)) {
+ Poll.forValue(() -> numCallLogs(sDeviceState.workProfile()))
+ .timeout(Duration.ofSeconds(10))
+ .toNotBeEqualTo(0).errorOnFail().await();
}
} finally {
try (PermissionContext pc = TestApis.permissions().withPermission(WRITE_CALL_LOG)) {
@@ -509,13 +523,13 @@ public final class WorkProfileTelephonyTest {
WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
new ManagedSubscriptionsPolicy(
ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
+ unsetDefaultSimForCallInWorkProfile();
}
}
@EnsureGlobalSettingSet(key =
Settings.Global.ALLOW_WORK_PROFILE_TELEPHONY_FOR_NON_DPM_ROLE_HOLDERS, value = "1")
- @EnsureHasWorkProfile(isOrganizationOwned = true, installInstrumentedApp = TRUE)
- @RequireRunOnInitialUser
+ @RequireRunOnWorkProfile(isOrganizationOwned = true)
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-2-1"})
@@ -531,17 +545,21 @@ public final class WorkProfileTelephonyTest {
dialerApp.packageName());
PermissionContext p = dialerApp.permissions().withPermission(CALL_PHONE).withAppOp(
OPSTR_CALL_PHONE)) {
+ setDefaultSimForCallInWorkProfile();
+
// This will create a call log in work profile
- dialerApp.telecomManager().placeCall(Uri.fromParts("tel", mDestinationNumber, null),
+ dialerApp.telecomManager().placeCall(Uri.fromParts("tel", sDestinationNumber, null),
null);
customEvents(dialerApp.packageName(), dialerApp.user()).whereTag().isEqualTo(
TestInCallService.TAG).whereData().isEqualTo(
"onStateChanged:" + Call.STATE_DISCONNECTED).poll();
- try (PermissionContext pc = TestApis.permissions().withPermission(READ_CALL_LOG)) {
- Poll.forValue(() -> numCallLogs()).timeout(Duration.ofSeconds(10)).toNotBeEqualTo(
- 0).await();
- assertThat(numCallLogs()).isEqualTo(0);
+ try (PermissionContext pc = TestApis.permissions().withPermission(READ_CALL_LOG,
+ CommonPermissions.INTERACT_ACROSS_USERS_FULL)) {
+ Poll.forValue(() -> numCallLogs(sDeviceState.workProfile().parent()))
+ .timeout(Duration.ofSeconds(10))
+ .toNotBeEqualTo(0).await();
+ assertThat(numCallLogs(sDeviceState.workProfile().parent())).isEqualTo(0);
}
} finally {
try (PermissionContext p2 = TestApis.permissions().withPermission(
@@ -554,52 +572,60 @@ public final class WorkProfileTelephonyTest {
WORK_PROFILE).devicePolicyManager().setManagedSubscriptionsPolicy(
new ManagedSubscriptionsPolicy(
ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
+ unsetDefaultSimForCallInWorkProfile();
}
}
- private void setPackageAsSmsRoleHolderForUser(String packageName, UserHandle userHandle)
- throws ExecutionException, InterruptedException, TimeoutException {
- CompletableFuture<Boolean> roleUpdateFuture = new CompletableFuture<>();
- SystemUtil.runWithShellPermissionIdentity(() -> {
- mRoleManager.addRoleHolderAsUser(ROLE_SMS, packageName,
- MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, sContext.getMainExecutor(),
- roleUpdateFuture::complete);
- });
- // Wait for the future to complete.
- roleUpdateFuture.get(60, TimeUnit.SECONDS);
- }
-
private String getDefaultDialerPackage() {
return sContext.getSystemService(TelecomManager.class).getDefaultDialerPackage();
}
private void assumeSmsCapableDevice() {
- assumeTrue(mTelephonyManager.isSmsCapable() || (mRoleManager != null
- && mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)));
+ assumeTrue(sTelephonyManager.isSmsCapable() || (sRoleManager != null
+ && sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)));
}
private void assumeCallCapableDevice() {
- assumeTrue(mTelephonyManager.isVoiceCapable() || (mRoleManager != null
- && mRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER)));
+ assumeTrue(sTelephonyManager.isVoiceCapable() || (sRoleManager != null
+ && sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER)));
}
private void assertValidSimCardPresent() {
assertTrue("[RERUN] This test requires SIM card to be present", isSimCardPresent());
assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.",
- TextUtils.isEmpty(mDestinationNumber));
+ TextUtils.isEmpty(sDestinationNumber));
}
private boolean isSimCardPresent() {
- return mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY;
+ return sTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY;
}
private CustomEvent.CustomEventQuery customEvents(String packageName, UserReference user) {
return CustomEvent.queryPackage(packageName).onUser(user);
}
- private int numCallLogs() {
- Cursor cursor = TestApis.context().instrumentedContext().getContentResolver().query(
+ private int numCallLogs(UserReference user) {
+ Cursor cursor = TestApis.context().androidContextAsUser(user).getContentResolver().query(
CallLog.Calls.CONTENT_URI, null, null, null, null);
return cursor.getCount();
}
+
+ private void setDefaultSimForCallInWorkProfile() {
+ int subId = SubscriptionManager.getSubscriptionId(DEFAULT_SIM_SLOT);
+ try (PermissionContext permissionContext = TestApis.permissions().withPermission(
+ MODIFY_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE)) {
+ PhoneAccountHandle handle =
+ sTelephonyManager.getPhoneAccountHandleForSubscriptionId(subId);
+ TestApis.context().instrumentedContext().getSystemService(
+ TelecomManager.class).setUserSelectedOutgoingPhoneAccount(handle);
+ }
+ }
+
+ private void unsetDefaultSimForCallInWorkProfile() {
+ try (PermissionContext permissionContext = TestApis.permissions().withPermission(
+ MODIFY_PHONE_STATE)) {
+ TestApis.context().instrumentedContext().getSystemService(TelecomManager.class)
+ .setUserSelectedOutgoingPhoneAccount(null);
+ }
+ }
}
diff --git a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
index 66d1e02fedf..c4811f6381f 100644
--- a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
@@ -30,6 +30,7 @@ import com.android.compatibility.common.util.DeviceReportLog;
import static org.junit.Assert.assertTrue;
+import org.junit.Before;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
@@ -45,8 +46,14 @@ public class RandomRWTest {
@Rule
public final TestName mTestName = new TestName();
+ @Before
+ public void setUp() throws Exception {
+ CarTestUtil.getInstance().setUp();
+ }
+
@After
public void tearDown() throws Exception {
+ CarTestUtil.getInstance().tearDown();
FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_WR);
FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_RD);
}
diff --git a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
index 1beb91a90bd..a4c6454c130 100644
--- a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
@@ -35,6 +35,7 @@ import com.android.compatibility.common.util.Stat;
import static org.junit.Assert.assertTrue;
+import org.junit.Before;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
@@ -58,8 +59,14 @@ public class SequentialRWTest {
@Rule
public final TestName mTestName = new TestName();
+ @Before
+ public void setUp() throws Exception {
+ CarTestUtil.getInstance().setUp();
+ }
+
@After
public void tearDown() throws Exception {
+ CarTestUtil.getInstance().tearDown();
FileUtil.removeFileOrDir(getContext(), DIR_SEQ_WR);
FileUtil.removeFileOrDir(getContext(), DIR_SEQ_UPDATE);
FileUtil.removeFileOrDir(getContext(), DIR_SEQ_RD);
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java
index cdf8e85139e..c6f8c4c4920 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/HandleSplashScreenExitActivity.java
@@ -44,6 +44,7 @@ import android.os.Bundle;
import android.os.SystemClock;
import android.server.wm.TestJournalProvider;
import android.view.SurfaceView;
+import android.view.ViewTreeObserver;
import android.window.SplashScreen;
public class HandleSplashScreenExitActivity extends Activity {
@@ -73,6 +74,7 @@ public class HandleSplashScreenExitActivity extends Activity {
if (getIntent().getBooleanExtra(DELAY_RESUME, false)) {
SystemClock.sleep(5000);
}
+ deferDraw(this);
}
private final SplashScreen.OnExitAnimationListener mSplashScreenExitHandler =
@@ -130,4 +132,17 @@ public class HandleSplashScreenExitActivity extends Activity {
mUiModeManager.setApplicationNightMode(MODE_NIGHT_AUTO);
}
}
+
+ /** Deferring show app window to let splash screen display for a while. */
+ static void deferDraw(Activity a) {
+ a.getWindow().getDecorView().getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ final long mCreateTime = SystemClock.uptimeMillis();
+
+ @Override
+ public boolean onPreDraw() {
+ return SystemClock.uptimeMillis() - mCreateTime > 500;
+ }
+ });
+ }
}
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceThemeActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceThemeActivity.java
index 052e8d7a4d8..1cf4c4620e0 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceThemeActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceThemeActivity.java
@@ -39,6 +39,7 @@ public class SplashScreenReplaceThemeActivity extends Activity {
super.onCreate(savedInstanceState);
getSplashScreen().setOnExitAnimationListener(mSplashScreenExitHandler);
mOverrideTheme = getIntent().getBooleanExtra(OVERRIDE_THEME_ENABLED, false);
+ HandleSplashScreenExitActivity.deferDraw(this);
}
@Override
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenStyleThemeActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenStyleThemeActivity.java
index 47142a32981..021ae95aa7c 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenStyleThemeActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenStyleThemeActivity.java
@@ -34,6 +34,7 @@ public class SplashScreenStyleThemeActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSplashScreen().setOnExitAnimationListener(mSplashScreenExitHandler);
+ HandleSplashScreenExitActivity.deferDraw(this);
}
private void onSplashScreenExit(SplashScreenView view) {
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingPlaceholderTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingPlaceholderTests.java
index 03a9762c96f..96915507a7a 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingPlaceholderTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingPlaceholderTests.java
@@ -221,6 +221,14 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
public void testPlaceholderLaunchedWhenTaskWidthIncreased() {
try (RotationSession rotationSession = new RotationSession()) {
rotationSession.set(ROTATION_0);
+
+ // Reduce display size by 50% so that display size won't exceed the maximum display
+ // size during the test.
+ final Size currentSize = mReportedDisplayMetrics.getSize();
+ final Size displaySize = new Size((int) (currentSize.getWidth() * 0.5),
+ (int) (currentSize.getHeight() * 0.5));
+ mReportedDisplayMetrics.setSize(displaySize);
+
final double splitTaskWidth = getTaskWidth() * 1.05;
final double splitTaskHeight = getTaskHeight() * 1.05;
@@ -246,9 +254,8 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
// Increase display size by 10% so that the primary and placeholder activities are
// stacked
- final Size currentSize = mReportedDisplayMetrics.getSize();
- mReportedDisplayMetrics.setSize(new Size((int) (currentSize.getWidth() * 1.1),
- (int) (currentSize.getHeight() * 1.1)));
+ mReportedDisplayMetrics.setSize(new Size((int) (displaySize.getWidth() * 1.1),
+ (int) (displaySize.getHeight() * 1.1)));
// Verify that the placeholder activity is launched into a split with the primary
// activity
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingTestBase.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingTestBase.java
index 65c87dc5001..61b4f38d8cb 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingTestBase.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingTestBase.java
@@ -20,13 +20,16 @@ import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSuppo
import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+import android.app.ActivityTaskManager;
import android.server.wm.ActivityManagerTestBase.ReportedDisplayMetrics;
import android.server.wm.UiDeviceUtils;
import android.server.wm.jetpack.utils.TestValueCountConsumer;
import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase;
import android.view.Display;
+import androidx.test.core.app.ApplicationProvider;
import androidx.window.extensions.WindowExtensions;
import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
import androidx.window.extensions.embedding.SplitInfo;
@@ -51,6 +54,7 @@ public class ActivityEmbeddingTestBase extends WindowManagerJetpackTestBase {
@Before
public void setUp() {
super.setUp();
+ assumeTrue(supportsMultiWindow());
assumeExtensionSupportedDevice();
WindowExtensions windowExtensions = getWindowExtensions();
assumeNotNull(windowExtensions);
@@ -64,6 +68,11 @@ public class ActivityEmbeddingTestBase extends WindowManagerJetpackTestBase {
UiDeviceUtils.pressUnlockButton();
}
+ /** Checks whether the device supports the multi-window feature or not. */
+ private static boolean supportsMultiWindow() {
+ return ActivityTaskManager.supportsMultiWindow(ApplicationProvider.getApplicationContext());
+ }
+
@After
public void cleanUp() {
mReportedDisplayMetrics.restoreDisplayMetrics();
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/SplitAttributesCalculatorTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/SplitAttributesCalculatorTest.java
index f60e08ecd08..93dc436723f 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/SplitAttributesCalculatorTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/SplitAttributesCalculatorTest.java
@@ -21,8 +21,6 @@ import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.EXPAND_SPLIT
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.HINGE_SPLIT_ATTRS;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createSplitPairRuleBuilder;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplitAttributes;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import static com.android.compatibility.common.util.PollingCheck.waitFor;
@@ -233,10 +231,13 @@ public class SplitAttributesCalculatorTest extends ActivityEmbeddingTestBase {
}
try (RotationSession rotationSession = new RotationSession()) {
- for (int rotation = ROTATION_90; rotation <= ROTATION_270; rotation++) {
+ final int initialRotation = activityA.getDisplay().getRotation();
+ for (int i = 1; i <= 3; i++) {
+ // Rotate the device by 90 degree clockwise.
+ final int rotation = (initialRotation + i) % 4;
rotationSession.set(rotation);
- verifier.waitAndAssertFunctionApplied("The calculator function mus be called for"
+ verifier.waitAndAssertFunctionApplied("The calculator function must be called for"
+ " rotation:" + rotation);
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
index 866b02813d6..c42a80b5730 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
@@ -44,6 +44,7 @@ import static android.server.wm.app.Components.TestActivity.TEST_ACTIVITY_ACTION
import static android.view.Display.DEFAULT_DISPLAY;
import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -172,13 +173,11 @@ public class AssistantStackTests extends ActivityManagerTestBase {
mWmState.assertFocusedRootTask("Assistant stack should be focused.",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
} else {
- final int testActivityWindowingMode =
- mWmState.getTaskDisplayArea(TEST_ACTIVITY).getWindowingMode();
mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
mWmState.assertFrontStack("TestActivity stack should be on top.",
- testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
- testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
}
// Now, tell it to finish itself and ensure that the assistant stack is brought back forward
@@ -215,12 +214,10 @@ public class AssistantStackTests extends ActivityManagerTestBase {
"TestActivity should be resumed");
mWmState.assertFocusedActivity("TestActivity should be focused", TEST_ACTIVITY);
- final int testActivityWindowingMode =
- mWmState.getTaskDisplayArea(TEST_ACTIVITY).getWindowingMode();
mWmState.assertFrontStack("TestActivity stack should be on top.",
- testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
- testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
}
@Test
@@ -344,8 +341,11 @@ public class AssistantStackTests extends ActivityManagerTestBase {
mWmState.assertFocusedRootTask("Expected assistant stack focused",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
final WindowManagerState amState = mWmState;
+ // If activity is hosted by created-by-organizer root task, the root task captured by
+ // WindowManagerState will have 0 child task. Otherwise, root task contains 1 child
+ // task.
assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
- hasSize(1));
+ hasSize(lessThanOrEqualTo(1)));
final int taskId = mWmState.getTaskByActivity(ASSISTANT_ACTIVITY)
.mTaskId;
@@ -376,8 +376,11 @@ public class AssistantStackTests extends ActivityManagerTestBase {
mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
mWmState.assertFocusedRootTask("Expected assistant stack focused",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
+ // If activity is hosted by created-by-organizer root task, the root task captured by
+ // WindowManagerState will have 0 child task. Otherwise, root task contains 1 child
+ // task.
assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
- hasSize(1));
+ hasSize(lessThanOrEqualTo(1)));
assertEquals(taskId,
mWmState.getTaskByActivity(ASSISTANT_ACTIVITY).mTaskId);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java b/tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java
index 9570fccab3f..104c07a1978 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java
@@ -152,6 +152,7 @@ public class BackGestureInvokedTest extends ActivityManagerTestBase {
launchActivity(componentName);
mWmState.waitForActivityState(componentName, STATE_RESUMED);
mWmState.assertVisibility(componentName, true);
+ mWmState.waitAndAssertImeWindowShownOnDisplay(DEFAULT_DISPLAY);
triggerBackEventByGesture(DEFAULT_DISPLAY);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatScaleTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatScaleTests.java
index 4ba6d4e4cd1..6ae297cbb50 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatScaleTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatScaleTests.java
@@ -73,9 +73,9 @@ public class CompatScaleTests extends ActivityManagerTestBase {
/**
* If application size is 1280, then Upscaling by 0.3 will make the surface 1280/0.3 = 4267.
* Some devices do not support this high resolution, so limiting Upscaling test case for
- * scaling >= 0.35.
+ * scaling >= 0.5.
*/
- public static float MAX_UPSCALING_TESTED = 0.35f;
+ public static float MAX_UPSCALING_TESTED = 0.5f;
@Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> data() {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayShapeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayShapeTests.java
index fd8f91e5b44..492745512a7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayShapeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayShapeTests.java
@@ -20,12 +20,11 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT;
import static android.view.RoundedCorner.POSITION_TOP_LEFT;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;
import android.graphics.Path;
@@ -50,13 +49,13 @@ import org.junit.Test;
@Presubmit
@android.server.wm.annotation.Group3
public class DisplayShapeTests extends WindowManagerTestBase {
- private static final String TAG = "DisplayShapeTests";
private Display mDisplay;
@Before
public void setUp() throws Exception {
mDisplay = mDm.getDisplay(DEFAULT_DISPLAY);
+ assumeNotNull(mDisplay);
}
@Test
@@ -76,25 +75,23 @@ public class DisplayShapeTests extends WindowManagerTestBase {
assumeTrue("Test does not apply for vendor image with API level lower than U",
PropertyUtil.isVendorApiLevelNewerThan(Build.VERSION_CODES.TIRAMISU));
- boolean hasRoundedCorners = false;
- RoundedCorner r;
+ boolean hasRoundedCorner = false;
for (int i = POSITION_TOP_LEFT; i <= POSITION_BOTTOM_LEFT; i++) {
- r = mDisplay.getRoundedCorner(POSITION_TOP_LEFT);
- if (r == null) {
- continue;
+ final RoundedCorner r = mDisplay.getRoundedCorner(i);
+ if (r != null && r.getRadius() > 0) {
+ hasRoundedCorner = true;
+ break;
}
- hasRoundedCorners = true;
- break;
}
- final Path path = mDisplay.getShape().getPath();
- final boolean isRect = path.isRect(null);
-
- // By default, if the config for display shape is not set, the returned shape will be
- // rectangular. The config must be set if the display has rounded corners.
- assertThat("The display has rounded corners but the returned path is a rectangular shape."
- + " Please set the config(config_mainDisplayShape) for display shape.",
- isRect, not(hasRoundedCorners));
+ if (hasRoundedCorner) {
+ // If the display shape is not configured, the returned path will be rectangular if the
+ // display is not round. The config must be set if the display is not round or
+ // rectangular.
+ assertFalse("The display has a rounded corner but the shape specifies a rectangle."
+ + " Please set the config (config_mainDisplayShape) for the display shape.",
+ mDisplay.getShape().getPath().isRect(null));
+ }
}
@Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java
index 3e2a292b4b3..f10fe84c432 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java
@@ -21,7 +21,6 @@ import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_NORMAL;
import static android.server.wm.app.Components.TEST_ACTIVITY;
import static android.server.wm.deskresources.Components.DESK_RESOURCES_ACTIVITY;
-import static android.view.Surface.ROTATION_270;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
@@ -31,6 +30,7 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Resources;
import android.platform.test.annotations.Presubmit;
+import android.view.Surface;
import org.junit.Test;
@@ -47,10 +47,10 @@ public class DockConfigChangeTests extends ActivityManagerTestBase {
// enabled.
assumeTrue(getConfigSkipRelaunchOnDock());
- // Set rotation to 270 first, since docking forces rotation to 270, causing an extra config
- // change.
+ // Set rotation to the same rotation as the device would be rotated to after docking. This
+ // prevents an extraneous config change from the device rotating when docked/undocked.
RotationSession rotationSession = createManagedRotationSession();
- rotationSession.set(ROTATION_270, /*waitDeviceRotation=*/ true);
+ rotateToDockRotation(rotationSession);
launchActivity(TEST_ACTIVITY);
waitAndAssertResumedActivity(TEST_ACTIVITY, "Activity must be resumed");
@@ -80,10 +80,10 @@ public class DockConfigChangeTests extends ActivityManagerTestBase {
// enabled.
assumeTrue(getConfigSkipRelaunchOnDock());
- // Set rotation to 270 first, since docking forces rotation to 270, causing an extra config
- // change.
+ // Set rotation to the same rotation as the device would be rotated to after docking. This
+ // prevents an extraneous config change from the device rotating when docked/undocked.
RotationSession rotationSession = createManagedRotationSession();
- rotationSession.set(ROTATION_270, /*waitDeviceRotation=*/ true);
+ rotateToDockRotation(rotationSession);
launchActivity(DESK_RESOURCES_ACTIVITY);
waitAndAssertResumedActivity(DESK_RESOURCES_ACTIVITY, "Activity must be resumed");
@@ -115,6 +115,43 @@ public class DockConfigChangeTests extends ActivityManagerTestBase {
"bool", "android"));
}
+ /**
+ * Rotates the device to the same rotation as it would rotate to when docked.
+ *
+ * Dock rotation is read from config_deskDockRotation.
+ */
+ void rotateToDockRotation(RotationSession rotationSession) {
+ int rotation = rotationDegreesToConst(mContext.getResources().getInteger(
+ Resources.getSystem().getIdentifier("config_deskDockRotation",
+ "integer", "android")));
+ if (rotation == -1) {
+ // -1 could come from the const itself, which means no rotation on dock, or from
+ // rotationDegreesToConst, which means we got an unexpected value from the resource.
+ return;
+ }
+ rotationSession.set(rotation);
+ }
+
+ /**
+ * Converts from a rotation in degrees to a {@link Surface.Rotation} constant.
+ *
+ * Returns -1 if a value that doesn't match a {@link Surface.Rotation} constant is provided.
+ */
+ private int rotationDegreesToConst(int rotationDegrees) {
+ switch (rotationDegrees) {
+ case 0:
+ return Surface.ROTATION_0;
+ case 90:
+ return Surface.ROTATION_90;
+ case 180:
+ return Surface.ROTATION_180;
+ case 270:
+ return Surface.ROTATION_270;
+ }
+ return -1;
+ }
+
+
private class DockTestSession implements AutoCloseable {
private void dock() {
runShellCommand("dumpsys DockObserver set state "
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java b/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
index ba78a0afb2f..40a11b146fd 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
@@ -51,6 +51,8 @@ import android.view.ViewGroup;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.UiAutomatorUtils;
+
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -220,7 +222,7 @@ public class DragDropTest extends WindowManagerTestBase {
View v = mActivity.findViewById(viewId);
View release = mActivity.findViewById(releaseViewId);
int [] releaseLoc = new int[2];
- release.getLocationOnScreen(releaseLoc);
+ release.getLocationInWindow(releaseLoc);
int action = DragEvent.ACTION_DRAG_ENDED;
mExpected.add(new LogEntry(v, action,
releaseLoc[0] + 6 / mInvCompatScale, releaseLoc[1] + 6 / mInvCompatScale,
@@ -334,6 +336,7 @@ public class DragDropTest extends WindowManagerTestBase {
@Before
public void setUp() throws InterruptedException {
assumeFalse(isWatchDevice());
+ UiAutomatorUtils.getUiDevice().waitForIdle();
mActivity = startActivityInWindowingMode(DragDropActivity.class, WINDOWING_MODE_FULLSCREEN);
mStartReceived = new CountDownLatch(1);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
index 713958d94a4..3911c16cf78 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
@@ -88,8 +88,6 @@ public class ForceRelayoutTestBase {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
- getWindow().setDecorFitsSystemWindows(false);
- getWindow().getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
View view = new View(this) {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
@@ -114,17 +112,21 @@ public class ForceRelayoutTestBase {
return WindowInsets.CONSUMED;
});
setContentView(view);
+
+ getWindow().setDecorFitsSystemWindows(false);
+ getWindow().getAttributes().layoutInDisplayCutoutMode =
+ LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
}
}
private static boolean remoteInsetsControllerControlsSystemBars() {
return InstrumentationRegistry.getInstrumentation().getTargetContext().getResources()
- .getBoolean(android.R.bool.config_remoteInsetsControllerControlsSystemBars);
+ .getBoolean(android.R.bool.config_remoteInsetsControllerControlsSystemBars);
}
private boolean isCar() {
PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
- .getPackageManager();
+ .getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
}
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 ed2d6100fee..83f04b89fce 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
@@ -49,7 +49,9 @@ import static org.junit.Assert.assertNotEquals;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.server.wm.CommandSession.ActivitySession;
@@ -313,8 +315,15 @@ public class StartActivityTests extends ActivityManagerTestBase {
if (useShellPermission) {
waitAndAssertResumedActivity(BROADCAST_RECEIVER_ACTIVITY,
"Activity should be started and resumed");
- mWmState.assertFrontStackActivityType("The activity type should be same as requested.",
- type);
+ if (type == ACTIVITY_TYPE_HOME && isAutomotive(mContext)
+ && hasSplitscreenMultitaskingFeature(mContext)) {
+ // For automotive devices with splitscreen multitasking, home activity might
+ // not be in front of the stack, hence, check for its visibility instead.
+ mWmState.assertHomeActivityVisible(/* visible= */ true);
+ } else {
+ mWmState.assertFrontStackActivityType(
+ "The activity type should be same as requested.", type);
+ }
mBroadcastActionTrigger.finishBroadcastReceiverActivity();
mWmState.waitAndAssertActivityRemoved(BROADCAST_RECEIVER_ACTIVITY);
} else {
@@ -323,6 +332,23 @@ public class StartActivityTests extends ActivityManagerTestBase {
}
/**
+ * Checks whether the device is automotive
+ */
+ private static boolean isAutomotive(Context context) {
+ PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
+ /**
+ * Checks whether the device has automotive splitscreen multitasking feature enabled
+ */
+ private static boolean hasSplitscreenMultitaskingFeature(Context context) {
+ PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(/* PackageManager.FEATURE_CAR_SPLITSCREEN_MULTITASKING */
+ "android.software.car.splitscreen_multitasking");
+ }
+
+ /**
* Assume there are 3 activities (A1, A2, B1) with default launch mode. The uid of B1 is
* different from A1 and A2. After A1 called {@link Activity#startActivities} to start B1 and
* A2, the result should be 3 tasks.
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
index 88e9f2c9522..8ed33a692f8 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
@@ -21,6 +21,7 @@ import static android.server.wm.CtsWindowInfoUtils.tapOnWindowCenter;
import static android.server.wm.CtsWindowInfoUtils.waitForWindowFocus;
import static android.server.wm.CtsWindowInfoUtils.waitForWindowInfo;
import static android.server.wm.CtsWindowInfoUtils.waitForWindowInfos;
+import static android.server.wm.CtsWindowInfoUtils.waitForWindowOnTop;
import static android.server.wm.CtsWindowInfoUtils.waitForWindowVisible;
import static android.server.wm.MockImeHelper.createManagedMockImeSession;
import static android.view.SurfaceControlViewHost.SurfacePackage;
@@ -180,6 +181,8 @@ public class SurfaceControlViewHostTests extends ActivityManagerTestBase impleme
mCtsTouchUtils = new CtsTouchUtils(mInstrumentation.getTargetContext());
mActivity = mActivityRule.launchActivity(null);
mInstrumentation.waitForIdleSync();
+ // Wait for device animation that shows above the activity to leave.
+ waitForWindowOnTop(mActivity.getWindow());
// This is necessary to call waitForWindowInfos
mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java
index 6e8f020f820..46bca49374d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java
@@ -158,7 +158,7 @@ public class TaskFragmentOrganizerTest extends TaskFragmentOrganizerTestBase {
mWmState.waitForActivityState(mLaunchingActivity, STATE_RESUMED);
- Task parentTask = mWmState.getRootTask(mOwnerActivity.getTaskId());
+ Task parentTask = mWmState.getTaskByActivity(mOwnerActivityName);
TaskFragment taskFragment = mWmState.getTaskFragmentByActivity(mLaunchingActivity);
// Assert window hierarchy must be as follows
@@ -186,8 +186,8 @@ public class TaskFragmentOrganizerTest extends TaskFragmentOrganizerTestBase {
assertEmptyTaskFragment(taskFragmentInfo, taskFragmentInfo.getFragmentToken());
mWmState.computeState(mOwnerActivityName);
- final int originalTaskFragCount = mWmState.getRootTask(mOwnerTaskId).getTaskFragments()
- .size();
+ final int originalTaskFragCount = mWmState.getTaskByActivity(mOwnerActivityName)
+ .getTaskFragments().size();
WindowContainerTransaction wct = new WindowContainerTransaction()
.deleteTaskFragment(taskFragToken);
@@ -200,7 +200,8 @@ public class TaskFragmentOrganizerTest extends TaskFragmentOrganizerTestBase {
taskFragToken);
mWmState.computeState(mOwnerActivityName);
- final int currTaskFragCount = mWmState.getRootTask(mOwnerTaskId).getTaskFragments().size();
+ final int currTaskFragCount = mWmState.getTaskByActivity(mOwnerActivityName)
+ .getTaskFragments().size();
assertWithMessage("TaskFragment with token " + taskFragToken + " must be"
+ " removed.").that(originalTaskFragCount - currTaskFragCount).isEqualTo(1);
}
@@ -219,8 +220,8 @@ public class TaskFragmentOrganizerTest extends TaskFragmentOrganizerTestBase {
assertNotEmptyTaskFragment(taskFragmentInfo, taskFragmentInfo.getFragmentToken());
mWmState.computeState(mOwnerActivityName);
- final int originalTaskFragCount = mWmState.getRootTask(mOwnerTaskId).getTaskFragments()
- .size();
+ final int originalTaskFragCount = mWmState.getTaskByActivity(mOwnerActivityName)
+ .getTaskFragments().size();
WindowContainerTransaction wct = new WindowContainerTransaction()
.deleteTaskFragment(taskFragToken);
@@ -233,7 +234,8 @@ public class TaskFragmentOrganizerTest extends TaskFragmentOrganizerTestBase {
taskFragToken);
mWmState.computeState(mOwnerActivityName);
- final int currTaskFragCount = mWmState.getRootTask(mOwnerTaskId).getTaskFragments().size();
+ final int currTaskFragCount = mWmState.getTaskByActivity(mOwnerActivityName)
+ .getTaskFragments().size();
assertWithMessage("TaskFragment with token " + taskFragToken + " must be"
+ " removed.").that(originalTaskFragCount - currTaskFragCount).isEqualTo(1);
}
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 4637ac7efde..d44b8e5c78a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
@@ -179,17 +179,18 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
*/
@Test
public void testUntrustedModeTaskFragment_setRelativeBoundsOutsideOfParentBounds() {
- final Task parentTask = mWmState.getRootTask(mOwnerTaskId);
+ final Task parentTask = mWmState.getTaskByActivity(mOwnerActivityName);
final Rect parentBounds = new Rect(parentTask.getBounds());
// Create a TaskFragment with activity embedded in untrusted mode.
final TaskFragmentInfo info = createTaskFragment(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
// Try to set relative bounds that is larger than its parent bounds.
mTaskFragmentOrganizer.resetLatch();
- final Rect taskFragBounds = new Rect(parentBounds);
- taskFragBounds.right++;
+ final Rect taskFragRelativeBounds = new Rect(parentBounds);
+ taskFragRelativeBounds.offsetTo(0, 0);
+ taskFragRelativeBounds.right++;
final WindowContainerTransaction wct = new WindowContainerTransaction()
- .setRelativeBounds(info.getToken(), taskFragBounds)
+ .setRelativeBounds(info.getToken(), taskFragRelativeBounds)
.setWindowingMode(info.getToken(), WINDOWING_MODE_MULTI_WINDOW);
// It is allowed to set TaskFragment bounds to outside of its parent bounds.
@@ -217,7 +218,7 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
*/
@Test
public void testUntrustedModeTaskFragment_startActivityInTaskFragmentOutsideOfParentBounds() {
- final Task parentTask = mWmState.getRootTask(mOwnerTaskId);
+ final Task parentTask = mWmState.getTaskByActivity(mOwnerActivityName);
final Rect parentBounds = new Rect(parentTask.getBounds());
final IBinder errorCallbackToken = new Binder();
final WindowContainerTransaction wct = new WindowContainerTransaction()
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
index e45b6ebfd29..ba9eb8ec631 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
@@ -46,6 +46,7 @@ import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.content.ComponentName;
+import android.content.pm.PackageManager;
import android.platform.test.annotations.Presubmit;
import org.junit.Before;
@@ -113,6 +114,7 @@ public class TransitionSelectionTests extends ActivityManagerTestBase {
// Test task open/close under normal timing
@Test
public void testOpenTask_NeitherWallpaper() {
+ assumeFalse(isAutomotive() && hasSplitscreenMultitaskingFeature());
testOpenTask(false /*bottomWallpaper*/, false /*topWallpaper*/, true /* topResizable */,
false /*slowStop*/, TRANSIT_TASK_OPEN, WINDOWING_MODE_FULLSCREEN);
}
@@ -126,6 +128,7 @@ public class TransitionSelectionTests extends ActivityManagerTestBase {
@Test
public void testCloseTask_NeitherWallpaper() {
+ assumeFalse(isAutomotive() && hasSplitscreenMultitaskingFeature());
testCloseTask(false /*bottomWallpaper*/, false /*topWallpaper*/, true /* topResizable */,
false /*slowStop*/, TRANSIT_TASK_CLOSE, WINDOWING_MODE_FULLSCREEN);
}
@@ -198,12 +201,14 @@ public class TransitionSelectionTests extends ActivityManagerTestBase {
// before AM receives its activitiyStopped
@Test
public void testCloseTask_NeitherWallpaper_SlowStop() {
+ assumeFalse(isAutomotive() && hasSplitscreenMultitaskingFeature());
testCloseTask(false /*bottomWallpaper*/, false /*topWallpaper*/, true /* topResizable */,
true /*slowStop*/, TRANSIT_TASK_CLOSE, WINDOWING_MODE_FULLSCREEN);
}
@Test
public void testCloseTask_BottomWallpaper_TopNonResizable_SlowStop() {
+ assumeFalse(isAutomotive() && hasSplitscreenMultitaskingFeature());
testCloseTask(true /*bottomWallpaper*/, false /*topWallpaper*/, false /* topResizable */,
true /*slowStop*/, TRANSIT_WALLPAPER_OPEN, WINDOWING_MODE_FULLSCREEN);
}
@@ -366,4 +371,21 @@ public class TransitionSelectionTests extends ActivityManagerTestBase {
assertEquals("Picked wrong transition", expectedTransit,
mWmState.getDefaultDisplayLastTransition());
}
+
+ /**
+ * Checks whether the device is automotive
+ */
+ private boolean isAutomotive() {
+ PackageManager pm = mContext.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
+ /**
+ * Checks whether the device has automotive splitscreen multitasking feature enabled
+ */
+ private boolean hasSplitscreenMultitaskingFeature() {
+ PackageManager pm = mContext.getPackageManager();
+ return pm.hasSystemFeature(/* PackageManager.FEATURE_CAR_SPLITSCREEN_MULTITASKING */
+ "android.software.car.splitscreen_multitasking");
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
index 761ec07fc51..653ee1d4647 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
@@ -68,6 +68,7 @@ import androidx.test.rule.ActivityTestRule;
import com.android.compatibility.common.util.CtsTouchUtils;
import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.UiAutomatorUtils;
import org.junit.Before;
import org.junit.Test;
@@ -118,6 +119,9 @@ public class WindowInputTests {
mActivity = mActivityRule.launchActivity(null);
mInputManager = mActivity.getSystemService(InputManager.class);
mInstrumentation.waitForIdleSync();
+ // TODO(b/295916860) - Replace this 'uidevice' workaround with an
+ // WindowInfosListener-based solution
+ UiAutomatorUtils.getUiDevice().waitForIdle();
mClickCount = 0;
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java
index 8d49372871c..9e6d82f7aaa 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsLayoutTests.java
@@ -69,13 +69,12 @@ public class WindowInsetsLayoutTests extends WindowManagerTestBase {
activity.assertMatchesWindowBounds();
});
- testSetFitInsetsTypesInner(Type.statusBars(), activity, mainWindowRoot);
- testSetFitInsetsTypesInner(Type.navigationBars(), activity, mainWindowRoot);
- testSetFitInsetsTypesInner(Type.systemBars(), activity, mainWindowRoot);
+ testSetFitInsetsTypesInner(Type.statusBars(), activity);
+ testSetFitInsetsTypesInner(Type.navigationBars(), activity);
+ testSetFitInsetsTypesInner(Type.systemBars(), activity);
}
- private void testSetFitInsetsTypesInner(
- int types, TestActivity activity, View mainWindowRoot) {
+ private void testSetFitInsetsTypesInner(int types, TestActivity activity) {
getInstrumentation().runOnMainSync(() -> {
activity.addChildWindow(types, Side.all(), false);
});
@@ -85,16 +84,9 @@ public class WindowInsetsLayoutTests extends WindowManagerTestBase {
PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot.getWidth() > 0);
getInstrumentation().runOnMainSync(() -> {
- final WindowInsets windowInsets = mainWindowRoot.getRootWindowInsets();
+ final WindowInsets windowInsets = childWindowRoot.getRootWindowInsets();
final Insets insets = windowInsets.getInsets(types);
- final int[] locationOnScreen = new int[2];
- childWindowRoot.getLocationOnScreen(locationOnScreen);
- assertEquals(insets.left, locationOnScreen[0]);
- assertEquals(insets.top, locationOnScreen[1]);
- assertEquals(insets.right,
- mainWindowRoot.getWidth() - locationOnScreen[0] - childWindowRoot.getWidth());
- assertEquals(insets.bottom,
- mainWindowRoot.getHeight()- locationOnScreen[1] - childWindowRoot.getHeight());
+ assertEquals(Insets.NONE, insets);
activity.removeChildWindow();
});
}
@@ -113,14 +105,13 @@ public class WindowInsetsLayoutTests extends WindowManagerTestBase {
activity.assertMatchesWindowBounds();
});
- testSetFitInsetsSidesInner(Side.LEFT, activity, mainWindowRoot);
- testSetFitInsetsSidesInner(Side.TOP, activity, mainWindowRoot);
- testSetFitInsetsSidesInner(Side.RIGHT, activity, mainWindowRoot);
- testSetFitInsetsSidesInner(Side.BOTTOM, activity, mainWindowRoot);
+ testSetFitInsetsSidesInner(Side.LEFT, activity);
+ testSetFitInsetsSidesInner(Side.TOP, activity);
+ testSetFitInsetsSidesInner(Side.RIGHT, activity);
+ testSetFitInsetsSidesInner(Side.BOTTOM, activity);
}
- private void testSetFitInsetsSidesInner(
- int sides, TestActivity activity, View mainWindowRoot) {
+ private void testSetFitInsetsSidesInner(int sides, TestActivity activity) {
final int types = Type.systemBars();
getInstrumentation().runOnMainSync(() -> {
activity.addChildWindow(types, sides, false);
@@ -131,16 +122,20 @@ public class WindowInsetsLayoutTests extends WindowManagerTestBase {
PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot.getWidth() > 0);
getInstrumentation().runOnMainSync(() -> {
- final WindowInsets windowInsets = mainWindowRoot.getRootWindowInsets();
+ final WindowInsets windowInsets = childWindowRoot.getRootWindowInsets();
final Insets insets = windowInsets.getInsets(types);
- final int[] locationOnScreen = new int[2];
- childWindowRoot.getLocationOnScreen(locationOnScreen);
- assertEquals((sides & Side.LEFT) != 0 ? insets.left : 0, locationOnScreen[0]);
- assertEquals((sides & Side.TOP) != 0 ? insets.top : 0, locationOnScreen[1]);
- assertEquals((sides & Side.RIGHT) != 0 ? insets.right : 0,
- mainWindowRoot.getWidth() - locationOnScreen[0] - childWindowRoot.getWidth());
- assertEquals((sides & Side.BOTTOM) != 0 ? insets.bottom : 0,
- mainWindowRoot.getHeight()- locationOnScreen[1] - childWindowRoot.getHeight());
+ if ((sides & Side.LEFT) != 0) {
+ assertEquals(0, insets.left);
+ }
+ if ((sides & Side.TOP) != 0) {
+ assertEquals(0, insets.top);
+ }
+ if ((sides & Side.RIGHT) != 0) {
+ assertEquals(0, insets.right);
+ }
+ if ((sides & Side.BOTTOM) != 0) {
+ assertEquals(0, insets.bottom);
+ }
activity.removeChildWindow();
});
}
@@ -203,6 +198,8 @@ public class WindowInsetsLayoutTests extends WindowManagerTestBase {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ final View view = new View(this);
+ setContentView(view);
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
getWindow().setAttributes(lp);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java
index 38c5a0f0c7b..60a8017a9f4 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityStarterTests.java
@@ -41,6 +41,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
+import static org.junit.Assume.assumeFalse;
import android.app.Activity;
import android.content.ComponentName;
@@ -152,6 +153,8 @@ public class ActivityStarterTests extends ActivityLifecycleClientTestBase {
*/
@Test
public void testLaunchNoHistoryActivityShowWhenLocked() {
+ // Allow TV devices to skip this test.
+ assumeFalse(isLeanBack());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.sleepDevice();
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index ee4270fce6b..f133224fc1e 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -870,8 +870,8 @@ public class WindowManagerState {
}
public int getRootTaskIdByActivity(ComponentName activityName) {
- final Task task = getTaskByActivity(activityName);
- return (task == null) ? INVALID_TASK_ID : task.mRootTaskId;
+ final Task rootTask = getRootTaskByActivity(activityName);
+ return (rootTask == null) ? INVALID_TASK_ID : rootTask.mTaskId;
}
public Task getTaskByActivity(ComponentName activityName) {
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodInfoTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodInfoTest.java
index 026c0756f8e..428c555d464 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodInfoTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodInfoTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
@@ -48,6 +49,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.FeatureUtil;
import com.android.compatibility.common.util.PropertyUtil;
import org.junit.Before;
@@ -248,6 +250,8 @@ public class InputMethodInfoTest {
@Test
public void testAtLeastOneEncryptionAwareInputMethodIsAvailable() {
+ assumeFalse(FeatureUtil.isWatch());
+
if (!mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_INPUT_METHODS)) {
return;
diff --git a/tests/media/AndroidTest.xml b/tests/media/AndroidTest.xml
index b82d166606a..afb4861c438 100644
--- a/tests/media/AndroidTest.xml
+++ b/tests/media/AndroidTest.xml
@@ -35,7 +35,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-3.4" />
+ <option name="media-folder-name" value="CtsMediaV2TestCases-3.5" />
<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 5829ad2374c..e3643d73789 100644
--- a/tests/media/DynamicConfig.xml
+++ b/tests/media/DynamicConfig.xml
@@ -1,5 +1,5 @@
<dynamicConfig>
<entry key="media_files_url">
- <value>https://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.4.zip</value>
+ <value>https://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.5.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/media/README.md b/tests/media/README.md
index d726b1f95c4..5601ad3d379 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://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.4.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://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.5.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/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java
index 80760b11385..828b6db8f39 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java
@@ -94,8 +94,18 @@ public class CodecDecoderTestBase extends CodecTestBase {
if (mIsVideo) {
ArrayList<MediaFormat> formatList = new ArrayList<>();
formatList.add(format);
- boolean selectHBD = doesAnyFormatHaveHDRProfile(mMediaType, formatList)
- || srcFile.contains("10bit");
+ boolean selectHBD = doesAnyFormatHaveHDRProfile(mMediaType, formatList);
+ if (!selectHBD && srcFile.contains("10bit")) {
+ selectHBD = true;
+ if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+ // In some cases, webm extractor may not signal profile for 10-bit VP9
+ // clips. In such cases, set profile to a 10-bit compatible profile.
+ // TODO (b/295804596) Remove the following once webm extractor signals
+ // profile correctly for all 10-bit clips
+ int[] profileArray = CodecTestBase.PROFILE_HDR_MAP.get(mMediaType);
+ format.setInteger(MediaFormat.KEY_PROFILE, profileArray[0]);
+ }
+ }
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
getColorFormat(mCodecName, mMediaType, mSurface != null, selectHBD));
if (selectHBD && (format.getInteger(MediaFormat.KEY_COLOR_FORMAT)
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
index 2b1f007fde3..dc17b8d99f4 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
@@ -139,8 +139,6 @@ public abstract class CodecTestBase {
"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";
public 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";
- public static final HashMap<Integer, String> HDR_DYNAMIC_INFO = new HashMap<>();
- public static final HashMap<Integer, String> HDR_DYNAMIC_INCORRECT_INFO = new HashMap<>();
public static final String CODEC_PREFIX_KEY = "codec-prefix";
public static final String MEDIA_TYPE_PREFIX_KEY = "media-type-prefix";
public static final String MEDIA_TYPE_SEL_KEY = "media-type-sel";
@@ -228,6 +226,48 @@ public abstract class CodecTestBase {
public static final int MAX_DISPLAY_HEIGHT_LAND =
Math.min(MAX_DISPLAY_WIDTH_CURRENT, MAX_DISPLAY_HEIGHT_CURRENT);
+ public static final String HDR10_INFO_SCENE_A =
+ "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";
+ public static final String HDR10_INFO_SCENE_B =
+ "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";
+ public static final String HDR10_INFO_SCENE_C =
+ "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";
+ public static final String HDR10_INFO_SCENE_D =
+ "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";
+
+ public static final String HDR10_INCORRECT_INFO_SCENE_A =
+ "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";
+ public static final String HDR10_INCORRECT_INFO_SCENE_B =
+ "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";
+ public static final String HDR10_INCORRECT_INFO_SCENE_C =
+ "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";
+ public static final String HDR10_INCORRECT_INFO_SCENE_D =
+ "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";
+
public static String mediaTypeSelKeys;
public static String codecPrefix;
public static String mediaTypePrefix;
@@ -396,40 +436,6 @@ public abstract class CodecTestBase {
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) {
@@ -998,6 +1004,20 @@ public abstract class CodecTestBase {
return Arrays.copyOfRange(tempArray, 0, i);
}
+ public static String byteArrayToHexString(byte[] bytes) {
+ final char[] hexArray =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ char[] hexChars = new char[bytes.length * 3];
+ int v;
+ for (int j = 0; j < bytes.length; j++) {
+ v = bytes[j] & 0xFF;
+ hexChars[j * 3] = hexArray[v >>> 4];
+ hexChars[j * 3 + 1] = hexArray[v & 0x0F];
+ hexChars[j * 3 + 2] = ' ';
+ }
+ return new String(hexChars);
+ }
+
protected abstract void enqueueInput(int bufferIndex) throws IOException;
protected abstract void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info);
@@ -1295,19 +1315,17 @@ public abstract class CodecTestBase {
}
}
- protected void validateHDRInfo(MediaFormat fmt, String hdrInfoKey, ByteBuffer hdrInfoRef) {
- ByteBuffer hdrInfo = fmt.getByteBuffer(hdrInfoKey, null);
- assertNotNull("error! no " + hdrInfoKey + " present in format : " + fmt + "\n "
- + mTestConfig + mTestEnv, hdrInfo);
- if (!hdrInfoRef.equals(hdrInfo)) {
+ protected void validateHDRInfo(String hdrInfoKey, ByteBuffer hdrInfoRef, ByteBuffer hdrInfoTest,
+ Long framePts) {
+ if (!hdrInfoRef.equals(hdrInfoTest)) {
StringBuilder msg = new StringBuilder(
"################### Error Details #####################\n");
byte[] ref = new byte[hdrInfoRef.capacity()];
hdrInfoRef.get(ref);
hdrInfoRef.rewind();
- byte[] test = new byte[hdrInfo.capacity()];
- hdrInfo.get(test);
- hdrInfo.rewind();
+ byte[] test = new byte[hdrInfoTest.capacity()];
+ hdrInfoTest.get(test);
+ hdrInfoTest.rewind();
msg.append("ref info :- \n");
for (byte b : ref) {
msg.append(String.format("%2x ", b));
@@ -1316,11 +1334,19 @@ public abstract class CodecTestBase {
for (byte b : test) {
msg.append(String.format("%2x ", b));
}
- fail("error! mismatch seen between ref and test info of " + hdrInfoKey + "\n"
- + mTestConfig + mTestEnv + msg);
+ fail("Frame pts " + framePts + ": error! mismatch seen between ref and test info of "
+ + hdrInfoKey + "\n" + mTestConfig + mTestEnv + msg);
}
}
+ protected void validateHDRInfo(MediaFormat fmt, String hdrInfoKey, ByteBuffer hdrInfoRef,
+ Long framePts) {
+ ByteBuffer hdrInfo = fmt.getByteBuffer(hdrInfoKey, null);
+ assertNotNull("error! no " + hdrInfoKey + " present in format : " + fmt + "\n "
+ + mTestConfig + mTestEnv, hdrInfo);
+ validateHDRInfo(hdrInfoKey, hdrInfoRef, hdrInfo, framePts);
+ }
+
protected void setUpSurface(CodecTestActivity activity) throws InterruptedException {
activity.waitTillSurfaceIsCreated();
mSurface = activity.getSurface();
diff --git a/tests/media/common/src/android/mediav2/common/cts/HDRDecoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/HDRDecoderTestBase.java
index c158b240453..746ab862ba2 100644
--- a/tests/media/common/src/android/mediav2/common/cts/HDRDecoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/HDRDecoderTestBase.java
@@ -41,21 +41,38 @@ public class HDRDecoderTestBase extends CodecDecoderTestBase {
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;
+ private Map<Long, String> mHdrDynamicInfoRef;
+ private Map<Long, String> mHdrDynamicInfoStream;
+ private Map<Long, String> mHdrDynamicInfoContainer;
+ private final ArrayList<Long> mTotalMetadataQueued = new ArrayList<>();
public HDRDecoderTestBase(String decoder, String mediaType, String testFile,
- String allTestParams) {
+ String allTestParams) {
super(decoder, mediaType, testFile, allTestParams);
}
+ private String getMetadataForPts(Map<Long, String> dynamicInfoList, Long pts) {
+ final int sttsToleranceUs = 1000;
+ if (dynamicInfoList.containsKey(pts)) return dynamicInfoList.get(pts);
+ for (Map.Entry<Long, String> entry : dynamicInfoList.entrySet()) {
+ Long keyPts = entry.getKey();
+ if (Math.abs(keyPts - pts) < sttsToleranceUs) return entry.getValue();
+ }
+ return null;
+ }
+
+ public void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
+ mTotalMetadataQueued.clear();
+ super.resetContext(isAsync, signalEOSWithLastFrame);
+ }
+
protected void enqueueInput(int bufferIndex) {
- if (mHdrDynamicInfoContainer != null && mHdrDynamicInfoContainer.containsKey(mInputCount)
- && mExtractor.getSampleSize() != -1) {
- insertHdrDynamicInfo(
- loadByteArrayFromString(mHdrDynamicInfoContainer.get(mInputCount)));
+ if (mHdrDynamicInfoContainer != null && mExtractor.getSampleSize() != -1) {
+ String info = getMetadataForPts(mHdrDynamicInfoContainer, mExtractor.getSampleTime());
+ if (info != null) {
+ insertHdrDynamicInfo(loadByteArrayFromString(info));
+ mTotalMetadataQueued.add(mExtractor.getSampleTime());
+ }
}
super.enqueueInput(bufferIndex);
}
@@ -63,17 +80,18 @@ public class HDRDecoderTestBase extends CodecDecoderTestBase {
protected 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);
+ String hdr10Info = getMetadataForPts(mHdrDynamicInfoRef, info.presentationTimeUs);
+ if (hdr10Info != null) {
+ validateHDRInfo(format, MediaFormat.KEY_HDR10_PLUS_INFO,
+ ByteBuffer.wrap(loadByteArrayFromString(hdr10Info)),
+ info.presentationTimeUs);
}
- validateHDRInfo(format, MediaFormat.KEY_HDR10_PLUS_INFO,
- ByteBuffer.wrap(loadByteArrayFromString(mHdrDynamicInfoCurrent)));
}
super.dequeueOutput(bufferIndex, info);
}
public void validateHDRInfo(String hdrStaticInfoStream, String hdrStaticInfoContainer,
- Map<Integer, String> hdrDynamicInfoStream, Map<Integer, String> hdrDynamicInfoContainer)
+ Map<Long, String> hdrDynamicInfoStream, Map<Long, String> hdrDynamicInfoContainer)
throws IOException, InterruptedException {
mHdrStaticInfoStream = hdrStaticInfoStream != null
? ByteBuffer.wrap(loadByteArrayFromString(hdrStaticInfoStream)) : null;
@@ -105,7 +123,7 @@ public class HDRDecoderTestBase extends CodecDecoderTestBase {
assertEquals("Container hdr10+ info size and elementary stream SEI hdr10+ info"
+ " size are unequal \n" + mTestConfig + mTestEnv, mHdrDynamicInfoStream.size(),
mHdrDynamicInfoContainer.size());
- for (Map.Entry<Integer, String> element : mHdrDynamicInfoStream.entrySet()) {
+ for (Map.Entry<Long, String> element : mHdrDynamicInfoStream.entrySet()) {
assertTrue("Container hdr10+ info and elementary stream SEI hdr10+ info "
+ "frame positions are not in sync \n" + mTestConfig + mTestEnv,
mHdrDynamicInfoContainer.containsKey(element.getKey()));
@@ -134,10 +152,14 @@ public class HDRDecoderTestBase extends CodecDecoderTestBase {
waitForAllOutputs();
if (mHdrStaticInfoRef != null) {
validateHDRInfo(mCodec.getOutputFormat(), MediaFormat.KEY_HDR_STATIC_INFO,
- mHdrStaticInfoRef);
+ mHdrStaticInfoRef, -1L);
}
mCodec.stop();
mCodec.release();
mExtractor.release();
+ if (mHdrDynamicInfoContainer != null) {
+ assertEquals("Test did not queue metadata of all frames",
+ mHdrDynamicInfoContainer.size(), mTotalMetadataQueued.size());
+ }
}
}
diff --git a/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
index e6fa7c00521..34627bc232a 100644
--- a/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
@@ -16,6 +16,7 @@
package android.mediav2.common.cts;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -25,11 +26,11 @@ import android.media.MediaFormat;
import org.junit.Assume;
-import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
/**
@@ -39,21 +40,61 @@ public class HDREncoderTestBase extends CodecEncoderTestBase {
private static final String LOG_TAG = HDREncoderTestBase.class.getSimpleName();
private ByteBuffer mHdrStaticInfo;
- private Map<Integer, String> mHdrDynamicInfo;
+ private Map<Long, String> mHdrDynamicInfo;
+ private ArrayList<Long> mTotalMetadataQueued;
+ private Map<Long, String> mHdrDynamicInfoReceived;
public HDREncoderTestBase(String encoderName, String mediaType,
EncoderConfigParams encCfgParams, String allTestParams) {
super(encoderName, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
}
+ private String getMetadataForPts(Map<Long, String> dynamicInfoList, Long pts) {
+ final int roundToleranceUs = 10;
+ if (dynamicInfoList.containsKey(pts)) return dynamicInfoList.get(pts);
+ for (Map.Entry<Long, String> entry : dynamicInfoList.entrySet()) {
+ Long keyPts = entry.getKey();
+ if (Math.abs(keyPts - pts) < roundToleranceUs) return entry.getValue();
+ }
+ return null;
+ }
+
+ public void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
+ if (mTotalMetadataQueued != null) mTotalMetadataQueued.clear();
+ if (mHdrDynamicInfoReceived != null) mHdrDynamicInfoReceived.clear();
+ super.resetContext(isAsync, signalEOSWithLastFrame);
+ }
+
protected void enqueueInput(int bufferIndex) {
- if (mHdrDynamicInfo != null && mHdrDynamicInfo.containsKey(mInputCount)) {
- insertHdrDynamicInfo(loadByteArrayFromString(mHdrDynamicInfo.get(mInputCount)));
+ if (mHdrDynamicInfo != null) {
+ long pts = mInputOffsetPts + mInputCount * 1000000L / mActiveEncCfg.mFrameRate;
+ String info = getMetadataForPts(mHdrDynamicInfo, pts);
+ if (info != null) {
+ insertHdrDynamicInfo(loadByteArrayFromString(info));
+ mTotalMetadataQueued.add(pts);
+ }
}
super.enqueueInput(bufferIndex);
}
- public void validateHDRInfo(String hdrStaticInfo, Map<Integer, String> hdrDynamicInfo)
+ protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+ if (mHdrDynamicInfo != null) {
+ if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+ MediaFormat outFormat = mCodec.getOutputFormat(bufferIndex);
+ ByteBuffer metadataBuff =
+ outFormat.getByteBuffer(MediaFormat.KEY_HDR10_PLUS_INFO, null);
+ if (metadataBuff != null) {
+ byte[] bytes = new byte[metadataBuff.remaining()];
+ metadataBuff.get(bytes);
+ mHdrDynamicInfoReceived.put(info.presentationTimeUs,
+ byteArrayToHexString(bytes));
+ }
+ }
+ }
+ super.dequeueOutput(bufferIndex, info);
+ }
+
+ public void validateHDRInfo(String hdrStaticInfo, Map<Long, String> hdrDynamicInfo)
throws IOException, InterruptedException {
mHdrStaticInfo = hdrStaticInfo != null
? ByteBuffer.wrap(loadByteArrayFromString(hdrStaticInfo)) : null;
@@ -74,10 +115,12 @@ public class HDREncoderTestBase extends CodecEncoderTestBase {
int frameLimit = 4;
if (mHdrDynamicInfo != null) {
- Integer lastHdr10PlusFrame =
- Collections.max(HDR_DYNAMIC_INFO.entrySet(), Map.Entry.comparingByKey())
+ mTotalMetadataQueued = new ArrayList<>();
+ mHdrDynamicInfoReceived = new HashMap();
+ Long lastHdr10PlusFramePts =
+ Collections.max(mHdrDynamicInfo.entrySet(), Map.Entry.comparingByKey())
.getKey();
- frameLimit = lastHdr10PlusFrame + 10;
+ frameLimit = (int) (lastHdr10PlusFramePts * mActiveEncCfg.mFrameRate / 1000000L) + 10;
}
int maxNumFrames = mInputData.length
/ (mActiveRawRes.mWidth * mActiveRawRes.mHeight * mActiveRawRes.mBytesPerSample);
@@ -98,12 +141,29 @@ public class HDREncoderTestBase extends CodecEncoderTestBase {
mCodec.stop();
mCodec.release();
+
+ // verify if the out fmt contains HDR Static info as expected
if (mHdrStaticInfo != null) {
- // verify if the out fmt contains HDR Static info as expected
- validateHDRInfo(fmt, MediaFormat.KEY_HDR_STATIC_INFO, mHdrStaticInfo);
+ validateHDRInfo(fmt, MediaFormat.KEY_HDR_STATIC_INFO, mHdrStaticInfo, -1L);
+ }
+
+ // verify if the out fmt contains HDR Dynamic info as expected
+ if (mHdrDynamicInfo != null) {
+ assertEquals("Test did not queue metadata of all frames", mHdrDynamicInfo.size(),
+ mTotalMetadataQueued.size());
+ for (Map.Entry<Long, String> entry : mHdrDynamicInfo.entrySet()) {
+ Long pts = entry.getKey();
+ assertTrue("At timestamp : " + pts + "application queued hdr10+ metadata,"
+ + " during dequeue application did not receive it in output format",
+ mHdrDynamicInfoReceived.containsKey(pts));
+ ByteBuffer hdrInfoRef = ByteBuffer.wrap(loadByteArrayFromString(entry.getValue()));
+ ByteBuffer hdrInfoTest =
+ ByteBuffer.wrap(loadByteArrayFromString(mHdrDynamicInfoReceived.get(pts)));
+ validateHDRInfo(MediaFormat.KEY_HDR10_PLUS_INFO, hdrInfoRef, hdrInfoTest, pts);
+ }
}
- // verify if the muxed file contains HDR Dynamic info as expected
+ // 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 + " but not decoding it \n"
@@ -111,10 +171,10 @@ public class HDREncoderTestBase extends CodecEncoderTestBase {
HDRDecoderTestBase decoderTest =
new HDRDecoderTestBase(decoder, mMediaType, mMuxedOutputFile, mAllTestParams);
- decoderTest.validateHDRInfo(hdrStaticInfo, hdrStaticInfo, mHdrDynamicInfo, mHdrDynamicInfo);
+ decoderTest.validateHDRInfo(hdrStaticInfo, hdrStaticInfo, mHdrDynamicInfo,
+ mHdrDynamicInfo);
if (HDR_INFO_IN_BITSTREAM_CODECS.contains(mMediaType)) {
decoderTest.validateHDRInfo(hdrStaticInfo, null, mHdrDynamicInfo, null);
}
- new File(mMuxedOutputFile).delete();
}
}
diff --git a/tests/media/copy_media.sh b/tests/media/copy_media.sh
index ddde84a1740..b0850ad64d1 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-3.4
+resLabel=CtsMediaV2TestCases-3.5
srcDir="/tmp/$resLabel"
tgtDir="/sdcard/test"
usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 6834b0c75e8..9dab4fc7bb7 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -175,8 +175,9 @@ public class CodecDecoderValidationTest extends CodecDecoderTestBase {
// video test vectors covering cdd requirements
// @CddTest(requirement="5.3.1/C-1-1")
- {MEDIA_TYPE_MPEG2, new String[]{"bbb_1920x1080_mpeg2_main_high.mp4"}, null, -1.0f,
- -1L, -1, -1, 1920, 1080, MediaUtils.isTv() ? CODEC_ANY : CODEC_OPTIONAL},
+ {MEDIA_TYPE_MPEG2, new String[]{"bbb_1920x1080_30fps_mpeg2_main_high.mp4"}, null,
+ -1.0f, -1L, -1, -1, 1920, 1080,
+ MediaUtils.isTv() ? CODEC_ANY : CODEC_OPTIONAL},
// @CddTest(requirement="5.3.2/C-1-1")
{MEDIA_TYPE_H263, new String[]{"bbb_352x288_384kbps_30fps_h263_baseline_l3.mp4"},
diff --git a/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java b/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
index 68cb56672a4..8e4100ec4c4 100644
--- a/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderHDRInfoTest.java
@@ -32,6 +32,7 @@ import org.junit.runners.Parameterized;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -51,14 +52,47 @@ import java.util.Map;
public class DecoderHDRInfoTest extends HDRDecoderTestBase {
private static final String LOG_TAG = DecoderHDRInfoTest.class.getSimpleName();
private static final String MEDIA_DIR = WorkDir.getMediaDirString();
+ public static final HashMap<Long, String> HDR_DYNAMIC_INFO_HEVC = new HashMap<>();
+ public static final HashMap<Long, String> HDR_DYNAMIC_INCORRECT_INFO_HEVC = new HashMap<>();
+ public static final HashMap<Long, String> HDR_DYNAMIC_INFO_AV1 = new HashMap<>();
+ public static final HashMap<Long, String> HDR_DYNAMIC_INCORRECT_INFO_AV1 = new HashMap<>();
+ public static final HashMap<Long, String> HDR_DYNAMIC_INFO_VP9 = new HashMap<>();
+
private final String mHDRStaticInfoStream;
private final String mHDRStaticInfoContainer;
- private final Map<Integer, String> mHDRDynamicInfoStream;
- private final Map<Integer, String> mHDRDynamicInfoContainer;
+ private final Map<Long, String> mHDRDynamicInfoStream;
+ private final Map<Long, String> mHDRDynamicInfoContainer;
+
+ static {
+ HDR_DYNAMIC_INFO_HEVC.put(0L, HDR10_INFO_SCENE_A);
+ HDR_DYNAMIC_INFO_HEVC.put(133333L, HDR10_INFO_SCENE_B);
+ HDR_DYNAMIC_INFO_HEVC.put(400000L, HDR10_INFO_SCENE_C);
+ HDR_DYNAMIC_INFO_HEVC.put(733333L, HDR10_INFO_SCENE_D);
+
+ HDR_DYNAMIC_INCORRECT_INFO_HEVC.put(0L, HDR10_INCORRECT_INFO_SCENE_A);
+ HDR_DYNAMIC_INCORRECT_INFO_HEVC.put(133333L, HDR10_INCORRECT_INFO_SCENE_B);
+ HDR_DYNAMIC_INCORRECT_INFO_HEVC.put(400000L, HDR10_INCORRECT_INFO_SCENE_C);
+ HDR_DYNAMIC_INCORRECT_INFO_HEVC.put(733333L, HDR10_INCORRECT_INFO_SCENE_D);
+
+ HDR_DYNAMIC_INFO_AV1.put(0L, HDR10_INFO_SCENE_A);
+ HDR_DYNAMIC_INFO_AV1.put(133000L, HDR10_INFO_SCENE_B);
+ HDR_DYNAMIC_INFO_AV1.put(400000L, HDR10_INFO_SCENE_C);
+ HDR_DYNAMIC_INFO_AV1.put(733000L, HDR10_INFO_SCENE_D);
+
+ HDR_DYNAMIC_INCORRECT_INFO_AV1.put(0L, HDR10_INCORRECT_INFO_SCENE_A);
+ HDR_DYNAMIC_INCORRECT_INFO_AV1.put(133000L, HDR10_INCORRECT_INFO_SCENE_B);
+ HDR_DYNAMIC_INCORRECT_INFO_AV1.put(400000L, HDR10_INCORRECT_INFO_SCENE_C);
+ HDR_DYNAMIC_INCORRECT_INFO_AV1.put(733000L, HDR10_INCORRECT_INFO_SCENE_D);
+
+ HDR_DYNAMIC_INFO_VP9.put(0L, HDR10_INFO_SCENE_A);
+ HDR_DYNAMIC_INFO_VP9.put(200000L, HDR10_INFO_SCENE_B);
+ HDR_DYNAMIC_INFO_VP9.put(400000L, HDR10_INFO_SCENE_C);
+ HDR_DYNAMIC_INFO_VP9.put(640000L, HDR10_INFO_SCENE_D);
+ }
public DecoderHDRInfoTest(String codecName, String mediaType, String testFile,
String hdrStaticInfoStream, String hdrStaticInfoContainer,
- Map<Integer, String> hdrDynamicInfoStream, Map<Integer, String> hdrDynamicInfoContainer,
+ Map<Long, String> hdrDynamicInfoStream, Map<Long, String> hdrDynamicInfoContainer,
String allTestParams) {
super(codecName, mediaType, MEDIA_DIR + testFile, allTestParams);
mHDRStaticInfoStream = hdrStaticInfoStream;
@@ -98,15 +132,15 @@ public class DecoderHDRInfoTest extends HDRDecoderTestBase {
{MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hdr10_only_container_av1.mkv",
null, HDR_STATIC_INFO, null, null},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_352x288_hdr10plus_hevc.mp4",
- null, null, HDR_DYNAMIC_INFO, null},
+ null, null, HDR_DYNAMIC_INFO_HEVC, null},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_352x288_hdr10plus_hevc.mp4",
- null, null, HDR_DYNAMIC_INFO, HDR_DYNAMIC_INCORRECT_INFO},
+ null, null, HDR_DYNAMIC_INFO_HEVC, HDR_DYNAMIC_INCORRECT_INFO_HEVC},
{MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hdr10plus_av1.mkv",
- null, null, HDR_DYNAMIC_INFO, null},
+ null, null, HDR_DYNAMIC_INFO_AV1, null},
{MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hdr10plus_av1.mkv",
- null, null, HDR_DYNAMIC_INFO, HDR_DYNAMIC_INCORRECT_INFO},
+ null, null, HDR_DYNAMIC_INFO_AV1, HDR_DYNAMIC_INCORRECT_INFO_AV1},
{MediaFormat.MIMETYPE_VIDEO_VP9, "cosmat_352x288_hdr10_only_container_vp9.mkv",
- null, null, null, HDR_DYNAMIC_INFO},
+ null, null, null, HDR_DYNAMIC_INFO_VP9},
});
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
diff --git a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
index 0b4ed23bbf1..93170eaf96f 100644
--- a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java
@@ -37,6 +37,7 @@ import org.junit.runners.Parameterized;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -56,13 +57,21 @@ import java.util.Objects;
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
public class EncoderHDRInfoTest extends HDREncoderTestBase {
private static final String LOG_TAG = EncoderHDRInfoTest.class.getSimpleName();
+ public static final HashMap<Long, String> HDR_DYNAMIC_INFO = new HashMap<>();
private final String mHDRStaticInfo;
- private final Map<Integer, String> mHDRDynamicInfo;
+ private final Map<Long, String> mHDRDynamicInfo;
+
+ static {
+ HDR_DYNAMIC_INFO.put(0L, HDR10_INFO_SCENE_A);
+ HDR_DYNAMIC_INFO.put(133333L, HDR10_INFO_SCENE_B);
+ HDR_DYNAMIC_INFO.put(400000L, HDR10_INFO_SCENE_C);
+ HDR_DYNAMIC_INFO.put(733333L, HDR10_INFO_SCENE_D);
+ }
public EncoderHDRInfoTest(String encoderName, String mediaType,
EncoderConfigParams encCfgParams, @SuppressWarnings("unused") String testLabel,
- String hdrStaticInfo, Map<Integer, String> hdrDynamicInfo, String allTestParams) {
+ String hdrStaticInfo, Map<Long, String> hdrDynamicInfo, String allTestParams) {
super(encoderName, mediaType, encCfgParams, allTestParams);
mHDRStaticInfo = hdrStaticInfo;
mHDRDynamicInfo = hdrDynamicInfo;
diff --git a/tests/media/src/android/mediav2/cts/ExtractorTest.java b/tests/media/src/android/mediav2/cts/ExtractorTest.java
index adafffe3814..10cd3e648b9 100644
--- a/tests/media/src/android/mediav2/cts/ExtractorTest.java
+++ b/tests/media/src/android/mediav2/cts/ExtractorTest.java
@@ -1452,8 +1452,8 @@ public class ExtractorTest {
// profile and level constraints as per sec 2.3.2 of cdd
/* TODO(b/159582475)
exhaustiveArgsList.add(new Object[]{MediaFormat.MIMETYPE_VIDEO_MPEG2, new String[]{
- "bbb_1920x1080_mpeg2_main_high.mp4",
- "bbb_1920x1080_mpeg2_main_high.mkv"},
+ "bbb_1920x1080_30fps_mpeg2_main_high.mp4",
+ "bbb_1920x1080_30fps_mpeg2_main_high.mkv"},
MediaCodecInfo.CodecProfileLevel.MPEG2ProfileMain,
MediaCodecInfo.CodecProfileLevel.MPEG2LevelHL, 1920, 1080});*/
}
diff --git a/tests/media/src/android/mediav2/cts/WorkDir.java b/tests/media/src/android/mediav2/cts/WorkDir.java
index 6ee7e018ad9..de9f200d7a8 100644
--- a/tests/media/src/android/mediav2/cts/WorkDir.java
+++ b/tests/media/src/android/mediav2/cts/WorkDir.java
@@ -24,6 +24,6 @@ import android.mediav2.common.cts.WorkDirBase;
*/
class WorkDir extends WorkDirBase {
static final String getMediaDirString() {
- return getMediaDirString("CtsMediaV2TestCases-3.4");
+ return getMediaDirString("CtsMediaV2TestCases-3.5");
}
}
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 5925552965d..258b30f7cc9 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
@@ -23,23 +23,26 @@ import static org.junit.Assume.assumeTrue;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint;
import android.media.MediaFormat;
import android.os.Build;
import android.os.SystemProperties;
+import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
+import android.view.Display;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
+import java.util.stream.Stream;
/**
* Test utilities.
@@ -97,14 +100,30 @@ public class Utils {
}
// When used from ItsService, context will be null
if (context != null) {
- WindowManager windowManager = context.getSystemService(WindowManager.class);
- WindowMetrics metrics = windowManager.getMaximumWindowMetrics();
- Rect displayBounds = metrics.getBounds();
- int widthPixels = displayBounds.width();
- int heightPixels = displayBounds.height();
- DISPLAY_DPI = context.getResources().getConfiguration().densityDpi;
- DISPLAY_LONG_PIXELS = Math.max(widthPixels, heightPixels);
- DISPLAY_SHORT_PIXELS = Math.min(widthPixels, heightPixels);
+ DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+ Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ Display.Mode maxResolutionDisplayMode =
+ Arrays.stream(displayManager.getDisplays())
+ .map(Display::getSupportedModes)
+ .flatMap(Stream::of)
+ .max(Comparator.comparing(Display.Mode::getPhysicalHeight))
+ .orElseThrow(
+ () -> new RuntimeException("Failed to determine max height"));
+ int maxWidthPixels = maxResolutionDisplayMode.getPhysicalWidth();
+ int maxHeightPixels = maxResolutionDisplayMode.getPhysicalHeight();
+ DISPLAY_LONG_PIXELS = Math.max(maxWidthPixels, maxHeightPixels);
+ DISPLAY_SHORT_PIXELS = Math.min(maxWidthPixels, maxHeightPixels);
+
+ int widthPixels = defaultDisplay.getMode().getPhysicalWidth();
+ int heightPixels = defaultDisplay.getMode().getPhysicalHeight();
+
+ DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ final double widthInch = (double) widthPixels / (double) metrics.xdpi;
+ final double heightInch = (double) heightPixels / (double) metrics.ydpi;
+ final double diagonalInch = Math.sqrt(widthInch * widthInch + heightInch * heightInch);
+ final double maxDiagonalPixels =
+ Math.sqrt(maxWidthPixels * maxWidthPixels + maxHeightPixels * maxHeightPixels);
+ DISPLAY_DPI = (int) (maxDiagonalPixels / diagonalInch);
ActivityManager activityManager = context.getSystemService(ActivityManager.class);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
index afc2ad0c1d1..29ed734acb9 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
@@ -935,7 +935,6 @@ class Encode extends CodecEncoderTestBase implements Callable<Double> {
super(mime);
mEncoderName = encoderName;
mIsAsync = isAsync;
- mSurface = MediaCodec.createPersistentInputSurface();
mFrameRate = frameRate;
mBitrate = bitrate;
mHeight = height;
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
index 507e3157704..0e295fcd712 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
@@ -63,11 +63,11 @@ public class MultiCodecPerfTestBase {
static Map<String, String> mTestFiles = new HashMap<>();
static Map<String, String> m720pTestFiles = new HashMap<>();
static Map<String, String> m1080pTestFiles = new HashMap<>();
- static Map<String, String> m2160pTestFiles = new HashMap<>();
- static Map<String, String> m2160p10bitTestFiles = new HashMap<>();
+ static Map<String, String> m2160pPc14TestFiles = new HashMap<>();
+ static Map<String, String> m2160pPc1410bitTestFiles = new HashMap<>();
static Map<String, String> m1080pWidevineTestFiles = new HashMap<>();
- static Map<String, String> m2160pWidevineTestFiles = new HashMap<>();
- static Map<String, String> m2160p10bitWidevineTestFiles = new HashMap<>();
+ static Map<String, String> m2160pPc14WidevineTestFiles = new HashMap<>();
+ static Map<String, String> m2160pPc1410bitWidevineTestFiles = new HashMap<>();
static {
mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AVC);
@@ -89,17 +89,23 @@ public class MultiCodecPerfTestBase {
m1080pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1920x1080_4mbps_30fps_vp9.webm");
m1080pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1920x1080_4mbps_30fps_av1.mp4");
- m2160pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_3840x2160_18mbps_30fps_avc.mp4");
- m2160pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_3840x2160_12mbps_30fps_hevc.mp4");
- m2160pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_3840x2160_12mbps_30fps_vp9.webm");
- m2160pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_3840x2160_12mbps_30fps_av1.mp4");
-
- m2160p10bitTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ m2160pPc14TestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC,
+ "bbb_3840x2160_18mbps_30fps_avc.mp4");
+ m2160pPc14TestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ "bbb_3840x2160_12mbps_30fps_hevc.mp4");
+ m2160pPc14TestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9,
+ "bbb_3840x2160_12mbps_30fps_vp9.webm");
+ // Limit AV1 4k tests to 1080p as per PC14 requirements
+ m2160pPc14TestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1,
+ "bbb_1920x1080_4mbps_30fps_av1.mp4");
+
+ m2160pPc1410bitTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC,
"bbb_3840x2160_12mbps_30fps_hevc_10bit.mp4");
- m2160p10bitTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9,
+ m2160pPc1410bitTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_3840x2160_12mbps_30fps_vp9_10bit.webm");
- m2160p10bitTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1,
- "bbb_3840x2160_12mbps_30fps_av1_10bit.mp4");
+ // Limit AV1 4k tests to 1080p as per PC14 requirements
+ m2160pPc1410bitTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1,
+ "bbb_1920x1080_4mbps_30fps_av1_10bit.mp4");
m1080pWidevineTestFiles
.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1920x1080_6mbps_30fps_avc_cenc.mp4");
@@ -111,20 +117,22 @@ public class MultiCodecPerfTestBase {
m1080pWidevineTestFiles
.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1920x1080_4mbps_30fps_av1_cenc.mp4");
- m2160pWidevineTestFiles
+ m2160pPc14WidevineTestFiles
.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_3840x2160_18mbps_30fps_avc_cenc.mp4");
- m2160pWidevineTestFiles
+ m2160pPc14WidevineTestFiles
.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_3840x2160_12mbps_30fps_hevc_cenc.mp4");
// TODO(b/230682028)
// m2160pWidevineTestFiles
// .put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_3840x2160_12mbps_30fps_vp9_cenc.webm");
- m2160pWidevineTestFiles
- .put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_3840x2160_12mbps_30fps_av1_cenc.mp4");
+ // Limit AV1 4k tests to 1080p as per PC14 requirements
+ m2160pPc14WidevineTestFiles
+ .put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1920x1080_4mbps_30fps_av1_cenc.mp4");
- m2160p10bitWidevineTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ m2160pPc1410bitWidevineTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC,
"bbb_3840x2160_12mbps_30fps_hevc_10bit_cenc.mp4");
- m2160p10bitWidevineTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1,
- "bbb_3840x2160_12mbps_30fps_av1_10bit_cenc.mp4");
+ // Limit AV1 4k tests to 1080p as per PC14 requirements
+ m2160pPc1410bitWidevineTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1,
+ "bbb_1920x1080_4mbps_30fps_av1_10bit_cenc.mp4");
}
String mMime;
@@ -172,9 +180,11 @@ public class MultiCodecPerfTestBase {
int[] maxMacroBlockRates1080p = new int[mimeCodecPairs.size()];
int required4kInstances = isEncoder ? REQUIRED_MIN_CONCURRENT_4K_ENCODER_INSTANCES :
REQUIRED_MIN_CONCURRENT_4K_DECODER_INSTANCES;
- int required1080pInstances =
- isEncoder ? REQUIRED_MIN_CONCURRENT_1080_ENCODER_INSTANCES :
- REQUIRED_MIN_CONCURRENT_1080_DECODER_INSTANCES;
+ // when testing secure codecs limit 4k to 2 instances
+ if (requiredMinInstances < REQUIRED_MIN_CONCURRENT_INSTANCES) {
+ required4kInstances = REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES;
+ }
+ int required1080pInstances = requiredMinInstances - required4kInstances;
int loopCount = 0;
for (Pair<String, String> mimeCodecPair : mimeCodecPairs) {
MediaCodec codec = MediaCodec.createByCodecName(mimeCodecPair.second);
@@ -183,14 +193,21 @@ public class MultiCodecPerfTestBase {
List<PerformancePoint> pps = cap.getVideoCapabilities().getSupportedPerformancePoints();
assertTrue(pps.size() > 0);
- boolean hasVP9 = mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
+ boolean hasAV1 = mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_AV1);
int requiredFrameRate =
height > 1080 ? required4kInstances * 30 : requiredMinInstances * 30;
int requiredFrameRate1080p = required1080pInstances * 30;
maxInstances[loopCount] = cap.getMaxSupportedInstances();
- PerformancePoint PPRes = new PerformancePoint(width, height, requiredFrameRate);
- PerformancePoint PPRes1080p = new PerformancePoint(1920, 1080, requiredFrameRate1080p);
+ PerformancePoint PPRes;
+ if (hasAV1 && height > 1080) {
+ // For 4k tests, if the codec is AV1 limit it to 1080p as per PC14 requirements
+ PPRes = new PerformancePoint(1920, 1080, requiredFrameRate);
+ } else {
+ PPRes = new PerformancePoint(width, height, requiredFrameRate);
+ }
+ PerformancePoint PPRes1080p =
+ new PerformancePoint(1920, 1080, requiredFrameRate1080p + requiredFrameRate);
maxMacroBlockRates[loopCount] = 0;
boolean supportsResolutionPerformance = false;
@@ -225,48 +242,56 @@ public class MultiCodecPerfTestBase {
}
loopCount++;
}
- Arrays.sort(maxInstances);
- Arrays.sort(maxFrameRates);
- Arrays.sort(maxMacroBlockRates);
- Arrays.sort(maxFrameRates1080p);
- Arrays.sort(maxMacroBlockRates1080p);
- int minOfMaxInstances = maxInstances[0];
- int minOfMaxFrameRates = maxFrameRates[0];
- int minOfMaxMacroBlockRates = maxMacroBlockRates[0];
- int minOfMaxFrameRates1080p = maxFrameRates1080p[0];
- int minOfMaxMacroBlockRates1080p = maxMacroBlockRates1080p[0];
// Calculate how many 30fps max instances it can support from it's mMaxFrameRate
// amd maxMacroBlockRate. (assuming 16x16 macroblocks)
if (height > 1080) {
- int blocksIn4k = (3840 / 16) * (2160 / 16);
- int blocksPerSecond4k = blocksIn4k * 30;
- int instances4k = Math.min((int) (minOfMaxFrameRates / 30.0),
- (int) (minOfMaxMacroBlockRates / blocksPerSecond4k));
- if (instances4k < required4kInstances) {
- Log.e(LOG_TAG, "Less than required 4k instances supported.");
- return 0;
- }
+ int i = 0;
+ for (Pair<String, String> mimeCodecPair : mimeCodecPairs) {
+ boolean hasAV1 = mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_AV1);
+
+ // Limit AV1 4k to 1920x1080 as per PC14 requirements
+ int blocksIn4k = hasAV1 ? (1920 / 16) * (1088 / 16) : (3840 / 16) * (2160 / 16);
+ int blocksPerSecond4k = blocksIn4k * 30;
+ int instances4k = Math.min((int) (maxFrameRates[i] / 30.0),
+ (int) (maxMacroBlockRates[i] / blocksPerSecond4k));
+ instances4k = Math.min(instances4k, maxInstances[i]);
+ if (instances4k < required4kInstances) {
+ Log.e(LOG_TAG, "Less than required 4k instances supported.");
+ return 0;
+ }
- int blocksIn1080p = (1920 / 16) * (1080 / 16);
- int blocksPerSecond1080p = blocksIn1080p * 30;
- int instances1080p = Math.min((int) (minOfMaxFrameRates1080p / 30.0),
- (int) (minOfMaxMacroBlockRates1080p / blocksPerSecond1080p));
- if (instances1080p < required1080pInstances) {
- Log.e(LOG_TAG, "Less than required 1080p instances supported.");
- return 0;
- }
+ int blocksIn1080p = (1920 / 16) * (1088 / 16);
+ int blocksPerSecond1080p = blocksIn1080p * 30;
+ int instances1080p = Math.min((int) (maxFrameRates1080p[i] / 30.0),
+ (int) (maxMacroBlockRates1080p[i] / blocksPerSecond1080p));
+ instances1080p = Math.min(instances1080p, maxInstances[i]);
+ if (instances1080p < required1080pInstances) {
+ Log.e(LOG_TAG, "Less than required 1080p instances supported.");
+ return 0;
+ }
- int totalBlockRates =
- (blocksIn4k * required4kInstances + blocksIn1080p * required1080pInstances)
- * 30;
- if(totalBlockRates < Math.max(minOfMaxMacroBlockRates, minOfMaxMacroBlockRates1080p)){
- return requiredMinInstances;
+ int totalBlockRates =
+ (blocksIn4k * required4kInstances + blocksIn1080p * required1080pInstances)
+ * 30;
+ if (totalBlockRates > Math.max(maxMacroBlockRates[i], maxMacroBlockRates1080p[i])) {
+ return 0;
+ }
+ i++;
}
- return 0;
+ return required4kInstances + required1080pInstances;
}
+
+ Arrays.sort(maxInstances);
+ Arrays.sort(maxFrameRates);
+ Arrays.sort(maxMacroBlockRates);
+ int minOfMaxInstances = maxInstances[0];
+ int minOfMaxFrameRates = maxFrameRates[0];
+ int minOfMaxMacroBlockRates = maxMacroBlockRates[0];
+
return Math.min(minOfMaxInstances, Math.min((int) (minOfMaxFrameRates / 30.0),
- (int) (minOfMaxMacroBlockRates / ((width / 16) * (height / 16)) / 30.0)));
+ (int) (minOfMaxMacroBlockRates / (((width + 15) / 16) * ((height + 15) / 16))
+ / 30.0)));
}
public int getRequiredMinConcurrentInstances720p(boolean hasVP9) throws IOException {
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
index bec9fef4607..843cf105671 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
@@ -164,13 +164,13 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase {
boolean bothSecure = isFirstSecure & isSecondSecure;
if (bothSecure) {
- testCodec(null, m2160pWidevineTestFiles, 2160, 3840,
+ testCodec(null, m2160pPc14WidevineTestFiles, 2160, 3840,
REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES);
} else if (onlyOneSecure) {
- testCodec(m2160pTestFiles, m2160pWidevineTestFiles, 2160, 3840,
+ testCodec(m2160pPc14TestFiles, m2160pPc14WidevineTestFiles, 2160, 3840,
REQUIRED_CONCURRENT_NON_SECURE_INSTANCES_WITH_SECURE + 1);
} else {
- testCodec(m2160pTestFiles, null, 2160, 3840, REQUIRED_MIN_CONCURRENT_INSTANCES);
+ testCodec(m2160pPc14TestFiles, null, 2160, 3840, REQUIRED_MIN_CONCURRENT_INSTANCES);
}
}
@@ -193,11 +193,11 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase {
boolean bothSecure = isFirstSecure & isSecondSecure;
if (bothSecure) {
- testCodec(null, m2160p10bitWidevineTestFiles, 2160, 3840,
+ testCodec(null, m2160pPc1410bitWidevineTestFiles, 2160, 3840,
REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES);
} else if (onlyOneSecure) {
// 2 non-secure 4k HDR, 1 secure 4k SDR , 1 non-secure 1080p SDR
- testCodec(m2160p10bitTestFiles, m2160pWidevineTestFiles, 2160, 3840,
+ testCodec(m2160pPc1410bitTestFiles, m2160pPc14WidevineTestFiles, 2160, 3840,
REQUIRED_CONCURRENT_NON_SECURE_INSTANCES_WITH_SECURE + 1);
} else {
Assume.assumeFalse("Skipping regular performance tests for pair of non-secure decoders",
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
index e052c454c34..e037f17db19 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
@@ -131,10 +131,10 @@ public class MultiDecoderPerfTest extends MultiCodecPerfTestBase {
Assume.assumeTrue(Utils.isUPerfClass() || !Utils.isPerfClass());
if (isSecureSupportedCodec(mDecoderName, mMime)) {
- testCodec(m2160pWidevineTestFiles, 2160, 3840,
+ testCodec(m2160pPc14WidevineTestFiles, 2160, 3840,
REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES);
} else {
- testCodec(m2160pTestFiles, 2160, 3840, REQUIRED_MIN_CONCURRENT_INSTANCES);
+ testCodec(m2160pPc14TestFiles, 2160, 3840, REQUIRED_MIN_CONCURRENT_INSTANCES);
}
}
@@ -150,7 +150,7 @@ public class MultiDecoderPerfTest extends MultiCodecPerfTestBase {
Assume.assumeTrue(Utils.isUPerfClass() || !Utils.isPerfClass());
Assume.assumeTrue("Skipping regular performance tests for non-secure codecs",
isSecureSupportedCodec(mDecoderName, mMime));
- testCodec(m2160p10bitWidevineTestFiles, 2160, 3840,
+ testCodec(m2160pPc1410bitWidevineTestFiles, 2160, 3840,
REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES);
}
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
index b4c52cda44f..ef17cf2c3ac 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
@@ -143,6 +143,8 @@ public class MultiEncoderPairPerfTest extends MultiCodecPerfTestBase {
int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width,
mimeEncoderPairs, true, requiredMinInstances);
double achievedFrameRate = 0.0;
+ boolean firstPairAV1 = mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_AV1);
+ boolean secondPairAV1 = mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_AV1);
if (maxInstances >= requiredMinInstances) {
int secondPairInstances = maxInstances / 2;
int firstPairInstances = maxInstances - secondPairInstances;
@@ -152,27 +154,33 @@ public class MultiEncoderPairPerfTest extends MultiCodecPerfTestBase {
List<Encode> testList = new ArrayList<>();
if (height > 1080) {
for (int i = 0; i < firstPairInstances1080p; i++) {
- testList.add(
- new Encode(mFirstPair.first, mFirstPair.second, mIsAsync, 1080, 1920,
- 30, 10000000));
+ testList.add(new Encode(mFirstPair.first, mFirstPair.second, mIsAsync, 1080,
+ 1920, 30, 10000000));
}
for (int i = 0; i < secondPairInstances1080p; i++) {
- testList.add(
- new Encode(mSecondPair.first, mSecondPair.second, mIsAsync, 1080, 1920,
- 30, 10000000));
+ testList.add(new Encode(mSecondPair.first, mSecondPair.second, mIsAsync, 1080,
+ 1920, 30, 10000000));
}
firstPairInstances -= firstPairInstances1080p;
secondPairInstances -= secondPairInstances1080p;
}
for (int i = 0; i < firstPairInstances; i++) {
- testList.add(
- new Encode(mFirstPair.first, mFirstPair.second, mIsAsync, height, width, 30,
- bitrate));
+ if (height > 1080 && firstPairAV1) {
+ testList.add(new Encode(mFirstPair.first, mFirstPair.second, mIsAsync, 1080,
+ 1920, 30, 10000000));
+ } else {
+ testList.add(new Encode(mFirstPair.first, mFirstPair.second, mIsAsync, height,
+ width, 30, bitrate));
+ }
}
for (int i = 0; i < secondPairInstances; i++) {
- testList.add(
- new Encode(mSecondPair.first, mSecondPair.second, mIsAsync, height, width,
- 30, bitrate));
+ if (height > 1080 && secondPairAV1) {
+ testList.add(new Encode(mSecondPair.first, mSecondPair.second, mIsAsync, 1080,
+ 1920, 30, 10000000));
+ } else {
+ testList.add(new Encode(mSecondPair.first, mSecondPair.second, mIsAsync, height,
+ width, 30, bitrate));
+ }
}
List<Future<Double>> resultList = pool.invokeAll(testList);
for (Future<Double> result : resultList) {
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
index b5d90e3eb48..79675d5883f 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
@@ -124,6 +124,7 @@ public class MultiEncoderPerfTest extends MultiCodecPerfTestBase {
int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width,
mimeEncoderPairs, true, requiredMinInstances);
double achievedFrameRate = 0.0;
+ boolean hasAV1 = mMime.equals(MediaFormat.MIMETYPE_VIDEO_AV1);
if (maxInstances >= requiredMinInstances) {
ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
List<Encode> testList = new ArrayList<>();
@@ -131,8 +132,13 @@ public class MultiEncoderPerfTest extends MultiCodecPerfTestBase {
int instances4k = maxInstances / 3;
int instances1080p = maxInstances - instances4k;
for (int i = 0; i < instances4k; i++) {
- testList.add(
- new Encode(mMime, mEncoderName, mIsAsync, height, width, 30, bitrate));
+ if (hasAV1) {
+ testList.add(new Encode(mMime, mEncoderName, mIsAsync, 1080, 1920, 30,
+ 10000000));
+ } else {
+ testList.add(new Encode(mMime, mEncoderName, mIsAsync, height, width, 30,
+ bitrate));
+ }
}
for (int i = 0; i < instances1080p; i++) {
testList.add(
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
index fe5669b8fcf..6fa052fec8d 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
@@ -146,7 +146,7 @@ public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase {
@CddTest(requirements = {"2.2.7.1/5.1/H-1-5", "2.2.7.1/5.1/H-1-6"})
public void test4k() throws Exception {
Assume.assumeTrue(Utils.isUPerfClass() || !Utils.isPerfClass());
- testCodec(m2160pTestFiles, 2160, 3840, REQUIRED_MIN_CONCURRENT_INSTANCES, false);
+ testCodec(m2160pPc14TestFiles, 2160, 3840, REQUIRED_MIN_CONCURRENT_INSTANCES, false);
}
/**
@@ -164,7 +164,7 @@ public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase {
Assume.assumeFalse("Skip HBD tests for avc",
mDecoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
|| mEncoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_AVC));
- testCodec(m2160p10bitTestFiles, 2160, 3840, 3, true);
+ testCodec(m2160pPc1410bitTestFiles, 2160, 3840, 3, true);
}
private void testCodec(Map<String, String> testFiles, int height, int width,
diff --git a/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
index 7861d1c5d1d..393d9044b76 100644
--- a/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
+++ b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
@@ -21,18 +21,23 @@ import static android.mediapc.cts.FrameDropTestBase.DECODE_31S;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
+import android.util.Pair;
import android.view.Surface;
import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayList;
-
+import java.util.LinkedList;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
/**
* The following class calculates the frame drops for the given array of testFiles playback.
* It will do playback for at least 30 seconds worth of input data or for utmost 31 seconds.
* If input reaches eos, it will rewind the input to start position.
*/
public class PlaybackFrameDrop extends CodecDecoderTestBase {
+ private static final int AV1_INITIAL_DELAY = 8;
private final String mDecoderName;
private final String[] mTestFiles;
private final int mEachFrameTimeIntervalUs;
@@ -49,6 +54,62 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
private long mDecodeStartTimeMs;
private int mSampleIndex;
private int mMaxNumFrames;
+ private int mInitialDelay;
+
+ private OutputHandler mOutputHandler;
+ private Thread mThread;
+
+ class OutputHandler implements Runnable {
+ private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mQueue = new LinkedList<>();
+ private boolean mStop = false;
+ private final Lock mLock = new ReentrantLock();
+ private final Condition mCondition = mLock.newCondition();
+
+ private Pair<Integer, MediaCodec.BufferInfo> getOutput() throws InterruptedException {
+ Pair<Integer, MediaCodec.BufferInfo> element = null;
+ mLock.lock();
+ while (!mStop) {
+ if (mQueue.isEmpty()) {
+ mCondition.await();
+ } else {
+ element = mQueue.remove(0);
+ break;
+ }
+ }
+ mLock.unlock();
+ return element;
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ Pair<Integer, MediaCodec.BufferInfo> element = getOutput();
+ if (element != null) {
+ releaseOutput(element.first, element.second);
+ } else {
+ break;
+ }
+ }
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+
+ public void add(int bufferIndex, MediaCodec.BufferInfo info) {
+ mLock.lock();
+ mQueue.add(new Pair<>(bufferIndex, info));
+ mCondition.signal();
+ mLock.unlock();
+ }
+
+ public void stop() throws Exception {
+ mLock.lock();
+ mStop = true;
+ mCondition.signal();
+ mLock.unlock();
+ }
+ }
PlaybackFrameDrop(String mime, String decoderName, String[] testFiles, Surface surface,
int frameRate, boolean isAsync) {
@@ -63,9 +124,13 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
mMaxPts = 0;
mSampleIndex = 0;
mFrameDropCount = 0;
- // Decode for 30 seconds
- mMaxNumFrames = frameRate * 30;
mBufferInfos = new ArrayList<>();
+ // When testing AV1, because of super frames, we allow initial few frames to be delayed.
+ mInitialDelay = mime.equals(MediaFormat.MIMETYPE_VIDEO_AV1) ? AV1_INITIAL_DELAY : 0;
+ // Decode for 30 seconds
+ mMaxNumFrames = frameRate * 30 + mInitialDelay + 1;
+ mOutputHandler = new OutputHandler();
+ mThread = new Thread(mOutputHandler);
}
private MediaFormat createInputList(MediaFormat format, ByteBuffer buffer,
@@ -149,11 +214,14 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
mCodec = MediaCodec.createByCodecName(mDecoderName);
configureCodec(formats.get(0), mIsAsync, false, false);
+ mThread.start();
mCodec.start();
mDecodeStartTimeMs = System.currentTimeMillis();
doWork(Integer.MAX_VALUE);
queueEOS();
waitForAllOutputs();
+ mOutputHandler.stop();
+ mThread.join();
mCodec.stop();
mCodec.release();
return mFrameDropCount;
@@ -193,15 +261,21 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
@Override
void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+ mOutputHandler.add(bufferIndex, info);
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
mSawOutputEOS = true;
}
+ }
+ void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) {
// We will limit the playback to 60 fps using the system timestamps.
long nowUs = System.nanoTime() / 1000;
+
if (mOutputCount == 0) {
- mRenderStartTimeUs = nowUs;
- mCodec.releaseOutputBuffer(bufferIndex, true);
- } else if (nowUs > getRenderTimeUs(mOutputCount + 1)) {
+ // delay rendering the first frame by the specific delay
+ mRenderStartTimeUs = nowUs + mInitialDelay * mEachFrameTimeIntervalUs;
+ }
+
+ if (nowUs > getRenderTimeUs(mOutputCount + 1)) {
// If the current sample timeStamp is greater than the actual presentation timeStamp
// of the next sample, we will consider it as a frame drop and don't render.
mFrameDropCount++;
diff --git a/tests/mocking/AndroidTest.xml b/tests/mocking/AndroidTest.xml
index de923261d67..dbc66f5bef9 100644
--- a/tests/mocking/AndroidTest.xml
+++ b/tests/mocking/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for Mockito mocking test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="mocking" />
+ <option name="config-descriptor:metadata" key="component" value="devtools" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/mocking/debuggable/AndroidTest.xml b/tests/mocking/debuggable/AndroidTest.xml
index 33240ef2bf4..b1588c70f57 100644
--- a/tests/mocking/debuggable/AndroidTest.xml
+++ b/tests/mocking/debuggable/AndroidTest.xml
@@ -17,7 +17,7 @@
<configuration description="Config for Mockito mocking (while debuggable) test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="mocking" />
+ <option name="config-descriptor:metadata" key="component" value="devtools" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/mocking/inline/AndroidTest.xml b/tests/mocking/inline/AndroidTest.xml
index d78c8cf19df..ccd1371c597 100644
--- a/tests/mocking/inline/AndroidTest.xml
+++ b/tests/mocking/inline/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for Mockito inline mocking test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="mocking" />
+ <option name="config-descriptor:metadata" key="component" value="devtools" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
index 136211f5229..4b7e402e164 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
@@ -89,7 +89,7 @@ public class SignatureTest extends AbstractSignatureTest {
*
* <p>Will check the entire API, and then report the complete list of failures</p>
*/
- @Test
+ @Test(timeout = 600000)
public void testRuntimeCompatibilityWithCurrentApi() {
runWithTestResultObserver(mResultObserver -> {
ApiComplianceChecker complianceChecker =
diff --git a/tests/signature/intent-check/AndroidTest.xml b/tests/signature/intent-check/AndroidTest.xml
index 7dbf56a4042..a9cda0b3635 100644
--- a/tests/signature/intent-check/AndroidTest.xml
+++ b/tests/signature/intent-check/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS Intent Signature test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="systems" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/storageaccess/Android.bp b/tests/storageaccess/Android.bp
new file mode 100644
index 00000000000..f2acdc22171
--- /dev/null
+++ b/tests/storageaccess/Android.bp
@@ -0,0 +1,50 @@
+// Copyright (C) 2023 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 {
+ name: "CtsStorageAccessTestCases",
+ defaults: ["cts_defaults"],
+
+ static_libs: [
+ // Among other things compatibility-device-util-axt "includes": androidx.test.core,
+ // androidx.core_core, androidx.test.ext.junit, androidx.test.rules,
+ // androidx.test.uiautomator_uiautomator
+ "compatibility-device-util-axt",
+ ],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt"
+ ],
+
+ // Need to run this on Android R and above.
+ min_sdk_version: "30",
+ sdk_version: "test_current",
+ dex_preopt: { enabled: false },
+ optimize: { enabled: false },
+
+ // Tag this module as a CTS and MTS test artifact.
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-documentsui",
+ ],
+}
diff --git a/tests/storageaccess/AndroidManifest.xml b/tests/storageaccess/AndroidManifest.xml
new file mode 100644
index 00000000000..c06b1900793
--- /dev/null
+++ b/tests/storageaccess/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.storageaccess.cts">
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+
+ <activity android:name="android.storageaccess.cts.ClientActivity"
+ android:exported="true"/>
+
+ <!-- Manifest merging is disabled for the CtsStorageAccessTestCases test module, so we
+ declare activities used by the androidx.test.core library "manually". -->
+ <activity android:name="androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity"
+ android:exported="true"/>
+
+ </application>
+
+ <!-- Self-instrumenting test package. -->
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="Storage Access CTS Tests"
+ android:targetPackage="android.storageaccess.cts">
+ </instrumentation>
+</manifest>
diff --git a/tests/storageaccess/AndroidTest.xml b/tests/storageaccess/AndroidTest.xml
new file mode 100644
index 00000000000..4a5cd14a432
--- /dev/null
+++ b/tests/storageaccess/AndroidTest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Config for Storage Access CTS Tests">
+ <option name="test-suite-tag" value="cts" />
+
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- com.android.tradefed.config.ConfigurationException: CtsStorageAccessTestCases.config:
+ class com.android.tradefed.targetprep.DeviceSetup needs to be configured with...-->
+ <option name="force-skip-system-props" value="true" />
+ <!-- ... in *TS. -->
+
+ <option name="restore-settings" value="true" />
+ <!-- settings put global verifier_engprod 1 -->
+ <option name="set-global-setting" key="verifier_engprod" value="1" />
+ <!-- settings put global verifier_verify_adb_installs 0 -->
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <!-- settings put system screen_off_timeout -1 -->
+ <option name="set-system-setting" key="screen_off_timeout" value="-1" />
+ <!-- settings put secure sleep_timeout -1 -->
+ <option name="set-secure-setting" key="sleep_timeout" value="-1" />
+
+ <!-- setprop debug.wm.disable_deprecated_abi_dialog 1 -->
+ <!-- Do NOT use the "set-property" option: it prompts DeviceSetup to reboot the device -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
+
+ <!-- locksettings set-disabled true -->
+ <option name="run-command" value="locksettings set-disabled true" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsStorageAccessTestCases.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.storageaccess.cts" />
+ </test>
+
+</configuration>
diff --git a/tests/storageaccess/OWNERS b/tests/storageaccess/OWNERS
new file mode 100644
index 00000000000..cdda1bbcc89
--- /dev/null
+++ b/tests/storageaccess/OWNERS
@@ -0,0 +1,11 @@
+# "Android > Android OS & Apps > Framework (Java + Native) > File Management" bug component
+# Bug component: 46626
+
+# Primary.
+sergeynv@google.com
+
+# Secondary.
+tylersaunders@google.com
+
+# Only if Primary and Secondary are unavailable.
+shikhamalhotra@google.com
diff --git a/tests/storageaccess/src/android/storageaccess/cts/ActivityScenarioExt.kt b/tests/storageaccess/src/android/storageaccess/cts/ActivityScenarioExt.kt
new file mode 100644
index 00000000000..7f0e39dd031
--- /dev/null
+++ b/tests/storageaccess/src/android/storageaccess/cts/ActivityScenarioExt.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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.storageaccess.cts
+
+import android.content.Intent
+import androidx.test.core.app.ActivityScenario
+import java.util.concurrent.CompletableFuture
+
+fun launchClientActivity(block: (ActivityScenario<ClientActivity>) -> Unit) =
+ ActivityScenario.launch(ClientActivity::class.java).use(block)
+
+fun ActivityScenario<ClientActivity>.startActivityForFutureResult(
+ intent: Intent,
+ requestCode: Int
+): CompletableFuture<ClientActivity.Result> {
+ val futureResult = CompletableFuture<ClientActivity.Result>()
+ onActivity { activity ->
+ // Careful: UI thread!
+ activity.startActivityForFutureResult(intent, requestCode, futureResult)
+ }
+ return futureResult
+} \ No newline at end of file
diff --git a/tests/storageaccess/src/android/storageaccess/cts/ClientActivity.kt b/tests/storageaccess/src/android/storageaccess/cts/ClientActivity.kt
new file mode 100644
index 00000000000..4192b1c6829
--- /dev/null
+++ b/tests/storageaccess/src/android/storageaccess/cts/ClientActivity.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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.storageaccess.cts
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+import android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+import android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+import java.util.concurrent.CompletableFuture
+
+
+class ClientActivity : Activity() {
+ private var pendingActivityResult: Boolean = false
+ private var activityResultFuture: CompletableFuture<Result>? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ window.addFlags(FLAG_KEEP_SCREEN_ON or FLAG_TURN_SCREEN_ON or FLAG_DISMISS_KEYGUARD)
+ }
+
+ fun startActivityForFutureResult(
+ intent: Intent,
+ requestCode: Int,
+ future: CompletableFuture<Result>
+ ) {
+ log("ClientActivity.startActivityFor_Future_Result() " +
+ "requestCode=$requestCode intent=$intent")
+ super.startActivityForResult(intent, requestCode)
+ activityResultFuture = future
+ }
+
+ override fun startActivityForResult(intent: Intent?, requestCode: Int, options: Bundle?) {
+ if (pendingActivityResult) {
+ // To avoid silly mistakes let's make sure we do not try to start multiple activities
+ // for result at the same time.
+ error("Cannot startActivityForResult(): already waiting for another result.")
+ }
+ pendingActivityResult = true
+ super.startActivityForResult(intent, requestCode, options)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ val result = Result(requestCode, resultCode, data)
+ log("ClientActivity.onActivityResult(): $result")
+
+ pendingActivityResult = false
+
+ activityResultFuture?.apply { complete(result) }
+ activityResultFuture = null
+ }
+
+ data class Result(val requestCode: Int, val resultCode: Int, val data: Intent?)
+} \ No newline at end of file
diff --git a/tests/storageaccess/src/android/storageaccess/cts/Constants.kt b/tests/storageaccess/src/android/storageaccess/cts/Constants.kt
new file mode 100644
index 00000000000..efdb6d18f03
--- /dev/null
+++ b/tests/storageaccess/src/android/storageaccess/cts/Constants.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+@file:JvmName("Constants")
+
+package android.storageaccess.cts
+
+const val DEBUG = false
diff --git a/tests/storageaccess/src/android/storageaccess/cts/LogUtils.kt b/tests/storageaccess/src/android/storageaccess/cts/LogUtils.kt
new file mode 100644
index 00000000000..40c4aff6225
--- /dev/null
+++ b/tests/storageaccess/src/android/storageaccess/cts/LogUtils.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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.storageaccess.cts
+
+import android.util.Log
+
+private const val TAG = "CtsStorageAccessTestCases"
+
+fun log(message: String) =
+ Log.d(TAG, if (DEBUG) "[${Thread.currentThread()}] $message" else message)
diff --git a/tests/storageaccess/src/android/storageaccess/cts/tests/ScopedDirectoryAccessClientTest.kt b/tests/storageaccess/src/android/storageaccess/cts/tests/ScopedDirectoryAccessClientTest.kt
new file mode 100644
index 00000000000..f148de78cc1
--- /dev/null
+++ b/tests/storageaccess/src/android/storageaccess/cts/tests/ScopedDirectoryAccessClientTest.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2023 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.storageaccess.cts.tests
+
+import android.app.Activity.RESULT_CANCELED
+import android.content.Context
+import android.os.Environment
+import android.os.storage.StorageManager
+import android.os.storage.StorageVolume
+import android.storageaccess.cts.launchClientActivity
+import android.storageaccess.cts.log
+import android.storageaccess.cts.startActivityForFutureResult
+import com.android.compatibility.common.util.ApiTest
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Test
+import java.util.concurrent.TimeUnit
+
+/** Test cases for [StorageVolume.createAccessIntent]. */
+class ScopedDirectoryAccessClientTest : TestBase() {
+
+ @Test
+ @ApiTest(apis = ["android.os.storage.StorageVolume#createAccessIntent"])
+ fun test_createAccessIntent_invalidPaths() {
+ val invalidPaths = listOf(
+ "",
+ "/dev/null",
+ "/../",
+ "/HiddenStuff")
+
+ volumes.forEach { volume ->
+ invalidPaths.forEach { path ->
+ assertNull("Should NOT be able get access intent for '$path' on $volume",
+ volume.createAccessIntent(path))
+ }
+ }
+
+ // Also test root of the primary volume.
+ assertNull("Should NOT be able get the Access Intent for root on the primary volume",
+ primaryVolume.createAccessIntent(/* root */ null))
+ }
+
+ @Test
+ @ApiTest(apis = ["android.os.storage.StorageVolume#createAccessIntent"])
+ fun test_accessIntentActivityCancelled_ForAllVolumesAndDirectories() {
+ val paths = listOf(
+ null, // Root. Will skip for the primary volume.
+ Environment.DIRECTORY_MUSIC,
+ Environment.DIRECTORY_PODCASTS,
+ Environment.DIRECTORY_RINGTONES,
+ Environment.DIRECTORY_NOTIFICATIONS,
+ Environment.DIRECTORY_PICTURES,
+ Environment.DIRECTORY_MOVIES,
+ Environment.DIRECTORY_DOWNLOADS,
+ Environment.DIRECTORY_DCIM,
+ Environment.DIRECTORY_DOCUMENTS)
+
+ // We will be incrementing this every time we startActivityForResult().
+ var requestCode = 100
+
+ launchClientActivity { scenario ->
+ volumes.forEach { volume ->
+ paths.forEach innerLoop@ { path ->
+ // Skip root on the primary volume for which we don't get the access intent:
+ // see test_createAccessIntent_invalidPaths above.
+ if (volume.isPrimary && path == null) return@innerLoop
+
+ val intent = volume.createAccessIntent(path)
+ assertNotNull("Could NOT get access intent for '$path' on $volume", intent)
+
+ log("Launching Access Intent for '$path' on $volume: ${intent!!}")
+ // Launch the access intent "for result", with a unique (incremented)
+ // request code.
+ val futureResult = scenario.startActivityForFutureResult(intent, ++requestCode)
+
+ // We expect the "target" activity to send RESULT_CANCELED right away, so
+ // waiting for 5sec should be enough.
+ futureResult.get(5, TimeUnit.SECONDS).let {
+ assertEquals(/* expected */ requestCode, /* actual */ it.requestCode)
+ assertEquals(/* expected */ RESULT_CANCELED, /* actual */ it.resultCode)
+ assertNull(it.data)
+ }
+ }
+ }
+
+ // Clean up the ActivityScenario (makes sure the Activity is "finished")
+ scenario.close()
+ }
+ }
+
+ private val storageManager: StorageManager
+ get() = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
+
+ private val volumes: List<StorageVolume>
+ get() = storageManager.storageVolumes.takeUnless { it.isEmpty() }
+ ?: error("Could not retrieve storage volumes")
+
+ private val primaryVolume: StorageVolume
+ get() = storageManager.primaryStorageVolume
+} \ No newline at end of file
diff --git a/tests/storageaccess/src/android/storageaccess/cts/tests/TestBase.kt b/tests/storageaccess/src/android/storageaccess/cts/tests/TestBase.kt
new file mode 100644
index 00000000000..f4e0ddce823
--- /dev/null
+++ b/tests/storageaccess/src/android/storageaccess/cts/tests/TestBase.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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.storageaccess.cts.tests
+
+import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
+import android.content.pm.PackageManager.FEATURE_LEANBACK
+import android.content.pm.PackageManager.FEATURE_TELEVISION
+import android.content.pm.PackageManager.FEATURE_WATCH
+import android.storageaccess.cts.DEBUG
+import android.storageaccess.cts.log
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+
+/** Base for the test classes. */
+abstract class TestBase {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()!!
+ private val device = UiDevice.getInstance(instrumentation)
+
+ protected val context = instrumentation.context!!
+ protected val contentResolver
+ get() = context.contentResolver!!
+
+ @Before
+ fun setUp_TestBase() {
+ if (DEBUG) log("setUp_TestBase")
+
+ with(context.packageManager) {
+ // Make sure we are running neither on a TV...
+ assumeFalse(hasSystemFeature(FEATURE_TELEVISION) || hasSystemFeature(FEATURE_LEANBACK))
+ // nor on a watch...
+ assumeFalse(hasSystemFeature(FEATURE_WATCH))
+ // nor in a car.
+ assumeFalse(hasSystemFeature(FEATURE_AUTOMOTIVE))
+ }
+
+ device.wakeUp()
+ device.executeShellCommand("wm dismiss-keyguard")
+ }
+
+ @After
+ fun tearDown_TestBase() {
+ if (DEBUG) log("tearDown_TestBase")
+ }
+
+ protected fun executeShellCommand(cmd: String): String {
+ if (DEBUG) log("executeShellCommand '$cmd'")
+ val output = device.executeShellCommand(cmd)
+ if (DEBUG) log("output: '$output'")
+ return output
+ }
+} \ No newline at end of file
diff --git a/tests/suspendapps/permission/AndroidTest.xml b/tests/suspendapps/permission/AndroidTest.xml
index e17ccd869fe..8ad9ba94579 100644
--- a/tests/suspendapps/permission/AndroidTest.xml
+++ b/tests/suspendapps/permission/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Suspend Apps test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="component" value="packagemanager"/>
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/suspendapps/tests/AndroidTest.xml b/tests/suspendapps/tests/AndroidTest.xml
index 6eaf9692914..1c28140627f 100644
--- a/tests/suspendapps/tests/AndroidTest.xml
+++ b/tests/suspendapps/tests/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Suspend Apps test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="component" value="packagemanager"/>
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/app/AndroidTest.xml b/tests/tests/app/AndroidTest.xml
index 7e323211264..5e4e17e754f 100644
--- a/tests/tests/app/AndroidTest.xml
+++ b/tests/tests/app/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Configuration for app Tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="misc" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
<option name="not-shardable" value="true" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/tests/tests/appcomponentfactory/AndroidTest.xml b/tests/tests/appcomponentfactory/AndroidTest.xml
index 69f53471cf5..f2169e8487f 100644
--- a/tests/tests/appcomponentfactory/AndroidTest.xml
+++ b/tests/tests/appcomponentfactory/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Configuration for app Tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="misc" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/appenumeration/AndroidTest.xml b/tests/tests/appenumeration/AndroidTest.xml
index 92e1358f784..bf57f213187 100644
--- a/tests/tests/appenumeration/AndroidTest.xml
+++ b/tests/tests/appenumeration/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for app enumeration CTS test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/car/src/android/car/cts/CarInputTest.java b/tests/tests/car/src/android/car/cts/CarInputTest.java
index 2611f98eac6..4086d46132c 100644
--- a/tests/tests/car/src/android/car/cts/CarInputTest.java
+++ b/tests/tests/car/src/android/car/cts/CarInputTest.java
@@ -50,6 +50,7 @@ import android.view.MotionEvent;
import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ActivityScenario;
+import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.CddTest;
@@ -68,6 +69,7 @@ import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
@RunWith(AndroidJUnit4.class)
+@FlakyTest(bugId = 279829443)
public class CarInputTest extends AbstractCarTestCase {
private static final String TAG = CarInputTest.class.getSimpleName();
private static final long ACTIVITY_WAIT_TIME_OUT_MS = 10_000L;
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index d7d28fad855..117090aac4d 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -39,6 +39,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
@@ -1383,6 +1384,10 @@ public class CarrierApiTest extends BaseCarrierApiTest {
@Test
public void testEapAkaAuthentication() {
+ // Wear devices do not yet support EapAkaAuthentication, so skip this test for now
+ if (isWear()) {
+ return;
+ }
assumeTrue(
"testEapAkaAuthentication requires a 2021 CTS UICC or newer",
UiccUtil.uiccHasCertificate(CTS_UICC_2021));
@@ -1434,4 +1439,8 @@ public class CarrierApiTest extends BaseCarrierApiTest {
mTelephonyManager.getNetworkSlicingConfiguration(
AsyncTask.SERIAL_EXECUTOR, resultFuture::complete);
}
+
+ private boolean isWear() {
+ return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
}
diff --git a/tests/tests/classloaderfactory/test-memcl/AndroidTest.xml b/tests/tests/classloaderfactory/test-memcl/AndroidTest.xml
index 64808d3ac8e..f28af37c6c8 100644
--- a/tests/tests/classloaderfactory/test-memcl/AndroidTest.xml
+++ b/tests/tests/classloaderfactory/test-memcl/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Configuration for app Tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="misc" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/tests/tests/classloaderfactory/test-pathcl/AndroidTest.xml b/tests/tests/classloaderfactory/test-pathcl/AndroidTest.xml
index b457fd46bad..9d6bc151464 100644
--- a/tests/tests/classloaderfactory/test-pathcl/AndroidTest.xml
+++ b/tests/tests/classloaderfactory/test-pathcl/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Configuration for app Tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="misc" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index 7d9727e4104..2f9bc651d6d 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS Content test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
diff --git a/tests/tests/content/TEST_MAPPING b/tests/tests/content/TEST_MAPPING
index 65b6edf08a7..fc008e1edae 100644
--- a/tests/tests/content/TEST_MAPPING
+++ b/tests/tests/content/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit-large": [
+ "postsubmit": [
{
"name": "CtsContentTestCases",
"options": [
diff --git a/tests/tests/content/pm/SecureFrp/AndroidTest.xml b/tests/tests/content/pm/SecureFrp/AndroidTest.xml
index a5e416d6c60..35e8d84e407 100644
--- a/tests/tests/content/pm/SecureFrp/AndroidTest.xml
+++ b/tests/tests/content/pm/SecureFrp/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Runs the secure FRP install tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<!-- Instant apps can't install packages. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index ada43ae4917..dc89b8c6a7a 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -502,9 +502,10 @@ public class AvailableIntentsTest extends AndroidTestCase {
}
public void testPowerUsageSummarySettings() {
- if(FeatureUtil.isWatch()){
+ if (FeatureUtil.isWatch() || FeatureUtil.isAutomotive()) {
return;
}
+
if (isBatteryPresent()) {
assertCanBeHandled(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY));
}
diff --git a/tests/tests/display/src/android/display/cts/DisplayManagerTest.java b/tests/tests/display/src/android/display/cts/DisplayManagerTest.java
index 670ca101e93..b85d5bbacdf 100644
--- a/tests/tests/display/src/android/display/cts/DisplayManagerTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayManagerTest.java
@@ -17,7 +17,7 @@
package android.display.cts;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowInsets.Type.systemBars;
import static org.junit.Assert.assertTrue;
@@ -45,6 +45,7 @@ import android.view.cts.surfacevalidator.SaveBitmapHelper;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
+import androidx.core.view.WindowCompat;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -59,7 +60,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
public class DisplayManagerTest {
- private static final String TAG = "MediaProjectionGlobalTest";
+ private static final String TAG = "DisplayManagerTest";
@Rule
public TestName mTestName = new TestName();
@@ -74,7 +75,7 @@ public class DisplayManagerTest {
private int mNumRetries;
- final HandlerThread mWorkerThread = new HandlerThread("MediaProjectGlobalTest");
+ final HandlerThread mWorkerThread = new HandlerThread("DisplayManagerTest");
private VirtualDisplay mVirtualDisplay;
@@ -200,6 +201,9 @@ public class DisplayManagerTest {
setContentView(mFrameLayout, layoutParams);
+ // Prevent certain devices from adding a left and right border
+ WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+
mFrameLayout.getViewTreeObserver().addOnWindowAttachListener(
new ViewTreeObserver.OnWindowAttachListener() {
@Override
@@ -232,14 +236,14 @@ public class DisplayManagerTest {
int testAreaWidth = mFrameLayout.getWidth();
int testAreaHeight = mFrameLayout.getHeight();
- Insets statusBarInsets = getWindow()
+ Insets systemBarInsets = getWindow()
.getDecorView()
.getRootWindowInsets()
- .getInsets(statusBars());
+ .getInsets(systemBars());
- return new Rect(statusBarInsets.left, statusBarInsets.top,
- testAreaWidth - statusBarInsets.right,
- testAreaHeight - statusBarInsets.bottom);
+ return new Rect(systemBarInsets.left, systemBarInsets.top,
+ testAreaWidth - systemBarInsets.right,
+ testAreaHeight - systemBarInsets.bottom);
}
}
}
diff --git a/tests/tests/gesture/AndroidTest.xml b/tests/tests/gesture/AndroidTest.xml
index 5a0d4869de0..66d7d2dc564 100644
--- a/tests/tests/gesture/AndroidTest.xml
+++ b/tests/tests/gesture/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS Gesture test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="uitoolkit" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/instantapp/AndroidTest.xml b/tests/tests/instantapp/AndroidTest.xml
index 3ec0d8b84f4..507af4ab5e1 100644
--- a/tests/tests/instantapp/AndroidTest.xml
+++ b/tests/tests/instantapp/AndroidTest.xml
@@ -18,7 +18,7 @@
<configuration description="Test module config for CTSInstantAppTests">
<option name="test-tag" value="CTSInstantAppTests" />
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/libnativehelper/AndroidTest.xml b/tests/tests/libnativehelper/AndroidTest.xml
index d6ddf785369..7482b7bc8f3 100644
--- a/tests/tests/libnativehelper/AndroidTest.xml
+++ b/tests/tests/libnativehelper/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Configuration for Libnativehelper Tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="libnativehelper" />
+ <option name="config-descriptor:metadata" key="component" value="art" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
diff --git a/tests/tests/match_flags/AndroidTest.xml b/tests/tests/match_flags/AndroidTest.xml
index 22cc54da021..aea3d436ee0 100644
--- a/tests/tests/match_flags/AndroidTest.xml
+++ b/tests/tests/match_flags/AndroidTest.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Config for match flag CTS test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/RingtoneManagerTest.java b/tests/tests/media/audio/src/android/media/audio/cts/RingtoneManagerTest.java
index 12ea166a227..5eb881eb1e4 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/RingtoneManagerTest.java
@@ -158,9 +158,9 @@ public class RingtoneManagerTest {
Uri bogus = Uri.parse("content://a_bogus_uri");
RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, bogus);
- // shouldn't be able to successfully set ringtone to bogus URI
- assertNotEquals(bogus, RingtoneManager.getActualDefaultRingtoneUri(mContext,
- RingtoneManager.TYPE_RINGTONE));
+ // not testing the matching getter after setting a bogus URI as ringtone
+ //assertNotEquals(bogus, RingtoneManager.getActualDefaultRingtoneUri(mContext,
+ // RingtoneManager.TYPE_RINGTONE));
assertEquals(Settings.System.DEFAULT_RINGTONE_URI,
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
diff --git a/tests/tests/media/misc/AndroidTest.xml b/tests/tests/media/misc/AndroidTest.xml
index 1ed72c0dd45..ed3133fe29c 100644
--- a/tests/tests/media/misc/AndroidTest.xml
+++ b/tests/tests/media/misc/AndroidTest.xml
@@ -41,7 +41,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="CtsMediaMiscTestCases-2.1" />
+ <option name="media-folder-name" value="CtsMediaMiscTestCases-2.2" />
<option name="dynamic-config-module" value="CtsMediaMiscTestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/media/misc/DynamicConfig.xml b/tests/tests/media/misc/DynamicConfig.xml
index 0918a54c5e6..ed21ce3cd35 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://dl.google.com/android/xts/cts/tests/tests/media/misc/CtsMediaMiscTestCases-2.1.zip</value>
+ <value>https://dl.google.com/android/xts/cts/tests/tests/media/misc/CtsMediaMiscTestCases-2.2.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/tests/media/misc/copy_media.sh b/tests/tests/media/misc/copy_media.sh
index ca7f3cb3091..c8381975d7b 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-2.1"
+copy_media "misc" "CtsMediaMiscTestCases-2.2"
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
index 01e3caf1f2d..85e4e73ef57 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
@@ -26,6 +26,7 @@ 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.assumeTrue;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -1193,15 +1194,46 @@ public class MediaMetadataRetrieverTest {
1 /*imageCount*/, 0 /*primary*/, false /*useGrid*/, true /*checkColor*/);
}
+ /**
+ * Test AVIF (1024x1024 with 2x2 grid) decoding
+ */
+ @Test
+ public void testGetImageAtIndexAvif1024x1024Grid2x2() throws Exception {
+ testGetImageAtIndexAvifGrid("sample_grid_1024x1024_2x2.avif", 1024 /* imageWidth */,
+ 1024 /* imageHeight */, 2 /* gridCols */, 2 /* gridRows */);
+ }
+
+ /**
+ * Test AVIF (1920x1080 with 2x4 grid) decoding
+ */
@Test
- public void testGetImageAtIndexAvifGrid() throws Exception {
+ public void testGetImageAtIndexAvif1920x1080Grid2x4() throws Exception {
+ testGetImageAtIndexAvifGrid("sample_grid_1920x1080_2x4.avif", 1920 /* imageWidth */,
+ 1080 /* imageHeight */, 2 /* gridCols */, 4 /* gridRows */);
+ }
+
+ /**
+ * Test AVIF (1920x1080 with 4x4 grid) decoding
+ */
+ @Test
+ public void testGetImageAtIndexAvif1920x1080Grid4x4() throws Exception {
+ testGetImageAtIndexAvifGrid("sample_grid_1920x1080_4x4.avif", 1920 /* imageWidth */,
+ 1080 /* imageHeight */, 4 /* gridCols */, 4 /* gridRows */);
+ }
+
+ private void testGetImageAtIndexAvifGrid(final String res, int imageWidth, int imageHeight,
+ int gridCols, int gridRows) throws Exception {
if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
- if (!MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AV1, 512, 512, 30)) {
- MediaUtils.skipTest("No AV1 codec for 512p");
+ int gridWidth = imageWidth / gridCols;
+ int gridHeight = imageHeight / gridRows;
+ if (!MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AV1, gridWidth, gridHeight, 30)) {
+ MediaUtils.skipTest("No AV1 codec for " + gridWidth + " x " + gridHeight);
+ //TODO (b/224402585) Remove the following once MediaUtils.skipTest() calls assumeTrue
+ assumeTrue("No AV1 codec for " + gridWidth + " x " + gridHeight, false);
return;
}
- testGetImage("sample_grid2x4.avif", 1920, 1080, "image/avif", 0 /*rotation*/,
- 1 /*imageCount*/, 0 /*primary*/, true /*useGrid*/, true /*checkColor*/);
+ testGetImage(res, imageWidth, imageHeight, "image/avif", 0 /*rotation*/, 1 /*imageCount*/,
+ 0 /*primary*/, true /*useGrid*/, true /*checkColor*/);
}
/**
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 183341e3d42..6cbab7c5376 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-2.1");
+ return getMediaDirString("CtsMediaMiscTestCases-2.2");
}
}
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 f9ee9681664..6e3e8e217c6 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
@@ -1287,7 +1287,12 @@ public class MediaPlayerTest extends MediaPlayerTestBase {
mOnSeekCompleteCalled.waitForSignal();
Thread.sleep(playTime);
assertFalse("MediaPlayer should not be playing", mMediaPlayer.isPlaying());
- assertEquals("MediaPlayer position should be 0", 0, mMediaPlayer.getCurrentPosition());
+ int positionAtStart = mMediaPlayer.getCurrentPosition();
+ // Allow both 0 and 23 (the timestamp of the second audio sample) to avoid flaky failures
+ // on builds that don't include http://r.android.com/2700283.
+ if (positionAtStart != 0 && positionAtStart != 23) {
+ fail("MediaPlayer position should be 0 or 23");
+ }
mMediaPlayer.start();
Thread.sleep(playTime);
diff --git a/tests/tests/notification/NotificationTrampolineBase/src/com/android/test/notificationtrampoline/NotificationTrampolineTestService.java b/tests/tests/notification/NotificationTrampolineBase/src/com/android/test/notificationtrampoline/NotificationTrampolineTestService.java
index 120186bbeb0..81d10e1d2b7 100644
--- a/tests/tests/notification/NotificationTrampolineBase/src/com/android/test/notificationtrampoline/NotificationTrampolineTestService.java
+++ b/tests/tests/notification/NotificationTrampolineBase/src/com/android/test/notificationtrampoline/NotificationTrampolineTestService.java
@@ -40,6 +40,7 @@ import androidx.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
/**
@@ -133,20 +134,21 @@ public class NotificationTrampolineTestService extends Service {
break;
}
case MESSAGE_CLICK_NOTIFICATION: {
- PendingIntent intent = Stream
- .of(mNotificationManager.getActiveNotifications())
+ AtomicInteger counter = new AtomicInteger();
+ Stream.of(mNotificationManager.getActiveNotifications())
.filter(sb -> sb.getId() == notificationId)
- .map(sb -> sb.getNotification().contentIntent)
- .findFirst()
- .orElse(null);
- if (intent != null) {
- try {
- intent.send();
- } catch (PendingIntent.CanceledException e) {
- throw new IllegalStateException("Notification PI cancelled", e);
- }
- }
- sendMessageToTest(mCallback, TEST_MESSAGE_NOTIFICATION_CLICKED, intent != null);
+ .flatMap(sb -> Stream.of(sb.getNotification().contentIntent,
+ sb.getNotification().publicVersion.contentIntent))
+ .forEach(intent -> {
+ try {
+ intent.send();
+ } catch (PendingIntent.CanceledException e) {
+ throw new IllegalStateException("Notification PI cancelled", e);
+ }
+ counter.getAndIncrement();
+ });
+ sendMessageToTest(mCallback, TEST_MESSAGE_NOTIFICATION_CLICKED,
+ counter.get() == 2);
break;
}
default:
@@ -164,10 +166,16 @@ public class NotificationTrampolineTestService extends Service {
}
private void postNotification(int notificationId, PendingIntent intent) {
+ Notification publicNotification =
+ new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(android.R.drawable.ic_info)
+ .setContentIntent(intent)
+ .build();
Notification notification =
new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_info)
.setContentIntent(intent)
+ .setPublicVersion(publicNotification)
.build();
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
diff --git a/tests/tests/os/src/android/os/cts/SeccompTest.java b/tests/tests/os/src/android/os/cts/SeccompTest.java
index 30f152a3b39..da4da9bef8c 100644
--- a/tests/tests/os/src/android/os/cts/SeccompTest.java
+++ b/tests/tests/os/src/android/os/cts/SeccompTest.java
@@ -58,8 +58,9 @@ public class SeccompTest extends AndroidTestCase {
// will not be correct, so skip those tests.
private boolean isRunningUnderEmulatedAbi() {
final String primaryAbi = Build.SUPPORTED_ABIS[0];
- return (CpuFeatures.isArmCpu() || CpuFeatures.isArm64Cpu()) &&
- !(primaryAbi.equals("armeabi-v7a") || primaryAbi.equals("arm64-v8a"));
+ return ((CpuFeatures.isArmCpu() || CpuFeatures.isArm64Cpu()) &&
+ !(primaryAbi.equals("armeabi-v7a") || primaryAbi.equals("arm64-v8a"))) ||
+ CpuFeatures.isNativeBridgedCpu();
}
public void testSeccomp() {
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/Android.bp b/tests/tests/packageinstaller/adminpackageinstaller/Android.bp
index f829a938076..6cb9baf4e62 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/Android.bp
+++ b/tests/tests/packageinstaller/adminpackageinstaller/Android.bp
@@ -26,6 +26,8 @@ android_test {
"androidx.test.rules",
"androidx.legacy_legacy-support-v4",
"cts-install-lib",
+ "Harrier",
+ "Nene",
],
libs: ["android.test.base"],
sdk_version: "test_current",
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
index f78d67e706e..ac018a4ff87 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
+++ b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
@@ -16,12 +16,13 @@
<configuration description="Config for CTS Admin Package Installer test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<!-- Device Owner-specific tests are not applicable to instant apps. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="multiuser" />
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="mkdir -p /data/local/tmp/cts/packageinstaller/" />
@@ -43,12 +44,10 @@
<target_preparer class="com.android.tradefed.targetprep.RunOnSystemUserTargetPreparer"/>
- <target_preparer class="com.android.tradefed.targetprep.DeviceOwnerTargetPreparer">
- <option name="device-owner-component-name" value="android.packageinstaller.admin.cts/.BasicAdminReceiver" />
- </target_preparer>
-
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.packageinstaller.admin.cts" />
+ <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" />
+ <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser" />
</test>
</configuration>
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/BasePackageInstallTest.java b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/BasePackageInstallTest.java
index c28466400e0..1b2c46734e9 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/BasePackageInstallTest.java
+++ b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/BasePackageInstallTest.java
@@ -15,7 +15,14 @@
*/
package android.packageinstaller.admin.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Instrumentation;
import android.app.PendingIntent;
+import android.app.UiAutomation;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -28,8 +35,15 @@ import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.support.test.uiautomator.UiDevice;
-import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.bedstead.nene.TestApis;
+
+import org.junit.After;
+import org.junit.Before;
import java.io.BufferedReader;
import java.io.File;
@@ -42,7 +56,8 @@ import java.util.ArrayList;
/**
* Base test case for testing PackageInstaller.
*/
-public class BasePackageInstallTest extends InstrumentationTestCase {
+public class BasePackageInstallTest {
+ private static final String TAG = BasePackageInstallTest.class.getSimpleName();
protected static final String TEST_APP_LOCATION =
"/data/local/tmp/cts/packageinstaller/CtsEmptyTestApp.apk";
protected static final String TEST_APP_PKG = "android.packageinstaller.emptytestapp.cts";
@@ -61,9 +76,13 @@ public class BasePackageInstallTest extends InstrumentationTestCase {
protected boolean mCallbackReceived;
protected int mCallbackStatus;
protected Intent mCallbackIntent;
+ protected ComponentName mDeviceOwner;
protected boolean mHasFeature;
+ protected boolean mAmIDeviceOwner;
+ protected Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ protected UiAutomation mUiAutomation = mInstrumentation.getUiAutomation();
protected final Object mPackageInstallerTimeoutLock = new Object();
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -85,13 +104,11 @@ public class BasePackageInstallTest extends InstrumentationTestCase {
}
};
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mContext = getInstrumentation().getContext();
- mDevice = UiDevice.getInstance(getInstrumentation());
- mDevicePolicyManager = (DevicePolicyManager)
- mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ @Before
+ public void setUp() throws Exception {
+ mContext = mInstrumentation.getContext();
+ mDevice = UiDevice.getInstance(mInstrumentation);
+ mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
mPackageManager = mContext.getPackageManager();
mPackageInstaller = mPackageManager.getPackageInstaller();
assertNotNull(mPackageInstaller);
@@ -105,11 +122,23 @@ public class BasePackageInstallTest extends InstrumentationTestCase {
}
}
- @Override
- protected void tearDown() throws Exception {
+ @Before
+ public void addDeviceOwner() {
+ mDeviceOwner = new ComponentName(mContext, BasicAdminReceiver.class);
+ try {
+ TestApis.devicePolicy().setDeviceOwner(mDeviceOwner);
+ mAmIDeviceOwner = true;
+ } catch (Exception e) {
+ mAmIDeviceOwner = false;
+ Log.e(TAG, e.getMessage());
+ }
+ }
+
+ @After
+ public void tearDown() throws Exception {
if (mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME) ||
mDevicePolicyManager.isProfileOwnerApp(PACKAGE_NAME)) {
- mDevicePolicyManager.setUninstallBlocked(getWho(), TEST_APP_PKG, false);
+ mDevicePolicyManager.setUninstallBlocked(mDeviceOwner, TEST_APP_PKG, false);
}
try {
mContext.unregisterReceiver(mBroadcastReceiver);
@@ -119,12 +148,17 @@ public class BasePackageInstallTest extends InstrumentationTestCase {
if (mSession != null) {
mSession.abandon();
}
-
- super.tearDown();
+ forceUninstall();
}
- protected static ComponentName getWho() {
- return new ComponentName(PACKAGE_NAME, BasicAdminReceiver.class.getName());
+ @After
+ public void removeDeviceOwner() {
+ try {
+ TestApis.devicePolicy().getDeviceOwner().remove();
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Could not find a device owner set by this test. "
+ + "Maybe an owner already exists?");
+ }
}
protected void assertInstallPackage() throws Exception {
@@ -220,8 +254,7 @@ public class BasePackageInstallTest extends InstrumentationTestCase {
}
public ArrayList<String> runShellCommand(String command) throws Exception {
- ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
- .executeShellCommand(command);
+ ParcelFileDescriptor pfd = mUiAutomation.executeShellCommand(command);
ArrayList<String> ret = new ArrayList<>();
// Read the input stream fully.
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/InstallReasonTest.java b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/InstallReasonTest.java
index 012952033b4..26a3d27d1f8 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/InstallReasonTest.java
+++ b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/InstallReasonTest.java
@@ -16,16 +16,26 @@
package android.packageinstaller.admin.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
import android.content.pm.PackageManager;
+import com.android.bedstead.harrier.BedsteadJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* This class tests that the install reason is correctly recorded for packages.
*/
+@RunWith(BedsteadJUnit4.class)
public class InstallReasonTest extends BasePackageInstallTest {
+ @Test
public void testInstallReason() throws Exception {
- if (!mHasFeature) {
- return;
- }
+ assumeTrue("FEATURE_DEVICE_ADMIN unavailable", mHasFeature);
+ assumeTrue("Could not set BasicAdminReceiver.class as device owner", mAmIDeviceOwner);
+
// Verify that since the Device Owner was sideloaded, its install reason is unknown.
assertEquals(PackageManager.INSTALL_REASON_UNKNOWN, getInstallReason(PACKAGE_NAME));
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
index cbdc928d2c5..790126129a5 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
+++ b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
@@ -15,6 +15,13 @@
*/
package android.packageinstaller.admin.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -28,11 +35,17 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
+import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.cts.install.lib.Install;
import com.android.cts.install.lib.InstallUtils;
import com.android.cts.install.lib.TestApp;
import com.android.cts.install.lib.Uninstall;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -40,36 +53,32 @@ import java.util.concurrent.TimeUnit;
* This class tests {@link PackageInstaller#ACTION_SESSION_COMMITTED} is properly sent to the
* launcher app.
*/
+@RunWith(BedsteadJUnit4.class)
public class SessionCommitBroadcastTest extends BasePackageInstallTest {
private static final long BROADCAST_TIMEOUT_SECS = 20;
-
private ComponentName mDefaultLauncher;
private ComponentName mThisAppLauncher;
private SessionCommitReceiver mReceiver;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- final String myPackageName = mContext.getPackageName();
- final int myUid = mPackageManager.getApplicationInfo(myPackageName, 0).uid;
- assertTrue("Test package:" + myPackageName + " (uid:" + myUid + ") is not an admin",
- mDevicePolicyManager.isDeviceOwnerApp(myPackageName));
+ @Before
+ public void setUpTest() throws Exception {
mDefaultLauncher = ComponentName.unflattenFromString(getDefaultLauncher());
mThisAppLauncher = new ComponentName(mContext, LauncherActivity.class);
mReceiver = new SessionCommitReceiver();
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDownTest() throws Exception {
mContext.unregisterReceiver(mReceiver);
Uninstall.packages(TestApp.A);
}
+ @Test
public void testBroadcastNotReceivedForDifferentLauncher() throws Exception {
- if (!mHasFeature) {
- return;
- }
+ assumeTrue("FEATURE_DEVICE_ADMIN unavailable", mHasFeature);
+ assumeTrue("Could not set BasicAdminReceiver.class as device owner", mAmIDeviceOwner);
+
if (mDefaultLauncher.equals(mThisAppLauncher)) {
// Find a different launcher
Intent homeIntent = new Intent(Intent.ACTION_MAIN)
@@ -101,10 +110,10 @@ public class SessionCommitBroadcastTest extends BasePackageInstallTest {
assertEquals(TEST_APP_PKG, info.getAppPackageName());
}
+ @Test
public void testBroadcastNotReceivedForUpdateInstall() throws Exception {
- if (!mHasFeature) {
- return;
- }
+ assumeTrue("FEATURE_DEVICE_ADMIN unavailable", mHasFeature);
+ assumeTrue("Could not set BasicAdminReceiver.class as device owner", mAmIDeviceOwner);
try {
setLauncher(mThisAppLauncher.flattenToString());
@@ -131,10 +140,11 @@ public class SessionCommitBroadcastTest extends BasePackageInstallTest {
}
}
+ @Test
public void testBroadcastReceivedForNewInstall() throws Exception {
- if (!mHasFeature) {
- return;
- }
+ assumeTrue("FEATURE_DEVICE_ADMIN unavailable", mHasFeature);
+ assumeTrue("Could not set BasicAdminReceiver.class as device owner", mAmIDeviceOwner);
+
setLauncher(mThisAppLauncher.flattenToString());
// install the app
@@ -152,10 +162,12 @@ public class SessionCommitBroadcastTest extends BasePackageInstallTest {
setLauncher(mDefaultLauncher.flattenToString());
}
+ @Test
public void testBroadcastReceivedForEnablingApp() throws Exception {
- if (!mHasFeature || !UserManager.supportsMultipleUsers()) {
- return;
- }
+ assumeTrue("FEATURE_DEVICE_ADMIN unavailable", mHasFeature);
+ assumeTrue("Cannot add multiple users", UserManager.supportsMultipleUsers());
+ assumeTrue("Could not set BasicAdminReceiver.class as device owner", mAmIDeviceOwner);
+
setLauncher(mThisAppLauncher.flattenToString());
ComponentName cn = new ComponentName(mContext, BasicAdminReceiver.class);
@@ -195,7 +207,7 @@ public class SessionCommitBroadcastTest extends BasePackageInstallTest {
private void setLauncher(String component) throws Exception {
runShellCommand("cmd package set-home-activity --user "
- + getInstrumentation().getContext().getUserId() + " " + component);
+ + mInstrumentation.getContext().getUserId() + " " + component);
}
private class SessionCommitReceiver extends BroadcastReceiver {
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SilentPackageInstallTest.java b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SilentPackageInstallTest.java
index 4c88b8225d1..370b9372444 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SilentPackageInstallTest.java
+++ b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SilentPackageInstallTest.java
@@ -16,14 +16,26 @@
package android.packageinstaller.admin.cts;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* This class tests silent package install and uninstall by a device owner.
*/
+@RunWith(BedsteadJUnit4.class)
public class SilentPackageInstallTest extends BasePackageInstallTest {
+
+ @Test
public void testSilentInstallUninstall() throws Exception {
- if (!mHasFeature) {
- return;
- }
+ assumeTrue("FEATURE_DEVICE_ADMIN unavailable", mHasFeature);
+ assumeTrue("Could not set BasicAdminReceiver.class as device owner", mAmIDeviceOwner);
+
// install the app
assertInstallPackage();
@@ -32,21 +44,22 @@ public class SilentPackageInstallTest extends BasePackageInstallTest {
assertFalse(isPackageInstalled(TEST_APP_PKG));
}
+ @Test
public void testUninstallBlocked() throws Exception {
- if (!mHasFeature) {
- return;
- }
+ assumeTrue("FEATURE_DEVICE_ADMIN unavailable", mHasFeature);
+ assumeTrue("Could not set BasicAdminReceiver.class as device owner", mAmIDeviceOwner);
+
// install the app
assertInstallPackage();
- mDevicePolicyManager.setUninstallBlocked(getWho(), TEST_APP_PKG, true);
- assertTrue(mDevicePolicyManager.isUninstallBlocked(getWho(), TEST_APP_PKG));
+ mDevicePolicyManager.setUninstallBlocked(mDeviceOwner, TEST_APP_PKG, true);
+ assertTrue(mDevicePolicyManager.isUninstallBlocked(mDeviceOwner, TEST_APP_PKG));
assertTrue(mDevicePolicyManager.isUninstallBlocked(null, TEST_APP_PKG));
assertFalse(tryUninstallPackage());
assertTrue(isPackageInstalled(TEST_APP_PKG));
- mDevicePolicyManager.setUninstallBlocked(getWho(), TEST_APP_PKG, false);
- assertFalse(mDevicePolicyManager.isUninstallBlocked(getWho(), TEST_APP_PKG));
+ mDevicePolicyManager.setUninstallBlocked(mDeviceOwner, TEST_APP_PKG, false);
+ assertFalse(mDevicePolicyManager.isUninstallBlocked(mDeviceOwner, TEST_APP_PKG));
assertFalse(mDevicePolicyManager.isUninstallBlocked(null, TEST_APP_PKG));
assertTrue(tryUninstallPackage());
assertFalse(isPackageInstalled(TEST_APP_PKG));
diff --git a/tests/tests/packageinstaller/atomicinstall/AndroidTest.xml b/tests/tests/packageinstaller/atomicinstall/AndroidTest.xml
index 73ff59a3a7b..2cf871ad9e1 100644
--- a/tests/tests/packageinstaller/atomicinstall/AndroidTest.xml
+++ b/tests/tests/packageinstaller/atomicinstall/AndroidTest.xml
@@ -15,12 +15,20 @@
-->
<configuration description="Runs the atomic install API tests">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<!-- Instant apps can't have INSTALL_PACKAGES permission. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <!-- disable GPP UI -->
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" />
+ <option name="set-global-setting" key="verifier_engprod" value="1" />
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <option name="restore-settings" value="true" />
+ </target_preparer>
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAtomicInstallTestCases.apk" />
diff --git a/tests/tests/packageinstaller/contentprovider/AndroidTestNoVisibility.xml b/tests/tests/packageinstaller/contentprovider/AndroidTestNoVisibility.xml
index 6cb94624a5f..d06ec4d7ad2 100644
--- a/tests/tests/packageinstaller/contentprovider/AndroidTestNoVisibility.xml
+++ b/tests/tests/packageinstaller/contentprovider/AndroidTestNoVisibility.xml
@@ -17,7 +17,7 @@
<configuration description="Config for CTS Package Scheme Test Cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/contentprovider/AndroidTestVisibility.xml b/tests/tests/packageinstaller/contentprovider/AndroidTestVisibility.xml
index 4dd6207dbed..e11d7fa3d07 100644
--- a/tests/tests/packageinstaller/contentprovider/AndroidTestVisibility.xml
+++ b/tests/tests/packageinstaller/contentprovider/AndroidTestVisibility.xml
@@ -17,7 +17,7 @@
<configuration description="Config for CTS Package Scheme Test Cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/install/AndroidTest.xml b/tests/tests/packageinstaller/install/AndroidTest.xml
index 260c1123b8b..28be32e1395 100644
--- a/tests/tests/packageinstaller/install/AndroidTest.xml
+++ b/tests/tests/packageinstaller/install/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Packageinstaller Session test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
index ac66ceddbda..75f079e73e7 100644
--- a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
+++ b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
@@ -39,6 +39,7 @@ import android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL
import android.content.pm.PackageManager
import android.provider.DeviceConfig
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 android.util.Log
@@ -161,7 +162,14 @@ open class PackageInstallerTestBase {
* Wait for session's install result and return it
*/
protected fun getInstallSessionResult(timeout: Long = TIMEOUT): SessionResult {
- return installSessionResult.poll(timeout, TimeUnit.MILLISECONDS)
+ return getInstallSessionResult(installSessionResult, timeout)
+ }
+
+ protected fun getInstallSessionResult(
+ installResult: LinkedBlockingQueue<SessionResult>,
+ timeout: Long = TIMEOUT
+ ): SessionResult {
+ return installResult.poll(timeout, TimeUnit.MILLISECONDS)
?: SessionResult(null /* status */, null /* preapproval */, "Fail to poll result")
}
@@ -361,16 +369,24 @@ open class PackageInstallerTestBase {
* @param resId The resource ID of the button to click
*/
fun clickInstallerUIButton(resId: String) {
+ clickInstallerUIButton(By.res(PACKAGE_INSTALLER_PACKAGE_NAME, resId))
+ }
+
+ /**
+ * Click a button in the UI of the installer app
+ *
+ * @param bySelector The bySelector of the button to click
+ */
+ fun clickInstallerUIButton(bySelector: BySelector) {
val startTime = System.currentTimeMillis()
while (startTime + TIMEOUT > System.currentTimeMillis()) {
try {
- uiDevice.wait(Until.findObject(By.res(PACKAGE_INSTALLER_PACKAGE_NAME, resId)), 1000)
- .click()
+ uiDevice.wait(Until.findObject(bySelector), 1000).click()
return
} catch (ignore: Throwable) {
}
}
- Assert.fail("Failed to click the button: $resId")
+ Assert.fail("Failed to click the button: $bySelector")
}
/**
diff --git a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PreapprovalInstallTest.kt b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PreapprovalInstallTest.kt
index de97e273c03..6df76dcf5fb 100644
--- a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PreapprovalInstallTest.kt
+++ b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PreapprovalInstallTest.kt
@@ -16,7 +16,9 @@
package android.packageinstaller.install.cts
+import android.Manifest
import android.app.PendingIntent
+import android.app.compat.CompatChanges
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -25,13 +27,22 @@ import android.content.pm.PackageInstaller
import android.icu.util.ULocale
import android.platform.test.annotations.AppModeFull
import android.provider.DeviceConfig
+import android.support.test.uiautomator.By
+import android.util.Log
+import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.compatibility.common.util.FutureResultActivity
import java.io.File
+import java.util.concurrent.LinkedBlockingQueue
+import java.util.regex.Pattern
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.fail
import org.junit.Assume
+import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -48,7 +59,10 @@ class PreapprovalInstallTest : PackageInstallerTestBase() {
const val TEST_APP_LABEL_PL = "Empty Test App Polish"
const val TEST_APP_LABEL_V2 = "Empty Test App V2"
const val TEST_FAKE_APP_LABEL = "Fake Test App"
+ const val TEST_INSTALLER_APK_NAME = "CtsEmptyInstallerApp.apk"
+ const val TEST_INSTALLER_APK_PACKAGE_NAME = "android.packageinstaller.emptyinstaller.cts"
const val PROPERTY_IS_PRE_APPROVAL_REQUEST_AVAILABLE = "is_preapproval_available"
+ const val CHANGE_ID_PRE_APPROVAL_WITH_UPDATE_OWNERSHIP_FIX = 293644536L
}
private val apkFile_pl = File(context.filesDir, TEST_APK_NAME_PL)
@@ -103,6 +117,130 @@ class PreapprovalInstallTest : PackageInstallerTestBase() {
}
/**
+ * Check that we can request a user pre-approval with updating ownership case, the action of
+ * the EXTRA_INTENT is PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.
+ */
+ @Test
+ fun requestUserPreapprovalWithUpdateOwnership_userAgree_statusSuccess() {
+ // If the build includes the fix, the feature is disabled. Otherwise, it is enabled.
+ assumeFalse(
+ "The rom doesn't include the fix for b/293644536",
+ CompatChanges.isChangeEnabled(CHANGE_ID_PRE_APPROVAL_WITH_UPDATE_OWNERSHIP_FIX)
+ )
+
+ // Get the value of updateOwnership property to restore it finally
+ var isUpdateOwnershipEnforcementAvailable: String? =
+ getDeviceProperty(PROPERTY_IS_UPDATE_OWNERSHIP_ENFORCEMENT_AVAILABLE)
+ setDeviceProperty(PROPERTY_IS_UPDATE_OWNERSHIP_ENFORCEMENT_AVAILABLE, "true")
+
+ // Install the test installer to request update ownership
+ installPackage(TEST_INSTALLER_APK_NAME)
+ // Install the test app and enable update ownership enforcement with the test installer
+ installTestPackage("--update-ownership -i $TEST_INSTALLER_APK_PACKAGE_NAME")
+ assertInstalled()
+
+ var isStatusPendingUserActionCalled = false
+ var installResult = LinkedBlockingQueue<SessionResult>()
+
+ // Create the receiver to handle the install result.
+ // 1. If the Success status comes before STATUS_PENDING_USER_ACTION, we can assert it first
+ // without waiting the timeout.
+ // 2. Assert the action of the EXTRA_INTENT is PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL
+ val receiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val status = intent.getIntExtra(
+ PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE_INVALID
+ )
+
+ val preapproval = intent.getBooleanExtra(
+ PackageInstaller.EXTRA_PRE_APPROVAL,
+ false /* defaultValue */
+ )
+ val msg = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
+ Log.d(TAG, "status: $status, msg: $msg preapproval: $preapproval")
+
+ if (status == PackageInstaller.STATUS_SUCCESS) {
+ // Make sure the PendingUserAction is called before success
+ assertEquals(true, isStatusPendingUserActionCalled)
+ } else if (status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
+ isStatusPendingUserActionCalled = true
+ val activityIntent =
+ intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)
+ assertEquals(
+ PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL,
+ activityIntent!!.action
+ )
+ assertEquals(activityIntent.extras!!.keySet().size, 1)
+ activityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or
+ Intent.FLAG_ACTIVITY_NEW_TASK)
+ installDialogStarter.activity.startActivityForResult(activityIntent)
+ }
+
+ installResult.offer(SessionResult(status, preapproval, msg))
+ }
+ }
+
+ var uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation()
+
+ try {
+ // Adopt the INSTALL_PACKAGES permission
+ uiAutomation.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGES)
+
+ val session = createSession(
+ 0 /* flags */, false /* isMultiPackage */,
+ null /* packageSource */
+ ).second
+
+ // Register the receiver for the install result
+ val action = "PreapprovalInstallTest.install_cb"
+ context.registerReceiver(receiver, IntentFilter(action), Context.RECEIVER_EXPORTED)
+
+ // Request user preapproval
+ FutureResultActivity.doAndAwaitStart {
+ val pendingIntent = PendingIntent.getBroadcast(
+ context, 0 /* requestCode */,
+ Intent(action).setPackage(context.packageName)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
+ )
+ session.requestUserPreapproval(
+ preparePreapprovalDetails(),
+ pendingIntent.intentSender
+ )
+ }
+
+ // The system should have asked us to launch the installer with pre-approval true
+ var result = getInstallSessionResult(installResult)
+ assertEquals(PackageInstaller.STATUS_PENDING_USER_ACTION, result.status)
+ assertEquals(true, result.preapproval)
+
+ // Click the "Update anyway" button on the update ownership dialog
+ clickInstallerUIButton(
+ By.text(
+ Pattern.compile(
+ "UPDATE ANYWAY",
+ Pattern.CASE_INSENSITIVE
+ )
+ )
+ )
+
+ // request should have succeeded
+ result = getInstallSessionResult(installResult)
+ assertEquals(PackageInstaller.STATUS_SUCCESS, result.status)
+ assertEquals(true, result.preapproval)
+ } finally {
+ context.unregisterReceiver(receiver)
+ uninstallPackage(TEST_INSTALLER_APK_PACKAGE_NAME)
+ uiAutomation.dropShellPermissionIdentity()
+ setDeviceProperty(
+ PROPERTY_IS_UPDATE_OWNERSHIP_ENFORCEMENT_AVAILABLE,
+ isUpdateOwnershipEnforcementAvailable
+ )
+ }
+ }
+
+ /**
* Request a user pre-approval, but then cancel it when it prompts.
*/
@Test
@@ -166,9 +304,15 @@ class PreapprovalInstallTest : PackageInstallerTestBase() {
val (sessionId, session) = createSession(0 /* flags */, false /* isMultiPackage */,
null /* packageSource */)
+ val latch = CountDownLatch(1)
val dummyReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- // Do nothing
+ // This is to make sure we receive the pre-approval intent before
+ // committing the session
+ val preapproval = intent.getBooleanExtra(PackageInstaller.EXTRA_PRE_APPROVAL, false)
+ if (preapproval) {
+ latch.countDown()
+ }
}
}
@@ -182,6 +326,7 @@ class PreapprovalInstallTest : PackageInstallerTestBase() {
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
session.requestUserPreapproval(preparePreapprovalDetails(), pendingIntent.intentSender)
+ latch.await(2000, TimeUnit.MILLISECONDS)
writeAndCommitSession(TEST_APK_NAME, session)
clickInstallerUIButton(INSTALL_BUTTON_ID)
diff --git a/tests/tests/packageinstaller/install_appop_default/AndroidTest.xml b/tests/tests/packageinstaller/install_appop_default/AndroidTest.xml
index de65129c403..7e48a7d3eb3 100644
--- a/tests/tests/packageinstaller/install_appop_default/AndroidTest.xml
+++ b/tests/tests/packageinstaller/install_appop_default/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Packageinstaller Session test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/install_appop_denied/AndroidTest.xml b/tests/tests/packageinstaller/install_appop_denied/AndroidTest.xml
index b1d19f80d4e..0f480af1a4d 100644
--- a/tests/tests/packageinstaller/install_appop_denied/AndroidTest.xml
+++ b/tests/tests/packageinstaller/install_appop_denied/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Packageinstaller Session test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/packagescheme/AndroidTestNoVisibility.xml b/tests/tests/packageinstaller/packagescheme/AndroidTestNoVisibility.xml
index 88fc9391c75..0acefa08906 100644
--- a/tests/tests/packageinstaller/packagescheme/AndroidTestNoVisibility.xml
+++ b/tests/tests/packageinstaller/packagescheme/AndroidTestNoVisibility.xml
@@ -17,7 +17,7 @@
<configuration description="Config for CTS Package Scheme Test Cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/packagescheme/AndroidTestVisibility.xml b/tests/tests/packageinstaller/packagescheme/AndroidTestVisibility.xml
index 96385c4ed69..ea57d5f7bd4 100644
--- a/tests/tests/packageinstaller/packagescheme/AndroidTestVisibility.xml
+++ b/tests/tests/packageinstaller/packagescheme/AndroidTestVisibility.xml
@@ -17,7 +17,7 @@
<configuration description="Config for CTS Package Scheme Test Cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/tapjacking/AndroidTest.xml b/tests/tests/packageinstaller/tapjacking/AndroidTest.xml
index 78a60e95a1b..4b11f120bea 100644
--- a/tests/tests/packageinstaller/tapjacking/AndroidTest.xml
+++ b/tests/tests/packageinstaller/tapjacking/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Packageinstaller Tapjacking test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/packageinstaller/uninstall/AndroidTest.xml b/tests/tests/packageinstaller/uninstall/AndroidTest.xml
index cabcb22f79b..021ec19ab72 100644
--- a/tests/tests/packageinstaller/uninstall/AndroidTest.xml
+++ b/tests/tests/packageinstaller/uninstall/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Packageinstaller Uninstall test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index df6110cd2d6..571ba479d82 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -799,7 +799,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
clearTargetSdkWarning()
}
- val useLegacyNavigation = isWatch || isTv || isAutomotive || manuallyNavigate
+ val useLegacyNavigation = isWatch || isAutomotive || manuallyNavigate
if (useLegacyNavigation) {
navigateToAppPermissionSettings()
val permissionLabel = getPermissionLabel(permission)
@@ -843,7 +843,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
if (targetSdk <= MAX_SDK_FOR_SDK_WARNING) {
clearTargetSdkWarning(QUICK_CHECK_TIMEOUT_MILLIS)
}
- val useLegacyNavigation = isWatch || isAutomotive || isTv || manuallyNavigate
+ val useLegacyNavigation = isWatch || isAutomotive || manuallyNavigate
if (useLegacyNavigation) {
navigateToAppPermissionSettings()
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/LocationProviderInterceptDialogTest.kt b/tests/tests/permission3/src/android/permission3/cts/LocationProviderInterceptDialogTest.kt
index 7966d2f3ec2..b092546d280 100644
--- a/tests/tests/permission3/src/android/permission3/cts/LocationProviderInterceptDialogTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/LocationProviderInterceptDialogTest.kt
@@ -23,6 +23,7 @@ import android.content.Intent
import android.location.LocationManager
import android.os.Build
import android.permission.cts.PermissionUtils
+import android.platform.test.annotations.FlakyTest
import androidx.test.filters.SdkSuppress
import androidx.test.uiautomator.By
import com.android.compatibility.common.util.AppOpsUtils
@@ -32,6 +33,7 @@ import java.util.concurrent.TimeUnit
import org.junit.Assert
import org.junit.Assume.assumeFalse
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
private const val EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME"
@@ -43,6 +45,7 @@ private const val ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_
* app in this test).
*/
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+@FlakyTest
@CddTest(requirement = "9.1/C-0-1")
class LocationProviderInterceptDialogTest : BaseUsePermissionTest() {
@Before
@@ -59,6 +62,7 @@ class LocationProviderInterceptDialogTest : BaseUsePermissionTest() {
}
@Test
+ @Ignore("b/288471744")
fun clickLocationPermission_showDialog_clickOk() {
openPermissionScreenForApp()
click(By.text("Location"))
@@ -69,6 +73,7 @@ class LocationProviderInterceptDialogTest : BaseUsePermissionTest() {
}
@Test
+ @Ignore("b/288471744")
fun clickLocationPermission_showDialog_clickLocationAccess() {
openPermissionScreenForApp()
click(By.text("Location"))
@@ -80,6 +85,7 @@ class LocationProviderInterceptDialogTest : BaseUsePermissionTest() {
}
@Test
+ @Ignore("b/288471744")
fun checkRestrictedPermissions() {
context.sendBroadcast(Intent(PermissionTapjackingTest.ACTION_SHOW_OVERLAY)
.putExtra("package", MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME)
diff --git a/tests/tests/provider/src/android/provider/cts/settings/Settings_MemoryUsageTest.java b/tests/tests/provider/src/android/provider/cts/settings/Settings_MemoryUsageTest.java
index 0132e2b2e2b..ef5c67b9f4e 100644
--- a/tests/tests/provider/src/android/provider/cts/settings/Settings_MemoryUsageTest.java
+++ b/tests/tests/provider/src/android/provider/cts/settings/Settings_MemoryUsageTest.java
@@ -37,7 +37,7 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class Settings_MemoryUsageTest {
- private static final String STRING_SETTING = Settings.System.RINGTONE;
+ private static final String STRING_SETTING = Settings.System.SCREEN_BRIGHTNESS;
private static final int sUserId = Process.myUserHandle().getIdentifier();
private ContentResolver mContentResolver;
diff --git a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
index aed73d9857a..24440fb7ebb 100644
--- a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
+++ b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
@@ -16,6 +16,8 @@
package android.provider.cts.settings;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -185,6 +187,17 @@ public class Settings_SystemTest extends StsExtraBusinessLogicTestCase {
}
@Test
+ @AsbSecurityTest(cveBugId = 227201030)
+ public void testInvalidRingtoneUriIsRejected() {
+ final ContentResolver cr = InstrumentationRegistry.getTargetContext().getContentResolver();
+ final String originalValue = System.getString(cr, System.RINGTONE);
+ final String invalidUri = "content://10@media/external/audio/media/1000000019";
+ System.putString(cr, System.RINGTONE, invalidUri);
+ // Assert that the insertion didn't take effect
+ assertThat(System.getString(cr, System.RINGTONE)).isEqualTo(originalValue);
+ }
+
+ @Test
public void testGetDefaultValues() {
final ContentResolver cr = InstrumentationRegistry.getTargetContext().getContentResolver();
diff --git a/tests/tests/resolverservice/AndroidTest.xml b/tests/tests/resolverservice/AndroidTest.xml
index fbd041daef8..99811f591e2 100644
--- a/tests/tests/resolverservice/AndroidTest.xml
+++ b/tests/tests/resolverservice/AndroidTest.xml
@@ -19,7 +19,7 @@
<configuration description="Config for CTS resolver service test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="packagemanager" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index ebf0a42411d..e7168c2568a 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -38,6 +38,9 @@
<!-- For FileIntegrityManager -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
+ <!-- CVE-2023-21143 -->
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+
<application android:usesCleartextTraffic="true">
<uses-library android:name="android.test.runner"/>
<uses-library android:name="org.apache.http.legacy"
diff --git a/tests/tests/security/res/layout/cve_2023_21143.xml b/tests/tests/security/res/layout/cve_2023_21143.xml
new file mode 100644
index 00000000000..d8c68451295
--- /dev/null
+++ b/tests/tests/security/res/layout/cve_2023_21143.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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">
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:src="@raw/cve_2023_21143" />
+
+</LinearLayout>
diff --git a/tests/tests/security/res/raw/cve_2023_21143.png b/tests/tests/security/res/raw/cve_2023_21143.png
new file mode 100644
index 00000000000..ce0fc57eaf6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2023_21143.png
Binary files differ
diff --git a/tests/tests/security/res/values/strings_CVE_2023_21143.xml b/tests/tests/security/res/values/strings_CVE_2023_21143.xml
new file mode 100644
index 00000000000..cef10c77e23
--- /dev/null
+++ b/tests/tests/security/res/values/strings_CVE_2023_21143.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2023 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="channelId">notification_channel_id</string>
+ <string name="channelName">notification_channel_name</string>
+ <string name="failMsg">Device is vulnerable to b/268193777 !!</string>
+ <string name="noPidFound">No pid found for com.android.systemui</string>
+ <string name="notificationSendingFailed">notification has not been sent successfully</string>
+ <string name="notificationText">notification_text</string>
+ <string name="shellCommandForHome">input keyevent KEYCODE_HOME</string>
+ <string name="systemuiPidCommand">pidof com.android.systemui</string>
+</resources>
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index fa99eba0815..880c5c612fa 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -299,6 +299,41 @@ public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
assertTrue(securityException);
}
+ @AsbSecurityTest(cveBugId = 289549315)
+ @Test
+ public void testActivityManager_backupAgentCreated_rejectIfCallerUidNotEqualsPackageUid()
+ throws Exception {
+ SecurityException securityException = null;
+ Exception unexpectedException = null;
+ try {
+ final Object iam = ActivityManager.class.getDeclaredMethod("getService").invoke(null);
+ Class.forName("android.app.IActivityManager").getDeclaredMethod("backupAgentCreated",
+ String.class, IBinder.class, int.class)
+ .invoke(iam, /* agentPackageName*/ "android", /* agent */ null, /* userId */ 0);
+ } catch (SecurityException e) {
+ securityException = e;
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof SecurityException) {
+ securityException = (SecurityException) e.getCause();
+ } else {
+ unexpectedException = e;
+ }
+ } catch (Exception e) {
+ unexpectedException = e;
+ }
+ if (unexpectedException != null) {
+ Log.w("ActivityManagerTest", "Unexpected exception", unexpectedException);
+ fail("ActivityManagerNative.backupAgentCreated() API should have thrown "
+ + "SecurityException when invoked from process with uid not matching target "
+ + "package uid.");
+ }
+
+ assertNotNull("Expected SecurityException when caller's uid doesn't match package uid",
+ securityException);
+ assertEquals("android does not belong to uid " + Process.myUid(),
+ securityException.getMessage());
+ }
+
/**
* Run ActivityManager.getHistoricalProcessExitReasons once, return the time spent on it.
*/
diff --git a/tests/tests/security/src/android/security/cts/CVE_2023_21143.java b/tests/tests/security/src/android/security/cts/CVE_2023_21143.java
new file mode 100644
index 00000000000..756782b3a85
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2023_21143.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 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 androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.sts.common.SystemUtil.poll;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.service.notification.StatusBarNotification;
+import android.widget.RemoteViews;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2023_21143 extends StsExtraBusinessLogicTestCase {
+ private Instrumentation mInstrumentation = null;
+
+ @Test
+ @AsbSecurityTest(cveBugId = 268193777)
+ public void testPocCVE_2023_21143() {
+ Context context = null;
+ try {
+ mInstrumentation = getInstrumentation();
+ context = mInstrumentation.getContext();
+
+ // Getting pid of com.android.systemui
+ final String systemuiPidCommand = context.getString(R.string.systemuiPidCommand);
+ final int initialPidOfSystemUI = getPid(systemuiPidCommand);
+ assumeTrue(context.getString(R.string.noPidFound), initialPidOfSystemUI != -1);
+
+ // Adding a remoteview with large size image to notification in order to reproduce the
+ // vulnerability
+ final String packageName = context.getPackageName();
+ RemoteViews remoteView = new RemoteViews(packageName, R.layout.cve_2023_21143);
+ NotificationChannel channel =
+ new NotificationChannel(
+ context.getString(R.string.channelId),
+ context.getString(R.string.channelName),
+ NotificationManager.IMPORTANCE_HIGH);
+ NotificationManager notificationManager =
+ context.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(channel);
+ Notification notification =
+ new Notification.Builder(context, context.getString(R.string.channelId))
+ .setContentText(context.getString(R.string.notificationText))
+ .setSmallIcon(Icon.createWithData(new byte[0], 0, 0))
+ .setCustomContentView(remoteView)
+ .build();
+ notificationManager.notify(1, notification);
+
+ // Assumption failure if notification has not been posted successfully.
+ assumeTrue(
+ context.getString(R.string.notificationSendingFailed),
+ poll(
+ () -> {
+ for (StatusBarNotification sbn :
+ notificationManager.getActiveNotifications()) {
+ if (sbn.getPackageName().equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }));
+
+ // Without fix, the systemui crashes and it's pid changes.
+ // Fail test only if pid has changed and notification is still visible.
+ boolean isDeviceVulnerable = false;
+ if (poll(() -> getPid(systemuiPidCommand) != initialPidOfSystemUI)) {
+ for (StatusBarNotification sbn : notificationManager.getActiveNotifications()) {
+ isDeviceVulnerable = sbn.getPackageName().equals(context.getPackageName());
+ if (isDeviceVulnerable) {
+ break;
+ }
+ }
+ }
+ assertFalse(context.getString(R.string.failMsg), isDeviceVulnerable);
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // In case of without fix, a crash window stays.
+ SystemUtil.runShellCommand(
+ mInstrumentation, context.getString(R.string.shellCommandForHome));
+ } catch (Exception ignore) {
+ // ignore
+ }
+ }
+ }
+
+ private int getPid(String commandToFindPid) {
+ try {
+ // Getting pid of com.android.systemui
+ return Integer.parseInt(
+ SystemUtil.runShellCommand(mInstrumentation, commandToFindPid).trim());
+ } catch (Exception e) {
+ // ignore and return -1
+ return -1;
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2023_40119.java b/tests/tests/security/src/android/security/cts/CVE_2023_40119.java
new file mode 100644
index 00000000000..96a7f29ce61
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2023_40119.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 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.assertEquals;
+import static org.junit.Assume.assumeNoException;
+
+import android.net.Uri;
+import android.os.Parcel;
+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_2023_40119 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 231476072)
+ @Test
+ public void testPocCVE_2023_40119() {
+ try {
+ Parcel parcel = Parcel.obtain();
+
+ // Create an evil URI passing a scheme (that hides an unsafe authority and the ssp both)
+ // , a fake ssp and a fragment to Uri.fromParts() and write the evil URI to a parcel.
+ Uri.fromParts(
+ "scheme://notAllowedAuthorityAndSsp" /* scheme */,
+ "allowedAuthorityAndSsp" /* scheme-specific-part */,
+ "fragment" /* fragment */)
+ .writeToParcel(parcel, 0 /* No additional flags or options */);
+ parcel.setDataPosition(0);
+
+ Uri uriFromParcel = Uri.CREATOR.createFromParcel(parcel);
+
+ // Without fix, the scheme from parsing the string representation of uriFromParcel will
+ // return "scheme" as Uri parser checks for the delimiter ':' but the scheme from
+ // uriFromParcel.getScheme() will return "scheme://notAllowedAuthorityAndSsp" which
+ // hides the "not allowed" authority ("notAllowedAuthorityAndSsp") in the scheme
+ // enabling bypass of authority checks.
+ assertEquals(
+ "Vulnerable to b/231476072 !!, URIs are not canonicalized across AIDL"
+ + " boundaries",
+ Uri.parse(uriFromParcel.toString()).getScheme(),
+ uriFromParcel.getScheme());
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index d088d0a77bc..9c8cd1e961a 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -24,21 +24,74 @@ package android.security.cts;
* to generate this file.
*/
class CertificateData {
+ static final String[] OPTIONAL_CERTIFICATE_DATA = {
+ "B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0",
+ "FF:BD:CD:E7:82:C8:43:5E:3C:6F:26:86:5C:CA:A8:3A:45:5B:C3:0A",
+ "51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39",
+ "58:D1:DF:95:95:67:6B:63:C0:F0:5B:1C:17:4D:8B:84:0B:C8:78:BD",
+ "6B:A0:B0:98:E1:71:EF:5A:AD:FE:48:15:80:77:10:F4:BD:6F:0B:28",
+ "53:A2:B0:4B:CA:6B:D6:45:E6:39:8A:8E:C4:0D:D2:BF:77:C3:A2:90",
+ "D0:67:C1:13:51:01:0C:AA:D0:C7:6A:65:37:31:16:26:4F:53:71:A2",
+ "17:F3:DE:5E:9F:0F:19:E9:8E:F6:1F:32:26:6E:20:C4:07:AE:30:EE",
+ "F3:3E:78:3C:AC:DF:F4:A2:CC:AC:67:55:69:56:D7:E5:16:3C:E1:ED",
+ "BC:B0:C1:9D:E9:98:92:70:19:38:57:E9:8D:A7:B4:5D:6E:EE:01:48",
+ "6A:92:E4:A8:EE:1B:EC:96:45:37:E3:29:57:49:CD:96:E3:E5:D2:60",
+ "77:D3:03:67:B5:E0:0C:15:F6:0C:38:61:DF:7C:E1:3B:92:46:4D:47",
+ "62:FF:D9:9E:C0:65:0D:03:CE:75:93:D2:ED:3F:2D:32:C9:E3:E5:4A",
+ "F9:E1:6D:DC:01:89:CF:D5:82:45:63:3E:C5:37:7D:C2:EB:93:6F:2B",
+ "ED:E5:71:80:2B:C8:92:B9:5B:83:3C:D2:32:68:3F:09:CD:A0:1E:46",
+ "C3:03:C8:22:74:92:E5:61:A2:9C:5F:79:91:2B:1E:44:13:91:30:3A",
+ "BD:B1:B9:3C:D5:97:8D:45:C6:26:14:55:F8:DB:95:C7:5A:D1:53:AF",
+ "5B:6E:68:D0:CC:15:B6:A0:5F:1E:C1:5F:AE:02:FC:6B:2F:5D:6F:74",
+ "84:1A:69:FB:F5:CD:1A:25:34:13:3D:E3:F8:FC:B8:99:D0:C9:14:B7",
+ "61:DB:8C:21:59:69:03:90:D8:7C:9C:12:86:54:CF:9D:3D:F4:DD:07",
+ "1F:5B:98:F0:E3:B5:F7:74:3C:ED:E6:B0:36:7D:32:CD:F4:09:41:67",
+ "02:2D:05:82:FA:88:CE:14:0C:06:79:DE:7F:14:10:E9:45:D7:A5:6D",
+ "A7:88:49:DC:5D:7C:75:8C:8C:DE:39:98:56:B3:AA:D0:B2:A5:71:35",
+ "9A:44:49:76:32:DB:DE:FA:D0:BC:FB:5A:7B:17:BD:9E:56:09:24:94",
+ "B8:0E:26:A9:BF:D2:B2:3B:C0:EF:46:C9:BA:C7:BB:F6:1D:0D:41:41",
+ "0B:BE:C2:27:22:49:CB:39:AA:DB:35:5C:53:E3:8C:AE:78:FF:B6:FE",
+ "A0:50:EE:0F:28:71:F4:27:B2:12:6D:6F:50:96:25:BA:CC:86:42:AF",
+ "CF:E9:70:84:0F:E0:73:0F:9D:F6:0C:7F:2C:4B:EE:20:46:34:9C:BB",
+ "39:B4:6C:D5:FE:80:06:EB:E2:2F:4A:BB:08:33:A0:AF:DB:B9:DD:84",
+ "F6:9C:DB:B0:FC:F6:02:13:B6:52:32:A6:A3:91:3F:16:70:DA:C3:E1",
+ "E5:8C:1C:C4:91:3B:38:63:4B:E9:10:6E:E3:AD:8E:6B:9D:D9:81:4A",
+ "B9:99:CD:D1:73:50:8A:C4:47:05:08:9C:8C:88:FB:BE:A0:2B:40:CD",
+ "C8:83:44:C0:18:AE:9F:CC:F1:87:B7:8F:22:D1:C5:D7:45:84:BA:E5",
+ "69:69:56:2E:40:80:F4:24:A1:E7:19:9F:14:BA:F3:EE:58:AB:6A:BB",
+ "75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE",
+ "DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13",
+ "78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C",
+ "8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0",
+ "74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE",
+ "5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6",
+ "76:E2:7E:C1:4F:DB:82:C1:C0:A6:75:B5:05:BE:3D:29:B4:ED:DB:BB",
+ "FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D",
+ "36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54",
+ "D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC",
+ "2A:1D:60:27:D9:4A:B1:0A:1C:4D:91:5C:CD:33:A0:CB:3E:2D:54:CB",
+ "DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9",
+ "30:D4:24:6F:07:FF:DB:91:89:8A:0B:E9:49:66:11:EB:8C:5E:46:E5",
+ "4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C",
+ "37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27",
+ "28:90:3A:63:5B:52:80:FA:E6:77:4C:0B:6D:A7:D6:BA:A6:4A:F2:E8",
+ "3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04",
+ "D2:73:96:2A:2A:5E:39:9F:73:3F:E1:C7:1E:64:3F:03:38:34:FC:4D",
+ "E1:C9:50:E6:EF:22:F8:4C:56:45:72:8B:92:20:60:D7:D5:A7:A3:E8"
+ };
+
static final String[] CERTIFICATE_DATA = {
"99:9A:64:C3:7F:F4:7D:9F:AB:95:F1:47:69:89:14:60:EE:C4:C3:C5",
"D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0",
- "6B:A0:B0:98:E1:71:EF:5A:AD:FE:48:15:80:77:10:F4:BD:6F:0B:28",
"92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F",
"B4:90:82:DD:45:0C:BE:8B:5B:B1:66:D3:E2:A4:08:26:CD:ED:42:CF",
"53:A2:B0:4B:CA:6B:D6:45:E6:39:8A:8E:C4:0D:D2:BF:77:C3:A2:90",
"58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0",
"55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1",
"D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD",
- "D0:67:C1:13:51:01:0C:AA:D0:C7:6A:65:37:31:16:26:4F:53:71:A2",
"09:3C:61:F3:8B:8B:DC:7D:55:DF:75:38:02:05:00:E1:25:F5:C8:36",
"27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4",
"AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A",
- "17:F3:DE:5E:9F:0F:19:E9:8E:F6:1F:32:26:6E:20:C4:07:AE:30:EE",
"1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46:3A:1B:69:AA",
"DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57",
"2D:0D:52:14:FF:9E:AD:99:24:01:74:20:47:6E:6C:85:27:27:F5:43",
@@ -52,7 +105,6 @@ class CertificateData {
"E0:11:84:5E:34:DE:BE:88:81:B9:9C:F6:16:26:D1:96:1F:C3:B9:31",
"93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17",
"50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31",
- "F3:3E:78:3C:AC:DF:F4:A2:CC:AC:67:55:69:56:D7:E5:16:3C:E1:ED",
"8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4",
"2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19",
"BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD",
@@ -62,7 +114,6 @@ class CertificateData {
"6A:92:E4:A8:EE:1B:EC:96:45:37:E3:29:57:49:CD:96:E3:E5:D2:60",
"74:3A:F0:52:9B:D0:32:A0:F4:4A:83:CD:D4:BA:A9:7B:7C:2E:C4:9A",
"66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B",
- "77:D3:03:67:B5:E0:0C:15:F6:0C:38:61:DF:7C:E1:3B:92:46:4D:47",
"F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC",
"62:FF:D9:9E:C0:65:0D:03:CE:75:93:D2:ED:3F:2D:32:C9:E3:E5:4A",
"F9:E1:6D:DC:01:89:CF:D5:82:45:63:3E:C5:37:7D:C2:EB:93:6F:2B",
@@ -70,8 +121,6 @@ class CertificateData {
"CA:BD:2A:79:A1:07:6A:31:F2:1D:25:36:35:CB:03:9D:43:29:A5:E8",
"43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37",
"05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43",
- "ED:E5:71:80:2B:C8:92:B9:5B:83:3C:D2:32:68:3F:09:CD:A0:1E:46",
- "C3:03:C8:22:74:92:E5:61:A2:9C:5F:79:91:2B:1E:44:13:91:30:3A",
"D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49",
"B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6",
"4C:DD:51:A3:D1:F5:20:32:14:B0:C6:C5:32:23:03:91:C7:46:42:6D",
@@ -102,7 +151,6 @@ class CertificateData {
"67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0",
"DD:FB:16:CD:49:31:C9:73:A2:03:7D:3F:C8:3A:4D:7D:77:5D:05:E4",
"36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7",
- "61:DB:8C:21:59:69:03:90:D8:7C:9C:12:86:54:CF:9D:3D:F4:DD:07",
"E2:52:FA:95:3F:ED:DB:24:60:BD:6E:28:F3:9C:CC:CF:5E:B3:3F:DE",
"26:F9:93:B4:ED:3D:28:27:B0:B9:4B:A7:E9:15:1D:A3:8D:92:E5:32",
"3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3",
@@ -122,8 +170,6 @@ class CertificateData {
"B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9",
"A7:88:49:DC:5D:7C:75:8C:8C:DE:39:98:56:B3:AA:D0:B2:A5:71:35",
"F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89",
- "9A:44:49:76:32:DB:DE:FA:D0:BC:FB:5A:7B:17:BD:9E:56:09:24:94",
- "B8:0E:26:A9:BF:D2:B2:3B:C0:EF:46:C9:BA:C7:BB:F6:1D:0D:41:41",
"DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4",
"D3:DD:48:3E:2B:BF:4C:05:E8:AF:10:F5:FA:76:26:CF:D3:DC:30:92",
"B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB",
@@ -150,9 +196,6 @@ class CertificateData {
"89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E",
"7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E",
"2F:8F:36:4F:E1:58:97:44:21:59:87:A5:2A:9A:D0:69:95:26:7F:B5",
- "F6:9C:DB:B0:FC:F6:02:13:B6:52:32:A6:A3:91:3F:16:70:DA:C3:E1",
- "E5:8C:1C:C4:91:3B:38:63:4B:E9:10:6E:E3:AD:8E:6B:9D:D9:81:4A",
- "B9:99:CD:D1:73:50:8A:C4:47:05:08:9C:8C:88:FB:BE:A0:2B:40:CD",
"14:88:4E:86:26:37:B0:26:AF:59:62:5C:40:77:EC:35:29:BA:96:01",
"8A:C7:AD:8F:73:AC:4E:C1:B5:75:4D:A5:40:F4:FC:CF:7C:B5:8E:8C",
"C8:83:44:C0:18:AE:9F:CC:F1:87:B7:8F:22:D1:C5:D7:45:84:BA:E5",
diff --git a/tests/tests/security/src/android/security/cts/CertificateTest.java b/tests/tests/security/src/android/security/cts/CertificateTest.java
index 75693383995..875d0aae2ab 100644
--- a/tests/tests/security/src/android/security/cts/CertificateTest.java
+++ b/tests/tests/security/src/android/security/cts/CertificateTest.java
@@ -97,8 +97,11 @@ public class CertificateTest {
System.setProperty("system.certs.enabled", mApexCertsEnabled);
Set<String> expectedCertificates = new HashSet<String>(
Arrays.asList(CertificateData.CERTIFICATE_DATA));
+ Set<String> optionalCertificates = new HashSet<String>(
+ Arrays.asList(CertificateData.OPTIONAL_CERTIFICATE_DATA));
Set<String> deviceCertificates = getDeviceCertificates();
deviceCertificates.removeAll(expectedCertificates);
+ deviceCertificates.removeAll(optionalCertificates);
assertEquals("Unknown CA certificates", Collections.EMPTY_SET, deviceCertificates);
}
diff --git a/tests/tests/sharesheet/AndroidTest.xml b/tests/tests/sharesheet/AndroidTest.xml
index 5a3c8354f0b..f198341a740 100644
--- a/tests/tests/sharesheet/AndroidTest.xml
+++ b/tests/tests/sharesheet/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for CTS Sharesheet test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="sysui" />
<!-- Instant apps can't access ShortcutManager -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/tests/tests/soundtrigger/AndroidTest.xml b/tests/tests/soundtrigger/AndroidTest.xml
index f6df62c4ca0..f9aa79ccff9 100644
--- a/tests/tests/soundtrigger/AndroidTest.xml
+++ b/tests/tests/soundtrigger/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS Voice Interaction test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="media" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 7b8b8654396..9c2b522d52d 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -78,14 +78,6 @@
</intent-filter>
</service>
- <service android:name="android.telecom.cts.CtsSimCallManagerConnectionService"
- android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
- android:exported="true">
- <intent-filter>
- <action android:name="android.telecom.ConnectionService"/>
- </intent-filter>
- </service>
-
<service android:name="android.telecom.cts.CtsSelfManagedConnectionService"
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
android:exported="true">
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index b0eca398b99..d2deeaf508a 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -140,7 +140,7 @@ public class CallDetailsTest extends BaseTelecomTestWithMockServices {
getInstrumentation().getTargetContext().getContentResolver();
try {
mContactUri = insertContactWithPhoto(
- resolver, getTestNumber().toString());
+ resolver, getTestNumber().getSchemeSpecificPart());
} catch (Exception e) {
assertTrue("Failed to insert test contact into ContactsProvider", false);
}
@@ -414,7 +414,7 @@ public class CallDetailsTest extends BaseTelecomTestWithMockServices {
if (!mShouldTestTelecom) {
return;
}
- String phoneNumber = getTestNumber().toString();
+ String phoneNumber = getTestNumber().getSchemeSpecificPart();
Uri contactRef = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
.appendPath(phoneNumber)
diff --git a/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java
index 883d8448000..06b9e12cf0a 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java
@@ -45,6 +45,8 @@ public class CarModeInCallServiceTest extends BaseTelecomTestWithMockServices {
private static final int ASYNC_TIMEOUT = 10000;
private static final String CARMODE_APP1_PACKAGE = "android.telecom.cts.carmodetestapp";
private static final String CARMODE_APP2_PACKAGE = "android.telecom.cts.carmodetestapptwo";
+ // Flag to temp disable (flaky) test
+ private static final boolean SHOULD_IGNORE_TEST = true;
private ICtsCarModeInCallServiceControl mCarModeIncallServiceControlOne;
private ICtsCarModeInCallServiceControl mCarModeIncallServiceControlTwo;
@@ -577,7 +579,7 @@ public class CarModeInCallServiceTest extends BaseTelecomTestWithMockServices {
}
public void testSwitchToCarModeWhenEnableCarModeApp() throws Exception {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || SHOULD_IGNORE_TEST) {
return;
}
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsSimCallManagerConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsSimCallManagerConnectionService.java
deleted file mode 100644
index 731f09f9499..00000000000
--- a/tests/tests/telecom/src/android/telecom/cts/CtsSimCallManagerConnectionService.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2015 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.telecom.cts;
-
-import android.content.Intent;
-import android.telecom.Conference;
-import android.telecom.Connection;
-import android.telecom.ConnectionRequest;
-import android.telecom.ConnectionService;
-import android.telecom.PhoneAccountHandle;
-import android.telecom.RemoteConference;
-import android.telecom.RemoteConnection;
-import android.util.Log;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * This is the official ConnectionService for Telecom's CTS App. Since telecom requires that a
- * CS be registered in the AndroidManifest.xml file, we have to have a single implementation
- * of a CS and this is it. To test specific CS behavior, tests will implement their own CS and
- * tell CtsConnectionService to forward any method invocations to that test's implementation.
- * This is set up using {@link #setUp} and should be cleaned up before the end of the test using
- * {@link #tearDown}.
- *
- * sConnectionService: Contains the connection service object provided by the current test in
- * progress. We use this object to forward any communication received from the
- * Telecom framework to the test connection service.
- * sTelecomConnectionService: Contains the connection service object registered to the Telecom
- * framework. We use this object to forward any communication from the
- * test connection service to the Telecom framework. After Telecom
- * binds to CtsConnectionService, this is set to be the instance of
- * CtsConnectionService created by the framework after Telecom binds.
- */
-public class CtsSimCallManagerConnectionService extends ConnectionService {
- private static final String LOG_TAG = "CtsSimCallManagerConnectionService";
- // This is the connection service implemented by the test
- private static ConnectionService sConnectionService;
- // This is the connection service registered with Telecom
- private static ConnectionService sTelecomConnectionService;
- private static boolean sIsBound = false;
- private static CountDownLatch sServiceUnBoundLatch = new CountDownLatch(1);
-
- @Override
- public void onBindClient(Intent intent) {
- sTelecomConnectionService = this;
- Log.i("TelecomCTS", "CS (sim call mgr) bound");
- sIsBound = true;
- }
-
- private static Object sLock = new Object();
-
- public static void setUp(ConnectionService connectionService) throws Exception {
- synchronized (sLock) {
- if (sConnectionService != null) {
- throw new Exception("Mock ConnectionService exists. Failed to call setUp().");
- }
- sConnectionService = connectionService;
- }
- }
-
- public static void tearDown() {
- synchronized (sLock) {
- sConnectionService = null;
- sTelecomConnectionService = null;
- }
- }
-
- @Override
- public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- return sConnectionService.onCreateOutgoingConnection(
- connectionManagerPhoneAccount, request);
- } else {
- Log.e(LOG_TAG,
- "Tried to create outgoing connection when sConnectionService null!");
- return null;
- }
- }
- }
-
- @Override
- public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- return sConnectionService.onCreateIncomingConnection(
- connectionManagerPhoneAccount, request);
- } else {
- Log.e(LOG_TAG,
- "Tried to create incoming connection when sConnectionService null!");
- return null;
- }
- }
- }
-
- @Override
- public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- if (sConnectionService != null) {
- sConnectionService.onCreateIncomingConnectionFailed(connectionManagerPhoneAccount,
- request);
- } else {
- Log.e(LOG_TAG,
- "onCreateIncomingConnectionFailed called when sConnectionService null!");
- }
- }
-
- @Override
- public Conference onCreateOutgoingConference(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- return sConnectionService.onCreateOutgoingConference(connectionManagerPhoneAccount,
- request);
- } else {
- Log.e(LOG_TAG,
- "onCreateOutgoingConference called when sConnectionService null!");
- return null;
- }
- }
- }
-
- @Override
- public void onCreateOutgoingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- sConnectionService.onCreateOutgoingConferenceFailed(connectionManagerPhoneAccount,
- request);
- } else {
- Log.e(LOG_TAG,
- "onCreateOutgoingConferenceFailed called when sConnectionService null!");
- }
- }
- }
-
- @Override
- public Conference onCreateIncomingConference(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- return sConnectionService.onCreateIncomingConference(connectionManagerPhoneAccount,
- request);
- } else {
- Log.e(LOG_TAG,
- "onCreateIncomingConference called when sConnectionService null!");
- return null;
- }
- }
- }
-
- @Override
- public void onCreateIncomingConferenceFailed(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- sConnectionService.onCreateIncomingConferenceFailed(connectionManagerPhoneAccount,
- request);
- } else {
- Log.e(LOG_TAG,
- "onCreateIncomingConferenceFailed called when sConnectionService null!");
- }
- }
- }
-
- @Override
- public void onConference(Connection connection1, Connection connection2) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- sConnectionService.onConference(connection1, connection2);
- } else {
- Log.e(LOG_TAG,
- "onConference called when sConnectionService null!");
- }
- }
- }
-
- @Override
- public void onRemoteExistingConnectionAdded(RemoteConnection connection) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- sConnectionService.onRemoteExistingConnectionAdded(connection);
- } else {
- Log.e(LOG_TAG,
- "onRemoteExistingConnectionAdded called when sConnectionService null!");
- }
- }
- }
-
- public static void addConferenceToTelecom(Conference conference) {
- synchronized (sLock) {
- if (sTelecomConnectionService != null) {
- sTelecomConnectionService.addConference(conference);
- } else {
- Log.e(LOG_TAG, "addConferenceToTelecom called when"
- + " sTelecomConnectionService null!");
- }
- }
- }
-
- public static void addExistingConnectionToTelecom(
- PhoneAccountHandle phoneAccountHandle, Connection connection) {
- synchronized (sLock) {
- if (sTelecomConnectionService != null) {
- sTelecomConnectionService.addExistingConnection(phoneAccountHandle, connection);
- } else {
- Log.e(LOG_TAG, "addExistingConnectionToTelecom called when"
- + " sTelecomConnectionService null!");
- }
- }
- }
-
- public static Collection<Connection> getAllConnectionsFromTelecom() {
- synchronized (sLock) {
- if (sTelecomConnectionService == null) {
- return Collections.EMPTY_LIST;
- }
- return sTelecomConnectionService.getAllConnections();
- }
- }
-
- public static RemoteConnection createRemoteOutgoingConnectionToTelecom(
- PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sTelecomConnectionService != null) {
- return sTelecomConnectionService.createRemoteOutgoingConnection(
- connectionManagerPhoneAccount, request);
- } else {
- Log.e(LOG_TAG, "createRemoteOutgoingConnectionToTelecom called when"
- + " sTelecomConnectionService null!");
- return null;
- }
- }
- }
-
- public static RemoteConnection createRemoteIncomingConnectionToTelecom(
- PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sTelecomConnectionService != null) {
- return sTelecomConnectionService.createRemoteIncomingConnection(
- connectionManagerPhoneAccount, request);
- } else {
- Log.e(LOG_TAG, "createRemoteIncomingConnectionToTelecom called when"
- + " sTelecomConnectionService null!");
- return null;
- }
- }
- }
-
- public static RemoteConference createRemoteIncomingConferenceToTelecom(
- PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sTelecomConnectionService != null) {
- return sTelecomConnectionService.createRemoteIncomingConference(
- connectionManagerPhoneAccount, request);
- } else {
- Log.e(LOG_TAG, "createRemoteIncomingConferenceToTelecom called when"
- + " sTelecomConnectionService null!");
- return null;
- }
- }
- }
-
-
- public static RemoteConference createRemoteOutgoingConferenceToTelecom(
- PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
- synchronized (sLock) {
- if (sTelecomConnectionService != null) {
- return sTelecomConnectionService.createRemoteOutgoingConference(
- connectionManagerPhoneAccount, request);
- } else {
- Log.e(LOG_TAG, "createRemoteOutgoingConferenceToTelecom called when"
- + " sTelecomConnectionService null!");
- return null;
- }
- }
- }
-
- @Override
- public void onRemoteConferenceAdded(RemoteConference conference) {
- synchronized (sLock) {
- if (sConnectionService != null) {
- sConnectionService.onRemoteConferenceAdded(conference);
- } else {
- Log.e(LOG_TAG,
- "onRemoteConferenceAdded called when sConnectionService null!");
- }
- }
- }
-
- @Override
- public void onConnectionServiceFocusGained() {
- synchronized (sLock) {
- if (sConnectionService != null) {
- sConnectionService.onConnectionServiceFocusGained();
- } else {
- Log.e(LOG_TAG,
- "onConnectionServiceFocusGained called when sConnectionService null!");
- }
- }
- }
-
- @Override
- public void onConnectionServiceFocusLost() {
- synchronized (sLock) {
- if (sConnectionService != null) {
- sConnectionService.onConnectionServiceFocusLost();
- } else {
- Log.e(LOG_TAG,
- "onConnectionServiceFocusLost called when sConnectionService null!");
- }
- }
- }
-
- @Override
- public boolean onUnbind(Intent intent) {
- synchronized (sLock) {
- Log.i(LOG_TAG, "Service has been unbound");
- sIsBound = false;
- sServiceUnBoundLatch.countDown();
- sConnectionService = null;
- sTelecomConnectionService = null;
- return super.onUnbind(intent);
- }
- }
-
- public static boolean isServiceRegisteredToTelecom() {
- return sTelecomConnectionService != null;
- }
-
- public static boolean isBound() {
- return sIsBound;
- }
-
- public static boolean waitForUnBinding() {
- return TestUtils.waitForLatchCountDown(sServiceUnBoundLatch);
- }
-}
diff --git a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallOnSimCallManagerTest.java b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallOnSimCallManagerTest.java
index 69d564f80c4..5cc1f70c80a 100644
--- a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallOnSimCallManagerTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallOnSimCallManagerTest.java
@@ -17,6 +17,7 @@
package android.telecom.cts;
import static android.telecom.cts.TestUtils.ACCOUNT_ID_1;
+import static android.telecom.cts.TestUtils.ACCOUNT_ID_EMERGENCY;
import static android.telecom.cts.TestUtils.ACCOUNT_LABEL;
import static android.telecom.cts.TestUtils.PACKAGE;
@@ -45,11 +46,14 @@ import java.util.concurrent.TimeUnit;
public class EmergencyCallOnSimCallManagerTest extends BaseTelecomTestWithMockServices {
private static final String TAG = "EmergencyCallOnSimCallManagerTest";
public static final String SIM_CALL_MANAGER_COMPONENT =
- "android.telecom.cts.CtsSimCallManagerConnectionService";
+ CtsConnectionService.class.getCanonicalName();
public static final PhoneAccountHandle TEST_SIM_CALL_MANAGER_PHONE_ACCOUNT_HANDLE =
new PhoneAccountHandle(new ComponentName(PACKAGE, SIM_CALL_MANAGER_COMPONENT),
ACCOUNT_ID_1);
+ public static final PhoneAccountHandle TEST_SIM_EMERGENCY_PHONE_ACCOUNT_HANDLE =
+ new PhoneAccountHandle(new ComponentName(PACKAGE, SIM_CALL_MANAGER_COMPONENT),
+ ACCOUNT_ID_EMERGENCY);
public static final PhoneAccount TEST_SIM_CALL_MANAGER_ACCOUNT = PhoneAccount.builder(
TEST_SIM_CALL_MANAGER_PHONE_ACCOUNT_HANDLE, ACCOUNT_LABEL)
.setAddress(Uri.parse("tel:555-TEST"))
@@ -61,7 +65,6 @@ public class EmergencyCallOnSimCallManagerTest extends BaseTelecomTestWithMockSe
.build();
private static final String TEST_PROVIDER = "test_provider";
- private static final Uri TEST_ADDRESS_1 = Uri.fromParts("sip", "call1@test.com", null);
@Override
public void setUp() throws Exception {
@@ -71,8 +74,7 @@ public class EmergencyCallOnSimCallManagerTest extends BaseTelecomTestWithMockSe
if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
try {
- setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
-
+ setupConnectionService(null, 0);
mTelecomManager.registerPhoneAccount(TEST_SIM_CALL_MANAGER_ACCOUNT);
TestUtils.enablePhoneAccount(getInstrumentation(),
TEST_SIM_CALL_MANAGER_PHONE_ACCOUNT_HANDLE);
@@ -295,7 +297,7 @@ public class EmergencyCallOnSimCallManagerTest extends BaseTelecomTestWithMockSe
TestUtils.setTestEmergencyPhoneAccountPackageFilter(getInstrumentation(), mContext);
// Emergency calls require special capabilities.
TestUtils.registerEmergencyPhoneAccount(getInstrumentation(),
- TEST_SIM_CALL_MANAGER_PHONE_ACCOUNT_HANDLE,
+ TEST_SIM_EMERGENCY_PHONE_ACCOUNT_HANDLE,
TestUtils.ACCOUNT_LABEL + "E", "tel:555-EMER");
mIsEmergencyCallingSetup = true;
}
@@ -306,6 +308,6 @@ public class EmergencyCallOnSimCallManagerTest extends BaseTelecomTestWithMockSe
TestUtils.clearSystemDialerOverride(getInstrumentation());
TestUtils.clearTestEmergencyNumbers(getInstrumentation());
TestUtils.clearTestEmergencyPhoneAccountPackageFilter(getInstrumentation());
- mTelecomManager.unregisterPhoneAccount(TEST_SIM_CALL_MANAGER_PHONE_ACCOUNT_HANDLE);
+ mTelecomManager.unregisterPhoneAccount(TEST_SIM_EMERGENCY_PHONE_ACCOUNT_HANDLE);
}
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
index 783200e7da0..117ab1a16a3 100644
--- a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
+++ b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
@@ -45,6 +45,8 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
private static final String DUMPSYS_COMMAND = "dumpsys telecom";
private static final int MIN_LINES_PER_DROPBOX_ENTRY = 15;
private static final int MAX_READ_BYTES_PER_DROP_BOX_ENTRY = 5000;
+ private static final long DAYS_BACK_TO_SEARCH_EMERGENCY_DROP_BOX_ENTRIES_IN_MS =
+ 30L * 24L * 60L * 60L * 1000L;
private static final String DIAG_ERROR_MSG = "DiagnosticDataCollector error executing cmd";
private CountDownLatch mLatchForDropBox;
private IntentFilter dropBoxIntentFilter;
@@ -170,11 +172,10 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
for (String line : content) {
assertFalse(line.contains(DIAG_ERROR_MSG));
//verify that telecom dumpsys output also has this data
- if (lineCount < MAX_LINES_TO_VERIFY_IN_DUMPSYS_OUTPUT) {
+ if (lineCount++ < MAX_LINES_TO_VERIFY_IN_DUMPSYS_OUTPUT) {
//we only check top x lines to verify presence in dumpsys output
assertTrue("line not found: " + line, dumpOutput.contains(line));
}
-
}
entry = dm.getNextEntry(DROPBOX_TAG, entryTime);
if(totalEntries >= 3)
@@ -187,7 +188,8 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
*/
public void testEmergencyCallFailureCreatesDropboxEntries() throws Exception {
if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
- long startTime = System.currentTimeMillis();
+ long startTime = System.currentTimeMillis()
+ - DAYS_BACK_TO_SEARCH_EMERGENCY_DROP_BOX_ENTRIES_IN_MS;
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java b/tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java
index 04b30f3b232..48ca465d5f6 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java
@@ -43,11 +43,13 @@ import androidx.test.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiTest;
+import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/** Test MockModemService interfaces. */
@@ -55,12 +57,13 @@ public class ConnectivityManagerTestOnMockModem {
private static final String TAG = "ConnectivityManagerTestOnMockModem";
private static final int TIMEOUT_NETWORK_VALIDATION = 20000;
private static final int WAIT_MSEC = 500;
+ private static final int NETWORK_AVAILABLE_SEC = 60;
private static boolean sIsValidate;
private static boolean sIsOnAvailable;
private static Network sDefaultNetwork;
private static Object sIsValidateLock = new Object();
private static Object sIsOnAvailableLock = new Object();
- private static NetworkCallback sNetworkCallback;
+ private static CMNetworkCallback sNetworkCallback;
private static MockModemManager sMockModemManager;
private static TelephonyManager sTelephonyManager;
private static ConnectivityManager sConnectivityManager;
@@ -69,6 +72,69 @@ public class ConnectivityManagerTestOnMockModem {
private static final boolean DEBUG = !"user".equals(Build.TYPE);
private static boolean sIsMultiSimDevice;
+ private static class CMNetworkCallback extends NetworkCallback {
+ final CountDownLatch mNetworkLatch = new CountDownLatch(1);
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
+ sDefaultNetwork = network;
+ Log.d(
+ TAG,
+ "Network capabilities changed. network: "
+ + network
+ + ", NetworkCapabilities: "
+ + nc);
+
+ if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
+ Log.d(
+ TAG,
+ "Network capabilities changed. network: "
+ + network
+ + " ,validation: Pass!");
+ synchronized (sIsValidateLock) {
+ sIsValidate = true;
+ sIsValidateLock.notify();
+ }
+ } else {
+ Log.d(
+ TAG,
+ "Network capabilities changed. network: "
+ + network
+ + " ,validation: Fail!");
+ synchronized (sIsValidateLock) {
+ sIsValidate = false;
+ }
+ }
+ }
+
+ @Override
+ public void onLost(Network network) {
+ sDefaultNetwork = network;
+ Log.d(TAG, "onLost(): network: " + network);
+ synchronized (sIsOnAvailableLock) {
+ sIsOnAvailable = false;
+ }
+ }
+
+ @Override
+ public void onAvailable(Network network) {
+ sDefaultNetwork = network;
+ Log.d(TAG, "onAvailable(): network: " + network);
+ synchronized (sIsOnAvailableLock) {
+ sIsOnAvailable = true;
+ mNetworkLatch.countDown();
+ }
+ }
+
+ public void awaitNetwork() throws InterruptedException {
+ Log.d(TAG, "awaitNetwork(): " + NETWORK_AVAILABLE_SEC + " sec");
+ mNetworkLatch.await(NETWORK_AVAILABLE_SEC, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {}
+ }
+
@BeforeClass
public static void beforeAllTests() throws Exception {
TimeUnit.SECONDS.sleep(10);
@@ -117,8 +183,6 @@ public class ConnectivityManagerTestOnMockModem {
sMockModemManager = new MockModemManager();
assertNotNull(sMockModemManager);
assertTrue(sMockModemManager.connectMockModemService());
- // register the network call back
- registerNetworkCallback();
}
@AfterClass
@@ -128,8 +192,6 @@ public class ConnectivityManagerTestOnMockModem {
if (!hasTelephonyFeature()) {
return;
}
- // unregister the network call back
- unregisterNetworkCallback();
// Rebind all interfaces which is binding to MockModemService to default.
assertNotNull(sMockModemManager);
assertTrue(sMockModemManager.disconnectMockModemService());
@@ -139,6 +201,15 @@ public class ConnectivityManagerTestOnMockModem {
@Before
public void beforeTest() throws Exception {
assumeTrue(hasTelephonyFeature());
+ registerNetworkCallback();
+ }
+
+ @After
+ public void afterTest() {
+ // unregister the network call back
+ if (sNetworkCallback != null) {
+ unregisterNetworkCallback();
+ }
}
private static boolean isMultiSim(TelephonyManager tm) {
@@ -200,63 +271,13 @@ public class ConnectivityManagerTestOnMockModem {
return sIsOnAvailable;
}
+ private static synchronized Network getDefaultNetwork() {
+ Log.d(TAG, "getDefaultNetwork: enter ");
+ return sDefaultNetwork;
+ }
+
private static void registerNetworkCallback() {
- sNetworkCallback =
- new NetworkCallback() {
- @Override
- public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
- sDefaultNetwork = network;
- Log.d(
- TAG,
- "Network capabilities changed. network: "
- + network
- + ", NetworkCapabilities: "
- + nc);
-
- if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
- Log.d(
- TAG,
- "Network capabilities changed. network: "
- + network
- + " ,validation: Pass!");
- synchronized (sIsValidateLock) {
- sIsValidate = true;
- sIsValidateLock.notify();
- }
- } else {
- Log.d(
- TAG,
- "Network capabilities changed. network: "
- + network
- + " ,validation: Fail!");
- synchronized (sIsValidateLock) {
- sIsValidate = false;
- }
- }
- }
-
- @Override
- public void onLost(Network network) {
- sDefaultNetwork = network;
- Log.d(TAG, "onLost(): network: " + network);
- synchronized (sIsOnAvailableLock) {
- sIsOnAvailable = false;
- }
- }
-
- @Override
- public void onAvailable(Network network) {
- sDefaultNetwork = network;
- Log.d(TAG, "onAvailable(): network: " + network);
- synchronized (sIsOnAvailableLock) {
- sIsOnAvailable = true;
- }
- }
-
- @Override
- public void onLinkPropertiesChanged(
- Network network, LinkProperties linkProperties) {}
- };
+ sNetworkCallback = new CMNetworkCallback();
try {
sConnectivityManager.registerNetworkCallback(
new NetworkRequest.Builder()
@@ -273,8 +294,11 @@ public class ConnectivityManagerTestOnMockModem {
private static void unregisterNetworkCallback() {
try {
sConnectivityManager.unregisterNetworkCallback(sNetworkCallback);
+ Log.d(TAG, "unregisterNetworkCallback");
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException during unregisterNetworkCallback(): ", e);
+ } finally {
+ sNetworkCallback = null;
}
}
@@ -297,13 +321,12 @@ public class ConnectivityManagerTestOnMockModem {
sMockModemManager.changeNetworkService(slotId, MOCK_SIM_PROFILE_ID_TWN_CHT, true);
// make sure the network is available
- TimeUnit.SECONDS.sleep(5);
+ sNetworkCallback.awaitNetwork();
assertTrue(getNetworkOnAvailable());
// make sure the network is validated
- sConnectivityManager.reportNetworkConnectivity(sDefaultNetwork, false);
+ sConnectivityManager.reportNetworkConnectivity(getDefaultNetwork(), false);
waitForExpectedValidationState(true, TIMEOUT_NETWORK_VALIDATION);
- TimeUnit.SECONDS.sleep(2);
assertTrue(getNetworkValidated());
// Leave Service
diff --git a/tests/tests/toastlegacy/OWNERS b/tests/tests/toastlegacy/OWNERS
index d21846d5234..4065d860f4f 100644
--- a/tests/tests/toastlegacy/OWNERS
+++ b/tests/tests/toastlegacy/OWNERS
@@ -1,2 +1,2 @@
-# Bug component: 137825
+# Bug component: 1012119
include ../toast/OWNERS
diff --git a/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
index f63dc376a6d..14dca76e0e6 100644
--- a/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
+++ b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
@@ -17,6 +17,7 @@
package android.widget.toast.cts.legacy;
import android.content.Intent;
+import android.os.UserManager;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.widget.toast.cts.BaseToastTest;
@@ -25,6 +26,7 @@ import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -129,6 +131,8 @@ public class ToastTest extends BaseToastTest {
@Test
public void testAddTwoToastsViaAddingWindowApisWhenUidFocusedQuickly() throws Exception {
+ // Not supporting this test on Headless devices
+ Assume.assumeFalse(UserManager.isHeadlessSystemUserMode());
// dismiss deprecated app warnings dialog
mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
Thread.sleep(WAIT_LEGACY_DIALOG_CLOSE_MS);
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
index c160744e110..353c5a4263e 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -658,7 +658,8 @@ public class TunerTest {
status.getInnerFec();
break;
case FrontendStatus.FRONTEND_STATUS_TYPE_MODULATION:
- if (info.getType() != FrontendSettings.TYPE_DVBT)
+ if (info.getType() != FrontendSettings.TYPE_DVBT &&
+ info.getType() != FrontendSettings.TYPE_ANALOG)
status.getModulation();
break;
case FrontendStatus.FRONTEND_STATUS_TYPE_SPECTRAL:
diff --git a/tests/tests/usb/AndroidTest.xml b/tests/tests/usb/AndroidTest.xml
index ef712366cc6..1cda028118d 100644
--- a/tests/tests/usb/AndroidTest.xml
+++ b/tests/tests/usb/AndroidTest.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Config for CTS USB test cases">
<option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="component" value="systems" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/view/res/layout-round/using_views_layout.xml b/tests/tests/view/res/layout-round/using_views_layout.xml
new file mode 100644
index 00000000000..6e548ea28fa
--- /dev/null
+++ b/tests/tests/view/res/layout-round/using_views_layout.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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">
+
+ <TextView
+ android:id="@+id/country"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/country"/>
+
+ <EditText
+ android:id="@+id/entry"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:drawable/editbox_background"
+ android:layout_below="@id/country"/>
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/entry"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="10dip"
+ android:text="@string/id_cancel"/>
+
+ <Button
+ android:id="@+id/ok"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/entry"
+ android:layout_toLeftOf="@id/cancel"
+ android:layout_marginLeft="10dip"
+ android:text="@string/id_ok"/>
+
+ <TextView
+ android:id="@+id/symbol"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/ok"
+ android:text="@string/symbol"/>
+
+ <TextView
+ android:id="@+id/symbolball"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/symbol"
+ android:layout_marginLeft="20dip"/>
+
+ <TextView
+ android:id="@+id/warning"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#aa0000"
+ android:layout_below="@id/symbolball"
+ android:text="@string/country_warning"
+ android:visibility="invisible"
+ android:layout_weight="2"/>
+
+</RelativeLayout>
+
diff --git a/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java b/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java
index 81d72342ef0..a8818880097 100644
--- a/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java
+++ b/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java
@@ -40,14 +40,6 @@ public class AutoHandwritingTest {
new ActivityTestRule<>(HandwritingActivity.class);
@Test
- public void autoHandwriting_defaultValueIsTrue() {
- Activity activity = mActivityRule.getActivity();
- View view = activity.findViewById(R.id.default_view);
-
- assertTrue(view.isAutoHandwritingEnabled());
- }
-
- @Test
public void autoHandwriting_setToTrueInXml() {
Activity activity = mActivityRule.getActivity();
View view = activity.findViewById(R.id.auto_handwriting_enabled);
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index f4cedb795aa..c3b8fb9be69 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -1131,7 +1131,7 @@ public class ViewGroupTest implements CTSResult {
}
private void onResolvePointerIcon_scrollabilityAffectsPointerIcon(boolean vertical,
- boolean canScroll, boolean pointerIsSystemArrow) {
+ boolean canScroll, boolean pointerIsArrayOrNull) {
// Arrange
@@ -1166,8 +1166,14 @@ public class ViewGroupTest implements CTSResult {
// Assert
- if (pointerIsSystemArrow) {
- assertEquals(PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW), actualResult);
+ if (pointerIsArrayOrNull) {
+ // When the returned PointerIcon is null it will fallback to the system default for the
+ // given source devices. For mouse devices, the default is TYPE_ARROW.
+ // We also allow it to return TYPE_ARROW so that we don't break CTS test compatibility.
+ if (actualResult != null) {
+ assertEquals(PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW),
+ actualResult);
+ }
} else {
assertEquals(expectedPointerIcon, actualResult);
}
diff --git a/tests/tests/voiceinteraction/Android.bp b/tests/tests/voiceinteraction/Android.bp
index 0ea0bf2c299..0105227a1cf 100644
--- a/tests/tests/voiceinteraction/Android.bp
+++ b/tests/tests/voiceinteraction/Android.bp
@@ -51,6 +51,7 @@ android_test {
// Tag this module as a cts test artifact
test_suites: [
"cts",
+ "gts",
"general-tests",
],
sdk_version: "test_current",
diff --git a/tests/tests/voiceinteraction/AndroidTest.xml b/tests/tests/voiceinteraction/AndroidTest.xml
index 2bd858b6d94..6191ac9a462 100644
--- a/tests/tests/voiceinteraction/AndroidTest.xml
+++ b/tests/tests/voiceinteraction/AndroidTest.xml
@@ -15,6 +15,8 @@
-->
<configuration description="Config for CTS Voice Interaction test cases">
<option name="test-suite-tag" value="cts" />
+ <!-- For downstream tests -->
+ <option name="test-suite-tag" value="gts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/AlwaysOnHotwordDetectorNoHdsTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/AlwaysOnHotwordDetectorNoHdsTest.java
new file mode 100644
index 00000000000..e384f632e2d
--- /dev/null
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/AlwaysOnHotwordDetectorNoHdsTest.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2023 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.voiceinteraction.cts;
+
+import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.MANAGE_HOTWORD_DETECTION;
+import static android.Manifest.permission.RECORD_AUDIO;
+import static android.content.pm.PackageManager.FEATURE_MICROPHONE;
+import static android.voiceinteraction.cts.testcore.Helper.CTS_SERVICE_PACKAGE;
+import static android.voiceinteraction.cts.testcore.Helper.MANAGE_VOICE_KEYPHRASES;
+import static android.voiceinteraction.cts.testcore.Helper.createKeyphraseArray;
+import static android.voiceinteraction.cts.testcore.Helper.createKeyphraseRecognitionExtraList;
+import static android.voiceinteraction.cts.testcore.Helper.waitForFutureDoneAndAssertSuccessful;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.media.soundtrigger.SoundTriggerInstrumentation.RecognitionSession;
+import android.os.Build;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.platform.test.annotations.AppModeFull;
+import android.service.voice.AlwaysOnHotwordDetector;
+import android.soundtrigger.cts.instrumentation.SoundTriggerInstrumentationObserver;
+import android.util.Log;
+import android.voiceinteraction.cts.services.CtsBasicVoiceInteractionService;
+import android.voiceinteraction.cts.testcore.VoiceInteractionServiceConnectedClassRule;
+import android.voiceinteraction.cts.testcore.VoiceInteractionServiceOverrideEnrollmentRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.CtsDownstreamingTest;
+import com.android.compatibility.common.util.RequiredFeatureRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/** Tests for {@link AlwaysOnHotwordDetector} APIs. */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "No real use case for instant mode hotword detector")
+public class AlwaysOnHotwordDetectorNoHdsTest {
+
+ private static final String TAG = "AlwaysOnHotwordDetectorNoHdsTest";
+ // The VoiceInteractionService used by this test
+ private static final String SERVICE_COMPONENT =
+ "android.voiceinteraction.cts.services.CtsBasicVoiceInteractionService";
+
+ private static final int WAIT_EXPECTED_NO_CALL_TIMEOUT_IN_MS = 750;
+
+ private static final Context sContext = getInstrumentation().getTargetContext();
+ private static final SoundTrigger.Keyphrase[] KEYPHRASE_ARRAY = createKeyphraseArray(sContext);
+
+ private final SoundTriggerInstrumentationObserver mInstrumentationObserver =
+ new SoundTriggerInstrumentationObserver();
+
+ private AtomicBoolean mOpNoted;
+
+ private static final boolean SYSPROP_HOTWORD_DETECTION_SERVICE_REQUIRED =
+ SystemProperties.getBoolean("ro.hotword.detection_service_required", false);
+
+ private final AppOpsManager.OnOpNotedListener mOnOpNotedListener =
+ (op, uid, pkgName, attributionTag, flags, result) -> {
+ Log.d(TAG, "Get OnOpNotedListener callback op = " + op + ", uid = " + uid);
+ // We adopt ShellPermissionIdentity to pass the permission check, so the uid should
+ // be the shell uid.
+ if (Process.SHELL_UID == uid) {
+ mOpNoted.set(true);
+ }
+ };
+
+ public static final class RequiredApiLevelRule implements TestRule {
+ private final int mRequiredApiLevel;
+ private final boolean mIsRequiredApiLevel;
+
+ RequiredApiLevelRule(int requiredApiLevel) {
+ mRequiredApiLevel = requiredApiLevel;
+ mIsRequiredApiLevel = isRequiredApiLevel(mRequiredApiLevel);
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ if (!mIsRequiredApiLevel) {
+ Log.d(TAG, "skipping "
+ + description.getClassName() + "#" + description.getMethodName()
+ + " because it requires API level " + mRequiredApiLevel);
+ assumeTrue("Device is not API level'" + mRequiredApiLevel,
+ mIsRequiredApiLevel);
+ return;
+ }
+ base.evaluate();
+ }
+ };
+ }
+
+ @Override
+ public String toString() {
+ return "RequiredApiLevelRule[" + mRequiredApiLevel + ", " + mIsRequiredApiLevel + "]";
+ }
+
+ static boolean isRequiredApiLevel(int requiredApiLevel) {
+ return ApiLevelUtil.isAtLeast(requiredApiLevel);
+ }
+ }
+
+ // For destroying in teardown
+ private AlwaysOnHotwordDetector mAlwaysOnHotwordDetector = null;
+
+ @Rule(order = 1)
+ public RequiredApiLevelRule REQUIRES_API_RULE = new RequiredApiLevelRule(
+ Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
+
+ @Rule(order = 2)
+ public RequiredFeatureRule REQUIRES_MIC_RULE = new RequiredFeatureRule(FEATURE_MICROPHONE);
+
+ @Rule(order = 3)
+ public VoiceInteractionServiceOverrideEnrollmentRule mEnrollOverrideRule =
+ new VoiceInteractionServiceOverrideEnrollmentRule(getService());
+
+ @ClassRule
+ public static final VoiceInteractionServiceConnectedClassRule sServiceRule =
+ new VoiceInteractionServiceConnectedClassRule(
+ sContext, getTestVoiceInteractionServiceName());
+
+
+ @BeforeClass
+ public static void setupClass() {
+ // TODO(b/276393203) delete this
+ SystemClock.sleep(8_000);
+ }
+
+ @Before
+ public void setup() {
+ // Hook up SoundTriggerInstrumentation to inject/observe STHAL operations.
+ // Requires MANAGE_SOUND_TRIGGER
+ runWithShellPermissionIdentity(mInstrumentationObserver::attachInstrumentation);
+ runWithShellPermissionIdentity(
+ () -> {
+ sContext.getSystemService(AppOpsManager.class)
+ .startWatchingNoted(
+ new String[] {
+ AppOpsManager.OPSTR_RECORD_AUDIO,
+ AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE,
+ AppOpsManager.OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
+ },
+ mOnOpNotedListener);
+ });
+ mOpNoted = new AtomicBoolean(false);
+ }
+
+ @After
+ public void tearDown() {
+ runWithShellPermissionIdentity(
+ () ->
+ sContext.getSystemService(AppOpsManager.class)
+ .stopWatchingNoted(mOnOpNotedListener));
+ // Destroy the framework session
+ if (mAlwaysOnHotwordDetector != null) {
+ mAlwaysOnHotwordDetector.destroy();
+ }
+
+ // Clean up any unexpected HAL state
+ try {
+ mInstrumentationObserver.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ // Clear the service state
+ getService().resetState();
+ // Drop any permissions we may still have
+ getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
+ }
+
+ @CddTest(requirements = {"9.8.2/H-4-1"})
+ @Test
+ @CtsDownstreamingTest
+ public void testStartRecognition_success() throws Exception {
+ createAndEnrollAlwaysOnHotwordDetector();
+ // Grab permissions for more than a single call since we get callbacks
+ adoptSoundTriggerPermissions();
+
+ startAndTriggerRecognition();
+ }
+
+ @CddTest(requirements = {"9.8.2/H-4-1"})
+ @Test
+ @CtsDownstreamingTest
+ public void ifExemptionEnabled_startRecognition_noRecordOpsNoted() throws Exception {
+ assumeFalse(SYSPROP_HOTWORD_DETECTION_SERVICE_REQUIRED);
+ createAndEnrollAlwaysOnHotwordDetector();
+ // Grab permissions for more than a single call since we get callbacks
+ adoptSoundTriggerPermissions();
+
+ startAndTriggerRecognition();
+
+ // in case of any late arriving callbacks
+ SystemClock.sleep(WAIT_EXPECTED_NO_CALL_TIMEOUT_IN_MS);
+ assertThat(mOpNoted.get()).isFalse();
+ }
+
+ @CddTest(requirements = {"9.8.2/H-4-1"})
+ @Test
+ @CtsDownstreamingTest
+ public void ifExemptionDisabled_startRecognition_RecordOpsNoted() throws Exception {
+ assumeTrue(SYSPROP_HOTWORD_DETECTION_SERVICE_REQUIRED);
+ createAndEnrollAlwaysOnHotwordDetector();
+ // Grab permissions for more than a single call since we get callbacks
+ adoptSoundTriggerPermissions();
+
+ startAndTriggerRecognition();
+
+ // in case of any late arriving callbacks
+ SystemClock.sleep(WAIT_EXPECTED_NO_CALL_TIMEOUT_IN_MS);
+ assertThat(mOpNoted.get()).isTrue();
+ }
+
+ private static String getTestVoiceInteractionServiceName() {
+ Log.d(TAG, "getTestVoiceInteractionServiceName()");
+ return CTS_SERVICE_PACKAGE + "/" + SERVICE_COMPONENT;
+ }
+
+ private static CtsBasicVoiceInteractionService getService() {
+ return (CtsBasicVoiceInteractionService) sServiceRule.getService();
+ }
+
+ private void adoptSoundTriggerPermissions() {
+ getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity(
+ RECORD_AUDIO,
+ CAPTURE_AUDIO_HOTWORD,
+ MANAGE_HOTWORD_DETECTION,
+ MANAGE_VOICE_KEYPHRASES);
+ }
+
+ private void createAndEnrollAlwaysOnHotwordDetector() throws InterruptedException {
+ mAlwaysOnHotwordDetector = null;
+ // Wait onAvailabilityChanged() callback called following AOHD creation.
+ getService().initAvailabilityChangeLatch();
+
+ // Load appropriate keyphrase model
+ // Required for the model to enter the enrolled state
+ runWithShellPermissionIdentity(
+ () ->
+ mEnrollOverrideRule
+ .getModelManager()
+ .updateKeyphraseSoundModel(
+ new SoundTrigger.KeyphraseSoundModel(
+ new UUID(5, 7),
+ new UUID(7, 5),
+ /* data= */ null,
+ KEYPHRASE_ARRAY)),
+ MANAGE_VOICE_KEYPHRASES);
+
+ // Create alwaysOnHotwordDetector
+ getService()
+ .createAlwaysOnHotwordDetectorNoHotwordDetectionService(
+ /* useExecutor= */ true, /* runOnMainThread= */ true);
+ try {
+ // Bad naming, this waits for AOHD creation
+ getService().waitSandboxedDetectionServiceInitializedCalledOrException();
+ } finally {
+ // Get the AlwaysOnHotwordDetector instance even if there is an error happened to avoid
+ // that we don't destroy the detector in tearDown method. It may be null here. We will
+ // check the status below.
+ mAlwaysOnHotwordDetector = getService().getAlwaysOnHotwordDetector();
+ }
+
+ // Verify that detector creation didn't throw
+ assertThat(getService().isCreateDetectorIllegalStateExceptionThrow()).isFalse();
+ assertThat(getService().isCreateDetectorSecurityExceptionThrow()).isFalse();
+
+ assertThat(mAlwaysOnHotwordDetector).isNotNull();
+
+ // verify we have entered the ENROLLED state
+ getService().waitAvailabilityChangedCalled();
+ assertThat(getService().getHotwordDetectionServiceAvailabilityResult())
+ .isEqualTo(AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED);
+ }
+
+ private void startAndTriggerRecognition() throws InterruptedException {
+ // Start recognition
+ mAlwaysOnHotwordDetector.startRecognition(0, new byte[] {1, 2, 3, 4, 5});
+ RecognitionSession recognitionSession =
+ waitForFutureDoneAndAssertSuccessful(
+ mInstrumentationObserver.getOnRecognitionStartedFuture());
+ assertThat(recognitionSession).isNotNull();
+
+ // Trigger recognition
+ getService().initDetectRejectLatch();
+ recognitionSession.triggerRecognitionEvent(
+ new byte[] {0x11, 0x22}, createKeyphraseRecognitionExtraList());
+ getService().waitOnDetectOrRejectCalled();
+
+ // Validate that we got a result
+ AlwaysOnHotwordDetector.EventPayload detectResult =
+ getService().getHotwordServiceOnDetectedResult();
+ assertThat(detectResult).isNotNull();
+ }
+}
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
index 92902e106ec..52d190ed340 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
@@ -159,7 +159,7 @@ public class VoiceInteractionRoleTest {
runWithShellPermissionIdentity(
() -> sRoleManager.removeRoleHolderAsUser(RoleManager.ROLE_ASSISTANT, packageName,
0, Process.myUserHandle(), sContext.getMainExecutor(), future));
- assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+ future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
}
private static class CallbackFuture extends CompletableFuture<Boolean>
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/services/CtsBasicVoiceInteractionService.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/services/CtsBasicVoiceInteractionService.java
index 0e02542ba72..53c93694fa0 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/services/CtsBasicVoiceInteractionService.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/services/CtsBasicVoiceInteractionService.java
@@ -145,53 +145,8 @@ public class CtsBasicVoiceInteractionService extends BaseVoiceInteractionService
Log.i(TAG, "createAlwaysOnHotwordDetectorNoHotwordDetectionService");
mDetectorInitializedLatch = new CountDownLatch(1);
- AlwaysOnHotwordDetector.Callback callback = new AlwaysOnHotwordDetector.Callback() {
- @Override
- public void onAvailabilityChanged(int status) {
- Log.i(TAG, "onAvailabilityChanged(" + status + ")");
- mAvailabilityStatus = status;
- setIsDetectorCallbackRunningOnMainThread(isRunningOnMainThread());
- if (mAvailabilityChangeLatch != null) {
- mAvailabilityChangeLatch.countDown();
- }
- }
-
- @Override
- public void onDetected(AlwaysOnHotwordDetector.EventPayload eventPayload) {
- // no-op
- }
-
- @Override
- public void onRejected(@NonNull HotwordRejectedResult result) {
- // no-op
- }
-
- @Override
- public void onError() {
- // no-op
- }
-
- @Override
- public void onRecognitionPaused() {
- // no-op
- }
-
- @Override
- public void onRecognitionResumed() {
- // no-op
- }
-
- @Override
- public void onHotwordDetectionServiceInitialized(int status) {
- // no-op
- }
-
- @Override
- public void onHotwordDetectionServiceRestarted() {
- // no-op
- }
- };
-
+ AlwaysOnHotwordDetector.Callback callback =
+ createAlwaysOnHotwordDetectorCallbackWithListeners();
final Handler handler = runOnMainThread ? new Handler(Looper.getMainLooper()) : mHandler;
handler.post(() -> runWithShellPermissionIdentity(() -> {
mAlwaysOnHotwordDetector = callCreateAlwaysOnHotwordDetectorNoHotwordDetectionService(
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewHandwritingGestureTest.java b/tests/tests/widget/src/android/widget/cts/TextViewHandwritingGestureTest.java
index f06111139b5..10196b03022 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewHandwritingGestureTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewHandwritingGestureTest.java
@@ -1981,7 +1981,7 @@ public class TextViewHandwritingGestureTest {
final int expectedColor = ColorUtils.setAlphaComponent(colorPrimary,
(int) (0.12f * Color.alpha(colorPrimary)));
- assertGestureHighlightRange(start, end, expectedColor);
+ assertGestureHighlightRange(start, end);
}
private void assertCursorOffset(int offset) {
@@ -2024,6 +2024,19 @@ public class TextViewHandwritingGestureTest {
assertGestureHighlightRange(start, end, color);
}
+ private void assertGestureHighlightRange(int start, int end) {
+ Canvas canvas = prepareMockCanvas();
+ mEditText.draw(canvas);
+
+ ArgumentCaptor<Path> pathCaptor = ArgumentCaptor.forClass(Path.class);
+ ArgumentCaptor<Paint> paintCaptor = ArgumentCaptor.forClass(Paint.class);
+ verify(canvas).drawPath(pathCaptor.capture(), paintCaptor.capture());
+
+ Path expectedPath = new Path();
+ mEditText.getLayout().getSelectionPath(start, end, expectedPath);
+ assertPathEquals(expectedPath, pathCaptor.getValue());
+ }
+
private void assertGestureHighlightRange(int start, int end, int color) {
Canvas canvas = prepareMockCanvas();
mEditText.draw(canvas);
diff --git a/tests/tests/wifi/AndroidManifest.xml b/tests/tests/wifi/AndroidManifest.xml
index e758789f185..b3fbee0a26a 100644
--- a/tests/tests/wifi/AndroidManifest.xml
+++ b/tests/tests/wifi/AndroidManifest.xml
@@ -42,7 +42,7 @@
(as opposed to HTTPS). -->
<application android:usesCleartextTraffic="true">
<uses-library android:name="android.test.runner"/>
- <activity android:name=".WaitForResultActivity"/>
+ <activity android:name=".WaitForResultActivity" android:screenOrientation="portrait"/>
<service
android:name="android.net.wifi.sharedconnectivity.service.cts.TestSharedConnectivityService"
android:exported="true">
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java
index 311d2e068f2..7c13a72ee56 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMaxBFrameTest.java
@@ -19,6 +19,7 @@ package android.videocodec.cts;
import static android.media.MediaFormat.PICTURE_TYPE_B;
import static android.media.MediaFormat.PICTURE_TYPE_I;
import static android.media.MediaFormat.PICTURE_TYPE_P;
+import static android.mediav2.common.cts.CodecTestBase.ComponentClass.HARDWARE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -113,7 +114,7 @@ public class VideoEncoderMaxBFrameTest extends VideoEncoderValidationTestBase {
maxBFrames), BIRTHDAY_FULLHD_LANDSCAPE, label});
}
}
- return prepareParamList(exhaustiveArgsList, true, false, true, false);
+ return prepareParamList(exhaustiveArgsList, true, false, true, false, HARDWARE);
}
public VideoEncoderMaxBFrameTest(String encoder, String mediaType, EncoderConfigParams cfg,
diff --git a/tools/cts-device-info/Android.bp b/tools/cts-device-info/Android.bp
index ad33ac29fec..e7cf2f95ec3 100644
--- a/tools/cts-device-info/Android.bp
+++ b/tools/cts-device-info/Android.bp
@@ -83,6 +83,7 @@ genrule {
" -a com.android.compatibility.common.deviceinfo.KeystoreAttestationDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.LocaleDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.MediaDeviceInfo " +
+ " -a com.android.compatibility.common.deviceinfo.MediaDrmDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.MediaOutputDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.MemoryDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.PackageDeviceInfo " +
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 ffb38a75956..a1f5efd0b62 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -154,4 +154,12 @@
<option name="compatibility:exclude-filter" value="CtsUwbMultiDeviceTestCase_UwbManagerTests" />
<option name="compatibility:exclude-filter" value="CtsUwbMultiDeviceTestCase_FiraRangingTests" />
+ <!-- b/290651182 -->
+ <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.CertificateTest#testNoAddedCertificates" />
+ <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.CertificateTest#testNoRemovedCertificates" />
+
+ <!-- b/296896687 -->
+ <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_30ms" />
+ <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_100ms" />
+
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-validation-exclude.xml b/tools/cts-tradefed/res/config/cts-validation-exclude.xml
index a13ab72d3eb..edc29af288d 100644
--- a/tools/cts-tradefed/res/config/cts-validation-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-validation-exclude.xml
@@ -498,4 +498,16 @@
<!-- b/292213604 -->
<option name="compatibility:exclude-filter" value="CtsDomainVerificationDeviceMultiUserTestCases" />
+
+ <!-- b/292536082 -->
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_policyNotAllowedToBeSet_throwsSecurityException[DelegateWithoutValidScope]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_policyNotAllowedToBeSet_throwsSecurityException[IncludeRunOnFinancedDeviceOwnerUser]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_nullPolicy_allowsAllProviders[IncludeRunOnDeviceOwnerUser]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_allowlistAndSystemPolicy_allowsAllowlistedAndSystemProviders[IncludeRunOnDeviceOwnerUser]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_null_setsPolicy[IncludeRunOnDeviceOwnerUser]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_blocklistPolicy_allowsNotBlocklistedProviders[IncludeRunOnDeviceOwnerUser]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_allowlistPolicy_allowsAllowlistedProviders[IncludeRunOnDeviceOwnerUser]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_policyIsSet[IncludeRunOnDeviceOwnerUser]" />
+ <option name="compatibility:exclude-filter" value="CtsCredentialManagerTestCases android.credentials.cts.CtsDevicePolicyTest#setCredentialManagerPolicy_allowlistAndSystemPolicy_allowsAllowlistedAndSystemProviders_SDK[IncludeRunOnDeviceOwnerUser]" />
+
</configuration>
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
index 3b370f49a2a..364123949a1 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
@@ -60,6 +60,7 @@ public class CtsConfigLoadingTest {
Arrays.asList(
// modifications to the list below must be reviewed
"abuse",
+ "adservices",
"art",
"auth",
"auto",
@@ -85,6 +86,8 @@ public class CtsConfigLoadingTest {
"mocking",
"networking",
"neuralnetworks",
+ "packagemanager",
+ "permissions",
"print",
"renderscript",
"security",