summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-02 22:27:17 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-11-02 22:27:17 +0000
commit7770650209e5e5fd6c5a327a222070e607317251 (patch)
tree54faccdf11bfbf483e03d2d0f6f21a8ebdd6a764
parent1cbdfeece7368a4b5218441565cbb5b78e0d20f6 (diff)
parent7f41e9b78576353c0015778657cd3e0a982cc9bb (diff)
downloadcts-android14-mainline-uwb-release.tar.gz
Snap for 11041982 from 7f41e9b78576353c0015778657cd3e0a982cc9bb to mainline-uwb-releaseaml_uwb_341310300aml_uwb_341310030android14-mainline-uwb-release
Change-Id: I7565adae4a1f1ebda1b519de4ee0b20cbed07427
-rw-r--r--apps/CameraITS/tests/scene1_1/test_locked_burst.py4
-rw-r--r--apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py21
-rw-r--r--apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py1
-rw-r--r--apps/CameraITS/tests/scene1_2/test_yuv_plus_raw.py1
-rw-r--r--apps/CameraITS/tests/scene2_a/test_reprocess_uv_swap.py3
-rw-r--r--apps/CameraITS/tests/scene2_d/test_autoframing.py (renamed from apps/CameraITS/tests/scene2_a/test_autoframing.py)24
-rw-r--r--apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py4
-rw-r--r--apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py6
-rw-r--r--apps/CameraITS/tests/scene6/test_zoom.py6
-rw-r--r--apps/CameraITS/tests/scene_extensions/scene_hdr/test_hdr_extension.py7
-rw-r--r--apps/CameraITS/tests/scene_extensions/scene_night/test_night_extension.py158
-rwxr-xr-xapps/CameraITS/tools/run_all_tests.py20
-rw-r--r--apps/CameraITS/utils/image_processing_utils.py10
-rw-r--r--apps/CameraITS/utils/its_session_utils.py45
-rw-r--r--apps/CameraITS/utils/opencv_processing_utils.py10
-rw-r--r--apps/CameraITS/utils/zoom_capture_utils.py11
-rw-r--r--apps/CtsVerifier/AndroidManifest.xml1
-rw-r--r--apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml12
-rw-r--r--apps/CtsVerifier/res/layout/ble_rssi_precision.xml7
-rw-r--r--apps/CtsVerifier/res/layout/ble_rx_tx_offset_precision.xml7
-rw-r--r--apps/CtsVerifier/res/layout/camera_performance.xml1
-rw-r--r--apps/CtsVerifier/res/layout/nan_accuracy.xml7
-rw-r--r--apps/CtsVerifier/res/values-watch/strings.xml25
-rw-r--r--apps/CtsVerifier/res/values/strings.xml3
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java15
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java8
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java173
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java19
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java26
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java33
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java25
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java37
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/NanAccuracyActivity.java13
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java2
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoAccounts.java8
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java2
-rw-r--r--common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java72
-rw-r--r--common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java2
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java16
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java56
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java2
-rw-r--r--common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java12
-rw-r--r--common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainPhoneShortcutStepAutomation.java30
-rw-r--r--common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainSmsShortcutStepAutomation.java30
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java6
-rwxr-xr-xhostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java17
-rw-r--r--hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/contacts/ContactsSharingTest.java2
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java2
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java5
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/BootCountTrackerRule.java2
-rw-r--r--hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java25
-rw-r--r--hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/common/src/com/android/cts/appdataisolation/common/FileUtils.java5
-rw-r--r--hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java5
-rw-r--r--hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java13
-rw-r--r--hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java33
-rw-r--r--hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java71
-rw-r--r--hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java34
-rw-r--r--hostsidetests/compilation/Android.bp12
-rw-r--r--hostsidetests/compilation/assets/package-dex-usage.textproto97
-rw-r--r--hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java35
-rw-r--r--hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java41
-rw-r--r--hostsidetests/compilation/src/android/compilation/cts/Utils.java26
-rw-r--r--hostsidetests/compilation/status_checker_app/src/android/compilation/cts/statuscheckerapp/StatusCheckerAppTest.java70
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp4
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java6
-rwxr-xr-xhostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java26
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PersonalAppsSuspensionTest.java6
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java4
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java2
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java1
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java2
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java14
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java1
-rw-r--r--hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalFeatureTest.java18
-rw-r--r--hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java24
-rw-r--r--hostsidetests/media/bitstreams/app/src/android/media/cts/bitstreams/app/MediaBitstreamsDeviceSideTest.java2
-rw-r--r--hostsidetests/multiuser/app/src/com/android/cts/multiuser/AccountCreator.java40
-rw-r--r--hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallationSessionReportedStatsTests.java3
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java87
-rw-r--r--hostsidetests/security/Android.bp10
-rw-r--r--hostsidetests/security/src/android/security/cts/KernelConfigTest.java2
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxHostTest.java24
-rw-r--r--hostsidetests/security/src/android/security/cts/SeamendcHostTest.java339
-rw-r--r--hostsidetests/securitybulletin/res/cve_2023_21118.binbin0 -> 60216 bytes
-rw-r--r--hostsidetests/securitybulletin/res/v1-only-10-signers.apkbin0 -> 18389 bytes
-rw-r--r--hostsidetests/securitybulletin/res/v1-only-11-signers.apkbin0 -> 22297 bytes
-rw-r--r--hostsidetests/securitybulletin/res/v2-only-10-signers.apkbin0 -> 20688 bytes
-rw-r--r--hostsidetests/securitybulletin/res/v2-only-11-signers.apkbin0 -> 24784 bytes
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp3
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/Android.bp37
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/poc.cpp55
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21118.java64
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21253.java126
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21254.java47
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21261.java12
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21291.java60
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_40120.java52
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/res/values/strings.xml1
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/src/android/security/cts/CVE_2021_0595_test/DeviceTest.java6
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/res/values/strings.xml3
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/src/android/security/cts/CVE_2023_21128_test/DeviceTest.java31
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21254/Android.bp52
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/AndroidManifest.xml25
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/src/android/security/cts/CVE_2023_21254_helper/PocActivity.java46
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/AndroidManifest.xml23
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/src/android/security/cts/CVE_2023_21254_test/DeviceTest.java154
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21291/Android.bp37
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21291/AndroidManifest.xml25
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-21291/src/android/security/cts/CVE_2023_21291/DeviceTest.java176
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-40120/Android.bp40
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-40120/AndroidManifest.xml24
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java148
-rw-r--r--hostsidetests/statsdatom/OWNERS7
-rw-r--r--hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/Checkers.java6
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS6
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS7
-rw-r--r--tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java7
-rw-r--r--tests/JobScheduler/src/android/jobscheduler/cts/UserInitiatedJobTest.java11
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java53
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java4
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java88
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java16
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/ResultsAssertionsUtils.java26
-rw-r--r--tests/accessibilityservice/AndroidManifest.xml1
-rw-r--r--tests/accessibilityservice/res/layout/accessibility_embedded_hierarchy_test_host_side.xml8
-rw-r--r--tests/accessibilityservice/res/values/dimens.xml9
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java65
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java141
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityInputConnectionTest.java4
-rwxr-xr-x[-rw-r--r--]tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityOverlayTest.java4
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java8
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java3
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java3
-rw-r--r--tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java32
-rw-r--r--tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java2
-rw-r--r--tests/app/FgsTest/src/android/app/cts/fgstest/ActivityManagerForegroundServiceTypeTest.java12
-rw-r--r--tests/app/WallpaperTest/src/android/app/cts/wallpapers/WallpaperManagerTest.java4
-rw-r--r--tests/app/src/android/app/cts/ActivityManagerTest.java5
-rw-r--r--tests/app/src/android/app/cts/DownloadManagerTest.java5
-rw-r--r--tests/app/src/android/app/cts/DownloadManagerTestBase.java20
-rw-r--r--tests/app/src/android/app/cts/ServiceTest.java47
-rw-r--r--tests/app/src/android/app/cts/SystemFeaturesTest.java9
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java5
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSessionCtsTestBase.java468
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java1
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java21
-rw-r--r--tests/appsearch/src/com/android/cts/appsearch/external/app/SearchSpecCtsTest.java22
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillAutoActivityLaunchTestCase.java2
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillManualActivityLaunchTestCase.java2
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java9
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java5
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java14
-rw-r--r--tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java8
-rw-r--r--tests/camera/libctscamera2jni/native-camera-jni.cpp2
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java63
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java11
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java2
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java4
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java21
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/RecordingTest.java16
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java83
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java2
-rw-r--r--tests/camera/src/android/hardware/cts/CameraTest.java2
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/DefaultDialerApplicationTest.java8
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java2
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java7
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/ManagedSubscriptionsPolicyTest.java13
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java1
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/ProfileOwnerTest.java6
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/ScreenCaptureDisabledTest.java9
-rw-r--r--tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java14
-rw-r--r--tests/devicestate/src/android/hardware/devicestate/cts/DeviceStateManagerTests.java9
-rw-r--r--tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java1
-rw-r--r--tests/framework/base/windowmanager/app/src/android/server/wm/app/FontScaleActivity.java2
-rw-r--r--tests/framework/base/windowmanager/jetpack/Android.bp1
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SdkAvailabilityTest.java20
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/area/ExtensionRearDisplayPresentationTest.java19
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingBoundsTests.java20
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingFinishTests.java26
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingIntegrationTests.java12
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingLaunchTests.java13
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingPlaceholderTests.java20
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityStackApisTests.java8
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java90
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java65
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java29
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java30
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java16
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java14
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java9
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java2
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java55
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java5
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java13
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java17
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java3
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java4
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java21
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java14
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java7
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java2
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java4
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java18
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java2
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java5
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java8
-rw-r--r--tests/framework/base/windowmanager/util/Android.bp22
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java24
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/CtsWindowInfoUtils.java48
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java4
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java5
-rw-r--r--tests/input/src/android/input/cts/UinputTouchDevice.kt3
-rw-r--r--tests/inputmethod/AndroidManifest.xml3
-rw-r--r--tests/inputmethod/AndroidTest.xml11
-rw-r--r--tests/inputmethod/mockime/Android.bp3
-rw-r--r--tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java2
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java2
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java45
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java14
-rw-r--r--tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java110
-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/CompareStreams.java21
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java12
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java19
-rwxr-xr-xtests/media/copy_media.sh2
-rw-r--r--tests/media/src/android/mediav2/cts/WorkDir.java2
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java14
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/Utils.java4
-rw-r--r--tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java8
-rw-r--r--tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java11
-rw-r--r--tests/mediapc/src/android/mediapc/cts/CodecTestBase.java132
-rw-r--r--tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java9
-rw-r--r--tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java3
-rw-r--r--tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java89
-rw-r--r--tests/openglperf2/AndroidTest.xml4
-rw-r--r--tests/signature/api-check/shared-libs-api/Android.bp8
-rw-r--r--tests/signature/api-check/system-api/Android.bp4
-rw-r--r--tests/signature/api/Android.bp2
-rw-r--r--tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java7
-rw-r--r--tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java41
-rw-r--r--tests/surfacecontrol/src/android/view/surfacecontrol/cts/SurfaceViewSyncTest.java2
-rw-r--r--tests/tests/appwidget/Android.bp2
-rw-r--r--tests/tests/appwidget/AndroidManifest.xml1
-rw-r--r--tests/tests/appwidget/AndroidTest.xml2
-rw-r--r--tests/tests/appwidget/AppBal/Android.bp41
-rwxr-xr-xtests/tests/appwidget/AppBal/AndroidManifest.xml56
-rw-r--r--tests/tests/appwidget/AppBal/res/xml/widget_info.xml24
-rw-r--r--tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalActivity.java52
-rw-r--r--tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalAppWidgetProvider.java21
-rw-r--r--tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalService.java62
-rw-r--r--tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/EmptyActivity.java20
-rw-r--r--tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.java2
-rw-r--r--tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java67
-rw-r--r--tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java28
-rw-r--r--tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java19
-rw-r--r--tests/tests/car/AndroidManifest.xml6
-rw-r--r--tests/tests/car/src/android/car/app/cts/CarActivityManagerTest.java14
-rw-r--r--tests/tests/car/src/android/car/cts/CarDisplayInputLockTest.java11
-rw-r--r--tests/tests/car/src/android/car/cts/CarOccupantConnectionManagerTest.java3
-rw-r--r--tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java3
-rw-r--r--tests/tests/car/src/android/car/cts/CarPowerManagerTest.java6
-rw-r--r--tests/tests/car/src/android/car/cts/CarRemoteDeviceManagerTest.java5
-rw-r--r--tests/tests/car/src/android/car/cts/OemCarServiceImplTest.java10
-rw-r--r--tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java16
-rw-r--r--tests/tests/companion/common/src/android/companion/cts/common/Constants.kt3
-rw-r--r--tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt13
-rw-r--r--tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/BinderLifecycleTest.kt6
-rw-r--r--tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/RebindServiceTest.kt12
-rw-r--r--tests/tests/companion/uicommon/src/android/companion/cts/uicommon/CompanionDeviceManagerUi.kt17
-rw-r--r--tests/tests/content/src/android/content/cts/AvailableIntentsTest.java11
-rw-r--r--tests/tests/content/src/android/content/cts/ContentProviderClientTest.java35
-rw-r--r--tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java7
-rw-r--r--tests/tests/display/src/android/display/cts/BrightnessTest.java32
-rw-r--r--tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java5
-rw-r--r--tests/tests/media/audio/Android.bp1
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/AudioCommunicationDeviceTest.java259
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java30
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/AudioModeListenerTest.java8
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/RingtoneManagerTest.java16
-rw-r--r--tests/tests/media/bettertogether/src/android/media/bettertogether/cts/MediaSessionManagerTest.java37
-rw-r--r--tests/tests/media/common/src/android/media/cts/CodecState.java25
-rw-r--r--tests/tests/media/common/src/android/media/cts/MediaCodecCryptoAsyncHelper.java6
-rw-r--r--tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java10
-rw-r--r--tests/tests/media/common/src/android/media/cts/NonBlockingAudioTrack.java23
-rw-r--r--tests/tests/media/common/src/android/media/cts/OutputSurface.java66
-rw-r--r--tests/tests/media/common/src/android/media/cts/TextureRender.java12
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecodeOnlyTest.java23
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java36
-rw-r--r--tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java2
-rw-r--r--tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java2
-rw-r--r--tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java10
-rw-r--r--tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java8
-rw-r--r--tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java13
-rwxr-xr-xtests/tests/notification/src/android/app/notification/current/cts/NotificationManagerTest.java8
-rw-r--r--tests/tests/os/assets/minijail/isolated-common.policy2
-rw-r--r--tests/tests/os/src/android/os/cts/FileObserverTest.java43
-rw-r--r--tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java8
-rw-r--r--tests/tests/permission/src/android/permission/cts/ShellCommandPermissionTest.java42
-rw-r--r--tests/tests/permission3/ImplicitUserSelectStorageApp/Android.bp4
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/CameraMicIndicatorsPermissionTest.kt6
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/ReviewAccessibilityServicesTest.kt21
-rw-r--r--tests/tests/permissionmultiuser/AndroidTest.xml2
-rw-r--r--tests/tests/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt13
-rw-r--r--tests/tests/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java3
-rw-r--r--tests/tests/provider/src/android/provider/cts/settings/Settings_MemoryUsageTest.java4
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_39738.java64
-rw-r--r--tests/tests/security/src/android/security/cts/PersistableBundleTest.java52
-rw-r--r--tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java209
-rw-r--r--tests/tests/systemui/src/android/systemui/cts/LightBarTests.java4
-rw-r--r--tests/tests/telephony/current/AndroidTest.xml4
-rw-r--r--tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockDataService.java5
-rw-r--r--tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigBase.java20
-rw-r--r--tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigInterface.java9
-rw-r--r--tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java8
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java21
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/MmsTest.java6
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java36
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java11
-rw-r--r--tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java15
-rw-r--r--tests/tests/text/src/android/text/method/cts/TouchTest.java9
-rw-r--r--tests/tests/text/src/android/text/util/cts/LinkifyTest.java4
-rw-r--r--tests/tests/tv/src/android/media/tv/tuner/cts/TunerFrontendTest.java5
-rw-r--r--tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java5
-rw-r--r--tests/tests/uiautomation/AndroidManifest.xml4
-rw-r--r--tests/tests/uiautomation/res/values/strings.xml37
-rw-r--r--tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java12
-rw-r--r--tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java47
-rw-r--r--tests/tests/uirendering/src/android/uirendering/cts/testclasses/GainmapTests.java15
-rw-r--r--tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt3
-rw-r--r--tests/tests/view/src/android/view/cts/AutoHandwritingTest.java8
-rw-r--r--tests/tests/view/src/android/view/cts/SDRTestActivity.java16
-rw-r--r--tests/tests/view/src/android/view/cts/TextureViewTest.java44
-rw-r--r--tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java19
-rw-r--r--tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppClipboardTest.java37
-rw-r--r--tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java138
-rw-r--r--tests/tests/voiceRecognition/src/android/voicerecognition/cts/CtsRecognitionService.java33
-rw-r--r--tests/tests/voiceRecognition/src/android/voicerecognition/cts/ModelDownloadCallback.java24
-rw-r--r--tests/tests/voiceinteraction/AndroidTest.xml7
-rw-r--r--tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java4
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceNonSharedIsolatedTest.java7
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceBasicTest.java7
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonIsolatedTest.java7
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonSharedIsolatedTest.java7
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectorTest.java7
-rw-r--r--tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java59
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java33
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java34
-rw-r--r--tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/SharedConnectivityTest.java6
-rw-r--r--tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/app/SharedConnectivityManagerTest.java19
-rw-r--r--tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java12
-rw-r--r--tests/wallpapereffectsgeneration/src/android/wallpapereffectsgeneration/cts/WallpaperEffectsGenerationManagerTest.java5
-rw-r--r--tools/cts-device-info/Android.bp2
-rw-r--r--tools/cts-tradefed/OWNERS1
-rw-r--r--tools/cts-tradefed/res/config/cts-known-failures.xml14
-rw-r--r--tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml27
-rw-r--r--tools/cts-tradefed/res/config/cts-on-aosp-include.xml266
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml17
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-on-r.xml11
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-on-s.xml9
-rw-r--r--tools/cts-tradefed/res/config/cts-validation-exclude.xml8
-rw-r--r--tools/cts-tradefed/res/config/grf-no-telephony.xml33
-rw-r--r--tools/cts-tradefed/res/config/multi-config.xml23
365 files changed, 6202 insertions, 2760 deletions
diff --git a/apps/CameraITS/tests/scene1_1/test_locked_burst.py b/apps/CameraITS/tests/scene1_1/test_locked_burst.py
index 46038412d42..c41089bce37 100644
--- a/apps/CameraITS/tests/scene1_1/test_locked_burst.py
+++ b/apps/CameraITS/tests/scene1_1/test_locked_burst.py
@@ -30,8 +30,8 @@ _FPS_MAX_DIFF = 2.0
_NAME = os.path.splitext(os.path.basename(__file__))[0]
_PATCH_H = 0.1 # center 10%
_PATCH_W = 0.1
-_PATCH_X = 0.5 - _PATCH_W
-_PATCH_Y = 0.5 - _PATCH_H
+_PATCH_X = 0.5 - _PATCH_W/2
+_PATCH_Y = 0.5 - _PATCH_H/2
_SPREAD_THRESH_MANUAL_SENSOR = 0.01
_SPREAD_THRESH = 0.03
_VALUE_THRESH = 0.1
diff --git a/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py b/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py
index 39fdf049360..94c534dbe9e 100644
--- a/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py
+++ b/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py
@@ -29,16 +29,18 @@ import image_processing_utils
import its_session_utils
import target_exposure_utils
+_JPG_STR = 'jpg'
_NAME = os.path.splitext(os.path.basename(__file__))[0]
_PATCH_H = 0.1 # center 10%
_PATCH_W = 0.1
_PATCH_X = 0.5 - _PATCH_W/2
_PATCH_Y = 0.5 - _PATCH_H/2
-_THRESHOLD_MAX_RMS_DIFF = 0.03
_PLOT_ALPHA = 0.5
_PLOT_MARKER_SIZE = 8
_PLOT_LEGEND_CIRCLE_SIZE = 10
_PLOT_LEGEND_TRIANGLE_SIZE = 6
+_THRESHOLD_MAX_RMS_DIFF = 0.03
+_YUV_STR = 'yuv'
def do_capture_and_extract_rgb_means(
@@ -76,7 +78,7 @@ def do_capture_and_extract_rgb_means(
cap['metadata']['android.sensor.exposureTime'],
cap['metadata']['android.sensor.sensitivity'],
cap['metadata']['android.lens.focusDistance'])
- if img_type == 'jpg':
+ if img_type == _JPG_STR:
if cap['format'] != 'jpeg':
raise AssertionError(f"{cap['format']} != jpeg")
img = image_processing_utils.decompress_jpeg_to_rgb_image(cap['data'])
@@ -93,7 +95,7 @@ def do_capture_and_extract_rgb_means(
image_processing_utils.write_image(
img, f'{name_with_log_path}_{img_type}_w{size[0]}_h{size[1]}.png')
- if img_type == 'jpg':
+ if img_type == _JPG_STR:
if img.shape[0] != size[1]:
raise AssertionError(f'{img.shape[0]} != {size[1]}')
if img.shape[1] != size[0]:
@@ -145,23 +147,28 @@ class YuvJpegAllTest(its_base_test.ItsBaseTest):
logging.debug('e_req: %d, s_req: %d', e, s)
req = capture_request_utils.manual_capture_request(
s, e, 0.0, True, props)
+ match_ar = None
else:
logging.debug('Using auto capture request')
cam.do_3a(do_af=False)
req = capture_request_utils.auto_capture_request(
linear_tonemap=True, props=props, do_af=False)
+ largest_yuv = capture_request_utils.get_largest_yuv_format(props)
+ match_ar = (largest_yuv['width'], largest_yuv['height'])
yuv_rgbs = []
for i, size in enumerate(
- capture_request_utils.get_available_output_sizes('yuv', props)):
+ capture_request_utils.get_available_output_sizes(
+ _YUV_STR, props, match_ar_size=match_ar)):
yuv_rgbs.append(do_capture_and_extract_rgb_means(
- req, cam, props, size, 'yuv', i, name_with_log_path, debug))
+ req, cam, props, size, _YUV_STR, i, name_with_log_path, debug))
jpg_rgbs = []
for i, size in enumerate(
- capture_request_utils.get_available_output_sizes('jpg', props)):
+ capture_request_utils.get_available_output_sizes(
+ _JPG_STR, props, match_ar_size=match_ar)):
jpg_rgbs.append(do_capture_and_extract_rgb_means(
- req, cam, props, size, 'jpg', i, name_with_log_path, debug))
+ req, cam, props, size, _JPG_STR, i, name_with_log_path, debug))
# Plot means vs format
pylab.figure(_NAME)
diff --git a/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py b/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py
index 35c857a235c..3e03ba4e89d 100644
--- a/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py
+++ b/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py
@@ -98,6 +98,7 @@ class YuvPlusJpegTest(its_base_test.ItsBaseTest):
req = capture_request_utils.auto_capture_request(
linear_tonemap=True, props=props, do_af=False)
+ cam.do_3a()
cap_yuv, cap_jpg = cam.do_capture(req, [fmt_yuv, fmt_jpg])
rgb_means_yuv = compute_means_and_save(cap_yuv, 'yuv', log_path)
rgb_means_jpg = compute_means_and_save(cap_jpg, 'jpg', log_path)
diff --git a/apps/CameraITS/tests/scene1_2/test_yuv_plus_raw.py b/apps/CameraITS/tests/scene1_2/test_yuv_plus_raw.py
index b3b35f5cea0..ba256dc122f 100644
--- a/apps/CameraITS/tests/scene1_2/test_yuv_plus_raw.py
+++ b/apps/CameraITS/tests/scene1_2/test_yuv_plus_raw.py
@@ -136,6 +136,7 @@ class YuvPlusRawTest(its_base_test.ItsBaseTest):
'yuv', props, max_size=_MAX_IMG_SIZE)[0]
out_surfaces = [{'format': raw_fmt},
{'format': 'yuv', 'width': w, 'height': h}]
+ cam.do_3a(do_af=False)
cap_raw, cap_yuv = cam.do_capture(req, out_surfaces)
msg = convert_and_compare_captures(cap_raw, cap_yuv, props,
log_path, raw_fmt)
diff --git a/apps/CameraITS/tests/scene2_a/test_reprocess_uv_swap.py b/apps/CameraITS/tests/scene2_a/test_reprocess_uv_swap.py
index 3efc22137cf..0fed3f3e791 100644
--- a/apps/CameraITS/tests/scene2_a/test_reprocess_uv_swap.py
+++ b/apps/CameraITS/tests/scene2_a/test_reprocess_uv_swap.py
@@ -133,6 +133,7 @@ class ReprocessUvSwapTest(its_base_test.ItsBaseTest):
# Create req, do caps and determine UV swap likelihood
req = capture_request_utils.auto_capture_request()
req['android.noiseReduction.mode'] = nr_mode
+ cam.do_3a()
caps_no_nr = cam.do_capture([req], out_surface)
caps = cam.do_capture([req], out_surface, reprocess_format)
@@ -206,6 +207,7 @@ class ReprocessUvSwapTest(its_base_test.ItsBaseTest):
# Create req, do caps and determine UV swap likelihood
req = capture_request_utils.auto_capture_request()
req['android.edge.mode'] = edge_mode
+ cam.do_3a()
caps_no_ee = cam.do_capture([req], out_surface)
caps = cam.do_capture([req], out_surface, reprocess_format)
@@ -266,6 +268,7 @@ class ReprocessUvSwapTest(its_base_test.ItsBaseTest):
# Create req, do caps and determine UV swap likelihood
req = capture_request_utils.auto_capture_request()
req['android.jpeg.orientation'] = applied_orientation
+ cam.do_3a()
caps_no_jpeg = cam.do_capture([req], out_surface)
caps = cam.do_capture([req], out_surface, reprocess_format)
diff --git a/apps/CameraITS/tests/scene2_a/test_autoframing.py b/apps/CameraITS/tests/scene2_d/test_autoframing.py
index c048d99fbad..db0fa3ae530 100644
--- a/apps/CameraITS/tests/scene2_a/test_autoframing.py
+++ b/apps/CameraITS/tests/scene2_d/test_autoframing.py
@@ -27,9 +27,10 @@ import image_processing_utils
import its_session_utils
import opencv_processing_utils
+_AUTOFRAMING_CONVERGED = 2
_CV2_FACE_SCALE_FACTOR = 1.05 # 5% step for resizing image to find face
_CV2_FACE_MIN_NEIGHBORS = 4 # recommended 3-6: higher for less faces
-_NUM_TEST_FRAMES = 20
+_NUM_TEST_FRAMES = 150
_NUM_FACES = 3
_W, _H = 640, 480
@@ -67,8 +68,7 @@ class AutoframingTest(its_base_test.ItsBaseTest):
# zooms into the scene so that none of the faces are in the view
# initially - which gives room for autoframing to take place.
max_zoom_ratio = camera_properties_utils.get_max_digital_zoom(props)
- cam.do_3a(do_af=False, zoom_ratio=max_zoom_ratio)
- cam.do_autoframing(zoom_ratio=max_zoom_ratio)
+ cam.do_3a(zoom_ratio=max_zoom_ratio)
req = capture_request_utils.auto_capture_request(
do_autoframing=True, zoom_ratio=max_zoom_ratio)
@@ -77,16 +77,20 @@ class AutoframingTest(its_base_test.ItsBaseTest):
caps = cam.do_capture([req]*_NUM_TEST_FRAMES, fmt)
for i, cap in enumerate(caps):
faces = cap['metadata']['android.statistics.faces']
+ autoframing_state = cap['metadata']['android.control.autoframingState']
+ logging.debug('Frame %d faces: %d, autoframingState: %d', i, len(faces),
+ autoframing_state)
+
# Face detection and autoframing could take several frames to warm up,
- # but should detect the correct number of faces in last frame
- if i == _NUM_TEST_FRAMES - 1:
+ # but should detect the correct number of faces before the last frame
+ if autoframing_state == _AUTOFRAMING_CONVERGED:
num_faces_found = len(faces)
if num_faces_found != _NUM_FACES:
raise AssertionError('Wrong num of faces found! Found: '
f'{num_faces_found}, expected: {_NUM_FACES}')
# Also check the faces with open cv to make sure the scene is not
- # distored or anything.
+ # distorted or anything.
img = image_processing_utils.convert_capture_to_rgb_image(
cap, props=props)
opencv_faces = opencv_processing_utils.find_opencv_faces(
@@ -95,10 +99,12 @@ class AutoframingTest(its_base_test.ItsBaseTest):
if num_opencv_faces != _NUM_FACES:
raise AssertionError('Wrong num of faces found with OpenCV! Found: '
f'{num_opencv_faces}, expected: {_NUM_FACES}')
+ break
+
+ # Autoframing didn't converge till the last frame
+ elif i == _NUM_TEST_FRAMES - 1:
+ raise AssertionError('Autoframing failed to converge')
- if not faces:
- continue
- logging.debug('Frame %d face metadata:', i)
logging.debug('Faces: %s', str(faces))
diff --git a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
index 9d3dfbc3953..f9ce1742cd1 100644
--- a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
+++ b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
@@ -34,6 +34,7 @@ _MAX_STABILIZED_RADIUS_RATIO = 1.25 # An FOV reduction of 20% corresponds to an
# increase in lengths of 25%. So the
# stabilized circle's radius can be at most
# 1.25 times that of an unstabilized circle
+_MAX_STABILIZED_RADIUS_ATOL = 1 # 1 pixel tol for radii inaccuracy
_ROUNDESS_DELTA_THRESHOLD = 0.05
_MAX_CENTER_THRESHOLD_PERCENT = 0.075
@@ -283,7 +284,8 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest):
stab_radius = stab_circle['r']
logging.debug('stabilized radius: %f', stab_radius)
- max_stab_radius = ustab_radius * _MAX_STABILIZED_RADIUS_RATIO
+ max_stab_radius = (ustab_radius * _MAX_STABILIZED_RADIUS_RATIO +
+ _MAX_STABILIZED_RADIUS_ATOL)
if stab_radius > max_stab_radius:
failure_string += (f'Too much FoV reduction: '
f'unstabilized radius: {ustab_radius}, '
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 acfef156b52..a0838b1a1b7 100644
--- a/apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py
+++ b/apps/CameraITS/tests/scene6/test_preview_video_zoom_match.py
@@ -44,7 +44,7 @@ _MIN_STR = 'min'
_MIN_AREA_RATIO = 0.00015 # based on 2000/(4000x3000) pixels
_MIN_CIRCLE_PTS = 25
_MIN_ZOOM_CHART_SCALING = 0.7
-_MIN_SIZE = 640*480 # VGA
+_MIN_SIZE = 1280*720 # 720P
_NAME = os.path.splitext(os.path.basename(__file__))[0]
_OFFSET_TOL = 5 # pixels
_RADIUS_RTOL = 0.1 # 10% tolerance Video/Preview circle size
@@ -87,7 +87,7 @@ def _extract_key_frame_from_recording(log_path, file_name):
return np_image
-class PreviewVideoZoomTest(its_base_test.ItsBaseTest):
+class PreviewVideoZoomMatchTest(its_base_test.ItsBaseTest):
"""Tests if preview matches video output when zooming.
Preview and video are recorded while do_3a() iterate through
@@ -100,7 +100,7 @@ class PreviewVideoZoomTest(its_base_test.ItsBaseTest):
match in zoom factors.
"""
- def test_preview_video_zoom(self):
+ def test_preview_video_zoom_match(self):
video_test_data = {}
preview_test_data = {}
log_path = self.log_path
diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py
index 2e34320bc5f..c451575fd55 100644
--- a/apps/CameraITS/tests/scene6/test_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_zoom.py
@@ -112,6 +112,7 @@ class ZoomTest(its_base_test.ItsBaseTest):
logging.debug('testing %s format', fmt)
test_data = {}
for i, z in enumerate(z_list):
+ logging.debug('zoom ratio: %.3f', z)
req['android.control.zoomRatio'] = z
cam.do_3a(zoom_ratio=z)
cap = cam.do_capture(
@@ -124,7 +125,10 @@ class ZoomTest(its_base_test.ItsBaseTest):
# determine radius tolerance of capture
cap_fl = cap['metadata']['android.lens.focalLength']
- radius_tol, offset_tol = test_tols[cap_fl]
+ radius_tol, offset_tol = test_tols.get(
+ cap_fl,
+ (zoom_capture_utils.RADIUS_RTOL, zoom_capture_utils.OFFSET_RTOL)
+ )
# Find the center circle in img
circle = zoom_capture_utils.get_center_circle(img, img_name, size, z,
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 7ff6cd8e9b9..9710a275052 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
@@ -33,6 +33,7 @@ import opencv_processing_utils
_NAME = os.path.splitext(os.path.basename(__file__))[0]
_EXTENSION_HDR = 3
+_TABLET_BRIGHTNESS = '12' # Highest minimum brightness on a supported tablet
_FMT_NAME = 'jpg'
_WIDTH = 1920
@@ -203,14 +204,16 @@ class HdrExtensionTest(its_base_test.ItsBaseTest):
raise AssertionError('Test must be run with tablet.')
# Validate lighting
- cam.do_3a()
+ cam.do_3a(do_af=False)
cap = cam.do_capture(
capture_request_utils.auto_capture_request(), cam.CAP_YUV)
y_plane, _, _ = image_processing_utils.convert_capture_to_planes(cap)
its_session_utils.validate_lighting(
- y_plane, self.scene, state='OFF', log_path=self.log_path)
+ y_plane, self.scene, state='OFF', log_path=self.log_path,
+ tablet_state='OFF')
self.setup_tablet()
+ self.set_screen_brightness(_TABLET_BRIGHTNESS)
its_session_utils.load_scene(
cam, props, self.scene, self.tablet, self.chart_distance,
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 c883d6fdd53..376b47b89f3 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,11 +30,11 @@ 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
+_TABLET_BRIGHTNESS = '12' # Highest minimum brightness on a supported tablet
_TAP_COORDINATES = (500, 500) # Location to tap tablet screen via adb
_TEST_REQUIRED_MPC = 34
-_MIN_AREA = 0
+_MIN_AREA = 0.001 # Circle must be >= 0.1% of image size
_WHITE = 255
_FMT_NAME = 'yuv' # To detect noise without conversion to RGB
@@ -86,42 +86,33 @@ def _convert_captures(cap, file_stem=None):
return y, image_processing_utils.convert_image_to_uint8(img)
-def _check_dot_intensity_diff(night_img, night_y, no_night_img, no_night_y):
+def _check_dot_intensity_diff(night_img, night_y):
"""Checks the difference between circle and dot intensities with Night ON.
- 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:
True if diff between circle and dot intensities is significant.
"""
- night_circle = opencv_processing_utils.find_circle(
- night_img,
- 'night_dot_intensity_check.png',
- _MIN_AREA,
- _WHITE,
- )
+ try:
+ night_circle = opencv_processing_utils.find_circle(
+ night_img,
+ 'night_dot_intensity_check.png',
+ _MIN_AREA,
+ _WHITE,
+ )
+ except AssertionError as e:
+ logging.debug(e)
+ return False
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(
[
@@ -129,27 +120,14 @@ def _check_dot_intensity_diff(night_img, night_y, no_night_img, no_night_y):
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
@@ -191,75 +169,6 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
* is brighter OR improves appearance of scene artifacts
"""
- def find_tablet_brightness(self, cam, default_brightness, file_stem,
- width, height, use_extensions=True):
- """Find maximum brightness at which orientation circle in scene is visible.
-
- Uses binary search on a range of (0, default_brightness), where visibility
- is defined by an intensity comparison with the center of the outer circle.
-
- Args:
- cam: its_session_utils object.
- default_brightness: int; brightness set by config.yml.
- file_stem: str; location and name to save files.
- width: int; width for both extension and non-extension captures.
- height: int; height for both extension and non-extension captures.
- use_extensions: bool; whether extension capture should be used.
- Returns:
- int; brightness at which orientation circle in scene is visible.
- """
- min_brightness = 0
- max_brightness = default_brightness
- final_brightness = None
- out_surfaces = {'format': _FMT_NAME, 'width': width, 'height': height}
- req = capture_request_utils.auto_capture_request()
- file_stem += '_night' if use_extensions else '_no_night'
- while min_brightness < max_brightness:
- brightness = (min_brightness + max_brightness) // 2
- self.set_screen_brightness(str(brightness))
-
- if use_extensions:
- logging.debug('Taking capture with night mode ON at brightness of %d',
- brightness)
- cap = cam.do_capture_with_extensions(
- req, _EXTENSION_NIGHT, out_surfaces)
- else:
- logging.debug('Taking capture with night mode OFF at brightness of %d',
- brightness)
- cap = cam.do_capture(req, out_surfaces)
- _, img = _convert_captures(cap, f'{file_stem}_brightness={brightness}')
-
- try:
- circle = opencv_processing_utils.find_circle(
- img,
- f'{file_stem}_center_circle_brightness={brightness}.png',
- _MIN_AREA, _WHITE)
- dots = _get_dots_from_circle(circle)
- # Compare orientation dot to surrounding circle center
- dot_mean = np.mean(img[dots[0][_Y_STRING], dots[0][_X_STRING]])
- circle_mean = np.mean(img[circle[_Y_STRING], circle[_X_STRING]])
- logging.debug('Dot mean: %.2f, center mean: %.2f',
- dot_mean, circle_mean)
- difference = circle_mean - dot_mean
- if difference < _DOT_INTENSITY_DIFF_TOL:
- logging.debug('Orientation dot is washed out at brightness %d',
- brightness)
- max_brightness = brightness
- else:
- logging.debug('Found orientation dot at brightness %d', brightness)
- min_brightness = brightness + 1
- final_brightness = brightness
- except AssertionError:
- logging.debug('Unable to find circle with brightness %d', brightness)
- max_brightness = brightness
- 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,
use_extensions=True):
"""Find maximum brightness at which orientation circle in scene is visible.
@@ -334,10 +243,6 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
'according to '
f'{its_session_utils.TABLET_REQUIREMENTS_URL}.')
- its_session_utils.load_scene(
- cam, props, self.scene, self.tablet, self.chart_distance,
- log_path=self.log_path)
-
# Establish connection with lighting controller
arduino_serial_port = lighting_control_utils.lighting_control(
self.lighting_cntl, self.lighting_ch)
@@ -346,6 +251,26 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
lighting_control_utils.set_lighting_state(
arduino_serial_port, self.lighting_ch, 'OFF')
+ # Check that tablet is connected and turn it off to validate lighting
+ if self.tablet:
+ lighting_control_utils.turn_off_device(self.tablet)
+ else:
+ raise AssertionError('Test must be run with tablet.')
+
+ # Validate lighting, then setup tablet
+ cam.do_3a(do_af=False)
+ cap = cam.do_capture(
+ capture_request_utils.auto_capture_request(), cam.CAP_YUV)
+ y_plane, _, _ = image_processing_utils.convert_capture_to_planes(cap)
+ its_session_utils.validate_lighting(
+ y_plane, self.scene, state='OFF', log_path=self.log_path,
+ tablet_state='OFF')
+ self.setup_tablet()
+
+ its_session_utils.load_scene(
+ cam, props, self.scene, self.tablet, self.chart_distance,
+ lighting_check=False, log_path=self.log_path)
+
# Tap tablet to remove gallery buttons
if self.tablet:
self.tablet.adb.shell(
@@ -369,18 +294,9 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
width, height = extension_capture_sizes[0]
# Set tablet brightness to darken scene
- file_stem = f'{test_name}_{_FMT_NAME}_{width}x{height}'
- night_brightness = self.find_tablet_brightness(
- cam, self.tablet_screen_brightness, file_stem,
- width, height, use_extensions=True)
- logging.debug('Night mode ON brightness: %d', night_brightness)
- no_night_brightness = self.find_tablet_brightness(
- cam, self.tablet_screen_brightness, file_stem,
- width, height, use_extensions=False)
- logging.debug('Night mode OFF brightness: %d', no_night_brightness)
- brightness = min(night_brightness, no_night_brightness)
- self.set_screen_brightness(str(brightness))
+ self.set_screen_brightness(_TABLET_BRIGHTNESS)
+ file_stem = f'{test_name}_{_FMT_NAME}_{width}x{height}'
out_surfaces = {'format': _FMT_NAME, 'width': width, 'height': height}
req = capture_request_utils.auto_capture_request()
@@ -396,7 +312,7 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
cam.do_3a()
no_night_capture_duration, no_night_cap = self._time_and_take_captures(
cam, req, out_surfaces, use_extensions=False)
- no_night_y, no_night_img = _convert_captures(
+ _, no_night_img = _convert_captures(
no_night_cap, f'{file_stem}_no_night')
# Assert correct behavior
@@ -413,7 +329,7 @@ class NightExtensionTest(its_base_test.ItsBaseTest):
'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)
+ night_img, night_y * 255)
if not dot_intensities_acceptable:
logging.debug('Comparing overall intensity of capture with '
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index b55e61d117d..0df3fd0d701 100755
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -89,6 +89,12 @@ _GROUPED_SCENES = {
'scene2_f']
}
+# Scene extensions
+_EXTENSIONS_SCENES = (
+ os.path.join('scene_extensions', 'scene_hdr'),
+ os.path.join('scene_extensions', 'scene_night'),
+)
+
# Scenes that have to be run manually regardless of configuration
_MANUAL_SCENES = ['scene5']
@@ -642,6 +648,13 @@ def main():
if (not s.startswith('scene') and
not s.startswith(('sensor_fusion', '<scene-name>'))):
scenes[i] = f'scene{s}'
+ # Handle scene_extensions
+ if s.startswith('extensions'):
+ scenes[i] = f'scene_{s}'
+ if s.startswith('hdr') or s.startswith('night'):
+ scenes[i] = f'scene_extensions/scene_{s}'
+ if s.startswith('scene_hdr') or s.startswith('scene_night'):
+ scenes[i] = f'scene_extensions/{s}'
# Expand GROUPED_SCENES and remove any duplicates
scenes = [_GROUPED_SCENES[s] if s in _GROUPED_SCENES else s for s in scenes]
@@ -714,9 +727,12 @@ def main():
if auto_scene_switch:
possible_scenes.remove('sensor_fusion')
else:
- possible_scenes = _AUTO_SCENES if auto_scene_switch else _ALL_SCENES
+ if 'scene_extensions' in scenes:
+ possible_scenes = _EXTENSIONS_SCENES
+ else:
+ possible_scenes = _AUTO_SCENES if auto_scene_switch else _ALL_SCENES
- if '<scene-name>' in scenes:
+ if '<scene-name>' in scenes or 'scene_extensions' in scenes:
per_camera_scenes = possible_scenes
else:
# Validate user input scene names
diff --git a/apps/CameraITS/utils/image_processing_utils.py b/apps/CameraITS/utils/image_processing_utils.py
index f8a5c523159..9ec4391cb86 100644
--- a/apps/CameraITS/utils/image_processing_utils.py
+++ b/apps/CameraITS/utils/image_processing_utils.py
@@ -1073,6 +1073,16 @@ def point_in_triangle(x1, y1, x2, y2, x3, y3, xp, yp, abs_tol):
return math.isclose(a, (a1 + a2 + a3), abs_tol=abs_tol)
+def distance(p, q):
+ """Returns the Euclidean distance from point p to point q.
+
+ Args:
+ p: an Iterable of numbers
+ q: an Iterable of numbers
+ """
+ return math.sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))
+
+
def p3_img_has_wide_gamut(wide_img):
"""Check if a DISPLAY_P3 image contains wide gamut pixels.
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index a1459aae462..af76b75e31a 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -60,6 +60,7 @@ _VALIDATE_LIGHTING_REGIONS = {
1-_VALIDATE_LIGHTING_PATCH_H),
}
_VALIDATE_LIGHTING_THRESH = 0.05 # Determined empirically from scene[1:6] tests
+_VALIDATE_LIGHTING_THRESH_DARK = 0.15 # Determined empirically for night test
_CMD_NAME_STR = 'cmdName'
_OBJ_VALUE_STR = 'objValue'
_STR_VALUE = 'strValue'
@@ -1400,7 +1401,8 @@ class ItsSession(object):
fmt = json_obj[_TAG_STR][:-5]
bufs[self._camera_id][fmt].append(buf)
nbufs += 1
- elif json_obj[_TAG_STR] == 'privImage':
+ # Physical camera is appended to the tag string of a private capture
+ elif json_obj[_TAG_STR].startswith('privImage'):
# The private image format buffers are opaque to camera clients
# and cannot be accessed.
nbufs += 1
@@ -1623,34 +1625,6 @@ class ItsSession(object):
raise error_util.CameraItsError('3A failed to converge')
return ae_sens, ae_exp, awb_gains, awb_transform, af_dist
- def do_autoframing(self, zoom_ratio=None):
- """Perform autoframing on the device.
-
- Args:
- zoom_ratio: Zoom ratio. None if default zoom.
- """
- cmd = {}
- cmd[_CMD_NAME_STR] = 'doAutoframing'
- if zoom_ratio:
- if self.zoom_ratio_within_range(zoom_ratio):
- cmd['zoomRatio'] = zoom_ratio
- else:
- raise AssertionError(f'Zoom ratio {zoom_ratio} out of range')
- converged = False
- self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
-
- while True:
- data, _ = self.__read_response_from_socket()
- if data[_TAG_STR] == 'autoframingConverged':
- converged = True
- elif data[_TAG_STR] == 'autoframingDone':
- break
- else:
- raise error_util.CameraItsError('Invalid command response')
-
- if not converged:
- raise error_util.CameraItsError('Autoframing failed to converge')
-
def calc_camera_fov(self, props):
"""Determine the camera field of view from internal params.
@@ -2010,7 +1984,8 @@ def load_scene(cam, props, scene, tablet, chart_distance, lighting_check=True,
validate_lighting(y_plane, scene, log_path=log_path)
-def validate_lighting(y_plane, scene, state='ON', log_path=None):
+def validate_lighting(y_plane, scene, state='ON', log_path=None,
+ tablet_state='ON'):
"""Validates the lighting level in scene corners based on empirical values.
Args:
@@ -2018,6 +1993,7 @@ def validate_lighting(y_plane, scene, state='ON', log_path=None):
scene: scene name
state: string 'ON' or 'OFF'
log_path: [Optional] path to store artifacts
+ tablet_state: string 'ON' or 'OFF'
Returns:
boolean True if lighting validated, else raise AssertionError
@@ -2027,6 +2003,11 @@ def validate_lighting(y_plane, scene, state='ON', log_path=None):
if log_path:
file_name = os.path.join(log_path, f'validate_lighting_{scene}.jpg')
+ if tablet_state == 'OFF':
+ validate_lighting_thresh = _VALIDATE_LIGHTING_THRESH_DARK
+ else:
+ validate_lighting_thresh = _VALIDATE_LIGHTING_THRESH
+
# Test patches from each corner.
for location, coordinates in _VALIDATE_LIGHTING_REGIONS.items():
patch = image_processing_utils.get_image_patch(
@@ -2035,14 +2016,14 @@ def validate_lighting(y_plane, scene, state='ON', log_path=None):
y_mean = image_processing_utils.compute_image_means(patch)[0]
logging.debug('%s corner Y mean: %.3f', location, y_mean)
if state == 'ON':
- if y_mean > _VALIDATE_LIGHTING_THRESH:
+ if y_mean > validate_lighting_thresh:
logging.debug('Lights ON in test rig.')
return True
else:
image_processing_utils.write_image(y_plane, file_name)
raise AssertionError('Lights OFF in test rig. Turn ON and retry.')
elif state == 'OFF':
- if y_mean < _VALIDATE_LIGHTING_THRESH:
+ if y_mean < validate_lighting_thresh:
logging.debug('Lights OFF in test rig.')
return True
else:
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index 028e64acf3a..63ca2af10bc 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -526,7 +526,8 @@ def find_circle(img, img_name, min_area, color, use_adaptive_threshold=False):
num_pts/radius >= CIRCLE_RADIUS_NUMPTS_THRESH and
math.isclose(1.0, fill, abs_tol=CIRCLE_COLOR_ATOL)):
radii = [
- math.dist((shape['ctx'], shape['cty']), numpy.squeeze(point))
+ image_processing_utils.distance(
+ (shape['ctx'], shape['cty']), numpy.squeeze(point))
for point in contour
]
minimum_radius, maximum_radius = min(radii), max(radii)
@@ -538,7 +539,8 @@ def find_circle(img, img_name, min_area, color, use_adaptive_threshold=False):
# Based on image height
center_distance_atol = img_size[0]*CIRCLE_LOCATION_VARIATION_RTOL
if math.isclose(
- math.dist(old_circle_center, new_circle_center),
+ image_processing_utils.distance(
+ old_circle_center, new_circle_center),
0,
abs_tol=center_distance_atol
) and maximum_radius - minimum_radius < circle['radius_spread']:
@@ -638,6 +640,8 @@ def find_center_circle(img, img_name, color, circle_ar_rtol, circlish_rtol,
# check contours and find the best circle candidates
circles = []
img_ctr = [gray.shape[1] // 2, gray.shape[0] // 2]
+ logging.debug('img center x,y: %d, %d', img_ctr[0], img_ctr[1])
+ logging.debug('min area: %d, min circle pts: %d', min_area, min_circle_pts)
for contour in contours:
area = cv2.contourArea(contour)
if area > min_area and len(contour) >= min_circle_pts:
@@ -654,6 +658,8 @@ def find_center_circle(img, img_name, color, circle_ar_rtol, circlish_rtol,
if not circles:
raise AssertionError('No circle was detected. Please take pictures '
'according to instructions carefully!')
+ else:
+ logging.debug('num of circles found: %s', len(circles))
if debug:
logging.debug('circles [x, y, r, pi*r**2/area, area]: %s', str(circles))
diff --git a/apps/CameraITS/utils/zoom_capture_utils.py b/apps/CameraITS/utils/zoom_capture_utils.py
index 2e862b4ad7a..1d6ddd48bf7 100644
--- a/apps/CameraITS/utils/zoom_capture_utils.py
+++ b/apps/CameraITS/utils/zoom_capture_utils.py
@@ -26,7 +26,7 @@ import opencv_processing_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
-_MIN_AREA_RATIO = 0.00015 # based on 2000/(4000x3000) pixels
+_MIN_AREA_RATIO = 0.00013 # Found empirically with partners
_MIN_CIRCLE_PTS = 25
_MIN_FOCUS_DIST_TOL = 0.80 # allow charts a little closer than min
_OFFSET_ATOL = 10 # number of pixels
@@ -114,11 +114,18 @@ def get_center_circle(img, img_name, size, zoom_ratio, min_zoom_ratio, debug):
# convert [0, 1] image to [0, 255] and cast as uint8
imgc = image_processing_utils.convert_image_to_uint8(imgc)
+ # Scale circlish RTOL for low zoom ratios
+ if zoom_ratio < 1:
+ circlish_rtol = _CIRCLISH_RTOL / zoom_ratio
+ else:
+ circlish_rtol = _CIRCLISH_RTOL
+ logging.debug('circlish_rtol: %.3f', circlish_rtol)
+
# Find the center circle in img
try:
circle = opencv_processing_utils.find_center_circle(
imgc, img_name, _CIRCLE_COLOR, circle_ar_rtol=_CIRCLE_AR_RTOL,
- circlish_rtol=_CIRCLISH_RTOL,
+ circlish_rtol=circlish_rtol,
min_area=_MIN_AREA_RATIO * size[0] * size[1] * zoom_ratio * zoom_ratio,
min_circle_pts=_MIN_CIRCLE_PTS, debug=debug)
if opencv_processing_utils.is_circle_cropped(circle, size):
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index a0b0c8167e2..29e4577dad1 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -5676,7 +5676,6 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_audio" />
- <meta-data android:name="test_required_features" android:value="android.hardware.hdmi.cec" />
<meta-data android:name="display_mode" android:value="multi_display_mode" />
<meta-data android:name="ApiTest"
android:value="android.media.AudioDescriptor#getStandard|
diff --git a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
index 590d426cf7f..09339aa91aa 100644
--- a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
@@ -120,6 +120,18 @@
</LinearLayout>
</LinearLayout>
+ <!-- Device Connection -->
+ <!--
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/headset_analog_plug_message"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/headset_analog_name"/>
+ -->
+
<!-- Keycodes -->
<LinearLayout
android:layout_width="match_parent"
diff --git a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml b/apps/CtsVerifier/res/layout/ble_rssi_precision.xml
index e33c94d932e..288e8f27c31 100644
--- a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml
+++ b/apps/CtsVerifier/res/layout/ble_rssi_precision.xml
@@ -18,6 +18,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:keepScreenOn="true"
android:orientation="vertical"
style="@style/RootLayoutPadding"
tools:ignore="Autofill">
@@ -49,6 +50,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
+ <CheckBox
+ android:id="@+id/is_manual_pass"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/is_manual_pass_text"/>
+
<Button
android:id="@+id/start_test"
android:layout_width="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/ble_rx_tx_offset_precision.xml b/apps/CtsVerifier/res/layout/ble_rx_tx_offset_precision.xml
index a60b0a775f2..3abe695b90e 100644
--- a/apps/CtsVerifier/res/layout/ble_rx_tx_offset_precision.xml
+++ b/apps/CtsVerifier/res/layout/ble_rx_tx_offset_precision.xml
@@ -19,6 +19,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
+ android:keepScreenOn="true"
style="@style/RootLayoutPadding"
tools:ignore="Autofill">
@@ -49,6 +50,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
+ <CheckBox
+ android:id="@+id/is_manual_pass"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/is_manual_pass_text"/>
+
<Button
android:id="@+id/start_test"
android:layout_width="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/camera_performance.xml b/apps/CtsVerifier/res/layout/camera_performance.xml
index bdac03f40a3..6cf9ea7b1f2 100644
--- a/apps/CtsVerifier/res/layout/camera_performance.xml
+++ b/apps/CtsVerifier/res/layout/camera_performance.xml
@@ -17,6 +17,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
+ android:keepScreenOn="true"
android:orientation="vertical">
<include layout="@layout/pass_fail_buttons"/>
diff --git a/apps/CtsVerifier/res/layout/nan_accuracy.xml b/apps/CtsVerifier/res/layout/nan_accuracy.xml
index 1aa565a322d..e89ad0eacfd 100644
--- a/apps/CtsVerifier/res/layout/nan_accuracy.xml
+++ b/apps/CtsVerifier/res/layout/nan_accuracy.xml
@@ -18,6 +18,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:keepScreenOn="true"
android:orientation="vertical"
style="@style/RootLayoutPadding"
tools:ignore="Autofill">
@@ -49,6 +50,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
+ <CheckBox
+ android:id="@+id/is_manual_pass"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/is_manual_pass_text"/>
+
<TextView
android:id="@+id/test_distance_radio_group_description"
android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/values-watch/strings.xml b/apps/CtsVerifier/res/values-watch/strings.xml
index 4f412bfc6dc..dd7db1b7208 100644
--- a/apps/CtsVerifier/res/values-watch/strings.xml
+++ b/apps/CtsVerifier/res/values-watch/strings.xml
@@ -38,10 +38,29 @@
<string name="device_owner_network_logging_ui_info">
1) Ensure the device has a lock screen enabled.\n
- 2) Enable network logging by tapping on the left button below.\n
+ 2) Enable network logging by tapping on the first button below.\n
3) View the lock screen by performing a palm press and then pressing a side button.\n
- 4) Check that an icon appeared at the top of the lock screen. Tap the icon and unlock the device.\n
- 5) Verify that a dialog about device monitoring opens, and informs you about: the name of the app that manages this device, details about the device owner\'s capabilities, and information that the admin can see the most recent network traffic log.\n
+ 4) Check that an icon is present at the top of the lock screen.\n
+ 5) Tapping the icon informs you about: the name of the app that manages this device, details about the device owner\'s capabilities, and information that the admin can see the most recent network traffic log.\n
+ 6) Unlock the device and verify that a notification about device monitoring is present.
+ 7) Tap the second button below to disable network logging.\n
+ 8) Verify that after tapping the icon, screen informs you of what your device owner can do, but it does not include the section about network traffic monitoring.\n
+ \n
+ If this device does not have quick settings, please skip this test and mark it passing.
+ </string>
+
+ <string name="enterprise_privacy_add_account_info">
+ Please do the following:\n
+ 1) Press the Clear Org button.\n
+ 2) Press the Open Settings button.\n
+ 3) In the screen that opens, verify that you are told that the device is managed.\n
+ 4) Use the Back button to return to this page.\n
+ 5) Press the Set Org button.\n
+ 6) Press the Open Settings button.\n
+ 7) In the screen that opens, verify that you are told that the device is managed by \"Foo, Inc.\".\n
+ 8) Tap the \"Learn more\" link or "Managed Device info" button.\n
+ 9) Verify that a screen informing you what your managing organization can do is shown.\n
+ 10) Use the Back button to return to this page.
</string>
<string name="enterprise_privacy_quick_settings_info">
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 17749a75145..4967f32879b 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -6896,6 +6896,7 @@ Follow the instructions on the screen to measure the frequency response for the
\nIf the TV device is launched on older Android letters, all tests will be disabled. Press Pass to pass this case.
</string>
<string name="is_reference_device_checkbox_text">Is Reference Device</string>
+ <string name="is_manual_pass_text">Pass test manually after test completion</string>
<string name="uwb_precision">Uwb Precision Test</string>
<string name="uwb_short_range">Uwb Short Range Test</string>
<string name="uwb_precision_instruction">
@@ -6945,7 +6946,7 @@ Follow the instructions on the screen to measure the frequency response for the
\n1. Ensure that the test is already started on the reference device.
\n2. Input the device ID of the reference device (displayed on the reference device) into the provided field and click "Start Test"
\n3. The test is automatically stopped and passed (or failed) when all the required data is collected
- \n4. The test is passed if the median RSSI from both DUT and reference device is between -65dBm and -45dBm.
+ \n4. The test is passed if the median RSSI from both DUT and reference device is between -65dBm and -35dBm.
\nReference device instructions
\n1. Ensure that the "Is reference device" checkbox is checked, then click, "Start Advertising"
</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 17485e1ac83..0f6d391473b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -160,7 +160,9 @@ public class AnalogHeadsetAudioActivity
mHeadsetVolUpText = (TextView)findViewById(R.id.headset_keycode_volume_up);
mHeadsetVolDownText = (TextView)findViewById(R.id.headset_keycode_volume_down);
- if (isTelevision()) {
+ mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+
+ if (isTelevisionOrFixedVolume()) {
mButtonsPromptTxt.setVisibility(View.GONE);
mHeadsetHookText.setVisibility(View.GONE);
mHeadsetVolUpText.setVisibility(View.GONE);
@@ -170,8 +172,6 @@ public class AnalogHeadsetAudioActivity
mResultsTxt = (TextView)findViewById(R.id.headset_results);
- mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
-
setupPlayer();
mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
@@ -183,7 +183,7 @@ public class AnalogHeadsetAudioActivity
showKeyMessagesState();
- setInfoResources(R.string.analog_headset_test, isTelevision()
+ setInfoResources(R.string.analog_headset_test, isTelevisionOrFixedVolume()
? R.string.analog_headset_test_info_tv : R.string.analog_headset_test_info, -1);
setPassFailButtonClickListeners();
@@ -219,7 +219,7 @@ public class AnalogHeadsetAudioActivity
mPlugIntentReceived &&
mHeadsetDeviceInfo != null &&
mPlaybackSuccess &&
- (isTelevision()
+ (isTelevisionOrFixedVolume()
|| ((mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown));
if (pass) {
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
@@ -560,7 +560,8 @@ public class AnalogHeadsetAudioActivity
return super.onKeyDown(keyCode, event);
}
- private boolean isTelevision() {
- return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ private boolean isTelevisionOrFixedVolume() {
+ return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || mAudioManager.isVolumeFixed();
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java
index f701ba0f38d..121841862bc 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java
@@ -177,14 +177,14 @@ public abstract class AudioColdStartBaseActivity
int id = v.getId();
if (id == R.id.audioJavaApiBtn) {
stopAudio();
- updateTestStateButtons();
clearResults();
+ updateTestStateButtons();
mAudioApi = BuilderBase.TYPE_JAVA;
mNumExchangeFrames = StreamBase.getNumBurstFrames(mAudioApi);
} else if (id == R.id.audioNativeApiBtn) {
stopAudio();
- updateTestStateButtons();
clearResults();
+ updateTestStateButtons();
mAudioApi = BuilderBase.TYPE_OBOE;
mNumExchangeFrames = StreamBase.getNumBurstFrames(mAudioApi);
} else if (id == R.id.coldstart_run_btn) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
index b3ae0afb20e..e1eba03d3c9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
@@ -70,16 +70,18 @@ public class AudioOutColdStartLatencyActivity
protected void onResume() {
super.onResume();
mTouchSoundsActive = SettingsUtils.areTouchSoundsActive(this);
- showTouchSoundsState();
+ updateTestStateButtons();
}
- private void showTouchSoundsState() {
+ @Override
+ protected void updateTestStateButtons() {
String message = getResources().getString(
mTouchSoundsActive
? R.string.audio_coldstart_touchsounds_message
: R.string.audio_coldstart_notouchsounds_message);
mAttributesTxt.setText(message);
- enableTest(!mTouchSoundsActive);
+ enableTest(!mTouchSoundsActive && !mIsTestRunning);
+ mStopBtn.setEnabled(!mTouchSoundsActive && mIsTestRunning);
}
@Override
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 d1c44ec4051..0d0d423baa7 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
@@ -101,7 +101,6 @@ import com.android.compatibility.common.util.ReportLog.Metric;
import com.android.cts.verifier.R;
import com.android.cts.verifier.camera.performance.CameraTestInstrumentation;
import com.android.cts.verifier.camera.performance.CameraTestInstrumentation.MetricListener;
-import com.android.ex.camera2.blocking.BlockingCameraManager;
import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
import com.android.ex.camera2.blocking.BlockingExtensionSessionCallback;
import com.android.ex.camera2.blocking.BlockingSessionCallback;
@@ -260,7 +259,7 @@ public class ItsService extends Service implements SensorEventListener {
private volatile BlockingQueue<Object[]> mSerializerQueue =
new LinkedBlockingDeque<Object[]>();
- private AtomicInteger mCountCallbacksRemaining = new AtomicInteger();
+ private final AtomicInteger mCountCallbacksRemaining = new AtomicInteger();
private AtomicInteger mCountRawOrDng = new AtomicInteger();
private AtomicInteger mCountRaw10 = new AtomicInteger();
private AtomicInteger mCountRaw12 = new AtomicInteger();
@@ -906,8 +905,6 @@ public class ItsService extends Service implements SensorEventListener {
doGetSensorEvents();
} else if ("do3A".equals(cmdObj.getString("cmdName"))) {
do3A(cmdObj);
- } else if ("doAutoframing".equals(cmdObj.getString("cmdName"))) {
- doAutoframing(cmdObj);
} else if ("doCapture".equals(cmdObj.getString("cmdName"))) {
doCapture(cmdObj);
} else if ("doVibrate".equals(cmdObj.getString("cmdName"))) {
@@ -2021,87 +2018,6 @@ public class ItsService extends Service implements SensorEventListener {
}
}
- private void doAutoframing(JSONObject params) throws ItsException {
- AutoframingResultListener autoframingListener = new AutoframingResultListener();
- try {
- CameraCharacteristics c = mCameraCharacteristics;
- Size[] sizes = ItsUtils.getYuvOutputSizes(c);
- int[] outputFormats = new int[1];
- outputFormats[0] = ImageFormat.YUV_420_888;
- Size[] outputSizes = new Size[1];
- outputSizes[0] = sizes[0];
- int width = outputSizes[0].getWidth();
- int height = outputSizes[0].getHeight();
-
- prepareImageReaders(outputSizes, outputFormats, /*inputSize*/null, /*inputFormat*/0,
- /*maxInputBuffers*/0);
-
- List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>(1);
- OutputConfiguration config =
- new OutputConfiguration(mOutputImageReaders[0].getSurface());
- outputConfigs.add(config);
- BlockingSessionCallback sessionListener = new BlockingSessionCallback();
- mCamera.createCaptureSessionByOutputConfigurations(
- outputConfigs, sessionListener, mCameraHandler);
- mSession = sessionListener.waitAndGetSession(TIMEOUT_IDLE_MS);
-
- // Add a listener that just recycles buffers; they aren't saved anywhere.
- ImageReader.OnImageAvailableListener readerListener =
- createAvailableListenerDropper();
- mOutputImageReaders[0].setOnImageAvailableListener(readerListener, mSaveHandlers[0]);
-
- double zoomRatio = params.optDouble(ZOOM_RATIO_KEY);
-
- mInterlockAutoframing.open();
- synchronized (mAutoframingStateLock) {
- mConvergedAutoframing = false;
- }
-
- long tstart = System.currentTimeMillis();
-
- // Keep issuing capture requests until autoframing has converged.
- while (true) {
- // Block until the next autoframing frame.
- if (!mInterlockAutoframing.block(TIMEOUT_AUTOFRAMING * 1000)
- || System.currentTimeMillis() - tstart > TIMEOUT_AUTOFRAMING * 1000) {
- throw new ItsException(
- "Autoframing failed to converge after " + TIMEOUT_AUTOFRAMING
- + " seconds.\n"
- + "Autoframing converge state: " + mConvergedAutoframing + ".");
- }
- mInterlockAutoframing.close();
-
- synchronized (mAutoframingStateLock) {
- if (!mConvergedAutoframing) {
- CaptureRequest.Builder req = mCamera.createCaptureRequest(
- CameraDevice.TEMPLATE_PREVIEW);
- req.set(CaptureRequest.CONTROL_AUTOFRAMING,
- CaptureRequest.CONTROL_AUTOFRAMING_ON);
- if (!Double.isNaN(zoomRatio)) {
- req.set(CaptureRequest.CONTROL_ZOOM_RATIO, (float) zoomRatio);
- }
- req.addTarget(mOutputImageReaders[0].getSurface());
-
- mSession.setRepeatingRequest(req.build(), autoframingListener,
- mResultHandler);
- } else {
- mSocketRunnableObj.sendResponse("autoframingConverged", "");
- Logt.i(TAG, "Autoframing converged");
- break;
- }
- }
- }
- } catch (android.hardware.camera2.CameraAccessException e) {
- throw new ItsException("Access error: ", e);
- } finally {
- mSocketRunnableObj.sendResponse("autoframingDone", "");
- autoframingListener.stop();
- if (mSession != null) {
- mSession.close();
- }
- }
- }
-
private void doVibrate(JSONObject params) throws ItsException {
try {
if (mVibrator == null) {
@@ -2714,7 +2630,7 @@ public class ItsService extends Service implements SensorEventListener {
return previewSize;
}
- private void configureAndCreateExtensionSession(
+ private Surface configureAndCreateExtensionSession(
Surface captureSurface,
int extension,
CameraExtensionSession.StateCallback stateCallback) throws ItsException {
@@ -2739,6 +2655,7 @@ public class ItsService extends Service implements SensorEventListener {
} catch (CameraAccessException e) {
throw new ItsException("Error creating extension session: " + e);
}
+ return previewSurface;
}
private void configureAndCreateCaptureSession(int requestTemplate, Surface recordSurface,
@@ -2991,11 +2908,6 @@ public class ItsService extends Service implements SensorEventListener {
List<CaptureRequest.Builder> requests = ItsSerializer.deserializeRequestList(
mCamera, params, "captureRequests");
- // optional background preview requests
- List<CaptureRequest.Builder> backgroundRequests = ItsSerializer.deserializeRequestList(
- mCamera, params, "repeatRequests");
- boolean backgroundRequest = backgroundRequests.size() > 0;
-
int numSurfaces = 0;
int numCaptureSurfaces = 0;
BlockingExtensionSessionCallback sessionListener =
@@ -3013,28 +2925,42 @@ public class ItsService extends Service implements SensorEventListener {
JSONArray jsonOutputSpecs = ItsUtils.getOutputSpecs(params);
prepareImageReadersWithOutputSpecs(jsonOutputSpecs, /*inputSize*/null,
- /*inputFormat*/0, /*maxInputBuffers*/0, backgroundRequest);
+ /*inputFormat*/0, /*maxInputBuffers*/0, /*backgroundRequest*/ false);
numSurfaces = mOutputImageReaders.length;
- numCaptureSurfaces = numSurfaces - (backgroundRequest ? 1 : 0);
+ numCaptureSurfaces = numSurfaces;
- configureAndCreateExtensionSession(mOutputImageReaders[0].getSurface(), extension,
+ Surface previewSurface = configureAndCreateExtensionSession(
+ mOutputImageReaders[0].getSurface(),
+ extension,
sessionListener);
mExtensionSession = sessionListener.waitAndGetSession(TIMEOUT_IDLE_MS);
- for (int i = 0; i < numSurfaces; i++) {
- ImageReader.OnImageAvailableListener readerListener;
- if (backgroundRequest && i == numSurfaces - 1) {
- readerListener = createAvailableListenerDropper();
- } else {
- // When image is available, decrements mCountCallbacksRemaining
- readerListener = createExtensionAvailableListener(mCaptureCallback);
- }
- mOutputImageReaders[i].setOnImageAvailableListener(readerListener,
- mSaveHandlers[i]);
+ CaptureRequest.Builder captureBuilder = requests.get(0);
+
+ if (params.optBoolean("waitAE", true)) {
+ // Set repeating request and wait for AE convergence.
+ Logt.i(TAG, "Waiting for AE to converge before taking extensions capture.");
+ captureBuilder.addTarget(previewSurface);
+ ImageReader.OnImageAvailableListener dropperListener =
+ createAvailableListenerDropper();
+ mOutputImageReaders[0].setOnImageAvailableListener(dropperListener,
+ mSaveHandlers[0]);
+ mExtensionSession.setRepeatingRequest(captureBuilder.build(),
+ new HandlerExecutor(mResultHandler),
+ mExtAEResultListener);
+ mCountCallbacksRemaining.set(1);
+ long timeout = TIMEOUT_CALLBACK * 1000;
+ waitForCallbacks(timeout);
+ mExtensionSession.stopRepeating();
+ captureBuilder.removeTarget(previewSurface);
+ mResultThread.sleep(PIPELINE_WARMUP_TIME_MS);
}
- CaptureRequest.Builder captureBuilder = requests.get(0);
+ ImageReader.OnImageAvailableListener readerListener =
+ createExtensionAvailableListener(mCaptureCallback);
+ mOutputImageReaders[0].setOnImageAvailableListener(readerListener,
+ mSaveHandlers[0]);
captureBuilder.addTarget(mOutputImageReaders[0].getSurface());
mExtensionSession.capture(captureBuilder.build(), new HandlerExecutor(mResultHandler),
mExtCaptureResultListener);
@@ -3049,6 +2975,8 @@ public class ItsService extends Service implements SensorEventListener {
BlockingExtensionSessionCallback.SESSION_CLOSED, TIMEOUT_SESSION_CLOSE);
} catch (android.hardware.camera2.CameraAccessException e) {
throw new ItsException("Access error: ", e);
+ } catch (InterruptedException e) {
+ throw new ItsException("Unexpected InterruptedException: ", e);
}
}
@@ -3862,6 +3790,41 @@ public class ItsService extends Service implements SensorEventListener {
}
};
+ private final ExtensionCaptureResultListener mExtAEResultListener =
+ new ExtensionCaptureResultListener() {
+ @Override
+ public void onCaptureProcessStarted(CameraExtensionSession session,
+ CaptureRequest request) {
+ }
+
+ @Override
+ public void onCaptureResultAvailable(CameraExtensionSession session,
+ CaptureRequest request,
+ TotalCaptureResult result) {
+ try {
+ if (request == null || result == null) {
+ throw new ItsException("Request/result is invalid");
+ }
+ if (result.get(CaptureResult.CONTROL_AE_STATE) ==
+ CaptureResult.CONTROL_AE_STATE_CONVERGED) {
+ synchronized(mCountCallbacksRemaining) {
+ mCountCallbacksRemaining.decrementAndGet();
+ mCountCallbacksRemaining.notify();
+ }
+ }
+ } catch (ItsException e) {
+ Logt.e(TAG, "Script error: ", e);
+ } catch (Exception e) {
+ Logt.e(TAG, "Script error: ", e);
+ }
+ }
+
+ @Override
+ public void onCaptureFailed(CameraExtensionSession session, CaptureRequest request) {
+ Logt.e(TAG, "Script error: capture failed");
+ }
+ };
+
private class CaptureCallbackWaiter extends CameraCaptureSession.CaptureCallback {
private final LinkedBlockingQueue<TotalCaptureResult> mResultQueue =
new LinkedBlockingQueue<>();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java
index 7e01303e2a9..54ed55f6e84 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java
@@ -3,6 +3,7 @@
package com.android.cts.verifier.deskclock;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.provider.AlarmClock;
@@ -156,6 +157,19 @@ public class DeskClockTestsActivity extends PassFailButtons.TestListActivity {
private void addTests(ArrayTestListAdapter adapter, TestInfo[] tests) {
for (TestInfo info : tests) {
+
+ // TODO(b/291214170): Enable START_ALARM test once Wear Alarm app fixes EXTRA_SKIP_UI.
+ // See b/291214170#comment14.
+ if (isWearDevice() && info.getTestId().equals(START_ALARM_TEST)) {
+ continue;
+ }
+
+ // TODO(b/232182401): Enable START_TIMER test once Wear Timer app fixes EXTRA_SKIP_UI.
+ // See b/232182401#comment7.
+ if (isWearDevice() && info.getTestId().equals(START_TIMER)) {
+ continue;
+ }
+
int title = info.getTitle();
String testId = info.getTestId();
Intent intent = IntentDrivenTestActivity.newIntent(this, testId, title,
@@ -166,6 +180,11 @@ public class DeskClockTestsActivity extends PassFailButtons.TestListActivity {
}
}
+ private boolean isWearDevice() {
+ final PackageManager pm = getApplicationContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
+
public static class DeskClockIntentFactory implements IntentFactory {
@Override
public Intent[] createIntents(String testId, int buttonText) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
index 605d895741e..66e3d91a60e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
@@ -132,7 +132,7 @@ public class EnterprisePrivacyTestListActivity extends PassFailButtons.TestListA
R.string.enterprise_privacy_page,
R.string.enterprise_privacy_page_info,
new ButtonInfo(R.string.go_button_text,
- new Intent(Settings.ACTION_SECURITY_SETTINGS))));
+ Utils.getManagedSettingsIntent(this))));
adapter.add(buildCommandTest(ENTERPRISE_PRIVACY_NETWORK_LOGGING,
R.string.enterprise_privacy_network_logging,
R.string.enterprise_privacy_network_logging_info,
@@ -250,18 +250,24 @@ public class EnterprisePrivacyTestListActivity extends PassFailButtons.TestListA
buildCommandIntentForCurrentUser(CommandReceiverActivity
.COMMAND_CLEAR_MAXIMUM_PASSWORD_ATTEMPTS))}));
}
+ ButtonInfo[] buttons;
+ if (Utils.isLockScreenManagedOrgNameSupported(this)) {
+ buttons = new ButtonInfo[] {
+ new ButtonInfo(R.string.enterprise_privacy_clear_organization,
+ buildCommandIntent(
+ CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)),
+ new ButtonInfo(R.string.enterprise_privacy_set_organization,
+ buildCommandIntent(
+ CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
+ .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME,
+ "Foo, Inc."))};
+ } else {
+ buttons = new ButtonInfo[]{};
+ }
adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_QUICK_SETTINGS,
R.string.enterprise_privacy_quick_settings,
R.string.enterprise_privacy_quick_settings_info,
- new ButtonInfo[] {
- new ButtonInfo(R.string.enterprise_privacy_clear_organization,
- buildCommandIntent(
- CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)),
- new ButtonInfo(R.string.enterprise_privacy_set_organization,
- buildCommandIntent(
- CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
- .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME,
- "Foo, Inc."))}));
+ buttons));
if (Utils.isLockscreenSupported(this)
&& FeatureUtil.isKeyguardShownWhenUserDoesntHaveCredentials(this)) {
adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_KEYGUARD,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
index 65a3488b5e3..a81cf5ce208 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
@@ -31,6 +31,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
@@ -162,6 +163,34 @@ public class Utils {
.show();
}
+
+ /**
+ * Depending on form factor, the location of enterprise info page is different.
+ * The helper function opening settings can cause confusion, hence differentiating location
+ * it opens based on type of device.
+ *
+ * @param context The calling context
+ */
+ static Intent getManagedSettingsIntent(Context context) {
+ if (isWatch(context)) {
+ return new Intent(Settings.ACTION_SETTINGS);
+ } else {
+ return new Intent(Settings.ACTION_SECURITY_SETTINGS);
+ }
+ }
+
+ /**
+ * Depending on form factor, device may not have room to show more than an icon
+ * for the enterprise managed cases.
+ * Returning an indicator, so the tests can be adjusted.
+ *
+ * @param context The calling context
+ */
+ static boolean isLockScreenManagedOrgNameSupported(Context context) {
+ return !isWatch(context);
+ }
+
+
static boolean isLockscreenSupported(Context context) {
return context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SECURE_LOCK_SCREEN);
@@ -171,4 +200,8 @@ public class Utils {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
|| context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION);
}
+
+ static boolean isWatch(Context context) {
+ return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java
index b2591ec85e3..1a3352dc6b8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java
@@ -49,6 +49,7 @@ public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
// Report log schema
private static final String KEY_REFERENCE_DEVICE = "reference_device";
+ private static final String KEY_RSSI_RANGE_95_PERCENTILE = "rssi_range_95_percentile";
// Thresholds
private static final int MAX_RSSI_RANGE_DBM = 18;
@@ -69,7 +70,10 @@ public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
private EditText mReferenceDeviceIdInput;
private String mReferenceDeviceName;
private CheckBox mIsReferenceDeviceCheckbox;
- private boolean mTestPassed;
+ private CheckBox mIsManualPassCheckbox;
+ private boolean mIsManualPass;
+ private boolean mTestCompleted;
+ private int mRssiRange;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -85,6 +89,7 @@ public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
mDeviceFoundTextView = findViewById(R.id.device_found_info);
mReferenceDeviceIdInput = findViewById(R.id.ref_device_id_input);
mIsReferenceDeviceCheckbox = findViewById(R.id.is_reference_device);
+ mIsManualPassCheckbox = findViewById(R.id.is_manual_pass);
mDutModeLayout = findViewById(R.id.dut_mode_layout);
mRefModeLayout = findViewById(R.id.ref_mode_layout);
DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
@@ -99,11 +104,15 @@ public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
mDeviceIdInfoTextView.setVisibility(View.GONE);
mDeviceFoundTextView.setVisibility(View.GONE);
isReferenceDevice = mIsReferenceDeviceCheckbox.isChecked();
+ mIsManualPass = mIsManualPassCheckbox.isChecked();
checkUiMode();
mIsReferenceDeviceCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
isReferenceDevice = isChecked;
checkUiMode();
});
+ mIsManualPassCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ mIsManualPass = isChecked;
+ });
mStartTestButton.setOnClickListener(v -> startTest());
mStopTestButton.setOnClickListener(v -> stopTest());
mStartAdvertisingButton.setOnClickListener(v -> startAdvertising());
@@ -116,6 +125,7 @@ public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
}
private void startTest() {
+ mTestCompleted = false;
if (!checkBluetoothEnabled()) {
return;
}
@@ -162,10 +172,15 @@ public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
Collections.sort(data);
// Calculate range at 95th percentile
int rssiRange = data.get(975) - data.get(25);
+ mRssiRange = rssiRange;
+ mTestCompleted = true;
if (rssiRange <= MAX_RSSI_RANGE_DBM) {
makeToast("Test passed! Rssi range is: " + rssiRange);
- getPassButton().performClick();
- mTestPassed = true;
+ if (mIsManualPass) {
+ getPassButton().setEnabled(true);
+ } else {
+ getPassButton().performClick();
+ }
} else {
makeToast("Test failed! Rssi range is: " + rssiRange);
}
@@ -244,9 +259,11 @@ public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
@Override
public void recordTestResults() {
- if (mTestPassed) {
+ if (mTestCompleted) {
getReportLog().addValue(KEY_REFERENCE_DEVICE, mReferenceDeviceName,
ResultType.NEUTRAL, ResultUnit.NONE);
+ getReportLog().addValue(KEY_RSSI_RANGE_95_PERCENTILE, mRssiRange, ResultType.NEUTRAL,
+ ResultUnit.NONE);
getReportLog().submit();
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java
index dd663bc3f97..c1589f6f3a5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxOffsetPrecisionActivity.java
@@ -49,10 +49,12 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
// Report log schema
private static final String KEY_REFERENCE_DEVICE = "reference_device";
+ private static final String KEY_RSSI_MEDIAN_DUT = "rssi_median_dut";
+ private static final String KEY_RSSI_MEDIAN_REFERENCE = "rssi_median_ref";
// Thresholds
private static final int MIN_RSSI_MEDIAN_DBM = -65;
- private static final int MAX_RSSI_MEDIAN_DBM = -45;
+ private static final int MAX_RSSI_MEDIAN_DBM = -35;
private boolean isReferenceDevice;
private BleScanner mBleScanner;
@@ -72,9 +74,12 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
private EditText mReferenceDeviceIdInput;
private String mReferenceDeviceName;
private CheckBox mIsReferenceDeviceCheckbox;
- private boolean mTestPassed;
+ private CheckBox mIsManualPassCheckbox;
+ private boolean mIsManualPass;
private byte mCurrentReferenceDeviceId = 0;
private byte mRssiMedianFromReferenceDevice = 0;
+ private int mRssiMedianOnDut = 0;
+ private boolean mTestCompleted;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -90,6 +95,7 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
mDeviceFoundTextView = findViewById(R.id.device_found_info);
mReferenceDeviceIdInput = findViewById(R.id.ref_device_id_input);
mIsReferenceDeviceCheckbox = findViewById(R.id.is_reference_device);
+ mIsManualPassCheckbox = findViewById(R.id.is_manual_pass);
mDutModeLayout = findViewById(R.id.dut_mode_layout);
mRefModeLayout = findViewById(R.id.ref_mode_layout);
mDutTestInfoTextView = findViewById(R.id.dut_test_result_info);
@@ -108,11 +114,15 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
mRefTestInfoTextView.setVisibility(View.GONE);
mDutTestInfoTextView.setVisibility(View.GONE);
isReferenceDevice = mIsReferenceDeviceCheckbox.isChecked();
+ mIsManualPass = mIsManualPassCheckbox.isChecked();
checkUiMode();
mIsReferenceDeviceCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
isReferenceDevice = isChecked;
checkUiMode();
});
+ mIsManualPassCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ mIsManualPass = isChecked;
+ });
mStartTestButton.setOnClickListener(v -> startTestAsDut());
mStopTestButton.setOnClickListener(v -> stopTest());
mStartAdvertisingButton.setOnClickListener(v -> startTestAsReferenceDevice());
@@ -125,6 +135,9 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
}
private void startTestAsDut() {
+ mTestCompleted = false;
+ mRssiMedianFromReferenceDevice = 0;
+ mRssiMedianOnDut = 0;
if (!checkBluetoothEnabled()) {
return;
}
@@ -134,6 +147,7 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
}
mStartTestButton.setEnabled(false);
mStopTestButton.setEnabled(true);
+ mDutTestInfoTextView.setVisibility(View.GONE);
mCurrentReferenceDeviceId = Byte.parseByte(mReferenceDeviceIdInput.getText().toString());
mIsReferenceDeviceCheckbox.setEnabled(false);
startAdvertising();
@@ -176,6 +190,7 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
if (!checkBluetoothEnabled()) {
return;
}
+ mRefTestInfoTextView.setVisibility(View.GONE);
startAdvertising();
mBleScanner.startScanning((uuids,
macAddress,
@@ -217,6 +232,8 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
startAdvertising();
return;
}
+ mRssiMedianOnDut = rssiMedian;
+ mTestCompleted = true;
String dutDeviceTestInfo = getString(R.string.dut_test_result_info_presence,
rssiMedian, mRssiMedianFromReferenceDevice);
mDutTestInfoTextView.setVisibility(View.VISIBLE);
@@ -226,8 +243,11 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
&& mRssiMedianFromReferenceDevice <= MAX_RSSI_MEDIAN_DBM) {
makeToast("Test passed! TX Rssi median is: " + rssiMedian + ". Rx Rssi median is: "
+ mRssiMedianFromReferenceDevice);
- mTestPassed = true;
- getPassButton().performClick();
+ if (mIsManualPass) {
+ getPassButton().setEnabled(true);
+ } else {
+ getPassButton().performClick();
+ }
} else {
makeToast("Test failed! TX Rssi median is: " + rssiMedian + ". Rx Rssi median is: "
+ mRssiMedianFromReferenceDevice);
@@ -244,11 +264,8 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
mStopTestButton.setEnabled(false);
mStartTestButton.setEnabled(true);
mIsReferenceDeviceCheckbox.setEnabled(true);
- mRssiMedianFromReferenceDevice = 0;
mCurrentReferenceDeviceId = 0;
- mRefTestInfoTextView.setVisibility(View.GONE);
mDeviceFoundTextView.setVisibility(View.GONE);
- mDutTestInfoTextView.setVisibility(View.GONE);
}
private void startAdvertising() {
@@ -319,9 +336,13 @@ public class BleRxTxOffsetPrecisionActivity extends PassFailButtons.Activity {
@Override
public void recordTestResults() {
- if (mTestPassed) {
+ if (mTestCompleted) {
getReportLog().addValue(KEY_REFERENCE_DEVICE, mReferenceDeviceName,
ResultType.NEUTRAL, ResultUnit.NONE);
+ getReportLog().addValue(KEY_RSSI_MEDIAN_DUT, mRssiMedianOnDut, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ getReportLog().addValue(KEY_RSSI_MEDIAN_REFERENCE, mRssiMedianFromReferenceDevice,
+ ResultType.NEUTRAL, ResultUnit.NONE);
getReportLog().submit();
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanAccuracyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanAccuracyActivity.java
index 4b8fbbff23f..dd39e36dfbe 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanAccuracyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanAccuracyActivity.java
@@ -62,6 +62,7 @@ public class NanAccuracyActivity extends PassFailButtons.Activity {
private Button mStartTestButton;
private Button mStartPublishingButton;
private CheckBox mReferenceDeviceCheckbox;
+ private CheckBox mIsManualPassCheckbox;
private LinearLayout mDutModeLayout;
private LinearLayout mRefModeLayout;
private TextView mDeviceFoundTextView;
@@ -70,6 +71,7 @@ public class NanAccuracyActivity extends PassFailButtons.Activity {
private EditText mServiceIdInputEditText;
private RadioGroup mTestDistanceRadioGroup;
private String mReferenceDeviceName = "";
+ private boolean mIsManualPass;
private final WifiAwarePeerListener mWifiAwarePeerListener = new WifiAwarePeerListener() {
@Override
public void onDeviceFound(PeerHandle peerHandle) {
@@ -96,6 +98,7 @@ public class NanAccuracyActivity extends PassFailButtons.Activity {
setPassFailButtonClickListeners();
getPassButton().setEnabled(false);
mReferenceDeviceCheckbox = findViewById(R.id.is_reference_device);
+ mIsManualPassCheckbox = findViewById(R.id.is_manual_pass);
mStartTestButton = findViewById(R.id.start_test);
Button stopTestButton = findViewById(R.id.stop_test);
mStartPublishingButton = findViewById(R.id.start_publishing);
@@ -118,8 +121,12 @@ public class NanAccuracyActivity extends PassFailButtons.Activity {
mWifiAwarePeer = new WifiAwarePeer(this, handler);
mReceivedSamples = new HashMap<>();
setUpActivity();
+ mIsManualPass = mIsManualPassCheckbox.isChecked();
mReferenceDeviceCheckbox.setOnCheckedChangeListener(
(buttonView, isChecked) -> setUpActivity());
+ mIsManualPassCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ mIsManualPass = isChecked;
+ });
mStartTestButton.setOnClickListener((view) -> startTest());
stopTestButton.setOnClickListener((view) -> stopTest());
mDeviceFoundTextView.setVisibility(View.GONE);
@@ -231,7 +238,11 @@ public class NanAccuracyActivity extends PassFailButtons.Activity {
+ new DecimalFormat("#.##").format((data.size() / (double) 100) * 100) + "%");
}
if (mTestResult.isAllPassed()) {
- getPassButton().performClick();
+ if (mIsManualPass) {
+ getPassButton().setEnabled(true);
+ } else {
+ getPassButton().performClick();
+ }
}
mReceivedSamples.clear();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
index 3bfac3a2b51..1d8e38cef33 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
@@ -224,7 +224,7 @@ public class MockTvInputService extends TvInputService {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED);
intentFilter.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
- registerReceiver(mBroadcastReceiver, intentFilter);
+ registerReceiver(mBroadcastReceiver, intentFilter, Context.RECEIVER_EXPORTED);
}
@Override
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoAccounts.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoAccounts.java
index 49889940770..c420c4a4f6f 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoAccounts.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoAccounts.java
@@ -39,6 +39,14 @@ public @interface EnsureHasNoAccounts {
/** Which user type the account must not be present added on. */
UserType onUser() default ANY;
+ /** Exclude pre created accounts. */
+ boolean allowPreCreatedAccounts() default true;
+
+ /** Behaviour if there are some accounts for the user. */
+ com.android.bedstead.harrier.annotations.FailureMode failureMode()
+ default com.android.bedstead.harrier.annotations.FailureMode.SKIP;
+
+
/**
* Weight sets the order that annotations will be resolved.
*
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java
index 1d49c7eba81..0e09981bf7c 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java
@@ -17,7 +17,6 @@
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_ORGANIZATION_OWNED_PROFILE_OWNER_PROFILE;
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;
@@ -29,7 +28,6 @@ import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
* <p>This is used by {@code DevicePolicyManager#setDefaultSmsApplication(ComponentName, String)}.
*/
@EnterprisePolicy(dpc = APPLIED_BY_DEVICE_OWNER
- | APPLIED_BY_ORGANIZATION_OWNED_PROFILE_OWNER_PROFILE
| APPLIES_TO_OWN_USER
| CANNOT_BE_APPLIED_BY_ROLE_HOLDER)
public final class DefaultSmsApplication {
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 7a7990d594f..ddfc0cd303c 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,7 +17,6 @@
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;
@@ -45,6 +44,7 @@ import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -76,7 +76,6 @@ 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;
@@ -101,6 +100,7 @@ import com.android.bedstead.harrier.annotations.RequireFeature;
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.RequireHasDefaultBrowser;
import com.android.bedstead.harrier.annotations.RequireHeadlessSystemUserMode;
import com.android.bedstead.harrier.annotations.RequireInstantApp;
import com.android.bedstead.harrier.annotations.RequireLowRamDevice;
@@ -1262,7 +1262,9 @@ public final class DeviceState extends HarrierRule {
if (annotation instanceof EnsureHasNoAccounts) {
EnsureHasNoAccounts ensureHasNoAccountsAnnotation =
(EnsureHasNoAccounts) annotation;
- ensureHasNoAccounts(ensureHasNoAccountsAnnotation.onUser());
+ ensureHasNoAccounts(ensureHasNoAccountsAnnotation.onUser(),
+ ensureHasNoAccountsAnnotation.allowPreCreatedAccounts(),
+ ensureHasNoAccountsAnnotation.failureMode());
continue;
}
@@ -1292,13 +1294,15 @@ public final class DeviceState extends HarrierRule {
requireQuickSettingsSupport.failureMode());
continue;
}
+
if (annotation instanceof RequireHasDefaultBrowser) {
RequireHasDefaultBrowser requireHasDefaultBrowser =
(RequireHasDefaultBrowser) annotation;
- UserReference user =
+ UserReference user =
resolveUserTypeToUser(requireHasDefaultBrowser.forUser());
- checkFailOrSkip("User: " + user + " does not have a default browser",
- !TestApis.roles().getRoleHoldersAsUser(ROLE_BROWSER, user).isEmpty(),
+
+ checkFailOrSkip("User: " + user + " does not have a default browser",
+ TestApis.packages().defaultBrowserForUser(user) != null,
requireHasDefaultBrowser.failureMode());
continue;
}
@@ -2834,7 +2838,8 @@ public final class DeviceState extends HarrierRule {
ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
}
- ensureHasNoAccounts(UserType.ANY);
+ ensureHasNoAccounts(UserType.ANY, /* allowPreCreatedAccounts= */ true,
+ FailureMode.FAIL);
ensureTestAppInstalled(RemoteDevicePolicyManagerRoleHolder.sTestApp, user);
TestApis.devicePolicy().setDevicePolicyManagementRoleHolder(
RemoteDevicePolicyManagerRoleHolder.sTestApp.pkg(), user);
@@ -3134,10 +3139,12 @@ public final class DeviceState extends HarrierRule {
}
if (Versions.meetsMinimumSdkVersionRequirement(Versions.U)) {
- ensureHasNoAccounts(UserType.ANY);
+ ensureHasNoAccounts(UserType.ANY, /* allowPreCreatedAccounts= */ true,
+ FailureMode.FAIL);
} else {
// Prior to U this only checked the system user
- ensureHasNoAccounts(UserType.SYSTEM_USER);
+ ensureHasNoAccounts(UserType.SYSTEM_USER, /* allowPreCreatedAccounts= */ true,
+ FailureMode.FAIL);
}
ensureHasNoProfileOwner(userReference);
@@ -3251,7 +3258,8 @@ public final class DeviceState extends HarrierRule {
mChangedProfileOwners.put(user, currentProfileOwner);
}
- ensureHasNoAccounts(user);
+ ensureHasNoAccounts(user, /* allowPreCreatedAccounts= */ true,
+ FailureMode.FAIL);
if (resolvedDpcTestApp != null) {
mProfileOwners.put(user,
@@ -3264,10 +3272,12 @@ public final class DeviceState extends HarrierRule {
}
if (Versions.meetsMinimumSdkVersionRequirement(Versions.U)) {
- ensureHasNoAccounts(user);
+ ensureHasNoAccounts(user, /* allowPreCreatedAccounts= */ true,
+ FailureMode.FAIL);
} else {
// Prior to U this incorrectly checked the system user
- ensureHasNoAccounts(UserType.SYSTEM_USER);
+ ensureHasNoAccounts(UserType.SYSTEM_USER, /* allowPreCreatedAccounts= */ true,
+ FailureMode.FAIL);
}
if (isPrimary) {
@@ -3822,7 +3832,7 @@ public final class DeviceState extends HarrierRule {
private void ensureGlobalSettingSet(String key, String value){
if (!mOriginalGlobalSettings.containsKey(key)) {
- mOriginalGlobalSettings.put(key, TestApis.settings().global().getString(value));
+ mOriginalGlobalSettings.put(key, TestApis.settings().global().getString(key));
}
TestApis.settings().global().putString(key, value);
@@ -3838,7 +3848,7 @@ public final class DeviceState extends HarrierRule {
}
if (!mOriginalSecureSettings.get(user).containsKey(key)) {
mOriginalSecureSettings.get(user)
- .put(key, TestApis.settings().secure().getString(user, value));
+ .put(key, TestApis.settings().secure().getString(user, key));
}
TestApis.settings().secure().putString(user, key, value);
@@ -4044,15 +4054,19 @@ public final class DeviceState extends HarrierRule {
}
}
- private void ensureHasNoAccounts(UserType userType) {
+ private void ensureHasNoAccounts(UserType userType, boolean allowPreCreatedAccounts,
+ FailureMode failureMode) {
if (userType == UserType.ANY) {
- TestApis.users().all().forEach(this::ensureHasNoAccounts);
+ TestApis.users().all().forEach(user -> ensureHasNoAccounts(user,
+ allowPreCreatedAccounts, failureMode));
} else {
- ensureHasNoAccounts(resolveUserTypeToUser(userType));
+ ensureHasNoAccounts(resolveUserTypeToUser(userType),
+ allowPreCreatedAccounts, failureMode);
}
}
- private void ensureHasNoAccounts(UserReference user) {
+ private void ensureHasNoAccounts(UserReference user, boolean allowPreCreatedAccounts,
+ FailureMode failureMode) {
if (REMOTE_ACCOUNT_AUTHENTICATOR_TEST_APP.pkg().installedOnUser(user)) {
user.start(); // The user has to be started to remove accounts
@@ -4060,9 +4074,25 @@ public final class DeviceState extends HarrierRule {
.forEach(AccountReference::remove);
}
- if (!TestApis.accounts().all(user).isEmpty()) {
- throw new NeneException("Expected no accounts on user " + user
- + " but there was some that could not be removed");
+ Set<AccountReference> accounts = TestApis.accounts().all(user);
+
+ // If allowPreCreatedAccounts is enabled, that means it's okay to have
+ // pre created accounts on the device.
+ // Now to EnsureHasNoAccounts we will only check that there are no non-pre created accounts.
+ // Non pre created accounts either have ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED
+ // or do not have ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED
+ if (allowPreCreatedAccounts) {
+ accounts = accounts.stream()
+ .filter(accountReference -> !accountReference.hasFeature(
+ DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED)
+ || accountReference.hasFeature(
+ DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED))
+ .collect(Collectors.toSet());
+ }
+
+ if (!accounts.isEmpty()) {
+ failOrSkip("Expected no user created accounts on user " + user
+ + " but there was some that could not be removed.", failureMode);
}
TestApis.devicePolicy().calculateHasIncompatibleAccounts();
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 5fed6b470fa..d5dc6804700 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
@@ -1329,6 +1329,8 @@ public class DeviceStateTest {
.isTrue();
}
+ //TODO(b/300218365): Test that settings are returned to their original values in teardown.
+
@EnsureSecureSettingSet(key = "testSecureSetting", value = "testValue")
@Test
public void ensureSecureSettingSetAnnotation_secureSettingIsSet() {
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 79492ec86bb..1217a4fc237 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
@@ -716,18 +716,20 @@ public final class Package {
PackageManager userPackageManager =
TestApis.context().androidContextAsUser(user).getPackageManager();
-
+ boolean shouldCheckPreviousProcess = runningProcess() != null;
// 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();
+
+ int previousPid = shouldCheckPreviousProcess ? runningProcess().pid() : -1;
+
Poll.forValue("Application flag", () -> {
userActivityManager.forceStopPackage(mPackageName);
- return userPackageManager.getPackageInfo(mPackageName, PackageManager.GET_META_DATA)
- .applicationInfo.flags;
- })
- .toMeet(flag ->(flag & FLAG_STOPPED) == FLAG_STOPPED
- || previousPid != runningProcess().pid())
+ return userPackageManager.getPackageInfo(mPackageName,
+ PackageManager.GET_META_DATA)
+ .applicationInfo.flags;
+ }).toMeet(flag -> !shouldCheckPreviousProcess || (flag & FLAG_STOPPED) == FLAG_STOPPED
+ || previousPid != runningProcess().pid())
.errorOnFail("Expected application flags to contain FLAG_STOPPED ("
+ FLAG_STOPPED + ")")
.await();
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
index d6cc3ae2116..7bce3ca8152 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
@@ -19,12 +19,15 @@ package com.android.bedstead.nene.packages;
import static android.Manifest.permission.INSTALL_PACKAGES;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.content.Intent.ACTION_VIEW;
import static android.content.pm.PackageInstaller.EXTRA_PACKAGE_NAME;
import static android.content.pm.PackageInstaller.EXTRA_STATUS;
import static android.content.pm.PackageInstaller.EXTRA_STATUS_MESSAGE;
import static android.content.pm.PackageInstaller.STATUS_FAILURE;
import static android.content.pm.PackageInstaller.STATUS_SUCCESS;
import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
+import static android.content.pm.PackageManager.MATCH_ALL;
+import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.R;
@@ -39,7 +42,9 @@ import android.content.IntentFilter;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.net.Uri;
import android.os.Build;
import android.util.Log;
@@ -71,7 +76,9 @@ import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -727,4 +734,53 @@ public final class Packages {
public Package launcher() {
return find(TestApis.ui().device().getLauncherPackageName());
}
+
+ /**
+ * Finds the browser assigned to handle browsing intents by default for selected user.
+ *
+ * @return the package for the default browser if there is one, null otherwise.
+ */
+ @SuppressWarnings("NewApi")
+ @Experimental
+ public Package defaultBrowserForUser(UserReference user) {
+ ResolveInfo resolvedActivity;
+ List<ResolveInfo> possibleActivities;
+ Intent toResolve = new Intent(ACTION_VIEW, Uri.parse("http://"));
+
+ PackageManager pm = TestApis.context()
+ .androidContextAsUser(user)
+ .getPackageManager();
+
+ if (Versions.meetsMinimumSdkVersionRequirement(Versions.T)) {
+ possibleActivities = pm.queryIntentActivities(toResolve,
+ PackageManager.ResolveInfoFlags.of(MATCH_ALL));
+ resolvedActivity = pm.resolveActivity(toResolve,
+ PackageManager.ResolveInfoFlags.of(MATCH_DEFAULT_ONLY));
+ } else {
+ possibleActivities = pm.queryIntentActivities(toResolve, MATCH_ALL);
+ resolvedActivity = pm.resolveActivity(toResolve, MATCH_DEFAULT_ONLY);
+ }
+
+ Set<String> possibleBrowserPackageName = possibleActivities.stream()
+ .map(Packages::extractPackageName)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ Log.e("SettingTest", "possibleBrowserPackageNames: " + possibleBrowserPackageName);
+
+ String resolvedBrowserPackageName = extractPackageName(resolvedActivity);
+ if (resolvedBrowserPackageName == null
+ || !possibleBrowserPackageName.contains(resolvedBrowserPackageName)) {
+ return null;
+ }
+
+ return find(resolvedBrowserPackageName);
+ }
+
+ private static String extractPackageName(@Nullable ResolveInfo nullableInfo) {
+ return Optional.ofNullable(nullableInfo)
+ .map(resolveInfo -> resolveInfo.activityInfo)
+ .map(activityInfo -> activityInfo.packageName)
+ .orElse(null);
+ }
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java
index f95107ded4b..531a08621e8 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java
@@ -59,7 +59,7 @@ public final class Poll<E> {
private static final String LOG_TAG = Poll.class.getName();
- private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(60);
+ private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(120);
private static final long SLEEP_MILLIS = 200; // TODO(b/223768343): Allow configuring
private final String mValueName;
private final ValueSupplier<E> mSupplier;
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 7998334ebb1..3d14dce9966 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
@@ -21,6 +21,7 @@ import static android.os.Build.VERSION_CODES.R;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeNotNull;
import static org.testng.Assert.assertThrows;
import android.content.Context;
@@ -364,6 +365,17 @@ public class PackageTest {
}
@Test
+ public void forceStop_whenNoRunningProcess_doesNotThrowException() {
+ final Package notRunningPackage = TestApis.packages().installedForUser().stream()
+ .filter(aPackage -> aPackage.runningProcess() == null)
+ .findFirst()
+ .get();
+ assumeNotNull(notRunningPackage);
+
+ notRunningPackage.forceStop();
+ }
+
+ @Test
@EnsureHasSecondaryUser
@RequireRunNotOnSecondaryUser
public void installedOnUsers_doesNotIncludeUserWithoutPackageInstalled() throws Exception {
diff --git a/common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainPhoneShortcutStepAutomation.java b/common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainPhoneShortcutStepAutomation.java
new file mode 100644
index 00000000000..4d95158edf3
--- /dev/null
+++ b/common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainPhoneShortcutStepAutomation.java
@@ -0,0 +1,30 @@
+/*
+ * 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 com.google.android.interactive.steps.enterprise.launcher;
+
+import com.android.interactive.Automation;
+import com.android.interactive.annotations.AutomationFor;
+
+@AutomationFor("com.google.android.interactive.steps.enterprise.launcher"
+ + ".DoesLauncherDefaultConfigurationContainPhoneShortcutStep")
+public class DoesLauncherDefaultConfigurationContainPhoneShortcutStepAutomation implements Automation<Boolean> {
+ @Override
+ public Boolean automate() throws Exception {
+ return true;
+ }
+}
diff --git a/common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainSmsShortcutStepAutomation.java b/common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainSmsShortcutStepAutomation.java
new file mode 100644
index 00000000000..d79cc7588db
--- /dev/null
+++ b/common/device-side/interactive/automation/src/main/java/com/google/android/interactive/steps/enterprise/launcher/DoesLauncherDefaultConfigurationContainSmsShortcutStepAutomation.java
@@ -0,0 +1,30 @@
+/*
+ * 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 com.google.android.interactive.steps.enterprise.launcher;
+
+import com.android.interactive.Automation;
+import com.android.interactive.annotations.AutomationFor;
+
+@AutomationFor("com.google.android.interactive.steps.enterprise.launcher"
+ + ".DoesLauncherDefaultConfigurationContainSmsShortcutStep")
+public class DoesLauncherDefaultConfigurationContainSmsShortcutStepAutomation implements Automation<Boolean> {
+ @Override
+ public Boolean automate() throws Exception {
+ return true;
+ }
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
index 7602ac26677..8ee9892a4d0 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
@@ -52,13 +52,17 @@ public final class OneTimeDeviceConfigListener implements OnPropertiesChangedLis
mNamespace = Objects.requireNonNull(namespace);
mKey = Objects.requireNonNull(key);
mTimeoutMs = timeoutMs;
+ Log.v(TAG, "Constructor: namespace=" + mNamespace + ", key=" + key
+ + ", timeoutMs=" + timeoutMs);
}
@Override
public void onPropertiesChanged(@NonNull Properties properties) {
+ Log.v(TAG, "onPropertiesChanged(): namespace=" + properties.getNamespace());
if (!properties.getNamespace().equals(mNamespace)
|| !properties.getKeyset().contains(mKey)) {
- Log.d(TAG, "ignoring callback for namespace: " + properties.getNamespace());
+ Log.d(TAG, "ignoring callback - wrong namespace or it doesn't contains the key "
+ + "(keySet=" + properties.getKeyset() + ")");
return;
}
mLatch.countDown();
diff --git a/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java b/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java
index d45a089d160..f2e4a0489e6 100755
--- a/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java
+++ b/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java
@@ -176,8 +176,21 @@ public class AppBindingHostTest extends BaseHostJUnit4Test implements IBuildRece
return false;
}
- private void setSmsApp(String pkg, int userId) throws Exception {
- runCommand("cmd role add-role-holder --user " + userId + " android.app.role.SMS " + pkg);
+ private void setSmsApp(String pkg, int userId) throws Throwable {
+ runWithRetries(300, () -> {
+ String output1 = runCommand("cmd role get-role-holders --user " + userId
+ + " android.app.role.SMS ");
+ if (output1.equals(pkg)) {
+ CLog.d(pkg + " has been set default sms app.");
+ } else {
+ String output2 = runCommand("cmd role add-role-holder --user " + userId
+ + " android.app.role.SMS " + pkg);
+ if (output2.contains("TimeoutException")) {
+ RunUtil.getDefault().sleep(10000);
+ throw new RuntimeException("cmd role add-role-holder timeout.");
+ }
+ }
+ });
}
private void uninstallTestApps(boolean always) throws Exception {
diff --git a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/contacts/ContactsSharingTest.java b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/contacts/ContactsSharingTest.java
index c100351ce70..483de25eb03 100644
--- a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/contacts/ContactsSharingTest.java
+++ b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/contacts/ContactsSharingTest.java
@@ -56,7 +56,7 @@ public class ContactsSharingTest extends AppCloningBaseHostTest {
private static final String CLONE_CONTACTS_PROVIDER_DATA_TEST_CLASS =
"CloneContactsProviderDataTest";
- private static final String CONTACTS_PROVIDER_PACKAGE_NAME = "com.android.providers.contacts";
+ private static final String CONTACTS_PROVIDER_PACKAGE_NAME = "android.providers.contacts";
private static final String OWNER_USER_ID = "0";
private static final String TEST_ACCOUNT_TYPE = "test.com";
private static TestContactsDataManager sTestContactsDataManager;
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 63c7a12fb28..a985e60291d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -460,7 +460,7 @@ public class AdoptableHostTest extends BaseHostJUnit4Test {
private LocalVolumeInfo waitForVolumeReady(LocalVolumeInfo vol) throws Exception {
int attempt = 0;
- while (attempt++ < 15) {
+ while (attempt++ < 30) {
if (getDevice().executeShellCommand("dumpsys package volumes").contains(vol.volId)) {
return vol;
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
index af59d7f552d..3722dd2867b 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
@@ -51,6 +51,7 @@ public class AppDataIsolationTests extends BaseAppSecurityTest {
private static final String APPA_CLASS =
"com.android.cts.appdataisolation.appa.AppATests";
private static final String APPA_METHOD_CREATE_CE_DE_DATA = "testCreateCeDeAppData";
+ private static final String APPA_METHOD_DELETE_EXTERNAL_DIRS = "testDeleteExternalDirs";
private static final String APPA_METHOD_CHECK_CE_DATA_EXISTS = "testAppACeDataExists";
private static final String APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST =
"testAppACeDataDoesNotExist";
@@ -248,6 +249,10 @@ public class AppDataIsolationTests extends BaseAppSecurityTest {
try {
runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_TEST_UNLOCK_DEVICE);
} catch (Exception e) {}
+ try {
+ runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_DELETE_EXTERNAL_DIRS);
+ } catch (Exception e) {}
+
getDevice().executeShellCommand("locksettings clear --old 1234");
getDevice().executeShellCommand("locksettings set-disabled true");
} finally {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BootCountTrackerRule.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BootCountTrackerRule.java
index 42d2a4ef692..5d2d7327121 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BootCountTrackerRule.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BootCountTrackerRule.java
@@ -82,7 +82,7 @@ public class BootCountTrackerRule implements TestRule {
private int getBootCount() throws DeviceNotAvailableException {
CommandResult result = getDevice().executeShellV2Command("settings get global boot_count");
if (result.getStatus() != CommandStatus.SUCCESS) {
- CLog.w("Failed to get boot count. Status: %d, Exit code: %d, Error: %s",
+ CLog.w("Failed to get boot count. Status: %s, Exit code: %d, Error: %s",
result.getStatus(), result.getExitCode(), result.getStderr());
return -1;
}
diff --git a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
index fbc0860c214..904842815f0 100644
--- a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
+++ b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/AppA/src/com/android/cts/appdataisolation/appa/AppATests.java
@@ -28,6 +28,7 @@ import static com.android.cts.appdataisolation.common.FileUtils.assertDirIsAcces
import static com.android.cts.appdataisolation.common.FileUtils.assertDirIsNotAccessible;
import static com.android.cts.appdataisolation.common.FileUtils.assertFileDoesNotExist;
import static com.android.cts.appdataisolation.common.FileUtils.assertFileExists;
+import static com.android.cts.appdataisolation.common.FileUtils.deleteFile;
import static com.android.cts.appdataisolation.common.FileUtils.touchFile;
import static com.android.cts.appdataisolation.common.UserUtils.getCurrentUserId;
@@ -45,6 +46,7 @@ import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.support.test.uiautomator.UiDevice;
import android.view.KeyEvent;
@@ -69,6 +71,7 @@ import java.util.concurrent.TimeUnit;
public class AppATests {
private static final long BIND_SERVICE_TIMEOUT_MS = 5000;
+ private static final int MAX_VOLD_QUERY_RETRIES = 20;
private Context mContext;
private UiDevice mDevice;
@@ -111,7 +114,7 @@ public class AppATests {
private void setUpExternalStoragePaths() {
File externalFilesDir = mContext.getExternalFilesDir("");
if (externalFilesDir != null) {
- mExternalDataPath = mContext.getExternalFilesDir("").getAbsolutePath();
+ mExternalDataPath = externalFilesDir.getAbsolutePath();
}
File obbDir = mContext.getObbDir();
if (obbDir != null) {
@@ -148,6 +151,15 @@ public class AppATests {
}
@Test
+ public void testDeleteExternalDirs() throws Exception {
+ deleteFile(mExternalDataPath, EXTERNAL_DATA_FILE_NAME);
+ deleteFile(mObbPath, OBB_FILE_NAME);
+
+ assertFileDoesNotExist(mExternalDataPath, EXTERNAL_DATA_FILE_NAME);
+ assertFileDoesNotExist(mObbPath, OBB_FILE_NAME);
+ }
+
+ @Test
public void testAppACeDataExists() {
assertFileExists(mCePath, CE_DATA_FILE_NAME);
}
@@ -263,7 +275,16 @@ public class AppATests {
assertTrue("User not unlocked", unlocked.await(1, TimeUnit.MINUTES));
assertTrue("No locked boot complete", bootCompleted.await(2, TimeUnit.MINUTES));
- setUpExternalStoragePaths();
+ // TODO(b/302586971): Remove this when the vold resets are resolved.
+ // vold can reset on an HSUM configuration during the user unlock flow; wait until valid
+ // values are returned for the external and obb directories before continuing with the test.
+ int numRetries = 0;
+ do {
+ numRetries++;
+ SystemClock.sleep(3000);
+ setUpExternalStoragePaths();
+ } while ((mExternalDataPath == null || mObbPath == null)
+ && numRetries <= MAX_VOLD_QUERY_RETRIES);
// The test app process should be still running, make sure CE DE now is available
testAppACeDataExists();
diff --git a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/common/src/com/android/cts/appdataisolation/common/FileUtils.java b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/common/src/com/android/cts/appdataisolation/common/FileUtils.java
index 15450f934d8..bda7f239b0c 100644
--- a/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/common/src/com/android/cts/appdataisolation/common/FileUtils.java
+++ b/hostsidetests/appsecurity/test-apps/AppDataIsolationTestApp/common/src/com/android/cts/appdataisolation/common/FileUtils.java
@@ -130,6 +130,11 @@ public class FileUtils {
file.createNewFile();
}
+ public static void deleteFile(String path, String name) throws IOException {
+ File file = new File(path, name);
+ file.delete();
+ }
+
public static String replacePackageAWithPackageB(String path) {
return path.replace(APPA_PKG, APPB_PKG);
}
diff --git a/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java b/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java
index 05c9834fbd2..02badd90758 100644
--- a/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java
+++ b/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java
@@ -27,11 +27,10 @@ import com.google.common.base.Strings;
public final class SettingsProviderInvalidKeyTest extends AndroidTestCase {
public void testLongKeysAreRejected() {
final ContentResolver resolver = getContext().getContentResolver();
- IllegalStateException thrown = expectThrows(IllegalStateException.class,
+ expectThrows(Throwable.class,
() -> Settings.System.putString(resolver, Strings.repeat("A", 65000), ""));
- assertTrue(thrown.getMessage().contains("adding too many system settings"));
// Repeated calls should throw as well
- expectThrows(IllegalStateException.class,
+ expectThrows(Throwable.class,
() -> Settings.System.putString(resolver, Strings.repeat("A", 65000), ""));
}
}
diff --git a/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java b/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
index ade4ecc723a..f3e53ddb635 100644
--- a/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
+++ b/hostsidetests/backup/RestoreSessionTest/src/android/cts/backup/restoresessionapp/RestoreSessionTest.java
@@ -64,7 +64,7 @@ public class RestoreSessionTest {
};
private static final int PACKAGES_COUNT = 2;
- private static final int RESTORE_TIMEOUT_SECONDS = 10;
+ private static final int RESTORE_TIMEOUT_SECONDS = 20;
private BackupManager mBackupManager;
private Set<String> mRestorePackages;
@@ -281,15 +281,10 @@ public class RestoreSessionTest {
@Override
public void onEvent(Bundle event) {
+ // Note: this logic will break if the test cases using TestBackupMonitor
+ // start restoring more than 1 package because the logic currently expects
+ // exactly 1 onEvent() call per package
super.onEvent(event);
-
- int eventType = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID);
-
- List<Integer> expectedEvents = Arrays.asList(
- BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH,
- BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS);
-
- assertThat(expectedEvents).contains(eventType);
mLatch.countDown();
}
}
diff --git a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
index cb120a0744f..184a41d5874 100644
--- a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
@@ -51,12 +51,18 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
"am start -n " + ANDROID_CLIENT_ACTIVITY + " --es powerpolicy ";
private static final int DEFAULT_TIMEOUT_SEC = 20;
+ private static final int BOOT_TIMEOUT_SEC = 60;
private final PowerPolicyTestAnalyzer mTestAnalyzer = new PowerPolicyTestAnalyzer(this);
@Before
public void checkPrecondition() throws Exception {
- checkDefaultPowerPolicySet("pre-condition");
+ waitForPowerState(PowerPolicyConstants.CarPowerState.ON);
+ PowerPolicyTestHelper testHelper = new PowerPolicyTestHelper(
+ /* testcase= */ "pre-condition", /* step= */ "testStep1",
+ /* frameCpms= */ getCpmsFrameworkLayerStateInfo(),
+ /* sysCpms= */ getCpmsSystemLayerStateInfo(), /* silentMode= */ null);
+ checkDefaultPowerPolicySet(testHelper);
}
@After
@@ -77,6 +83,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
teststep = "switch to forced silent";
enterForcedSilentMode();
testHelper = getTestHelper(testcase, 1, teststep);
+ // Test starts in ON state, state shouldn't change between test start and this check
testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.NO_USER_INTERACTION);
testHelper.checkSilentModeStatus(true);
@@ -86,6 +93,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
teststep = "restore to normal mode";
leaveForcedSilentMode();
testHelper = getTestHelper(testcase, 2, teststep);
+ // Test starts in ON state, state shouldn't change between test start and this check
testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
testHelper.checkSilentModeStatus(false);
@@ -116,6 +124,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
for (int i = 0; i < stepNames.length; i++) {
triggerVhalPowerStateReq(vhalReqs[i], PowerPolicyConstants.ShutdownParam.NOT_USED);
PowerPolicyTestHelper testHelper = getTestHelper(testcase, i + 1, stepNames[i]);
+ // power state shouldn't change
testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
}
@@ -130,6 +139,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
teststep = "check the inital power policies";
testHelper = getTestHelper(testcase, stepNo++, teststep);
+ // Test starts in ON state, state shouldn't change between test start and this check
testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
// save number of device power policies
int registeredPoliciesNumber = testHelper.getNumberOfRegisteredPolicies();
@@ -205,8 +215,9 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
// need to find a way to move reboot device into AfterAll
rebootDevice();
teststep = "reboot to clear added test power policies";
+ // device was restarted, need to wait for ON state
+ waitForPowerState(PowerPolicyConstants.CarPowerState.ON);
testHelper = getTestHelper(testcase, stepNo++, teststep);
- testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
testHelper.checkTotalRegisteredPolicies(registeredPoliciesNumber);
}
@@ -214,6 +225,18 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
return executeCommand("dumpsys activity %s", ANDROID_CLIENT_ACTIVITY);
}
+ private void waitForPowerState(int powerState) throws Exception {
+ //need to wait for ON state
+ CommonTestUtils.waitUntil("timed out (" + BOOT_TIMEOUT_SEC
+ + "s) waiting for ON state", BOOT_TIMEOUT_SEC,
+ () -> {
+ CpmsFrameworkLayerStateInfo frameworkLayerStateInfo =
+ getCpmsFrameworkLayerStateInfo();
+ return frameworkLayerStateInfo != null
+ && frameworkLayerStateInfo.getCurrentState() == powerState;
+ });
+ }
+
private PowerPolicyTestHelper getTestHelper(String testcase, int stepNo, String stepName)
throws Exception {
CpmsSystemLayerStateInfo cpmsSystemInfo = getCpmsSystemLayerStateInfo();
@@ -359,11 +382,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
}
}
- private void checkDefaultPowerPolicySet(String testcase) throws Exception {
- String teststep = "check if the car power is on the ON state";
- PowerPolicyTestHelper testHelper = new PowerPolicyTestHelper(testcase, teststep,
- getCpmsFrameworkLayerStateInfo(), getCpmsSystemLayerStateInfo(), null);
- testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
+ private void checkDefaultPowerPolicySet(PowerPolicyTestHelper testHelper) throws Exception {
testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.INITIAL_ALL_ON);
testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.DEFAULT_ALL_ON);
}
diff --git a/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java b/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
index b58078b01ef..0a7e766f882 100644
--- a/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PreCreateUsersHostTest.java
@@ -61,7 +61,7 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
@Presubmit
@Test
public void testAppsAreNotInstalledOnPreCreatedUser() throws Exception {
- appsAreNotInstalledOnPreCreatedUserTest(/* isGuest= */ false, /* afterReboot= */ false);
+ appsAreNotInstalledOnPreCreatedUserTest(/* isGuest= */ false);
}
/**
@@ -70,31 +70,10 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
@Presubmit
@Test
public void testAppsAreNotInstalledOnPreCreatedGuest() throws Exception {
- appsAreNotInstalledOnPreCreatedUserTest(/* isGuest= */ true, /* afterReboot= */ false);
+ appsAreNotInstalledOnPreCreatedUserTest(/* isGuest= */ true);
}
- /**
- * Makes sure an app installed for a regular user is not visible to a pre-created user, even
- * after the system restarts
- */
- @Presubmit
- @Test
- public void testAppsAreNotInstalledOnPreCreatedUserAfterReboot() throws Exception {
- appsAreNotInstalledOnPreCreatedUserTest(/* isGuest= */ false, /* afterReboot= */ true);
- }
-
- /**
- * Same as {@link #testAppsAreNotInstalledOnPreCreatedUserAfterReboot()}, but for a guest
- * user.
- */
- @Presubmit
- @Test
- public void testAppsAreNotInstalledOnPreCreatedGuestAfterReboot() throws Exception {
- appsAreNotInstalledOnPreCreatedUserTest(/* isGuest= */ true, /* afterReboot= */ true);
- }
-
- private void appsAreNotInstalledOnPreCreatedUserTest(boolean isGuest,
- boolean afterReboot) throws Exception {
+ private void appsAreNotInstalledOnPreCreatedUserTest(boolean isGuest) throws Exception {
deletePreCreatedUsers();
requiresExtraUsers(1);
@@ -106,14 +85,6 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
assertAppInstalledForUser(APP_PKG, initialUserId);
assertAppNotInstalledForUser(APP_PKG, preCreatedUserId);
- if (afterReboot) {
- restartSystem();
- waitForCarServiceReady();
-
- // Checks again
- assertAppInstalledForUser(APP_PKG, initialUserId);
- assertAppNotInstalledForUser(APP_PKG, preCreatedUserId);
- }
convertPreCreatedUser(isGuest, preCreatedUserId);
assertAppNotInstalledForUser(APP_PKG, preCreatedUserId);
}
@@ -124,7 +95,7 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
@Presubmit
@Test
public void testAppPermissionsPreCreatedUserPackages() throws Exception {
- appPermissionsPreCreatedUserPackagesTest(/* isGuest= */ false, /* afterReboot= */ false);
+ appPermissionsPreCreatedUserPackagesTest(/* isGuest= */ false);
}
/**
@@ -133,29 +104,10 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
@Presubmit
@Test
public void testAppPermissionsPreCreatedGuestPackages() throws Exception {
- appPermissionsPreCreatedUserPackagesTest(/* isGuest= */ true, /* afterReboot= */ false);
- }
-
- /**
- * Verifies a pre-created user have same packages as non-precreated users.
- */
- @Presubmit
- @Test
- public void testAppPermissionsPreCreatedUserPackagesAfterReboot() throws Exception {
- appPermissionsPreCreatedUserPackagesTest(/* isGuest= */ false, /* afterReboot= */ true);
- }
-
- /**
- * Verifies a pre-created guest have same packages as non-precreated users.
- */
- @Presubmit
- @Test
- public void testAppPermissionsPreCreatedGuestPackagesAfterReboot() throws Exception {
- appPermissionsPreCreatedUserPackagesTest(/* isGuest= */ true, /* afterReboot= */ true);
+ appPermissionsPreCreatedUserPackagesTest(/* isGuest= */ true);
}
- private void appPermissionsPreCreatedUserPackagesTest(boolean isGuest, boolean afterReboot)
- throws Exception {
+ private void appPermissionsPreCreatedUserPackagesTest(boolean isGuest) throws Exception {
deletePreCreatedUsers();
requiresExtraUsers(2);
@@ -172,16 +124,12 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
// There can be just one guest by default, so remove it now otherwise
// convertPreCreatedUser() below will fail
- if (isGuest && !afterReboot) {
+ if (isGuest) {
removeUser(referenceUserId);
}
int preCreatedUserId = preCreateUser(isGuest);
- if (afterReboot) {
- restartSystem();
- }
-
convertPreCreatedUser(isGuest, preCreatedUserId);
// Some permissions (e.g. Role permission) are given only after initialization.
switchUser(preCreatedUserId);
@@ -300,9 +248,4 @@ public final class PreCreateUsersHostTest extends CarHostJUnit4TestCase {
fail("Created new " + type + " with id " + newUserId + ", which doesn't match pre-created "
+ "id " + expectedId);
}
-
- private void restartSystem() throws Exception {
- // Restart the system to make sure PackageManager preserves the installed bit
- restartSystemServer();
- }
}
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java
index 84d37ad407f..82790090dae 100644
--- a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java
@@ -93,31 +93,6 @@ public final class PowerPolicyTestHelper {
assertWithMessage(REGISTERED_POLICY_ASSERT_MSG).that(status).isTrue();
}
- public void checkRegisteredPolicy(String policyId) {
- boolean status = false;
- for (PowerPolicyDef def : mSystemCpms.getRegisteredPolicies()) {
- if (def.getPolicyId().equals(policyId)) {
- status = true;
- break;
- }
- }
- assertWithMessage(REGISTERED_POLICY_ASSERT_MSG).that(status).isTrue();
- }
-
- public void checkPendingPolicyId(String id) {
- boolean status = false;
- if (id == null) {
- if (mSystemCpms.getPendingPolicyId() != null) {
- CLog.w("PowerPolicyTestHelper expected non null pending policy");
- } else {
- status = true;
- }
- } else {
- status = id.equals(mSystemCpms.getPendingPolicyId());
- }
- assertWithMessage(PENDING_POLICY_ASSERT_MSG).that(status).isTrue();
- }
-
public void checkTotalRegisteredPolicies(int totalNum) {
assertWithMessage(TOTAL_REGISTERED_POLICIES_ASSERT_MSG)
.that(mSystemCpms.getRegisteredPolicies().size()).isEqualTo(totalNum);
@@ -138,11 +113,6 @@ public final class PowerPolicyTestHelper {
.that(expected.equals(mFrameCpms.getCurrentPolicyGroupId())).isTrue();
}
- public void checkPowerPolicyGroups(PowerPolicyGroups expected) {
- assertWithMessage("checkPowerPolicyGroups")
- .that(expected.equals(mFrameCpms.getPowerPolicyGroups())).isTrue();
- }
-
public int getNumberOfRegisteredPolicies() {
return mSystemCpms.getTotalRegisteredPolicies();
}
@@ -158,7 +128,7 @@ public final class PowerPolicyTestHelper {
}
}
- public String getCurrentPolicyId() {
- return mFrameCpms.getCurrentPolicyId();
+ public int getCurrentPowerState() {
+ return mFrameCpms.getCurrentState();
}
}
diff --git a/hostsidetests/compilation/Android.bp b/hostsidetests/compilation/Android.bp
index f7c1b3b8208..0226fbe4d40 100644
--- a/hostsidetests/compilation/Android.bp
+++ b/hostsidetests/compilation/Android.bp
@@ -28,6 +28,7 @@ java_defaults {
":AppUsedByOtherApp_1_dm",
":AppUsedByOtherApp_2_prof",
":AppUsingOtherApp",
+ ":CompilationTestCases_package-dex-usage",
":CtsCompilationApp",
":CtsCompilationApp_profile",
":CtsCompilationApp_dm",
@@ -133,3 +134,14 @@ genrule {
],
out: ["AppUsedByOtherApp_2.prof"],
}
+
+genrule {
+ name: "CompilationTestCases_package-dex-usage",
+ tools: ["aprotoc"],
+ cmd: "$(location aprotoc) " +
+ "--encode=com.android.server.art.proto.DexUseProto " +
+ "art/libartservice/service/proto/dex_use.proto " +
+ "< $(in) > $(out)",
+ srcs: ["assets/package-dex-usage.textproto"],
+ out: ["package-dex-usage.pb"],
+}
diff --git a/hostsidetests/compilation/assets/package-dex-usage.textproto b/hostsidetests/compilation/assets/package-dex-usage.textproto
new file mode 100644
index 00000000000..5b1dc72a938
--- /dev/null
+++ b/hostsidetests/compilation/assets/package-dex-usage.textproto
@@ -0,0 +1,97 @@
+package_dex_use {
+ owning_package_name: "android.compilation.cts.statuscheckerapp"
+ # Invalid dex paths. They should not be loaded.
+ secondary_dex_use {
+ dex_file: "relative/bad_1.apk"
+ user_id {
+ value: 0
+ }
+ record {
+ loading_package_name: "android.compilation.cts.statuscheckerapp"
+ isolated_process: false
+ class_loader_context: "PCL[]"
+ abi_name: "x86_64"
+ last_used_at_ms: 1672498800000
+ }
+ }
+ secondary_dex_use {
+ dex_file: "/non-normal/./bad_2.apk"
+ user_id {
+ value: 0
+ }
+ record {
+ loading_package_name: "android.compilation.cts.statuscheckerapp"
+ isolated_process: false
+ class_loader_context: "PCL[]"
+ abi_name: "x86_64"
+ last_used_at_ms: 1672498800000
+ }
+ }
+ # Invalid class loader contexts. They should not be loaded either.
+ secondary_dex_use {
+ dex_file: "/absolute/path/bad_3.apk"
+ user_id {
+ value: 0
+ }
+ record {
+ loading_package_name: "android.compilation.cts.statuscheckerapp"
+ isolated_process: false
+ class_loader_context: "ABC"
+ abi_name: "x86_64"
+ last_used_at_ms: 1672498800000
+ }
+ }
+ secondary_dex_use {
+ dex_file: "/absolute/path/bad_4.apk"
+ user_id {
+ value: 0
+ }
+ record {
+ loading_package_name: "android.compilation.cts.statuscheckerapp"
+ isolated_process: false
+ class_loader_context: "PCL[./bar.jar]"
+ abi_name: "x86_64"
+ last_used_at_ms: 1672498800000
+ }
+ }
+ # Valid paths and class loader contexts.
+ secondary_dex_use {
+ dex_file: "/absolute/path/good_1.apk"
+ user_id {
+ value: 0
+ }
+ record {
+ loading_package_name: "android.compilation.cts.statuscheckerapp"
+ isolated_process: false
+ class_loader_context: "PCL[]"
+ abi_name: "x86_64"
+ last_used_at_ms: 1672498800000
+ }
+ }
+ secondary_dex_use {
+ dex_file: "/absolute/path/good_2.apk"
+ user_id {
+ value: 0
+ }
+ record {
+ loading_package_name: "android.compilation.cts.statuscheckerapp"
+ isolated_process: false
+ class_loader_context: "PCL[bar.jar]"
+ abi_name: "x86_64"
+ last_used_at_ms: 1672498800000
+ }
+ }
+ secondary_dex_use {
+ dex_file: "/absolute/path/good_3.apk"
+ user_id {
+ value: 0
+ }
+ record {
+ loading_package_name: "android.compilation.cts.statuscheckerapp"
+ isolated_process: false
+ class_loader_context: "=UnsupportedClassLoaderContext="
+ abi_name: "x86_64"
+ last_used_at_ms: 1672498800000
+ }
+ }
+}
diff --git a/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java b/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java
index ac048ce65f2..db815a9e833 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/AdbRootDependentCompilationTest.java
@@ -53,8 +53,12 @@ public class AdbRootDependentCompilationTest extends BaseHostJUnit4Test {
"android.compilation.cts.appusedbyotherapp";
private static final String APP_USING_OTHER_APP_PACKAGE =
"android.compilation.cts.appusingotherapp";
+ private static final String STATUS_CHECKER_PKG = "android.compilation.cts.statuscheckerapp";
private static final int PERMISSIONS_LENGTH = 10;
private static final int READ_OTHER = 7;
+ private static final String PACKAGE_DEX_USAGE_PATH = "/data/system/package-dex-usage.pb";
+ private static final String PACKAGE_DEX_USAGE_BACKUP_PATH =
+ "/data/local/tmp/package-dex-usage.pb.bak";
enum ProfileLocation {
CUR("/data/misc/profiles/cur/0/"),
@@ -221,6 +225,29 @@ public class AdbRootDependentCompilationTest extends BaseHostJUnit4Test {
.containsExactly("android.compilation.cts.appusedbyotherapp.MyActivity.method2()");
}
+ @Test
+ public void testSecondaryDexUseLoading() throws Exception {
+ mUtils.assertCommandSucceeds(
+ String.format("cp %s %s", PACKAGE_DEX_USAGE_PATH, PACKAGE_DEX_USAGE_BACKUP_PATH));
+ try {
+ mUtils.pushFromResource("/package-dex-usage.pb", PACKAGE_DEX_USAGE_PATH);
+ applyPackageDexUsageChanges();
+
+ String dump = mUtils.assertCommandSucceeds("pm art dump " + STATUS_CHECKER_PKG);
+ Utils.dumpDoesNotContainDexFile(dump, "bad_1.apk");
+ Utils.dumpDoesNotContainDexFile(dump, "bad_2.apk");
+ Utils.dumpDoesNotContainDexFile(dump, "bad_3.apk");
+ Utils.dumpDoesNotContainDexFile(dump, "bad_4.apk");
+ Utils.dumpContainsDexFile(dump, "good_1.apk");
+ Utils.dumpContainsDexFile(dump, "good_2.apk");
+ Utils.dumpContainsDexFile(dump, "good_3.apk");
+ } finally {
+ mUtils.assertCommandSucceeds(String.format(
+ "cp %s %s", PACKAGE_DEX_USAGE_BACKUP_PATH, PACKAGE_DEX_USAGE_PATH));
+ applyPackageDexUsageChanges();
+ }
+ }
+
/**
* Places the profile in the specified locations, recompiles (without -f)
* and checks the compiler-filter in the odex file.
@@ -423,4 +450,12 @@ public class AdbRootDependentCompilationTest extends BaseHostJUnit4Test {
.isEqualTo(PERMISSIONS_LENGTH);
return permissions;
}
+
+ private void applyPackageDexUsageChanges() throws Exception {
+ mUtils.assertCommandSucceeds(
+ String.format("chown system:system %s", PACKAGE_DEX_USAGE_PATH));
+ mUtils.assertCommandSucceeds(String.format("chmod 600 %s", PACKAGE_DEX_USAGE_PATH));
+ mUtils.assertCommandSucceeds(String.format("restorecon %s", PACKAGE_DEX_USAGE_PATH));
+ mUtils.softReboot();
+ }
}
diff --git a/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java b/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
index 00eb56f2c45..489855e7e10 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
@@ -152,6 +152,22 @@ public class CompilationTest extends BaseHostJUnit4Test {
}
@Test
+ public void testCompileSecondaryDexUnsupportedClassLoader() throws Exception {
+ String filename = "secondary-unsupported-clc.jar";
+ var options = new DeviceTestRunOptions(STATUS_CHECKER_PKG)
+ .setTestClassName(STATUS_CHECKER_CLASS)
+ .setTestMethodName("createAndLoadSecondaryDexUnsupportedClassLoader")
+ .addInstrumentationArg("secondary-dex-filename", filename);
+ assertThat(runDeviceTests(options)).isTrue();
+
+ // "speed" should be downgraded to "verify" because the CLC is unsupported.
+ mUtils.assertCommandSucceeds(
+ "pm compile --secondary-dex -m speed -f " + STATUS_CHECKER_PKG);
+ String dump = mUtils.assertCommandSucceeds("dumpsys package " + STATUS_CHECKER_PKG);
+ checkDexoptStatus(dump, Pattern.quote(filename), "verify");
+ }
+
+ @Test
public void testSecondaryDexReporting() throws Exception {
var options = new DeviceTestRunOptions(STATUS_CHECKER_PKG)
.setTestClassName(STATUS_CHECKER_CLASS)
@@ -159,15 +175,34 @@ public class CompilationTest extends BaseHostJUnit4Test {
.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);
+ String dump = mUtils.assertCommandSucceeds("dumpsys package " + STATUS_CHECKER_PKG);
+ Utils.dumpDoesNotContainDexFile(dump, "reported_bad_1.apk");
+ Utils.dumpDoesNotContainDexFile(dump, "reported_bad_2.apk");
+ Utils.dumpDoesNotContainDexFile(dump, "reported_bad_3.apk");
+ Utils.dumpDoesNotContainDexFile(dump, "reported_bad_4.apk");
+ Utils.dumpContainsDexFile(dump, "reported_good_1.apk");
+ Utils.dumpContainsDexFile(dump, "reported_good_2.apk");
+ Utils.dumpContainsDexFile(dump, "reported_good_3.apk");
+
+ // Check that ART Service doesn't crash on various operations after invalid dex paths and
+ // class loader contexts are reported.
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");
}
+ @Test
+ public void testGetDexFileOutputPaths() throws Exception {
+ mUtils.assertCommandSucceeds("pm compile -m verify -f " + STATUS_CHECKER_PKG);
+
+ var options = new DeviceTestRunOptions(STATUS_CHECKER_PKG)
+ .setTestClassName(STATUS_CHECKER_CLASS)
+ .setTestMethodName("testGetDexFileOutputPaths")
+ .setDisableHiddenApiCheck(true);
+ assertThat(runDeviceTests(options)).isTrue();
+ }
+
private void checkDexoptStatus(String dump, String dexfilePattern, String statusPattern) {
// Matches the dump output typically being:
// /data/user/0/android.compilation.cts.statuscheckerapp/secondary.jar
diff --git a/hostsidetests/compilation/src/android/compilation/cts/Utils.java b/hostsidetests/compilation/src/android/compilation/cts/Utils.java
index c1413fea7cb..b14376fbaec 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/Utils.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/Utils.java
@@ -30,10 +30,14 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Pattern;
public class Utils {
+ private static final Duration SOFT_REBOOT_TIMEOUT = Duration.ofMinutes(3);
+
private final TestInformation mTestInfo;
public Utils(TestInformation testInfo) throws Exception {
@@ -103,7 +107,29 @@ public class Utils {
return file;
}
+ public void softReboot() throws Exception {
+ // `waitForBootComplete` relies on `dev.bootcomplete`.
+ mTestInfo.getDevice().executeShellCommand("setprop dev.bootcomplete 0");
+ mTestInfo.getDevice().executeShellCommand("setprop ctl.restart zygote");
+ boolean success = mTestInfo.getDevice().waitForBootComplete(SOFT_REBOOT_TIMEOUT.toMillis());
+ assertWithMessage("Soft reboot didn't complete in %ss", SOFT_REBOOT_TIMEOUT.getSeconds())
+ .that(success)
+ .isTrue();
+ }
+
+ public static void dumpContainsDexFile(String dump, String dexFile) {
+ assertThat(dump).containsMatch(dexFileToPattern(dexFile));
+ }
+
+ public static void dumpDoesNotContainDexFile(String dump, String dexFile) {
+ assertThat(dump).doesNotContainMatch(dexFileToPattern(dexFile));
+ }
+
private String getDmPath(String apkPath) throws Exception {
return apkPath.replaceAll("\\.apk$", ".dm");
}
+
+ private static Pattern dexFileToPattern(String dexFile) {
+ return Pattern.compile(String.format("[\\s/](%s)\\s?", Pattern.quote(dexFile)));
+ }
}
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 87357811e5d..c9a02f9ebb1 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
@@ -21,6 +21,7 @@ import static dalvik.system.DexFile.OptimizationInfo;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import androidx.test.core.app.ApplicationProvider;
@@ -30,9 +31,12 @@ import androidx.test.runner.AndroidJUnit4;
import dalvik.system.ApplicationRuntime;
import dalvik.system.BaseDexClassLoader;
+import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
+import dalvik.system.VMRuntime;
import com.google.common.io.ByteStreams;
+import com.google.common.truth.Correspondence;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,6 +47,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Paths;
import java.util.Map;
+import java.util.function.BiFunction;
/**
* An instrumentation test that checks optimization status.
@@ -69,44 +74,70 @@ public class StatusCheckerAppTest {
public void createAndLoadSecondaryDex() throws Exception {
Bundle bundle = InstrumentationRegistry.getArguments();
String secondaryDexFilename = bundle.getString("secondary-dex-filename");
- createAndLoadSecondaryDex(secondaryDexFilename);
+ createAndLoadSecondaryDex(secondaryDexFilename, PathClassLoader::new);
}
- private String createAndLoadSecondaryDex(String secondaryDexFilename) throws Exception {
- Context context = ApplicationProvider.getApplicationContext();
- String dataDir = context.getApplicationInfo().dataDir;
- File secondaryDexFile = Paths.get(dataDir, secondaryDexFilename).toFile();
+ @Test
+ public void createAndLoadSecondaryDexUnsupportedClassLoader() throws Exception {
+ Bundle bundle = InstrumentationRegistry.getArguments();
+ String secondaryDexFilename = bundle.getString("secondary-dex-filename");
+ createAndLoadSecondaryDex(secondaryDexFilename, CustomClassLoader::new);
+ }
+
+ private String createAndLoadSecondaryDex(String secondaryDexFilename,
+ BiFunction<String, ClassLoader, ClassLoader> classLoaderCtor) throws Exception {
+ File secondaryDexFile =
+ Paths.get(getApplicationInfo().dataDir, secondaryDexFilename).toFile();
if (secondaryDexFile.exists()) {
secondaryDexFile.delete();
}
copyResourceToFile(SECONDARY_DEX_RES, secondaryDexFile);
assertThat(secondaryDexFile.setReadOnly()).isTrue();
- new PathClassLoader(secondaryDexFile.getAbsolutePath(), this.getClass().getClassLoader());
+ classLoaderCtor.apply(secondaryDexFile.getAbsolutePath(), this.getClass().getClassLoader());
return secondaryDexFile.getAbsolutePath();
}
+ private ApplicationInfo getApplicationInfo() {
+ Context context = ApplicationProvider.getApplicationContext();
+ return context.getApplicationInfo();
+ }
+
@Test
public void testSecondaryDexReporting() throws Exception {
- String fooPath = createAndLoadSecondaryDex("foo.jar");
- createAndLoadSecondaryDex("bar.jar");
-
+ String dataDir = getApplicationInfo().dataDir;
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[]"));
+ reporter.report(Map.of("relative/reported_bad_1.apk", "PCL[]"));
+ reporter.report(
+ Map.of(Paths.get(dataDir, "non-normal/./reported_bad_2.apk").toString(), "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]"));
+ reporter.report(Map.of(Paths.get(dataDir, "reported_bad_3.apk").toString(), "ABC"));
+ reporter.report(
+ Map.of(Paths.get(dataDir, "reported_bad_4.apk").toString(), "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="));
+ reporter.report(Map.of(Paths.get(dataDir, "reported_good_1.apk").toString(), "PCL[]"));
+ reporter.report(
+ Map.of(Paths.get(dataDir, "reported_good_2.apk").toString(), "PCL[bar.jar]"));
+ reporter.report(Map.of(Paths.get(dataDir, "reported_good_3.apk").toString(),
+ "=UnsupportedClassLoaderContext="));
+ }
+
+ @Test
+ public void testGetDexFileOutputPaths() throws Exception {
+ String[] paths = DexFile.getDexFileOutputPaths(
+ getApplicationInfo().sourceDir, VMRuntime.getRuntime().vmInstructionSet());
+
+ // We can't be too specific because the paths are ART-internal and are subject to change.
+ assertThat(paths)
+ .asList()
+ .comparingElementsUsing(Correspondence.from(String::endsWith, "ends with"))
+ .containsAtLeast(".odex", ".vdex");
}
public File copyResourceToFile(String resourceName, File file) throws Exception {
@@ -116,4 +147,11 @@ public class StatusCheckerAppTest {
}
return file;
}
+
+ // A custom class loader that is unsupported by CLC encoding.
+ public class CustomClassLoader extends PathClassLoader {
+ public CustomClassLoader(String dexPath, ClassLoader parent) {
+ super(dexPath, parent);
+ }
+ }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp
index b73b888b697..fa396ae1de0 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/Android.bp
@@ -36,6 +36,7 @@ android_test_helper_app {
"ShortcutManagerTestUtils",
"MetricsRecorder",
"statsdprotolite",
+ "cts-keystore-test-util",
],
resource_dirs: ["res"],
asset_dirs: ["assets"],
@@ -70,6 +71,7 @@ android_test_helper_app {
"ShortcutManagerTestUtils",
"MetricsRecorder",
"statsdprotolite",
+ "cts-keystore-test-util",
],
resource_dirs: ["res"],
asset_dirs: ["assets"],
@@ -103,6 +105,7 @@ android_test_helper_app {
"ShortcutManagerTestUtils",
"MetricsRecorder",
"statsdprotolite",
+ "cts-keystore-test-util",
],
resource_dirs: ["res"],
asset_dirs: ["assets"],
@@ -140,6 +143,7 @@ android_test_helper_app {
"ShortcutManagerTestUtils",
"MetricsRecorder",
"statsdprotolite",
+ "cts-keystore-test-util",
],
resource_dirs: ["res"],
asset_dirs: ["assets"],
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
index b191de53ed1..a764358194d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
@@ -126,7 +126,7 @@ public class AlwaysOnVpnTest extends BaseDeviceAdminTest {
VpnTestHelper.setAlwaysOnVpn(
mContext, VPN_PACKAGE, /* lockdown */ false, /* allowlist */ false);
- assertConnectivity(true, "VPN service not started, no lockdown");
+ waitForConnectivity("VPN service not started, no lockdown");
assertNotNull(receiver.awaitForBroadcast(VPN_ON_START_TIMEOUT_MS));
VpnTestHelper.setAlwaysOnVpn(
@@ -138,7 +138,7 @@ public class AlwaysOnVpnTest extends BaseDeviceAdminTest {
VpnTestHelper.setAlwaysOnVpn(
mContext, VPN_PACKAGE, /* lockdown */ true, /* allowlist */ true);
- assertConnectivity(true, "VPN in lockdown, service not started, app allowlisted");
+ waitForConnectivity("VPN in lockdown, service not started, app allowlisted");
assertNotNull(receiver.awaitForBroadcast(VPN_ON_START_TIMEOUT_MS));
VpnTestHelper.setAlwaysOnVpn(
@@ -167,7 +167,7 @@ public class AlwaysOnVpnTest extends BaseDeviceAdminTest {
VpnTestHelper.setAlwaysOnVpn(
mContext, VPN_PACKAGE, /* lockdown */ true, /* allowlist */ true);
- assertConnectivity(true, "VPN in lockdown, service not started, app allowlisted");
+ waitForConnectivity("VPN in lockdown, service not started, app allowlisted");
assertNotNull(receiver.awaitForBroadcast(VPN_ON_START_TIMEOUT_MS));
// Make VPN workable again and restart.
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
index 8c08811ef4c..2d361b26b06 100755
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
@@ -33,6 +33,7 @@ import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.keystore.cts.Attestation;
import android.keystore.cts.AuthorizationList;
+import android.keystore.cts.util.TestUtils;
import android.net.Uri;
import android.os.Build;
import android.os.Process;
@@ -293,11 +294,26 @@ public class KeyManagementTest extends BaseDeviceAdminTest {
Attestation attestationRecord = Attestation.loadFromCertificate((X509Certificate) leaf);
AuthorizationList teeAttestation = attestationRecord.getTeeEnforced();
assertThat(teeAttestation).isNotNull();
- assertThat(teeAttestation.getBrand()).isEqualTo(Build.BRAND);
- assertThat(teeAttestation.getDevice()).isEqualTo(Build.DEVICE);
- assertThat(teeAttestation.getProduct()).isEqualTo(Build.PRODUCT);
- assertThat(teeAttestation.getManufacturer()).isEqualTo(Build.MANUFACTURER);
- assertThat(teeAttestation.getModel()).isEqualTo(Build.MODEL);
+ final String platformReportedBrand =
+ TestUtils.isPropertyEmptyOrUnknown(Build.BRAND_FOR_ATTESTATION)
+ ? Build.BRAND : Build.BRAND_FOR_ATTESTATION;
+ assertThat(teeAttestation.getBrand()).isEqualTo(platformReportedBrand);
+ final String platformReportedDevice =
+ TestUtils.isPropertyEmptyOrUnknown(Build.DEVICE_FOR_ATTESTATION)
+ ? Build.DEVICE : Build.DEVICE_FOR_ATTESTATION;
+ assertThat(teeAttestation.getDevice()).isEqualTo(platformReportedDevice);
+ final String platformReportedProduct =
+ TestUtils.isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION)
+ ? Build.PRODUCT : Build.PRODUCT_FOR_ATTESTATION;
+ assertThat(teeAttestation.getProduct()).isEqualTo(platformReportedProduct);
+ final String platformReportedManufacturer =
+ TestUtils.isPropertyEmptyOrUnknown(Build.MANUFACTURER_FOR_ATTESTATION)
+ ? Build.MANUFACTURER : Build.MANUFACTURER_FOR_ATTESTATION;
+ assertThat(teeAttestation.getManufacturer()).isEqualTo(platformReportedManufacturer);
+ final String platformReportedModel =
+ TestUtils.isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION)
+ ? Build.MODEL : Build.MODEL_FOR_ATTESTATION;
+ assertThat(teeAttestation.getModel()).isEqualTo(platformReportedModel);
assertThat(teeAttestation.getSerialNumber()).isEqualTo(expectedSerial);
assertThat(teeAttestation.getImei()).isEqualTo(expectedImei);
assertThat(teeAttestation.getMeid()).isEqualTo(expectedMeid);
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PersonalAppsSuspensionTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PersonalAppsSuspensionTest.java
index 6fcd364d6b7..bc60faf3b1c 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PersonalAppsSuspensionTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PersonalAppsSuspensionTest.java
@@ -39,6 +39,8 @@ import org.junit.runner.RunWith;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import com.android.compatibility.common.util.PollingCheck;
+
/**
* Test for personal app suspension APIs available to POs on organization owned devices.
*/
@@ -47,6 +49,7 @@ public class PersonalAppsSuspensionTest {
private static final ComponentName ADMIN = BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT;
private final Context mContext = InstrumentationRegistry.getContext();
private final DevicePolicyManager mDpm = mContext.getSystemService(DevicePolicyManager.class);
+ public static final long WAIT_FOR_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED_TIMEOUT_MS = 20000;
@Test
public void testSuspendPersonalApps() {
@@ -98,7 +101,8 @@ public class PersonalAppsSuspensionTest {
public void testComplianceAcknowledgementRequiredReceived() {
final SharedPreferences pref =
mContext.getSharedPreferences(COMPLIANCE_ACK_PREF_NAME, Context.MODE_PRIVATE);
- assertThat(pref.getBoolean(COMPLIANCE_ACK_PREF_KEY_BCAST_RECEIVED, false)).isTrue();
+ PollingCheck.waitFor(WAIT_FOR_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED_TIMEOUT_MS,
+ () -> pref.getBoolean(COMPLIANCE_ACK_PREF_KEY_BCAST_RECEIVED, false));
}
@Test
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
index 6d699a83769..1fbcc9e290a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
@@ -28,6 +28,8 @@ import static android.app.admin.SecurityLog.LEVEL_WARNING;
import static android.app.admin.SecurityLog.TAG_ADB_SHELL_CMD;
import static android.app.admin.SecurityLog.TAG_ADB_SHELL_INTERACTIVE;
import static android.app.admin.SecurityLog.TAG_APP_PROCESS_START;
+import static android.app.admin.SecurityLog.TAG_BLUETOOTH_CONNECTION;
+import static android.app.admin.SecurityLog.TAG_BLUETOOTH_DISCONNECTION;
import static android.app.admin.SecurityLog.TAG_CAMERA_POLICY_SET;
import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_INSTALLED;
import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_REMOVED;
@@ -162,6 +164,8 @@ public class SecurityLoggingTest extends BaseDeviceAdminTest {
.put(TAG_CAMERA_POLICY_SET, of(S, I, I, I))
.put(TAG_PASSWORD_COMPLEXITY_REQUIRED, of(S, I, I, I))
.put(TAG_PASSWORD_CHANGED, of(I, I))
+ .put(TAG_BLUETOOTH_CONNECTION, of(S, I, S))
+ .put(TAG_BLUETOOTH_DISCONNECTION, of(S, S))
.build();
private static final String GENERATED_KEY_ALIAS = "generated_key_alias";
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index ea8c7dabcb1..5836ad178f7 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -87,7 +87,7 @@ public abstract class BaseDevicePolicyTest extends BaseHostJUnit4Test {
private static final String FEATURE_WATCH = "android.hardware.type.watch";
//The maximum time to wait for user to be unlocked.
- private static final long USER_UNLOCK_TIMEOUT_SEC = 30;
+ private static final long USER_UNLOCK_TIMEOUT_SEC = 60;
private static final String USER_STATE_UNLOCKED = "RUNNING_UNLOCKED";
protected static final String PERMISSION_INTERACT_ACROSS_USERS =
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 5799abd579a..bc40dbd3afd 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -529,6 +529,7 @@ public final class ManagedProfileTest extends BaseManagedProfileTest {
installAppAsUser(SHARING_APP_2_APK, mPrimaryUserId);
installAppAsUser(SHARING_APP_1_APK, mProfileUserId);
installAppAsUser(SHARING_APP_2_APK, mProfileUserId);
+ RunUtil.getDefault().sleep(3000);
try {
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileSharingTest",
"addCrossProfileIntents", mProfileUserId);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index 4f0ce17a01a..1417f41a2f9 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -547,6 +547,7 @@ public final class OrgOwnedProfileOwnerTest extends BaseDevicePolicyTest {
try {
toggleQuietMode(true);
+ waitForBroadcastIdle();
toggleQuietMode(false);
// Ensure the DPC has handled the broadcast
waitForBroadcastIdle();
@@ -576,6 +577,7 @@ public final class OrgOwnedProfileOwnerTest extends BaseDevicePolicyTest {
try {
toggleQuietMode(true);
+ waitForBroadcastIdle();
toggleQuietMode(false);
// Ensure the DPC has handled the broadcast
waitForBroadcastIdle();
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
index 3b178a68a0d..94f43fca212 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
@@ -435,6 +435,20 @@ public class BaseHdmiCecCtsTest extends BaseHostJUnit4Test {
} else {
throw new Exception("Unsupported final power state!");
}
+ // We first give 2 seconds to enter the transition state, and then
+ // MAX_SLEEP_TIME_SECONDS to go from the transition state to the final state.
+ do {
+ TimeUnit.SECONDS.sleep(HdmiCecConstants.SLEEP_TIMESTEP_SECONDS);
+ waitTimeSeconds += HdmiCecConstants.SLEEP_TIMESTEP_SECONDS;
+ hdmiCecClient.sendCecMessage(cecClientDevice, CecOperand.GIVE_POWER_STATUS);
+ powerStatus =
+ CecMessage.getParams(
+ hdmiCecClient.checkExpectedOutput(
+ cecClientDevice, CecOperand.REPORT_POWER_STATUS));
+ if (powerStatus == finalState) {
+ return;
+ }
+ } while (waitTimeSeconds <= HdmiCecConstants.SLEEP_TIME_DELAY_SECONDS);
do {
TimeUnit.SECONDS.sleep(HdmiCecConstants.SLEEP_TIMESTEP_SECONDS);
waitTimeSeconds += HdmiCecConstants.SLEEP_TIMESTEP_SECONDS;
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
index c5541d39b82..0ff99dd9a92 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
@@ -38,6 +38,7 @@ public final class HdmiCecConstants {
public static final int DEVICE_WAIT_TIME_MS = 5000;
public static final int MAX_SLEEP_TIME_SECONDS = 8;
public static final int SLEEP_TIMESTEP_SECONDS = 1;
+ public static final int SLEEP_TIME_DELAY_SECONDS = 2;
public static final int DEFAULT_PHYSICAL_ADDRESS = 0x1000;
public static final int TV_PHYSICAL_ADDRESS = 0x0000;
public static final int PHYSICAL_ADDRESS_LENGTH = 4; /* Num nibbles in CEC message */
diff --git a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalFeatureTest.java b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalFeatureTest.java
index a83705956c3..6e74b377bc2 100644
--- a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalFeatureTest.java
+++ b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalFeatureTest.java
@@ -48,15 +48,20 @@ public class IncrementalFeatureTest extends BaseHostJUnit4Test {
@Before
public void setUp() throws Exception {
- // Test devices that are launched with R and above; ignore non-targeted devices
- assumeTrue(getDevice().getLaunchApiLevel() >= 30 /* Build.VERSION_CODES.R */);
+ int launchApiLevel = getDevice().getLaunchApiLevel();
+
+ // Devices that launched with R may fail GSI testing if they have incfs built into the
+ // kernel.
+ // Test R devices that report the feature.
+ // Test all devices S and above.
+ assumeTrue((launchApiLevel == 30 && featureAvailable())
+ || launchApiLevel > 30);
}
@CddTest(requirement="4/C-1-1")
@Test
public void testFeatureAvailable() throws Exception {
- assertTrue("true\n".equals(getDevice().executeShellCommand(
- "pm has-feature android.software.incremental_delivery")));
+ assertTrue(featureAvailable());
}
@CddTest(requirement="4/C-1-1,C-3-1")
@@ -78,4 +83,9 @@ public class IncrementalFeatureTest extends BaseHostJUnit4Test {
assertTrue(getDevice().isPackageInstalled(TEST_APP_PACKAGE_NAME));
getDevice().uninstallPackage(TEST_APP_PACKAGE_NAME);
}
+
+ private boolean featureAvailable() throws Exception {
+ return "true\n".equals(getDevice().executeShellCommand(
+ "pm has-feature android.software.incremental_delivery"));
+ }
}
diff --git a/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java b/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
index 54862a0ffb6..66e4953b03d 100644
--- a/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
+++ b/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
@@ -16,7 +16,6 @@
package android.jdwptunnel.cts;
-import com.android.tradefed.util.RunUtil;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -25,9 +24,11 @@ import static org.junit.Assert.fail;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.AbiUtils;
+import com.android.tradefed.util.RunUtil;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.ReferenceType;
@@ -130,13 +131,20 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
private String startupForwarding(String packageName, String shortClassName, boolean debug)
throws Exception {
moveToHomeScreen();
- mDevice.executeShellCommand(
- "cmd activity start-activity "
- + (debug ? "-D" : "")
- + " -W -n "
- + packageName
- + "/."
- + shortClassName);
+ new Thread(() -> {
+ try {
+ mDevice.executeShellCommand(
+ "cmd activity start-activity "
+ + (debug ? "-D" : "")
+ + " -W -n "
+ + packageName
+ + "/."
+ + shortClassName);
+ } catch (DeviceNotAvailableException e) {
+ CLog.i("Failed to start activity for package: " + packageName, e);
+ }
+ }).start();
+
// Don't keep trying after a minute.
final Instant deadline = Instant.now().plusSeconds(60);
String pid = "";
diff --git a/hostsidetests/media/bitstreams/app/src/android/media/cts/bitstreams/app/MediaBitstreamsDeviceSideTest.java b/hostsidetests/media/bitstreams/app/src/android/media/cts/bitstreams/app/MediaBitstreamsDeviceSideTest.java
index 1839296bb97..3c2275384c1 100644
--- a/hostsidetests/media/bitstreams/app/src/android/media/cts/bitstreams/app/MediaBitstreamsDeviceSideTest.java
+++ b/hostsidetests/media/bitstreams/app/src/android/media/cts/bitstreams/app/MediaBitstreamsDeviceSideTest.java
@@ -338,7 +338,7 @@ public class MediaBitstreamsDeviceSideTest {
});
return conform.get(15, TimeUnit.SECONDS).toString();
} catch (Exception e) {
- return e.toString();
+ return e.toString().replaceAll("\\R", " ");
} finally {
ex.release();
if (d != null) {
diff --git a/hostsidetests/multiuser/app/src/com/android/cts/multiuser/AccountCreator.java b/hostsidetests/multiuser/app/src/com/android/cts/multiuser/AccountCreator.java
index 408eb5733fa..63fc6bf6199 100644
--- a/hostsidetests/multiuser/app/src/com/android/cts/multiuser/AccountCreator.java
+++ b/hostsidetests/multiuser/app/src/com/android/cts/multiuser/AccountCreator.java
@@ -31,10 +31,18 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
@RunWith(JUnit4.class)
public class AccountCreator {
private static final String TAG = "MultiuserAccountCreator";
+ private static final int ACCOUNT_AUTHENTICATOR_TIMEOUT_MILLISECONDS = 180000; // 180 seconds
+
+ private static final int ACCOUNT_AUTHENTICATOR_WAIT_TIME_MILLISECONDS = 5000; // 5 seconds
+
private Context mContext;
@Before
@@ -48,6 +56,9 @@ public class AccountCreator {
final AccountManager accountManager = mContext.getSystemService(AccountManager.class);
Log.i(TAG, "Adding account");
+
+ waitForAccountAuthenticator(MockAuthenticator.ACCOUNT_TYPE, accountManager);
+
final AccountManagerFuture<Bundle> future = accountManager.addAccount(
MockAuthenticator.ACCOUNT_TYPE, null, null, null, null, null, null);
@@ -65,4 +76,33 @@ public class AccountCreator {
Log.i(TAG, "Successfully added account; all is good");
}
+
+
+ private void waitForAccountAuthenticator(String accountType, AccountManager am) {
+ long startTime = System.currentTimeMillis();
+
+ while (System.currentTimeMillis() - startTime < ACCOUNT_AUTHENTICATOR_TIMEOUT_MILLISECONDS
+ && !accountAuthenticatorExists(accountType, am)) {
+ Log.w(TAG, "Account authenticator not found for accountType: " + accountType);
+ sleep(ACCOUNT_AUTHENTICATOR_WAIT_TIME_MILLISECONDS);
+ }
+
+ Log.i(TAG, "Account authenticator found for accountType: " + accountType);
+ }
+
+
+ private boolean accountAuthenticatorExists(String accountType, AccountManager am) {
+
+ Set<String> authenticatorTypes = Arrays.stream(am.getAuthenticatorTypes())
+ .map(authenticatorDescription -> authenticatorDescription.type)
+ .collect(Collectors.toSet());
+
+ return authenticatorTypes.contains(accountType);
+ }
+
+ private void sleep(int timeout) {
+ try {
+ Thread.sleep(timeout);
+ } catch (InterruptedException ex) { }
+ }
}
diff --git a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallationSessionReportedStatsTests.java b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallationSessionReportedStatsTests.java
index 3c76407ff3f..4ee5e37f6bb 100644
--- a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallationSessionReportedStatsTests.java
+++ b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallationSessionReportedStatsTests.java
@@ -65,6 +65,9 @@ public class PackageInstallationSessionReportedStatsTests extends PackageManager
}
public void testPackageInstallationSessionReportedForApkSuccessWithReplace() throws Exception {
+ if (!Utils.hasIncrementalFeature(getDevice())) {
+ return;
+ }
ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
AtomsProto.Atom.PACKAGE_INSTALLATION_SESSION_REPORTED_FIELD_NUMBER);
RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_SHORT);
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 8dd4f7a8211..07f57e79207 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java
@@ -18,6 +18,7 @@ package android.scopedstorage.cts.device;
import static android.app.AppOpsManager.permissionToOp;
import static android.os.SystemProperties.getBoolean;
+import static android.scopedstorage.cts.device.FileCreationUtils.createContentFromResource;
import static android.scopedstorage.cts.lib.TestUtils.allowAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.getPicturesDir;
import static android.scopedstorage.cts.lib.TestUtils.readMaximumRowIdFromDatabaseAs;
@@ -32,13 +33,15 @@ import static org.junit.Assume.assumeTrue;
import android.Manifest;
import android.app.Instrumentation;
import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
+import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.platform.test.annotations.FlakyTest;
import android.provider.MediaStore;
-import android.scopedstorage.cts.lib.TestUtils;
import android.util.Log;
import androidx.test.core.app.ApplicationProvider;
@@ -47,7 +50,10 @@ import androidx.test.uiautomator.UiDevice;
import com.android.cts.install.lib.TestApp;
+import com.google.common.io.Files;
+
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -60,6 +66,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
@RunWith(Parameterized.class)
public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
@@ -71,9 +78,6 @@ 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);
@@ -99,8 +103,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
mContentResolver = mContext.getContentResolver();
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
mDevice = UiDevice.getInstance(inst);
- final int mMediaFilesCount = TestUtils.queryWithArgsAs(APP_FM,
- MediaStore.Files.getContentUri(mVolumeName), null);
+ final int mMediaFilesCount = getMediaFilesCount();
Log.d(TAG, "Number of media files on device: " + mMediaFilesCount);
assumeTrue("The number of media files is too large; Skipping the test as it "
@@ -115,6 +118,8 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
}
@Test
+ @FlakyTest
+ @Ignore
public void testAttributesRestoration() throws Exception {
Map<File, Uri> fileToUriMap = new HashMap<>();
@@ -122,7 +127,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
setFlag("persist.sys.fuse.backup.internal_db_backup", true);
setFlag("persist.sys.fuse.backup.external_volume_backup", true);
- fileToUriMap = createFilesAsTestApp(APP_NO_PERMS, 5);
+ fileToUriMap = createFiles(5);
final Map<File, Bundle> fileToAttributesMapBeforeRestore = setAttributes(fileToUriMap);
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
@@ -135,7 +140,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
mDevice.executeShellCommand("pm clear " + getMediaProviderPackageName());
// Sleeping to make sure the db recovering is completed
- Thread.sleep(20000);
+ Thread.sleep(40000);
verifyAttributes(fileToUriMap, fileToAttributesMapBeforeRestore);
} finally {
@@ -160,7 +165,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
0);
allowAppOpsToUid(fmUid, OPSTR_MANAGE_EXTERNAL_STORAGE);
- files.addAll(createFilesAsTestApp(APP_FM, 5).keySet());
+ files.addAll(createFiles(5).keySet());
long maxRowIdOfInternalDbBeforeReset = readMaximumRowIdFromDatabaseAs(APP_FM,
MediaStore.Files.getContentUri(MediaStore.VOLUME_INTERNAL));
@@ -208,18 +213,20 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
}
}
- private Map<File, Uri> createFilesAsTestApp(TestApp app, int count) throws Exception {
+ private Map<File, Uri> createFiles(int count) throws Exception {
final Map<File, Uri> files = new HashMap<>();
+ File buffer = new File(getPicturesDir(),
+ "Cts_buffer_" + System.currentTimeMillis() + ".jpg");
+ createContentFromResource(R.raw.img_with_metadata, buffer);
for (int i = 1; i <= count; i++) {
final File file = new File(getPicturesDir(),
"Cts_" + System.currentTimeMillis() + ".jpg");
- final boolean isFileCreated = !file.exists()
- && TestUtils.createFileAs(app, file.getAbsolutePath());
- if (!isFileCreated) {
+ if (!file.createNewFile()) {
throw new RuntimeException(
"File was not created on path: " + file.getAbsolutePath());
}
+ Files.copy(buffer, file);
final Uri uri = MediaStore.scanFile(mContentResolver, file);
if (uri == null) {
@@ -233,12 +240,12 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
}
private void verifyAttributes(Map<File, Uri> fileToUriMap,
- Map<File, Bundle> fileToAttributesMapBeforeRestore) throws Exception {
+ Map<File, Bundle> fileToAttributesMapBeforeRestore) {
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());
+ final Bundle attributesAfterRestore = queryMedia(entry.getValue(),
+ originalAttributes.keySet());
assertWithMessage("Uri doesn't point to a media file after db restore")
.that(attributesAfterRestore.isEmpty()).isFalse();
@@ -257,22 +264,23 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
Log.d(TAG, "Finished attributes verification after db restore");
}
- private Map<File, Bundle> setAttributes(Map<File, Uri> fileToUriMap) throws Exception {
+ private Map<File, Bundle> setAttributes(Map<File, Uri> fileToUriMap) {
final Map<File, Bundle> fileToAttributes = new HashMap<>();
int seed = 0;
for (Map.Entry<File, Uri> entry : fileToUriMap.entrySet()) {
final Bundle attributes = generateAttributes(seed++);
+ updateMedia(entry.getValue(), attributes);
- TestUtils.updateMediaByUriAs(APP_NO_PERMS, entry.getValue(), attributes);
-
- final Bundle autoGeneratedAttributes = TestUtils.queryMediaByUriAs(APP_NO_PERMS,
- entry.getValue(), new HashSet<>(Arrays.asList(
+ final Bundle autoGeneratedAttributes = queryMedia(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);
+ Log.d(TAG, String.format("Attributes to verify - uri: %s, attributes: %s",
+ entry.getKey(), attributes));
}
return fileToAttributes;
}
@@ -288,10 +296,41 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest {
return attributes;
}
- private void setFlag(String flagName, boolean value) throws Exception {
- mDevice.executeShellCommand(
+ private Bundle queryMedia(Uri uri, Set<String> projection) {
+ try (Cursor c = mContentResolver.query(uri,
+ projection.toArray(new String[0]), null, null)) {
+ final Bundle result = new Bundle();
+ c.moveToFirst();
+ for (String column : projection) {
+ result.putString(column, c.getString(c.getColumnIndex(column)));
+ }
+
+ return result;
+ }
+ }
+
+ private int getMediaFilesCount() {
+ try (Cursor c = mContentResolver.query(MediaStore.Files.getContentUri(mVolumeName),
+ new String[]{MediaStore.MediaColumns.DISPLAY_NAME},
+ null, null)) {
+ return c.getCount();
+ }
+ }
+
+ private boolean updateMedia(Uri uri, Bundle attributes) {
+ final ContentValues values = new ContentValues();
+ for (String key : attributes.keySet()) {
+ values.put(key, attributes.getString(key));
+ }
+ return mContentResolver.update(uri, values, null, null) == 1;
+ }
+
+ private static void setFlag(String flagName, boolean value) throws Exception {
+ final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ final UiDevice uiDevice = UiDevice.getInstance(inst);
+ uiDevice.executeShellCommand(
"setprop " + flagName + " " + value);
- final String newValue = mDevice.executeShellCommand("getprop " + flagName).trim();
+ final String newValue = uiDevice.executeShellCommand("getprop " + flagName).trim();
assumeTrue("Not able to set flag: " + flagName,
String.valueOf(value).equals(newValue));
diff --git a/hostsidetests/security/Android.bp b/hostsidetests/security/Android.bp
index 4798f0c04de..4ca90cca077 100644
--- a/hostsidetests/security/Android.bp
+++ b/hostsidetests/security/Android.bp
@@ -81,27 +81,19 @@ java_genrule_host {
"checkfc",
"property_info_checker",
"searchpolicy",
- "seamendc",
"secilc",
"sepolicy-analyze",
"sepolicy_tests",
"treble_sepolicy_tests",
],
- tool_files: [
- ":apex_sepolicy-33.cil",
- ":apex_sepolicy-33.decompiled.cil",
- ],
out: ["CtsSecurityHostTestCases_StaticLibs.jar"],
cmd: "$(location soong_zip) -jar -o $(location CtsSecurityHostTestCases_StaticLibs.jar) -j " +
"-f $(location checkseapp) " +
"-f $(location checkfc) " +
"-f $(location property_info_checker) " +
"-f $(location searchpolicy) " +
- "-f $(location seamendc) " +
"-f $(location secilc) " +
"-f $(location sepolicy-analyze) " +
"-f $(location sepolicy_tests) " +
- "-f $(location treble_sepolicy_tests) " +
- "-f $(location :apex_sepolicy-33.cil) " +
- "-f $(location :apex_sepolicy-33.decompiled.cil)",
+ "-f $(location treble_sepolicy_tests)",
}
diff --git a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
index 975b95b949a..9ddb278dba6 100644
--- a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
+++ b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
@@ -296,6 +296,8 @@ public class KernelConfigTest extends BaseHostJUnit4Test {
result.put("KHAJE", null);
result.put("BENGAL-IOT", null);
result.put("BENGALP-IOT", null);
+ result.put("SCUBAIIOT", null);
+ result.put("SCUBAPIIOT", null);
result.put("DEFAULT", new String[]{"CONFIG_UNMAP_KERNEL_AT_EL0=y"});
return result;
}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index ce80ad0eacb..c96b411c9c2 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -55,6 +55,7 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -641,6 +642,27 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
}
/**
+ * Asserts that the actual file contains all the lines from the expected file.
+ * It does not guarantee the order of the lines.
+ *
+ * @param expectedFile
+ * The file with the expected contents.
+ * @param actualFile
+ * The actual file being checked.
+ */
+ private void assertContainsAllLines(File expectedFile, File actualFile) throws Exception {
+ List<String> expectedLines = Files.readAllLines(expectedFile.toPath());
+ List<String> actualLines = Files.readAllLines(actualFile.toPath());
+
+ HashSet<String> expected = new HashSet(expectedLines);
+ HashSet<String> actual = new HashSet(actualLines);
+
+ /* remove all seen lines from expected, ignoring new entries */
+ expected.removeAll(actual);
+ assertTrue("Line removed: " + String.join("\n", expected), expected.isEmpty());
+ }
+
+ /**
* Tests that the seapp_contexts file on the device contains
* the standard AOSP entries.
*
@@ -740,7 +762,7 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
/* retrieve the AOSP service_contexts file from jar */
aospSvcFile = copyResourceToTempFile("/plat_service_contexts");
- assertFileStartsWith(aospSvcFile, deviceSvcFile);
+ assertContainsAllLines(aospSvcFile, deviceSvcFile);
}
/**
diff --git a/hostsidetests/security/src/android/security/cts/SeamendcHostTest.java b/hostsidetests/security/src/android/security/cts/SeamendcHostTest.java
deleted file mode 100644
index d0e337301af..00000000000
--- a/hostsidetests/security/src/android/security/cts/SeamendcHostTest.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.security.cts;
-
-import static org.junit.Assert.assertTrue;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Stream;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class SeamendcHostTest extends BaseHostJUnit4Test {
-
- private ITestDevice mDevice;
-
- // executable binaries
- private File seamendc;
- private File secilc;
- private File searchpolicy;
- private File libsepolwrap;
-
- // CIL policies
- private File mPlatPolicyCil;
- private File mPlatCompatCil;
- private File mSystemExtPolicyCil;
- private File mSystemExtMappingCil;
- private File mSystemExtCompatCil;
- private File mProductPolicyCil;
- private File mProductMappingCil;
- private File mVendorPolicyCil;
- private File mPlatPubVersionedCil;
- private File mOdmPolicyCil;
- private File mApexSepolicyCil;
- private File mApexSepolicyDecompiledCil;
-
- @Before
- public void setUp() throws Exception {
- mDevice = getDevice();
-
- seamendc = copyResToTempFile("/seamendc");
- seamendc.setExecutable(true);
- secilc = copyResToTempFile("/secilc");
- secilc.setExecutable(true);
- searchpolicy = copyResToTempFile("/searchpolicy");
- searchpolicy.setExecutable(true);
- libsepolwrap = new CompatibilityBuildHelper(getBuild()).getTestFile("libsepolwrap.so");
- libsepolwrap.deleteOnExit();
-
- // Pull CIL files for policy compilation, using selinux.cpp as reference
- // https://cs.android.com/android/platform/superproject/+/master:system/core/init/selinux.cpp;l=378-453;drc=2d579af880afae96239c80765b11c7dbc2c1b264
- mPlatPolicyCil = getPlatPolicyFromDevice();
- String vendorMappingVersion =
- readFirstLine("/vendor/etc/selinux/", "plat_sepolicy_vers.txt");
- mPlatCompatCil =
- getDeviceFile("/system/etc/selinux/mapping/", vendorMappingVersion + ".cil");
- mSystemExtPolicyCil = getDeviceFile("/system_ext/etc/selinux/", "system_ext_sepolicy.cil");
- mSystemExtMappingCil =
- getDeviceFile("/system_ext/etc/selinux/mapping/", vendorMappingVersion + ".cil");
- mSystemExtCompatCil =
- getDeviceFile(
- "/system_ext/etc/selinux/mapping/", vendorMappingVersion + ".compat.cil");
- mProductPolicyCil = getDeviceFile("/product/etc/selinux/", "product_sepolicy.cil");
- mProductMappingCil =
- getDeviceFile("/product/etc/selinux/mapping", vendorMappingVersion + ".cil");
- mVendorPolicyCil = getDeviceFile("/vendor/etc/selinux/", "vendor_sepolicy.cil");
- mPlatPubVersionedCil = getDeviceFile("/vendor/etc/selinux/", "plat_pub_versioned.cil");
- mOdmPolicyCil = getDeviceFile("/odm/etc/selinux/", "odm_sepolicy.cil");
- mApexSepolicyCil = copyResToTempFile("/apex_sepolicy.cil");
-
- mApexSepolicyDecompiledCil = copyResToTempFile("/apex_sepolicy.decompiled.cil");
- }
-
- /**
- * Verifies that the files necessary for policy compilation exist.
- *
- * @throws Exception
- */
- @Test
- public void testRequiredDeviceFilesArePresent() throws Exception {
- assertTrue(mPlatPolicyCil.getName() + " is missing", mPlatPolicyCil != null);
- assertTrue(mPlatCompatCil.getName() + " is missing", mPlatCompatCil != null);
- assertTrue(mVendorPolicyCil.getName() + " is missing", mVendorPolicyCil != null);
- assertTrue(mPlatPubVersionedCil.getName() + " is missing", mPlatPubVersionedCil != null);
- }
-
- private File getPlatPolicyFromDevice() throws Exception {
- File policyFile = getDeviceFile("/system_ext/etc/selinux/", "userdebug_plat_sepolicy.cil");
- if (policyFile == null) {
- policyFile = getDeviceFile("/debug_ramdisk/", "userdebug_plat_sepolicy.cil");
- }
- if (policyFile == null) {
- policyFile = getDeviceFile("/system/etc/selinux/", "plat_sepolicy.cil");
- }
- return policyFile;
- }
-
- private String readFirstLine(String filePath, String fileName) throws Exception {
- try (BufferedReader brTest =
- new BufferedReader(new FileReader(getDeviceFile(filePath, fileName)))) {
- return brTest.readLine();
- }
- }
-
- private File getDeviceFile(String filePath, String fileName) throws Exception {
- String deviceFile = filePath + fileName;
- File file = File.createTempFile(fileName, ".tmp");
- file.deleteOnExit();
- return mDevice.pullFile(deviceFile, file) ? file : null;
- }
-
- private static File copyResToTempFile(String resName) throws IOException {
- InputStream is = SeamendcHostTest.class.getResourceAsStream(resName);
- File tempFile = File.createTempFile(resName, ".tmp");
- FileOutputStream os = new FileOutputStream(tempFile);
- byte[] buf = new byte[1024];
- int len;
- while ((len = is.read(buf)) != -1) {
- os.write(buf, 0, len);
- }
- os.flush();
- os.close();
- tempFile.deleteOnExit();
- return tempFile;
- }
-
- private static String runProcess(String... args) throws Exception {
- ProcessBuilder pb = new ProcessBuilder(args);
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- p.waitFor();
- return errorString.toString();
- }
-
- private String searchpolicySource(File policy, String name) throws Exception {
- return runProcess(
- searchpolicy.getAbsolutePath(),
- "--allow",
- "-s",
- name,
- "--libpath",
- libsepolwrap.getAbsolutePath(),
- policy.getAbsolutePath());
- }
-
- private String searchpolicyTarget(File policy, String name) throws Exception {
- return runProcess(
- searchpolicy.getAbsolutePath(),
- "--allow",
- "-t",
- name,
- "--libpath",
- libsepolwrap.getAbsolutePath(),
- policy.getAbsolutePath());
- }
-
- /** Uses searchpolicy to verify the two policies wrt the provided source type. */
- private void assertSource(File left, File right, String type, boolean equal) throws Exception {
- String diff = diff(searchpolicySource(left, type), searchpolicySource(right, type));
- if (equal) {
- assertTrue("Policy sources are not equal:\n" + diff, diff.length() == 0);
- } else {
- assertTrue("Policy sources should be different.", diff.length() != 0);
- }
- }
-
- private void assertSourceEqual(File left, File right, String type) throws Exception {
- assertSource(left, right, type, /* equal= */ true);
- }
-
- private void assertSourceNotEqual(File left, File right, String type) throws Exception {
- assertSource(left, right, type, /* equal= */ false);
- }
-
- /** Uses searchpolicy to verify the two policies wrt the provided target type. */
- private void assertTarget(File left, File right, String type, boolean equal) throws Exception {
- String diff = diff(searchpolicyTarget(left, type), searchpolicyTarget(right, type));
- if (equal) {
- assertTrue("Policies are not equal:\n" + diff, diff.length() == 0);
- } else {
- assertTrue("Policies should be different.", diff.length() != 0);
- }
- }
-
- private void assertTargetEqual(File left, File right, String type) throws Exception {
- assertTarget(left, right, type, /* equal= */ true);
- }
-
- private void assertTargetNotEqual(File left, File right, String type) throws Exception {
- assertTarget(left, right, type, /* equal= */ false);
- }
-
- private File runSeamendc(File basePolicy, File... cilFiles) throws Exception {
- File output = File.createTempFile("seamendc-out", ".binary");
- output.deleteOnExit();
- String errorString =
- runProcess(
- Stream.concat(
- Stream.of(
- seamendc.getAbsolutePath(),
- "-b",
- basePolicy.getAbsolutePath(),
- "-o",
- output.getAbsolutePath()),
- Stream.of(cilFiles).map(File::getAbsolutePath))
- .toArray(String[]::new));
- assertTrue(errorString, errorString.length() == 0);
- return output;
- }
-
- private File runSecilc(File... cilFiles) throws Exception {
- File fileContexts = File.createTempFile("file_contexts", ".txt");
- fileContexts.deleteOnExit();
- File output = File.createTempFile("secilc-out", ".binary");
- output.deleteOnExit();
- String errorString =
- runProcess(
- Stream.concat(
- Stream.of(
- secilc.getAbsolutePath(),
- "-m",
- "-M",
- "true",
- "-G",
- "-N",
- "-c",
- "30",
- "-f",
- fileContexts.getAbsolutePath(),
- "-o",
- output.getAbsolutePath()),
- Stream.of(cilFiles)
- .filter(Objects::nonNull)
- .map(File::getAbsolutePath))
- .toArray(String[]::new));
- assertTrue(errorString, errorString.length() == 0);
- return output;
- }
-
- private static String diff(String left, String right) {
- List<String> leftLines = Arrays.asList(left.split("\\r?\\n"));
- List<String> rightLines = Arrays.asList(right.split("\\r?\\n"));
-
- // Generate diff information.
- List<String> unifiedDiff =
- difflib.DiffUtils.generateUnifiedDiff(
- "original",
- "diff",
- leftLines,
- difflib.DiffUtils.diff(leftLines, rightLines),
- /* contextSize= */ 0);
- StringBuilder stringBuilder = new StringBuilder();
- for (String delta : unifiedDiff) {
- stringBuilder.append(delta);
- stringBuilder.append("\n");
- }
-
- return stringBuilder.toString();
- }
-
- /**
- * Verifies the output of seamendc against the binary policy obtained by secilc-compiling the
- * CIL policies on the device. The binary policies must be the same.
- *
- * @throws Exception
- */
- @Test
- public void testSeamendcAgainstSecilc() throws Exception {
- File secilcOutWithApex =
- runSecilc(
- mPlatPolicyCil,
- mPlatCompatCil,
- mSystemExtPolicyCil,
- mSystemExtMappingCil,
- mSystemExtCompatCil,
- mProductPolicyCil,
- mProductMappingCil,
- mVendorPolicyCil,
- mPlatPubVersionedCil,
- mOdmPolicyCil,
- mApexSepolicyCil);
- File secilcOutWithoutApex =
- runSecilc(
- mPlatPolicyCil,
- mPlatCompatCil,
- mSystemExtPolicyCil,
- mSystemExtMappingCil,
- mSystemExtCompatCil,
- mProductPolicyCil,
- mProductMappingCil,
- mVendorPolicyCil,
- mPlatPubVersionedCil,
- mOdmPolicyCil);
- File seamendcOutWithApex = runSeamendc(secilcOutWithoutApex, mApexSepolicyDecompiledCil);
-
- // system/sepolicy/com.android.sepolicy/33/shell.te
- assertSourceNotEqual(secilcOutWithoutApex, seamendcOutWithApex, "shell");
- assertTargetEqual(secilcOutWithoutApex, seamendcOutWithApex, "shell");
- assertSourceEqual(secilcOutWithApex, seamendcOutWithApex, "shell");
- assertTargetEqual(secilcOutWithApex, seamendcOutWithApex, "shell");
- }
-}
diff --git a/hostsidetests/securitybulletin/res/cve_2023_21118.bin b/hostsidetests/securitybulletin/res/cve_2023_21118.bin
new file mode 100644
index 00000000000..6dc2aaab8d2
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2023_21118.bin
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/v1-only-10-signers.apk b/hostsidetests/securitybulletin/res/v1-only-10-signers.apk
new file mode 100644
index 00000000000..198beeb6510
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/v1-only-10-signers.apk
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/v1-only-11-signers.apk b/hostsidetests/securitybulletin/res/v1-only-11-signers.apk
new file mode 100644
index 00000000000..95e6c61e2f6
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/v1-only-11-signers.apk
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/v2-only-10-signers.apk b/hostsidetests/securitybulletin/res/v2-only-10-signers.apk
new file mode 100644
index 00000000000..ad34c14ced8
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/v2-only-10-signers.apk
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/v2-only-11-signers.apk b/hostsidetests/securitybulletin/res/v2-only-11-signers.apk
new file mode 100644
index 00000000000..674b6e4d7d6
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/v2-only-11-signers.apk
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
index 382d629cdb3..aa676df02d2 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.bp
@@ -30,8 +30,9 @@ cc_test {
],
static_libs: [
"libpdfium-libopenjpeg2",
+ "libpdfium-fxcrt",
],
include_dirs: [
- "external/pdfium/third_party/libopenjpeg20",
+ "external/pdfium/third_party/libopenjpeg",
],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/Android.bp
new file mode 100644
index 00000000000..e235d48c482
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/Android.bp
@@ -0,0 +1,37 @@
+/*
+ * 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"],
+}
+
+cc_test {
+ name: "CVE-2023-21118",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ shared_libs: [
+ "libsensor",
+ "libbinder",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ "-DENABLE_SELECTIVE_OVERLOADING",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/poc.cpp
new file mode 100644
index 00000000000..e79dc696f96
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2023-21118/poc.cpp
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+#include <binder/Parcel.h>
+#include <sensor/Sensor.h>
+
+#include <fstream>
+
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+
+using namespace android;
+using namespace std;
+
+char enable_selective_overload = ENABLE_NONE;
+
+void fillParcel(Parcel &reply) {
+ ifstream inputFile("cve_2023_21118.bin", ios::binary);
+ FAIL_CHECK(inputFile.is_open());
+
+ // Compute size of file
+ inputFile.seekg(0, std::ios::end);
+ std::streampos fileSize = inputFile.tellg();
+ inputFile.seekg(0, std::ios::beg);
+
+ // Fill parcel with file data
+ vector<uint8_t> fileData(fileSize);
+ inputFile.read(reinterpret_cast<char *>(fileData.data()), fileSize);
+ inputFile.close();
+ reply.write(fileData.data(), fileSize);
+ reply.setDataPosition(25044 /* Set data position to required position */);
+}
+
+int main() {
+ Parcel reply;
+ Sensor s;
+ fillParcel(reply);
+ enable_selective_overload = ENABLE_ALL;
+ reply.read(s);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ return 0;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21118.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21118.java
new file mode 100644
index 00000000000..b0eb7c61760
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21118.java
@@ -0,0 +1,64 @@
+/*
+ * 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 com.android.sts.common.NativePocCrashAsserter.assertNoCrash;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.NativePoc;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_21118 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 269014004)
+ @Test
+ public void testPocCVE_2023_21118() {
+ try {
+ String binaryName = "CVE-2023-21118";
+ String inputFile = "cve_2023_21118.bin";
+
+ String[] signals = {TombstoneUtils.Signals.SIGSEGV};
+ TombstoneUtils.Config crashConfig =
+ new TombstoneUtils.Config()
+ .setProcessPatterns(binaryName)
+ .setBacktraceIncludes(
+ new BacktraceFilterPattern(
+ "libsensor.so", "android::Sensor::unflatten"))
+ .setSignals(signals);
+
+ // Running the PoC for CVE-2023-21118
+ NativePoc.builder()
+ .pocName(binaryName)
+ .resources(inputFile)
+ .asserter(assertNoCrash(crashConfig))
+ .build()
+ .run(this);
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21253.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21253.java
new file mode 100644
index 00000000000..957c459a9b9
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21253.java
@@ -0,0 +1,126 @@
+/*
+ * 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 com.android.tradefed.util.CommandStatus.SUCCESS;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import static java.lang.String.format;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.util.CommandResult;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_21253 extends NonRootSecurityTestCase {
+ private final List<String> mAssumptionFailureList = new ArrayList<String>();
+ private final List<String> mFailureList = new ArrayList<String>();
+
+ @AsbSecurityTest(cveBugId = 266580022)
+ @Test
+ public void testPocCVE_2023_21253() {
+ try {
+ // Prebuilt apks used in this test are same as used in ApkVerifierTest.java. Dependence
+ // on prebuilt apks cannot be removed because with fix, apks with more than 10 signers
+ // cannot be built due to changes done in 'apksigner'.
+ final String v1Only10SignersApk = "v1-only-10-signers.apk";
+ final String v1Only11SignersApk = "v1-only-11-signers.apk";
+ final String v2Only10SignersApk = "v2-only-10-signers.apk";
+ final String v2Only11SignersApk = "v2-only-11-signers.apk";
+
+ // Check V1 apk signature scheme
+ checkApkSignerScheme(v1Only10SignersApk, v1Only11SignersApk, "V1 apk signature");
+
+ // Check V2 apk signature scheme
+ checkApkSignerScheme(v2Only10SignersApk, v2Only11SignersApk, "V2 apk signature");
+
+ // Fail the test if any failure strings are present in mFailureList
+ assertTrue(
+ format(
+ "Vulnerable to b/266580022! Failures are :- %s",
+ mFailureList.toString()),
+ mFailureList.isEmpty());
+
+ // Assumption failure if any exception messages are present in mAssumptionFailureList
+ assumeTrue(
+ format("Exceptions occurred :- %s", mAssumptionFailureList.toString()),
+ mAssumptionFailureList.isEmpty());
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ private void checkApkSignerScheme(
+ String apkWith10Signers, String apkWith11Signers, String apkSignerScheme) {
+ try {
+ final CommandResult outputV1Only10 = installAndCheck(apkWith10Signers);
+ final CommandResult outputV1Only11 = installAndCheck(apkWith11Signers);
+ if (outputV1Only10.getStatus() != SUCCESS) {
+ // outputV1Only10 should be successful as it is expected that installation of an apk
+ // with 10 signers should be allowed
+ mAssumptionFailureList.add(
+ format("Unable to install app %s with 10 signatures", apkWith10Signers));
+ return;
+ }
+ if (outputV1Only11.getStatus() == SUCCESS) {
+ // Add scheme to mFailureList if installation of an apk with 11 signers is
+ // successful
+ mFailureList.add(
+ format(
+ "%s scheme allows installation of apk %s with more than 10 signers",
+ apkSignerScheme, apkWith11Signers));
+ }
+ } catch (Exception e) {
+ // Add exception occurred in mAssumptionFailureList. This is done to avoid test
+ // termination midway and ensure that both the schemes are checked
+ mAssumptionFailureList.add(
+ format(
+ "Exception %s occurred while checking %s apk signer scheme",
+ e.getMessage(), apkSignerScheme));
+ }
+ }
+
+ private CommandResult installAndCheck(String apkName) throws Exception {
+ final ITestDevice device = getDevice();
+ final String apkPath = AdbUtils.TMP_PATH + apkName;
+ try {
+ // Push apk file to /data/local/tmp
+ AdbUtils.pushResource(AdbUtils.RESOURCE_ROOT + apkName, apkPath, device);
+
+ // Install apk
+ return device.executeShellV2Command("pm install " + apkPath);
+ } finally {
+ // Uninstall apk
+ device.executeShellV2Command("pm uninstall android.appsecurity.cts.tinyapp");
+
+ // Remove apk file from /data/local/tmp
+ AdbUtils.removeResources(new String[] {apkName}, AdbUtils.TMP_PATH, device);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21254.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21254.java
new file mode 100644
index 00000000000..0155a9d4f5e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21254.java
@@ -0,0 +1,47 @@
+/*
+ * 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.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_21254 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 254736794)
+ @Test
+ public void testPocCVE_2023_21254() {
+ try {
+ // Install test-app and helper-app
+ installPackage("CVE-2023-21254-test.apk");
+ installPackage("CVE-2023-21254-helper.apk");
+
+ // Run Device test
+ final String testPkg = "android.security.cts.CVE_2023_21254_test";
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testPocCVE_2023_21254");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21261.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21261.java
index 68babce9570..d2c57f89a23 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21261.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21261.java
@@ -32,9 +32,7 @@ import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
-// CVE-2023-21261 includes fix for 2 vulnerabilities.
-// 1.CVE-2022-27405
-// 2.CVE-2022-27406
+// CVE-2023-21261 includes fix for CVE-2022-27406.
// Hence checking for both the vulnerabilties
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2023_21261 extends NonRootSecurityTestCase {
@@ -51,14 +49,6 @@ public class CVE_2023_21261 extends NonRootSecurityTestCase {
String binaryName = "CVE-2023-21261";
String inputFile = "cve_2023_21261.ttf";
- // Running the PoC for CVE-2022-27405
- NativePoc.builder()
- .pocName(binaryName)
- .args("CVE-2022-27405", inputFile)
- .resources(inputFile)
- .asserter(assertNotVulnerableExitCode())
- .build()
- .run(this);
TombstoneUtils.Config crashConfig =
new TombstoneUtils.Config()
.setProcessPatterns(binaryName)
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21291.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21291.java
new file mode 100644
index 00000000000..d197a926b0b
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_21291.java
@@ -0,0 +1,60 @@
+/*
+ * 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.SystemUtil;
+import com.android.sts.common.UserUtils;
+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_21291 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 277593270)
+ @Test
+ public void testPocCVE_2023_21291() {
+ try {
+ // Install application
+ installPackage("CVE-2023-21291.apk", "-g");
+
+ // Create a secondary user cve_2023_21291_user and enable global hidden_api_policy to
+ // access hidden field in DeviceTest
+ ITestDevice device = getDevice();
+ try (AutoCloseable closable =
+ SystemUtil.withSetting(device, "global", "hidden_api_policy", "1");
+ AutoCloseable asSecondaryUser =
+ new UserUtils.SecondaryUser(device)
+ .name("cve_2023_21291_user")
+ .withUser()) {
+
+ // Run DeviceTest
+ final String testPkg = "android.security.cts.CVE_2023_21291";
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testPocCVE_2023_21291");
+ }
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_40120.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_40120.java
new file mode 100644
index 00000000000..a489cea954e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_40120.java
@@ -0,0 +1,52 @@
+/*
+ * 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.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_40120 extends NonRootSecurityTestCase {
+
+ @AsbSecurityTest(cveBugId = 274775190)
+ @Test
+ public void testPocCVE_2023_40120() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2023_40120";
+ installPackage("CVE-2023-40120.apk");
+
+ // Run DeviceTest
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testPocCVE_2023_40120");
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // To exit test gracefully
+ getDevice().executeShellV2Command("input keyevent KEYCODE_HOME");
+ } catch (Exception e) {
+ // ignore the exceptions
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/res/values/strings.xml
index faf549e4171..b0493f1d681 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/res/values/strings.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/res/values/strings.xml
@@ -16,6 +16,7 @@
-->
<resources>
+ <string name="deviceLockFailMessage">Device is not Locked!</string>
<string name="helperAppPackage">android.security.cts.CVE_2021_0595_helper</string>
<string name="launchSecondPocActivityAction">launchSecondPocActivity</string>
<string name="testFailMessage">Vulnerable to b/177457096</string>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/src/android/security/cts/CVE_2021_0595_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/src/android/security/cts/CVE_2021_0595_test/DeviceTest.java
index 431d44519e6..b3784f5199b 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/src/android/security/cts/CVE_2021_0595_test/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0595/test-app/src/android/security/cts/CVE_2021_0595_test/DeviceTest.java
@@ -19,10 +19,11 @@ package android.security.cts.CVE_2021_0595_test;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assume.assumeTrue;
import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
import android.app.Instrumentation;
+import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
@@ -72,6 +73,9 @@ public class DeviceTest {
// Swipe/Remove Lock Screen
device.pressMenu();
+ assumeTrue(
+ context.getString(R.string.deviceLockFailMessage),
+ context.getSystemService(KeyguardManager.class).isDeviceLocked());
assertFalse(
context.getString(R.string.testFailMessage),
context.getString(R.string.helperAppPackage)
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/res/values/strings.xml
index 2318fa6cf23..1fca4928f9e 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/res/values/strings.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/res/values/strings.xml
@@ -16,6 +16,9 @@
-->
<resources>
+ <string name="bucketValueChangeFailMessage">Unable to set standby bucket value!!</string>
<string name="helperAppPackage">android.security.cts.CVE_2023_21128_helper</string>
+ <string name="protectedPackageFailMessage">App not added in admin protected packages list
+ </string>
<string name="testFailMessage">Vulnerable to b/272042183</string>
</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/src/android/security/cts/CVE_2023_21128_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/src/android/security/cts/CVE_2023_21128_test/DeviceTest.java
index 755aaae2ed4..c033c7d9fe2 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/src/android/security/cts/CVE_2023_21128_test/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21128/test-app/src/android/security/cts/CVE_2023_21128_test/DeviceTest.java
@@ -16,13 +16,17 @@
package android.security.cts.CVE_2023_21128_test;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
import android.app.admin.DevicePolicyManager;
-import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
@@ -34,6 +38,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
+import java.util.List;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
@@ -56,14 +61,26 @@ public class DeviceTest {
add(helperAppPackage);
}
});
-
- AmUtils.setStandbyBucket(helperAppPackage, UsageStatsManager.STANDBY_BUCKET_ACTIVE);
+ List<String> packages = dpm.getUserControlDisabledPackages(componentName);
+ assumeTrue(
+ context.getString(R.string.protectedPackageFailMessage),
+ packages.contains(helperAppPackage));
+ AmUtils.setStandbyBucket(helperAppPackage, STANDBY_BUCKET_ACTIVE);
+ final int firstStandbyBucketValue = AmUtils.getStandbyBucket(helperAppPackage);
+ AmUtils.setStandbyBucket(helperAppPackage, STANDBY_BUCKET_NEVER);
+ final int secondStandbyBucketValue = AmUtils.getStandbyBucket(helperAppPackage);
+ boolean passCondition =
+ (firstStandbyBucketValue == STANDBY_BUCKET_EXEMPTED
+ && secondStandbyBucketValue == STANDBY_BUCKET_EXEMPTED);
+ boolean failCondition =
+ (firstStandbyBucketValue == STANDBY_BUCKET_ACTIVE
+ && secondStandbyBucketValue == STANDBY_BUCKET_NEVER);
+ assumeTrue(
+ context.getString(R.string.bucketValueChangeFailMessage),
+ passCondition || failCondition);
// Test fails if the AdminProtected package bucket is not equal STANDBY_BUCKET_EXEMPTED
- assertFalse(
- context.getString(R.string.testFailMessage),
- AmUtils.getStandbyBucket(helperAppPackage)
- != UsageStatsManager.STANDBY_BUCKET_EXEMPTED);
+ assertFalse(context.getString(R.string.testFailMessage), failCondition);
} catch (Exception e) {
assumeNoException(e);
} finally {
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/Android.bp
new file mode 100644
index 00000000000..e8ef24656a8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/Android.bp
@@ -0,0 +1,52 @@
+/*
+ * 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-21254-helper",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "helper-app/src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ manifest: "helper-app/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+ name: "CVE-2023-21254-test",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "test-app/src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.uiautomator_uiautomator",
+ "compatibility-device-util-axt",
+ "sts-device-util",
+ ],
+ manifest: "test-app/AndroidManifest.xml",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/AndroidManifest.xml
new file mode 100644
index 00000000000..8bbf9e8d296
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?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_21254_helper">
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <application>
+ <activity android:name=".PocActivity"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/src/android/security/cts/CVE_2023_21254_helper/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/src/android/security/cts/CVE_2023_21254_helper/PocActivity.java
new file mode 100644
index 00000000000..3d3b2f76fae
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/helper-app/src/android/security/cts/CVE_2023_21254_helper/PocActivity.java
@@ -0,0 +1,46 @@
+/*
+ * 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_21254_helper;
+
+import static android.Manifest.permission.RECORD_AUDIO;
+import static android.app.ApplicationExitInfo.REASON_USER_REQUESTED;
+
+import android.app.Activity;
+import android.content.pm.PackageManager;
+
+public class PocActivity extends Activity {
+ private static final int REQUEST_CODE = 1;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (checkSelfPermission(RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
+ requestPermissions(new String[] {RECORD_AUDIO}, REQUEST_CODE);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
+ super.onRequestPermissionsResult(requestCode, permissions, results);
+ if (requestCode == REQUEST_CODE
+ && permissions[0].equals(RECORD_AUDIO)
+ && results[0] == PackageManager.PERMISSION_GRANTED) {
+ // Terminate app process if one-time permission is granted
+ System.exit(REASON_USER_REQUESTED);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/AndroidManifest.xml
new file mode 100644
index 00000000000..d9d25026922
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?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_21254_test">
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_21254_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/src/android/security/cts/CVE_2023_21254_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/src/android/security/cts/CVE_2023_21254_test/DeviceTest.java
new file mode 100644
index 00000000000..c5db133992a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21254/test-app/src/android/security/cts/CVE_2023_21254_test/DeviceTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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_21254_test;
+
+import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.RECORD_AUDIO;
+import static android.app.ApplicationExitInfo.REASON_USER_REQUESTED;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.sts.common.SystemUtil.poll;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import static java.lang.String.format;
+
+import android.app.ActivityManager;
+import android.app.ApplicationExitInfo;
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.function.BooleanSupplier;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testPocCVE_2023_21254() {
+ try {
+ final Instrumentation instrumentation = getInstrumentation();
+ final Context context = instrumentation.getContext();
+ final UiAutomation uiAutomation = instrumentation.getUiAutomation();
+ final String helperAppPkg = "android.security.cts.CVE_2023_21254_helper";
+
+ // Revoke RECORD_AUDIO permission for helperAppPkg
+ uiAutomation.revokeRuntimePermission(helperAppPkg, RECORD_AUDIO, context.getUser());
+
+ // Wait until RECORD_AUDIO permission is revoked for helperAppPkg
+ BooleanSupplier permissionCheck =
+ new BooleanSupplier() {
+ @Override
+ public boolean getAsBoolean() {
+ PackageManager pm = context.getPackageManager();
+ return pm.checkPermission(RECORD_AUDIO, helperAppPkg)
+ == PERMISSION_DENIED;
+ }
+ };
+ assumeTrue(
+ format(
+ "%s permission is not revoked for %s package hence skipping",
+ RECORD_AUDIO, helperAppPkg),
+ poll(permissionCheck));
+
+ // Start targetActivity from helper app which will request for one-time permission
+ final String targetActivity = "android.security.cts.CVE_2023_21254_helper.PocActivity";
+ Intent intent =
+ new Intent()
+ .setClassName(helperAppPkg, targetActivity)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+
+ // Grant one-time permission to helperAppPkg. This has dependence on UI since permission
+ // required to grant one-time permission MANAGE_ONE_TIME_PERMISSION_SESSIONS cannot be
+ // granted to test-app or used via adoptShellPermissionIdentity
+ final UiDevice uiDevice = UiDevice.getInstance(instrumentation);
+ final long uiTimeoutMs = 2_000L;
+ BySelector selector =
+ By.res(createCaseInsensitivePattern(".*permission_allow_one_time_button.*"))
+ .pkg(createCaseInsensitivePattern(".*permissioncontroller.*"));
+ assumeTrue(
+ "UI element for allowing one-time permission not found",
+ uiDevice.wait(Until.hasObject(selector), uiTimeoutMs));
+ uiDevice.findObject(selector).click();
+ // If in case GrantPermissionsActivity is launched twice due to race condition, click UI
+ // element again to grant one-time permission
+ if (!uiDevice.wait(Until.gone(selector), uiTimeoutMs)) {
+ uiDevice.findObject(selector).click();
+ }
+
+ // Wait until helperAppPkg app process is terminated
+ runWithShellPermissionIdentity(
+ () -> {
+ assumeTrue(
+ format(
+ "%s app process not terminated and hence skipping",
+ helperAppPkg),
+ poll(
+ () -> {
+ // Pass pid and maxNum as 0 to
+ // getHistoricalProcessExitReasons() in
+ // order to get all matching records for helperAppPkg.
+ final List<ApplicationExitInfo> infos =
+ context.getSystemService(ActivityManager.class)
+ .getHistoricalProcessExitReasons(
+ helperAppPkg,
+ 0 /* pid */,
+ 0 /* maxNum */);
+ for (ApplicationExitInfo info : infos) {
+ if (info.getStatus() == REASON_USER_REQUESTED) {
+ return true;
+ }
+ }
+ return false;
+ }));
+ },
+ DUMP);
+
+ // Without fix, one-time permission for helperAppPkg is not revoked after app process
+ // terminates and hence test fails
+ assertTrue(
+ "Device is vulnerable to b/254736794!! One-time permissions can be held"
+ + " indefinitely due to activity manager bug",
+ poll(permissionCheck));
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+
+ private Pattern createCaseInsensitivePattern(String pattern) {
+ return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/Android.bp
new file mode 100644
index 00000000000..5b4d51fe0a5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/Android.bp
@@ -0,0 +1,37 @@
+/*
+ * 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-21291",
+ defaults: ["cts_support_defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
+ "sts-device-util",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/AndroidManifest.xml
new file mode 100644
index 00000000000..b5bd6186951
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?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_21291">
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_21291" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/src/android/security/cts/CVE_2023_21291/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/src/android/security/cts/CVE_2023_21291/DeviceTest.java
new file mode 100644
index 00000000000..ee75317d11c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-21291/src/android/security/cts/CVE_2023_21291/DeviceTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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_21291;
+
+import static android.Manifest.permission.CREATE_USERS;
+import static android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+
+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.app.Person;
+import android.content.ContentProvider;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.drawable.Icon;
+import android.os.UserManager;
+import android.provider.MediaStore;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testPocCVE_2023_21291() {
+ try {
+ Instrumentation instrumentation = getInstrumentation();
+ Context context = instrumentation.getContext();
+ final UserManager userManager = context.getSystemService(UserManager.class);
+
+ // Check if the device supports multiple users or not
+ assumeTrue(
+ "This device does not support multiple users",
+ userManager.supportsMultipleUsers());
+
+ // Get the user id of "cve_2023_21291_user"
+ int testUserId =
+ SystemUtil.runWithShellPermissionIdentity(
+ () -> {
+ List<UserInfo> list = userManager.getUsers();
+ for (UserInfo info : list) {
+ if (info.toString().contains("cve_2023_21291_user")) {
+ return info.getUserHandle().getIdentifier();
+ }
+ }
+ return -1;
+ },
+ CREATE_USERS);
+ assumeTrue("Unable to find the user cve_2023_21291_user", testUserId != -1);
+
+ // Insert a placeholder content in the new user and query it to see if it has been
+ // inserted successfully
+ final String imagesContentUri = EXTERNAL_CONTENT_URI.toString();
+ assumeTrue(
+ "Failed to insert a placeholder content in the test user",
+ poll(
+ () -> {
+ try {
+ SystemUtil.runShellCommand(
+ instrumentation,
+ String.format(
+ "content insert --user %d --uri %s --bind "
+ + "_display_name:s:cve_2023_21291.jpg",
+ testUserId, imagesContentUri));
+ return SystemUtil.runShellCommand(
+ instrumentation,
+ String.format(
+ "content query " + "--user %d --uri %s",
+ testUserId, imagesContentUri))
+ .contains("Row");
+ } catch (Exception e) {
+ Log.i("CVE-2023-21291", "Got an exception: " + e);
+ }
+ return false;
+ }));
+
+ // Create notificationManager
+ NotificationManager notificationManager =
+ context.getSystemService(NotificationManager.class);
+
+ // Create notificationChannel
+ String channelId = "cve_2023_21291_channel_id";
+ notificationManager.createNotificationChannel(
+ new NotificationChannel(
+ channelId,
+ "cve_2023_21291_channel_name" /* notification channel name */,
+ NotificationManager.IMPORTANCE_DEFAULT));
+
+ // Post the Notification and check if any security exception is caught
+ try {
+ notificationManager.notify(
+ 0 /* notification id */,
+ new Notification.Builder(context)
+ .setChannelId(channelId)
+ .setStyle(
+ new Notification.MessagingStyle(
+ new Person.Builder()
+ .setName("cve_2023_21291_person")
+ .build())
+ .setShortcutIcon(
+ Icon.createWithContentUri(
+ ContentProvider.maybeAddUserId(
+ EXTERNAL_CONTENT_URI,
+ testUserId))))
+ .setSmallIcon(
+ Icon.createWithData(
+ new byte[0] /* data */,
+ 0 /* offset */,
+ 0 /* length */))
+ .build());
+ } catch (SecurityException securityException) {
+ if (securityException
+ .getLocalizedMessage()
+ .toLowerCase()
+ .contains(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString())) {
+ // Ignore exception thrown with fix and exit the test
+ return;
+ } else {
+ throw securityException;
+ }
+ }
+
+ // Check if notification gets posted or not, fail the test if notification gets posted
+ assertFalse(
+ "Device is vulnerable to b/277593270 hence images belonging to another user on"
+ + " the same device can be displayed in conversation notifications",
+ poll(
+ () -> {
+ StatusBarNotification[] activeNotifications =
+ notificationManager.getActiveNotifications();
+ for (StatusBarNotification notification : activeNotifications) {
+ if (notification
+ .getPackageName()
+ .equals(context.getPackageName())) {
+ return true;
+ }
+ }
+ return false;
+ }));
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/Android.bp
new file mode 100644
index 00000000000..2015242f475
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * 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-40120",
+ defaults: [
+ "cts_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "sts-device-util",
+ "truth-prebuilt",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/AndroidManifest.xml
new file mode 100644
index 00000000000..020a20f5a09
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?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_40120">
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2023_40120" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java
new file mode 100644
index 00000000000..c0c1ce514df
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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_40120;
+
+import static android.provider.Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.sts.common.SystemUtil.poll;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.common.truth.TruthJUnit.assume;
+
+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.media.MediaMetadata;
+import android.media.session.MediaSession;
+import android.service.notification.StatusBarNotification;
+
+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;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testPocCVE_2023_40120() {
+ try {
+ Instrumentation instrumentation = getInstrumentation();
+ Context context = instrumentation.getContext();
+
+ // Create a MediaSession
+ MediaSession session =
+ new MediaSession(context, "cve_2023_40120_session" /* session name */);
+
+ // Create a MediaMetadata object, pass an empty 'METADATA_KEY_TITLE' and set metadata
+ // for session
+ String artistName = "testArtist";
+ session.setMetadata(
+ new MediaMetadata.Builder()
+ .putString(MediaMetadata.METADATA_KEY_TITLE, "")
+ .putString(MediaMetadata.METADATA_KEY_ARTIST, artistName)
+ .build());
+
+ // Create notificationManager
+ NotificationManager notificationManager =
+ context.getSystemService(NotificationManager.class);
+
+ // Create notificationChannel
+ String channelId = "cve_2023_40120_channel_id";
+ notificationManager.createNotificationChannel(
+ new NotificationChannel(
+ channelId,
+ "cve_2023_40120_channel_name" /* notification channel name */,
+ NotificationManager.IMPORTANCE_DEFAULT));
+
+ // Post the Notification and check if any security exception is caught
+ notificationManager.notify(
+ 0 /* notification id */,
+ new Notification.Builder(context)
+ .setChannelId(channelId)
+ .setStyle(
+ new Notification.DecoratedMediaCustomViewStyle()
+ .setMediaSession(session.getSessionToken()))
+ .setSmallIcon(
+ Icon.createWithData(
+ new byte[0] /* data */, 0 /* offset */, 0 /* length */))
+ .build());
+
+ // Check if notification gets posted or not
+ assume().withMessage("Notification was not posted")
+ .that(
+ poll(
+ () -> {
+ StatusBarNotification[] activeNotifications =
+ notificationManager.getActiveNotifications();
+ for (StatusBarNotification notification :
+ activeNotifications) {
+ if (notification
+ .getPackageName()
+ .equals(context.getPackageName())) {
+ return true;
+ }
+ }
+ return false;
+ }))
+ .isTrue();
+
+ // Launch notification shade
+ UiDevice uiDevice = UiDevice.getInstance(instrumentation);
+ assume().withMessage("Unable to launch notification shade")
+ .that(uiDevice.openNotification())
+ .isTrue();
+
+ // Wait for 'qs_media_controls' resource id to appear
+ String systemuiPackage = "com.android.systemui";
+ UiObject2 resIdObj =
+ uiDevice.wait(
+ Until.findObject(By.res(systemuiPackage, SHOW_MEDIA_ON_QUICK_SETTINGS)),
+ 3000);
+
+ // Assumption failure if 'resIdObj' is null
+ assume().withMessage("resource id qs_media_controls not found")
+ .that(resIdObj)
+ .isNotNull();
+
+ // Assumption failure if 'testArtist' text is not present in notification
+ assume().withMessage("testArtist text not found")
+ .that(resIdObj.getContentDescription().contains(artistName))
+ .isTrue();
+
+ // Fail the test if either notification title is not present or notification title text
+ // is null
+ UiObject2 headerTitleObj =
+ resIdObj.getParent().findObject(By.res(systemuiPackage, "header_title"));
+ assertWithMessage("Device is vulnerable to b/274775190 hence foreground services can be"
+ + " started with an empty notification")
+ .that(headerTitleObj == null || headerTitleObj.getText() == null)
+ .isFalse();
+ } catch (Exception e) {
+ assume().that(e).isNull();
+ }
+ }
+}
diff --git a/hostsidetests/statsdatom/OWNERS b/hostsidetests/statsdatom/OWNERS
index 6639230e260..78465ae52a6 100644
--- a/hostsidetests/statsdatom/OWNERS
+++ b/hostsidetests/statsdatom/OWNERS
@@ -1,11 +1,12 @@
# Bug component: 366902
jeffreyhuang@google.com
-jtnguyen@google.com
+monicamwang@google.com
muhammadq@google.com
-ruchirr@google.com
+rayhdez@google.com
+sharaienko@google.com
singhtejinder@google.com
tsaichristine@google.com
-yro@google.com
+yaochen@google.com
per-file apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java = file:platform/frameworks/base:/core/java/android/permission/OWNERS
per-file apps/statsdapp/src/com/android/server/cts/device/statsdatom/VibratorTests.java = file:platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/Checkers.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/Checkers.java
index ff37e40cb9c..febea070781 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/Checkers.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/Checkers.java
@@ -65,8 +65,10 @@ public class Checkers {
@Test
public void checkConfigShowUserSwitcher() {
- assertThat(Resources.getSystem().getBoolean(com.android.internal
- .R.bool.config_showUserSwitcherByDefault)).isTrue();
+ Resources resources = Resources.getSystem();
+ int resourceId = resources.getIdentifier("config_showUserSwitcherByDefault",
+ "bool", "android");
+ assertThat(resources.getBoolean(resourceId)).isTrue();
}
/**
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
index f78f90be623..f24a8785d22 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/net/OWNERS
@@ -1,12 +1,14 @@
# These atom tests are co-owned by statsd and network team
jchalard@google.com
jeffreyhuang@google.com
-jtnguyen@google.com
junyulai@google.com
lorenzo@google.com
+monicamwang@google.com
muhammadq@google.com
+rayhdez@google.com
ruchirr@google.com
+sharaienko@google.com
singhtejinder@google.com
sudheersai@google.com
tsaichristine@google.com
-yro@google.com \ No newline at end of file
+yaochen@google.com
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS
index a716430f28b..e7960a8684e 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/OWNERS
@@ -1,8 +1,9 @@
# These atom tests are owned by the statsd team.
jeffreyhuang@google.com
-jtnguyen@google.com
+monicamwang@google.com
muhammadq@google.com
-ruchirr@google.com
+rayhdez@google.com
+sharaienko@google.com
singhtejinder@google.com
tsaichristine@google.com
-yro@google.com
+yaochen@google.com
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index c6f547c955c..4ac8177d316 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -1375,7 +1375,7 @@ public class JobThrottlingTest {
private boolean isTestAppTempWhitelisted() throws Exception {
final String output = mUiDevice.executeShellCommand("cmd deviceidle tempwhitelist").trim();
for (String line : output.split("\n")) {
- if (line.contains("UID=" + mTestPackageUid)) {
+ if (line.contains("UID=" + UserHandle.getAppId(mTestPackageUid))) {
return true;
}
}
@@ -1413,6 +1413,7 @@ public class JobThrottlingTest {
private void tempWhitelistTestApp(long duration) throws Exception {
mUiDevice.executeShellCommand("cmd deviceidle tempwhitelist -d " + duration
+ + " -u " + UserHandle.myUserId()
+ " " + TEST_APP_PACKAGE);
}
@@ -1453,7 +1454,9 @@ public class JobThrottlingTest {
}
private boolean removeTestAppFromTempWhitelist() throws Exception {
- mUiDevice.executeShellCommand("cmd deviceidle tempwhitelist -r " + TEST_APP_PACKAGE);
+ mUiDevice.executeShellCommand("cmd deviceidle tempwhitelist"
+ + " -u " + UserHandle.myUserId()
+ + " -r " + TEST_APP_PACKAGE);
return waitUntilTrue(SHELL_TIMEOUT, () -> !isTestAppTempWhitelisted());
}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/UserInitiatedJobTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/UserInitiatedJobTest.java
index 9207071214c..0acb5b4c34f 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/UserInitiatedJobTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/UserInitiatedJobTest.java
@@ -37,7 +37,7 @@ import android.jobscheduler.cts.jobtestapp.TestFgsService;
import android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
-import android.os.UserManager;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -198,7 +198,9 @@ public class UserInitiatedJobTest {
try (WatchUidRunner uidWatcher = new WatchUidRunner(
InstrumentationRegistry.getInstrumentation(), testAppInfo.uid)) {
// Taking the app off the temp whitelist should make it go UID idle.
- SystemUtil.runShellCommand("cmd deviceidle tempwhitelist -r " + TEST_APP_PACKAGE);
+ SystemUtil.runShellCommand("cmd deviceidle tempwhitelist"
+ + " -u " + UserHandle.myUserId()
+ + " -r " + TEST_APP_PACKAGE);
uidWatcher.waitFor(WatchUidRunner.CMD_IDLE);
Thread.sleep(1000); // Wait a bit for JS to process.
}
@@ -217,8 +219,6 @@ public class UserInitiatedJobTest {
*/
@Test
public void testRestrictedToggling() throws Exception {
- assumeFalse("Skipping test not supported on HSUM devices.",
- mContext.getSystemService(UserManager.class).isHeadlessSystemUserMode());
try (TestNotificationListener.NotificationHelper notificationHelper =
new TestNotificationListener.NotificationHelper(
mContext, TEST_APP_PACKAGE)) {
@@ -240,7 +240,8 @@ public class UserInitiatedJobTest {
assertTrue(mTestAppInterface.awaitJobStart(DEFAULT_WAIT_TIMEOUT_MS));
// Take the app off the temp whitelist so it doesn't retain the exemptions.
- SystemUtil.runShellCommand("cmd deviceidle tempwhitelist -r " + TEST_APP_PACKAGE);
+ SystemUtil.runShellCommand("cmd deviceidle tempwhitelist -u " + UserHandle.myUserId()
+ + " -r " + TEST_APP_PACKAGE);
// Restrict app. Job should stop immediately and shouldn't restart.
mTestAppInterface.setTestPackageRestricted(true);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
index dbb3ad7b353..227b4c6fa16 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/ActionGetContentOnlyTest.java
@@ -19,29 +19,20 @@ package android.photopicker.cts;
import static android.photopicker.cts.util.GetContentActivityAliasUtils.clearPackageData;
import static android.photopicker.cts.util.GetContentActivityAliasUtils.getDocumentsUiPackageName;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUriAndPath;
-import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAndClickBrowse;
-import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
-import static android.photopicker.cts.util.ResultsAssertionsUtils.assertNoPersistedWriteGrant;
-import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPersistedReadGrants;
-import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPersistedWriteGrants;
-import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertReadOnlyAccess;
-import static android.photopicker.cts.util.UiAssertionUtils.assertThatShowsPickerUi;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static org.junit.Assume.assumeTrue;
-
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
-import android.os.Build;
import android.photopicker.cts.util.GetContentActivityAliasUtils;
+import android.photopicker.cts.util.UiAssertionUtils;
import android.util.Pair;
import androidx.test.uiautomator.UiObject;
@@ -51,7 +42,6 @@ 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;
@@ -150,7 +140,6 @@ 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,
@@ -180,47 +169,13 @@ public class ActionGetContentOnlyTest extends PhotoPickerBaseTest {
}
@Test
- public void testChooserIntent_mediaFilter_verifyReadGrantsOnly() throws Exception {
- assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU);
- final int itemCount = 1;
- mUriList.addAll(createImagesAndGetUris(itemCount, mContext.getUserId()));
-
+ public void testChooserIntent_mediaFilter() throws Exception {
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
mActivity.startActivityForResult(Intent.createChooser(intent, TAG), REQUEST_CODE);
// Should open Picker
- assertThatShowsPickerUi();
- final UiObject item = findItemList(itemCount).get(0);
- clickAndWait(sDevice, item);
-
- final Uri uri = mActivity.getResult().data.getData();
- assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
- assertNoPersistedWriteGrant(uri, mContext.getContentResolver());
- }
-
- @Test
- public void testChooserIntent_mediaFilter_verifyReadAndWriteGrants() throws Exception {
- assumeTrue(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU);
- final int itemCount = 1;
- mUriList.addAll(createImagesAndGetUris(itemCount, mContext.getUserId()));
-
- final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setType("image/*");
- mActivity.startActivityForResult(Intent.createChooser(intent, TAG), REQUEST_CODE);
-
- // Should open Picker
- assertThatShowsPickerUi();
- final UiObject item = findItemList(itemCount).get(0);
- clickAndWait(sDevice, item);
-
- final Uri uri = mActivity.getResult().data.getData();
- assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
- // Write grants given to picker uris when launched via ACTION_GET_CONTENT in Android
- // R & S to resolve samsung message app issue.
- assertPersistedWriteGrants(uri, mContext.getContentResolver());
+ UiAssertionUtils.assertThatShowsPickerUi();
}
@Test
@@ -242,7 +197,7 @@ public class ActionGetContentOnlyTest extends PhotoPickerBaseTest {
findAndClickMediaIcon();
// Should open Picker
- assertThatShowsPickerUi();
+ UiAssertionUtils.assertThatShowsPickerUi();
}
private void findAndClickMediaIcon() throws Exception {
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java b/tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java
index 502fd8860f9..76ff2175e9f 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/ActionPickImagesOnlyTest.java
@@ -22,7 +22,7 @@ import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
-import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPersistedReadGrants;
+import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPersistedGrant;
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertRedactedReadOnlyAccess;
@@ -158,7 +158,7 @@ public class ActionPickImagesOnlyTest extends PhotoPickerBaseTest {
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
index 3b144105f7f..08639ae26e8 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java
@@ -20,6 +20,8 @@ import static android.photopicker.cts.PhotoPickerCloudUtils.disableCloudMediaAnd
import static android.photopicker.cts.PhotoPickerCloudUtils.enableCloudMediaAndSetAllowedCloudProviders;
import static android.photopicker.cts.PhotoPickerCloudUtils.getAllowedProvidersDeviceConfig;
import static android.photopicker.cts.PhotoPickerCloudUtils.isCloudMediaEnabled;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.REGEX_PACKAGE_NAME;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.isPhotoPickerVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsActionBarIsVisible;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsActivityIsVisible;
@@ -27,15 +29,25 @@ import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsDesc
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsFragmentContainerExists;
import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsTitleIsVisible;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import android.content.Intent;
import android.os.Build;
+import android.os.UserHandle;
import android.photopicker.cts.util.PhotoPickerUiUtils;
import android.provider.MediaStore;
+import androidx.annotation.NonNull;
+import androidx.test.filters.LargeTest;
import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiSelector;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
+import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.BeforeClass;
@@ -48,12 +60,18 @@ import org.junit.runner.RunWith;
*/
// TODO(b/195009187): Enabling settings page requires setting allowed_cloud_providers device config.
// We currently can't do this in R.
-@RunWith(AndroidJUnit4.class)
+@RunWith(BedsteadJUnit4.class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
private static boolean sCloudMediaPreviouslyEnabled;
private static String sPreviouslyAllowedCloudProviders;
+ private static final String EXTRA_TAB_USER_ID = "user_id";
+ private static final String TAB_CONTAINER_RESOURCE_ID =
+ REGEX_PACKAGE_NAME + ":id/tab_container";
+ private static final String TAB_LAYOUT_RESOURCE_ID = REGEX_PACKAGE_NAME + ":id/tabs";
+ private static final String PERSONAL_TAB_TITLE_ENGLISH = "Personal";
+ private static final String WORK_TAB_TITLE_ENGLISH = "Work";
@BeforeClass
public static void setUpBeforeClass() {
@@ -78,8 +96,15 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
}
}
+ @After
+ public void tearDown() {
+ if (mActivity != null) {
+ mActivity.finish();
+ }
+ }
+
@Test
- public void testSettingsLaunchFromOverflowMenu() throws Exception {
+ public void testSettingsLaunchFromOverflowMenu_WorkDisabled() throws Exception {
// Launch PhotoPickerActivity.
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
mActivity.startActivityForResult(intent, REQUEST_CODE);
@@ -96,5 +121,62 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest {
verifySettingsTitleIsVisible();
verifySettingsDescriptionIsVisible();
verifySettingsFragmentContainerExists();
+
+ // Verify Tab container (to switch profiles) is not visible since Work profile is disabled.
+ verifySettingsTabContainerIsNotVisible();
+ }
+
+ @Test
+ @LargeTest
+ @RequireRunOnWorkProfile
+ public void testSettingsLaunchedInPersonalProfile_WorkEnabled() throws Exception {
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES_SETTINGS);
+
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ sDevice.waitForIdle();
+ verifySettingsActivityIsVisible();
+
+ verifySettingsTabContainerIsVisible();
+ assertWithMessage("Personal tab is not selected")
+ .that(isSelectedTabTitle(PERSONAL_TAB_TITLE_ENGLISH)).isTrue();
+ }
+
+ @Test
+ @LargeTest
+ @RequireRunOnWorkProfile
+ public void testSettingsLaunchedInWorkProfile() throws Exception {
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES_SETTINGS);
+ intent.putExtra(EXTRA_TAB_USER_ID, UserHandle.myUserId());
+
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ sDevice.waitForIdle();
+ verifySettingsActivityIsVisible();
+
+ verifySettingsTabContainerIsVisible();
+ assertWithMessage("Work tab is not selected")
+ .that(isSelectedTabTitle(WORK_TAB_TITLE_ENGLISH)).isTrue();
+ }
+
+ private static void verifySettingsTabContainerIsVisible() {
+ assertWithMessage("Timed out waiting for settings profile select tab container to appear")
+ .that(findObject(TAB_CONTAINER_RESOURCE_ID).waitForExists(SHORT_TIMEOUT))
+ .isTrue();
+ }
+
+ private static void verifySettingsTabContainerIsNotVisible() {
+ assertWithMessage("Found the settings profile select tab container")
+ .that(findObject(TAB_CONTAINER_RESOURCE_ID).waitForExists(SHORT_TIMEOUT))
+ .isFalse();
+ }
+
+ private static boolean isSelectedTabTitle(@NonNull String tabTitle)
+ throws UiObjectNotFoundException {
+ final UiObject tabLayout = findObject(TAB_LAYOUT_RESOURCE_ID);
+ final UiObject tab = tabLayout.getChild(new UiSelector().textContains(tabTitle));
+ return tab.isSelected();
+ }
+
+ private static UiObject findObject(@NonNull String resourceId) {
+ return sDevice.findObject(new UiSelector().resourceIdMatches(resourceId));
}
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index 012ab52f075..293cbacd05c 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -36,7 +36,7 @@ import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddOrSe
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertContainsMimeType;
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertExtension;
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertMimeType;
-import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPersistedReadGrants;
+import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPersistedGrant;
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.ResultsAssertionsUtils.assertRedactedReadOnlyAccess;
@@ -123,7 +123,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
@@ -227,7 +227,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
}
@@ -275,7 +275,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
}
@@ -315,7 +315,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
}
@@ -577,7 +577,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
assertMimeType(uri, mimeType);
}
@@ -623,7 +623,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < itemCount; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
assertContainsMimeType(uri, mimeTypes);
}
@@ -660,7 +660,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < itemCount; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
- assertPersistedReadGrants(uri, mContext.getContentResolver());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
assertMimeType(uri, mimeType);
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/ResultsAssertionsUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/ResultsAssertionsUtils.java
index eac38c3d956..2f346770215 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/ResultsAssertionsUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/ResultsAssertionsUtils.java
@@ -21,7 +21,6 @@ import static android.provider.MediaStore.PickerMediaColumns;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import android.content.ContentResolver;
@@ -63,33 +62,18 @@ public class ResultsAssertionsUtils {
assertThat(auth).isEqualTo("picker");
}
- public static void assertPersistedReadGrants(Uri uri, ContentResolver resolver) {
+ public static void assertPersistedGrant(Uri uri, ContentResolver resolver) {
resolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
- final List<Uri> readUris = new ArrayList<>();
- for (UriPermission perm : uriPermissions) {
- if (perm.isReadPermission()) {
- readUris.add(perm.getUri());
- }
- }
- assertThat(readUris).contains(uri);
- }
- public static void assertPersistedWriteGrants(Uri uri, ContentResolver resolver) {
- resolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
- final List<Uri> writeUris = new ArrayList<>();
+ final List<Uri> uris = new ArrayList<>();
for (UriPermission perm : uriPermissions) {
- if (perm.isWritePermission()) {
- writeUris.add(perm.getUri());
+ if (perm.isReadPermission()) {
+ uris.add(perm.getUri());
}
}
- assertThat(writeUris).contains(uri);
- }
- public static void assertNoPersistedWriteGrant(Uri uri, ContentResolver resolver) {
- assertThrows(SecurityException.class, () -> resolver.takePersistableUriPermission(uri,
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
+ assertThat(uris).contains(uri);
}
public static void assertMimeType(Uri uri, String expectedMimeType) throws Exception {
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index e9417e0e7bd..550c8e7d437 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -89,7 +89,6 @@
<activity android:label="@string/accessibility_embedded_hierarchy_test_activity"
android:name=".AccessibilityEmbeddedHierarchyTest$AccessibilityEmbeddedHierarchyActivity"
- android:theme="@android:style/Theme.Dialog"
android:screenOrientation="locked"/>
<activity android:label="@string/accessibility_drag_and_drop_test_activity"
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 4c52f05af5e..c54157520ff 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="@dimen/embedded_hierarchy_host_layout_size"
- android:layout_height="@dimen/embedded_hierarchy_host_layout_size"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:orientation="vertical">
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
@@ -27,7 +27,7 @@
<SurfaceView
android:id="@+id/host_surfaceview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_width="@dimen/embedded_hierarchy_embedded_layout_size"
+ android:layout_height="@dimen/embedded_hierarchy_embedded_layout_size"/>
</LinearLayout>
diff --git a/tests/accessibilityservice/res/values/dimens.xml b/tests/accessibilityservice/res/values/dimens.xml
index 2f96ab30b89..40a16be21ce 100644
--- a/tests/accessibilityservice/res/values/dimens.xml
+++ b/tests/accessibilityservice/res/values/dimens.xml
@@ -19,9 +19,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>
+ <!-- Dimens used in AccessibilityEmbeddedHierarchyTest. Need to be small enough
+ for a watch screen because this test checks boundsInScreen. -->
+ <!-- Smaller than the host activity layout view so that it can be embedded inside. -->
+ <dimen name="embedded_hierarchy_embedded_layout_size">100dp</dimen>
<!-- Amount that the embedded layout can move while still remaining inside the host. -->
- <dimen name="embedded_hierarchy_embedded_layout_movement_size">50dp</dimen>
+ <dimen name="embedded_hierarchy_embedded_layout_movement_size">25dp</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 ba7a0ddc6ab..999b392627e 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.cts.activities.AccessibilityTestActivity;
+import android.accessibilityservice.cts.utils.DisplayUtils;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.graphics.Point;
@@ -34,13 +35,13 @@ import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.server.wm.CtsWindowInfoUtils;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.Display;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityWindowInfo;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -56,6 +57,7 @@ import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -157,6 +159,8 @@ public class AccessibilityEmbeddedHierarchyTest {
final Rect hostViewBoundsInScreen = new Rect();
final Rect embeddedViewBoundsInScreen = new Rect();
+ parent.refresh();
+ target.refresh();
parent.getBoundsInScreen(hostViewBoundsInScreen);
target.getBoundsInScreen(embeddedViewBoundsInScreen);
@@ -164,35 +168,38 @@ public class AccessibilityEmbeddedHierarchyTest {
"hostViewBoundsInScreen" + hostViewBoundsInScreen.toShortString()
+ " doesn't contain embeddedViewBoundsInScreen"
+ embeddedViewBoundsInScreen.toShortString()).that(
- hostViewBoundsInScreen.contains(embeddedViewBoundsInScreen)).isTrue();
+ DisplayUtils.fuzzyBoundsInScreenContains(
+ hostViewBoundsInScreen, embeddedViewBoundsInScreen)).isTrue();
}
@Test
public void testEmbeddedViewHasCorrectBoundAfterHostViewMove() throws TimeoutException {
final AccessibilityNodeInfo target =
findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
+ final AccessibilityNodeInfo parent = target.getParent();
final Rect hostViewBoundsInScreen = new Rect();
final Rect newEmbeddedViewBoundsInScreen = new Rect();
final Rect oldEmbeddedViewBoundsInScreen = new Rect();
+ target.refresh();
target.getBoundsInScreen(oldEmbeddedViewBoundsInScreen);
// 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);
+ mActivity.moveSurfaceViewLayoutPosition(moveAmountPx, moveAmountPx, false);
+ parent.refresh();
target.refresh();
- final AccessibilityNodeInfo parent = target.getParent();
-
- target.getBoundsInScreen(newEmbeddedViewBoundsInScreen);
parent.getBoundsInScreen(hostViewBoundsInScreen);
+ target.getBoundsInScreen(newEmbeddedViewBoundsInScreen);
assertWithMessage(
"hostViewBoundsInScreen" + hostViewBoundsInScreen.toShortString()
+ " doesn't contain newEmbeddedViewBoundsInScreen"
+ newEmbeddedViewBoundsInScreen.toShortString()).that(
- hostViewBoundsInScreen.contains(newEmbeddedViewBoundsInScreen)).isTrue();
+ DisplayUtils.fuzzyBoundsInScreenContains(hostViewBoundsInScreen,
+ newEmbeddedViewBoundsInScreen)).isTrue();
assertWithMessage(
"newEmbeddedViewBoundsInScreen" + newEmbeddedViewBoundsInScreen.toShortString()
+ " shouldn't be the same with oldEmbeddedViewBoundsInScreen"
@@ -209,7 +216,7 @@ public class AccessibilityEmbeddedHierarchyTest {
// Move Host SurfaceView out of screen
final Point screenSize = getScreenSize();
- mActivity.moveSurfaceViewLayoutPosition(screenSize.x, screenSize.y);
+ mActivity.moveSurfaceViewLayoutPosition(screenSize.x * 2, screenSize.y * 2, true);
target.refresh();
assertWithMessage("Embedded view should be invisible after moving out of screen.").that(
@@ -233,6 +240,13 @@ public class AccessibilityEmbeddedHierarchyTest {
return null;
}
+ private static AccessibilityNodeInfo findHostAccessibilityNodeInfo(
+ AccessibilityNodeInfo root) {
+ List<AccessibilityNodeInfo> nodes =
+ root.findAccessibilityNodeInfosByViewId(HOST_PARENT_RESOURCE_NAME);
+ return nodes.isEmpty() ? null : nodes.get(0);
+ }
+
private Point getScreenSize() {
final DisplayManager dm = sInstrumentation.getContext().getSystemService(
DisplayManager.class);
@@ -288,7 +302,7 @@ public class AccessibilityEmbeddedHierarchyTest {
// No-op
}
- public void waitForEmbeddedHierarchy() {
+ private void waitForEmbeddedHierarchy() {
try {
assertWithMessage("timed out waiting for embedded hierarchy to init.").that(
mCountDownLatch.await(3, TimeUnit.SECONDS)).isTrue();
@@ -297,19 +311,34 @@ public class AccessibilityEmbeddedHierarchyTest {
}
}
- public void moveSurfaceViewLayoutPosition(int x, int y) throws TimeoutException {
+ private void moveSurfaceViewLayoutPosition(int x, int y, boolean offScreen)
+ throws TimeoutException {
+ final AccessibilityNodeInfo surfaceViewNode = findHostAccessibilityNodeInfo(
+ sUiAutomation.getRootInActiveWindow());
+ final Rect expectedBounds = new Rect(), boundsAfter = new Rect();
+ surfaceViewNode.getBoundsInScreen(expectedBounds);
+ expectedBounds.offset(x, y);
sUiAutomation.executeAndWaitForEvent(
() -> sInstrumentation.runOnMainSync(() -> {
- mSurfaceView.setX(x);
- mSurfaceView.setY(y);
- mSurfaceView.requestLayout();
+ mSurfaceView.setTranslationX(x);
+ mSurfaceView.setTranslationY(y);
}),
(event) -> {
- final Rect boundsInScreen = new Rect();
- final AccessibilityWindowInfo window =
- sUiAutomation.getRootInActiveWindow().getWindow();
- window.getBoundsInScreen(boundsInScreen);
- return !boundsInScreen.isEmpty();
+ surfaceViewNode.refresh();
+ surfaceViewNode.getBoundsInScreen(boundsAfter);
+ final boolean hasExpectedPosition;
+ if (offScreen) {
+ hasExpectedPosition = !surfaceViewNode.isVisibleToUser();
+ } else {
+ hasExpectedPosition = DisplayUtils.fuzzyBoundsInScreenSameOrigin(
+ expectedBounds, boundsAfter);
+ }
+ if (!hasExpectedPosition) {
+ Log.i(AccessibilityEmbeddedHierarchyTest.class.getSimpleName(),
+ "mSurfaceView expected bounds: " + expectedBounds
+ + "\tActual bounds: " + boundsAfter);
+ }
+ return hasExpectedPosition;
}, DEFAULT_TIMEOUT_MS);
}
}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
index 75305724c68..e23cc53925b 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
@@ -16,9 +16,8 @@
package android.accessibilityservice.cts;
-import static android.accessibility.cts.common.ShellCommandBuilder.execShellCommand;
-import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.AM_BROADCAST_CLOSE_SYSTEM_DIALOG_COMMAND;
import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.homeScreenOrBust;
+import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.isHomeScreenShowing;
import static org.junit.Assert.assertTrue;
@@ -27,10 +26,10 @@ import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Instrumentation;
import android.app.UiAutomation;
-import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
+import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -39,32 +38,19 @@ import com.android.compatibility.common.util.CddTest;
import org.junit.After;
import org.junit.AfterClass;
-import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.concurrent.TimeoutException;
-
/**
- * Test global actions
+ * Test invoking the various {@link AccessibilityService#performGlobalAction(int)}} actions.
*/
@Presubmit
@AppModeFull
@RunWith(AndroidJUnit4.class)
@CddTest(requirements = {"3.10/C-1-1,C-1-2"})
public class AccessibilityGlobalActionsTest {
- /**
- * Timeout required for pending Binder calls or event processing to
- * complete.
- */
- private static final long TIMEOUT_ASYNC_PROCESSING = 5000;
-
- /**
- * The timeout since the last accessibility event to consider the device idle.
- */
- private static final long TIMEOUT_ACCESSIBILITY_STATE_IDLE = 500;
private static Instrumentation sInstrumentation;
private static UiAutomation sUiAutomation;
@@ -80,6 +66,8 @@ public class AccessibilityGlobalActionsTest {
AccessibilityServiceInfo info = sUiAutomation.getServiceInfo();
info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
sUiAutomation.setServiceInfo(info);
+ // Start on a clean home screen with any system dialogs removed.
+ homeScreenOrBust(sInstrumentation.getContext(), sUiAutomation);
}
@AfterClass
@@ -87,155 +75,116 @@ public class AccessibilityGlobalActionsTest {
sUiAutomation.destroy();
}
- @Before
- public void setUp() throws Exception {
- // Make sure we start test on home screen so we can know if clean up is successful
- // or not in the end.
- homeScreenOrBust(sInstrumentation.getContext(), sUiAutomation);
- }
-
@After
public void tearDown() throws Exception {
- // Make sure we clean up and back to home screen again, or let test fail...
- homeScreenOrBust(sInstrumentation.getContext(), sUiAutomation);
+ // The majority of system actions involve System UI requests that both:
+ // - Can take a few seconds to take effect on certain device types.
+ // - Perform behavior that depends on the specific SystemUI implementation of the device,
+ // making it untestable to a device-agnostic CTS test like this.
+ // So instead of waiting for any specific condition, we repeatedly try to get to the home
+ // screen to clean up before starting the next test.
+
+ // Arbitrary number of retries. Each attempt may wait at most
+ // AsyncUtils.DEFAULT_TIMEOUT_MS ms before failing, so keep this small.
+ final int numAttempts = 3;
+ for (int attempt = 1; attempt <= numAttempts; attempt++) {
+ if (isHomeScreenShowing(sInstrumentation.getContext(), sUiAutomation)) {
+ break;
+ }
+ try {
+ homeScreenOrBust(sInstrumentation.getContext(), sUiAutomation);
+ } catch (AssertionError e) {
+ if (attempt == numAttempts) {
+ // Fail if the last attempt still couldn't get to a clean home screen.
+ throw e;
+ }
+ }
+ }
}
@MediumTest
@Test
- public void testPerformGlobalActionBack() throws Exception {
+ public void testPerformGlobalActionBack() {
assertTrue(sUiAutomation.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionHome() throws Exception {
+ public void testPerformGlobalActionHome() {
assertTrue(sUiAutomation.performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionRecents() throws Exception {
- // Perform the action.
- boolean actionWasPerformed = sUiAutomation.performGlobalAction(
+ public void testPerformGlobalActionRecents() {
+ // Not all devices support GLOBAL_ACTION_RECENTS, but there is no current feature flag for
+ // this. Our best hope is to test that this does throw a runtime error.
+ sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_RECENTS);
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
-
- if (actionWasPerformed) {
- // This is a necessary since the global action does not
- // dismiss recents until they stop animating. Sigh...
- SystemClock.sleep(5000);
- }
}
@MediumTest
@Test
- public void testPerformGlobalActionNotifications() throws Exception {
- // Perform the action under test
+ public void testPerformGlobalActionNotifications() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionQuickSettings() throws Exception {
- // Check whether the action succeeded.
+ public void testPerformGlobalActionQuickSettings() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionPowerDialog() throws Exception {
- // Check whether the action succeeded.
+ public void testPerformGlobalActionPowerDialog() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_POWER_DIALOG));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
- @MediumTest
+ @LargeTest
@Test
- public void testPerformActionScreenshot() throws Exception {
- // Action should succeed
+ public void testPerformActionScreenshot() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT));
// Ideally should verify that we actually have a screenshot, but it's also possible
- // for the screenshot to fail
- waitForIdle();
- execShellCommand(sUiAutomation, AM_BROADCAST_CLOSE_SYSTEM_DIALOG_COMMAND);
+ // for the screenshot to fail.
}
@MediumTest
@Test
- public void testPerformGlobalActionDpadUp() throws Exception {
- // Check whether the action succeeded.
+ public void testPerformGlobalActionDpadUp() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_DPAD_UP));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionDpadDown() throws Exception {
- // Check whether the action succeeded.
+ public void testPerformGlobalActionDpadDown() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_DPAD_DOWN));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionDpadLeft() throws Exception {
- // Check whether the action succeeded.
+ public void testPerformGlobalActionDpadLeft() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_DPAD_LEFT));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionDpadRight() throws Exception {
- // Check whether the action succeeded.
+ public void testPerformGlobalActionDpadRight() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_DPAD_RIGHT));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
}
@MediumTest
@Test
- public void testPerformGlobalActionDpadCenter() throws Exception {
- // Check whether the action succeeded.
+ public void testPerformGlobalActionDpadCenter() {
assertTrue(sUiAutomation.performGlobalAction(
AccessibilityService.GLOBAL_ACTION_DPAD_CENTER));
-
- // Sleep a bit so the UI is settled.
- waitForIdle();
- }
-
- private void waitForIdle() throws TimeoutException {
- sUiAutomation.waitForIdle(TIMEOUT_ACCESSIBILITY_STATE_IDLE, TIMEOUT_ASYNC_PROCESSING);
}
}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityInputConnectionTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityInputConnectionTest.java
index 5ce7582dd4e..29388b32525 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityInputConnectionTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityInputConnectionTest.java
@@ -127,7 +127,9 @@ public final class AccessibilityInputConnectionTest {
// For some reasons, Mockito.spy() for real Framework classes did not work...
// Use NoOpInputConnection/InputConnectionSplitter instead.
final InputConnection spy = Mockito.spy(new NoOpInputConnection());
- mLastInputConnectionSpy.set(spy);
+ if (mLastInputConnectionSpy.get() == null) {
+ mLastInputConnectionSpy.set(spy);
+ }
return new InputConnectionSplitter(ic, spy);
}
};
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityOverlayTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityOverlayTest.java
index e04254d8818..f8fa76d2575 100644..100755
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityOverlayTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityOverlayTest.java
@@ -158,8 +158,8 @@ public class AccessibilityOverlayTest {
final Button button = new Button(mService);
button.setText("Button");
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
- params.width = 1;
- params.height = 1;
+ params.width = 10;
+ params.height = 10;
params.flags =
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
index 2dc4ef1941c..eea01e28c20 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
@@ -51,6 +51,7 @@ public class AccessibilityVolumeTest {
boolean mSingleVolume;
// If a11y volume is stuck at a single value, don't run the tests
boolean mFixedA11yVolume;
+ boolean mIsPlatformAutomotive;
private InstrumentedAccessibilityServiceTestRule<InstrumentedAccessibilityService>
mServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
@@ -74,6 +75,8 @@ public class AccessibilityVolumeTest {
mSingleVolume = (pm != null) && (pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
|| pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION))
|| mAudioManager.isVolumeFixed();
+ mIsPlatformAutomotive = (pm != null)
+ && (pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
final int MIN = mAudioManager.getStreamMinVolume(AudioManager.STREAM_ACCESSIBILITY);
final int MAX = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ACCESSIBILITY);
mFixedA11yVolume = (MIN == MAX);
@@ -98,7 +101,10 @@ public class AccessibilityVolumeTest {
@AppModeFull
@FlakyTest
public void testChangeAccessibilityVolume_inAccessibilityService_shouldWork() {
- if (mSingleVolume || mFixedA11yVolume) {
+ // TODO(b/233287010): Fix voice interaction and a11y concurrency in audio policy service
+ // Automotive product would prevent setting a given UID as accessibility service
+ // thus AudioService would not allow changing accessibility volume.
+ if (mSingleVolume || mFixedA11yVolume || mIsPlatformAutomotive) {
return;
}
final int startingVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ACCESSIBILITY);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
index bac5418c874..c4883eea5ff 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
@@ -59,6 +59,7 @@ import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.cts.activities.AccessibilityWindowQueryActivity;
import android.accessibilityservice.cts.activities.NonDefaultDisplayActivity;
+import android.accessibilityservice.cts.utils.DisplayUtils;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.LocaleManager;
@@ -1054,7 +1055,7 @@ public class AccessibilityWindowQueryTest {
window.getBoundsInScreen(mTempBounds);
final int[] location = new int[2];
mViewRoot.getLocationOnScreen(location);
- if (location[0] == mTempBounds.left && location[1] == mTempBounds.top) {
+ if (DisplayUtils.fuzzyBoundsInScreenSameOrigin(location, mTempBounds)) {
mTargetWindow = window;
return true;
}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java
index dc8b1ef9e15..050843abd54 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/ActivityLaunchUtils.java
@@ -178,7 +178,7 @@ public class ActivityLaunchUtils {
FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
}
- private static boolean isHomeScreenShowing(Context context, UiAutomation uiAutomation) {
+ public static boolean isHomeScreenShowing(Context context, UiAutomation uiAutomation) {
final List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
final PackageManager packageManager = context.getPackageManager();
final List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(
@@ -320,6 +320,7 @@ public class ActivityLaunchUtils {
throw new TimeoutException(timeout.getMessage() + "\n\nTimeout exception records : \n"
+ timeoutExceptionRecords);
}
+ instrumentation.waitForIdleSync();
return (T) mTempActivity;
}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java
index 402b8aeca1b..cadca2270eb 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/DisplayUtils.java
@@ -42,12 +42,44 @@ import com.android.compatibility.common.util.TestUtils;
*/
public class DisplayUtils {
private static final int DISPLAY_ADDED_TIMEOUT_MS = 5000;
+ // Tolerance that allows for rounding differences in how various parts of
+ // Android calculate on-screen bounds given non-integer screen scaling or
+ // dp/pixel density.
+ private static final int BOUNDS_IN_SCREEN_TOLERANCE_PX = 1;
public static int getStatusBarHeight(Activity activity) {
return activity.getWindow().getDecorView().getRootWindowInsets()
.getInsets(WindowInsets.Type.statusBars()).top;
}
+ /**
+ * Checks if the bounds origin match the provided point, to a tolerance of
+ * {@link #BOUNDS_IN_SCREEN_TOLERANCE_PX} pixels.
+ */
+ public static boolean fuzzyBoundsInScreenSameOrigin(int[] origin, Rect bounds) {
+ return Math.abs((origin[0]) - bounds.left) <= BOUNDS_IN_SCREEN_TOLERANCE_PX
+ && Math.abs((origin[1]) - bounds.top) <= BOUNDS_IN_SCREEN_TOLERANCE_PX;
+ }
+
+ /**
+ * Checks if the bounds origins match each other, to a tolerance of
+ * {@link #BOUNDS_IN_SCREEN_TOLERANCE_PX} pixels.
+ */
+ public static boolean fuzzyBoundsInScreenSameOrigin(Rect boundsA, Rect boundsB) {
+ return Math.abs((boundsA.left) - boundsB.left) <= BOUNDS_IN_SCREEN_TOLERANCE_PX
+ && Math.abs((boundsA.top) - boundsB.top) <= BOUNDS_IN_SCREEN_TOLERANCE_PX;
+ }
+
+ /**
+ * Checks if a larger rect contains another, to a tolerance of
+ * {@link #BOUNDS_IN_SCREEN_TOLERANCE_PX} pixels.
+ */
+ public static boolean fuzzyBoundsInScreenContains(Rect larger, Rect smaller) {
+ final Rect largerExpanded = new Rect(larger);
+ largerExpanded.inset(-BOUNDS_IN_SCREEN_TOLERANCE_PX, -BOUNDS_IN_SCREEN_TOLERANCE_PX);
+ return largerExpanded.contains(smaller);
+ }
+
public static class VirtualDisplaySession implements AutoCloseable {
private VirtualDisplay mVirtualDisplay;
private ImageReader mReader;
diff --git a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
index 949c8f88825..d6b3c46aefb 100644
--- a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
+++ b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
@@ -1402,7 +1402,7 @@ public final class ActivityManagerAppExitInfoTest {
@Test
public void testFreezerEnabled() throws Exception {
if (FIRST_SDK_IS_AT_LEAST_U
- && SystemProperties.get("ro.kernel.version").compareTo("4") > 0) {
+ && SystemProperties.get("ro.kernel.version").compareTo("5") >= 0) {
// We expect all devices with kernel 5.x that first shipped with U to support Freezer
assertTrue(ActivityManager.getService().isAppFreezerSupported());
} else {
diff --git a/tests/app/FgsTest/src/android/app/cts/fgstest/ActivityManagerForegroundServiceTypeTest.java b/tests/app/FgsTest/src/android/app/cts/fgstest/ActivityManagerForegroundServiceTypeTest.java
index 45b2aae9816..a489281dcd7 100644
--- a/tests/app/FgsTest/src/android/app/cts/fgstest/ActivityManagerForegroundServiceTypeTest.java
+++ b/tests/app/FgsTest/src/android/app/cts/fgstest/ActivityManagerForegroundServiceTypeTest.java
@@ -594,7 +594,8 @@ public final class ActivityManagerForegroundServiceTypeTest {
if (!ArrayUtils.isEmpty(appops)) {
for (String appop : appops) {
// Because we're adopting the shell identity, we have to set the appop to shell here
- executeShellCommand("appops set --uid " + SHELL_PKG_NAME + " " + appop + " allow");
+ executeShellCommand("appops set --user " + UserHandle.myUserId()
+ + " --uid " + SHELL_PKG_NAME + " " + appop + " allow");
}
}
if (!ArrayUtils.isEmpty(specialOps)) {
@@ -604,7 +605,8 @@ public final class ActivityManagerForegroundServiceTypeTest {
}
if (!ArrayUtils.isEmpty(roles)) {
for (String role: roles) {
- executeShellCommand("cmd role add-role-holder " + role + " " + packageName);
+ executeShellCommand("cmd role add-role-holder --user " + UserHandle.myUserId()
+ + " " + role + " " + packageName);
}
}
}
@@ -612,7 +614,8 @@ public final class ActivityManagerForegroundServiceTypeTest {
private void resetPermissions(TestPermissionInfo[] permissions, String packageName)
throws Exception {
mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
- executeShellCommand("appops reset " + SHELL_PKG_NAME);
+ executeShellCommand("appops reset --user " + UserHandle.myUserId()
+ + " " + SHELL_PKG_NAME);
if (permissions != null) {
final SpecialPermissionOp[] specialOps = Arrays.stream(permissions)
.filter(p-> p.mSpecialOp != null)
@@ -629,7 +632,8 @@ public final class ActivityManagerForegroundServiceTypeTest {
}
if (!ArrayUtils.isEmpty(roles)) {
for (String role: roles) {
- executeShellCommand("cmd role remove-role-holder " + role + " " + packageName);
+ executeShellCommand("cmd role remove-role-holder --user "
+ + UserHandle.myUserId() + " " + role + " " + packageName);
}
}
}
diff --git a/tests/app/WallpaperTest/src/android/app/cts/wallpapers/WallpaperManagerTest.java b/tests/app/WallpaperTest/src/android/app/cts/wallpapers/WallpaperManagerTest.java
index c7ea05a23dd..d41303a7c99 100644
--- a/tests/app/WallpaperTest/src/android/app/cts/wallpapers/WallpaperManagerTest.java
+++ b/tests/app/WallpaperTest/src/android/app/cts/wallpapers/WallpaperManagerTest.java
@@ -696,6 +696,10 @@ public class WallpaperManagerTest {
@Test
public void invokeOnColorsChangedListenerTest_systemOnly() {
+ if (mWallpaperManager.isLockscreenLiveWallpaperEnabled()) {
+ verifyColorListenerInvoked(FLAG_SYSTEM, FLAG_SYSTEM);
+ return;
+ }
int both = FLAG_LOCK | FLAG_SYSTEM;
// Expect both since the first step is to migrate the current wallpaper
// to the lock screen.
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index e254cee00b3..2b8402aba92 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -107,6 +107,7 @@ import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RestrictedBuildTest;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.server.wm.WindowManagerStateHelper;
import android.server.wm.settings.SettingsSession;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -1722,8 +1723,11 @@ public final class ActivityManagerTest {
}
}));
+ final WindowManagerStateHelper wms = new WindowManagerStateHelper();
mTargetContext.startActivity(intent);
watcher3.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
+ wms.waitForValidState(new ComponentName(CANT_SAVE_STATE_1_PACKAGE_NAME,
+ "CantSave1Activity"));
heavyLatchHolder[0] = new CountDownLatch(1);
testFunc[0] = level -> TRIM_MEMORY_RUNNING_MODERATE <= (int) level
@@ -1742,6 +1746,7 @@ public final class ActivityManagerTest {
heavyLatchHolder[0] = new CountDownLatch(1);
testFunc[0] = level -> TRIM_MEMORY_BACKGROUND == (int) level;
mTargetContext.startActivity(homeIntent);
+ wms.waitForHomeActivityVisible();
assertTrue("Failed to wait for the trim memory event",
heavyLatchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 32043d25059..321ac8bca22 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -26,7 +26,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeFalse;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
@@ -724,8 +723,8 @@ public class DownloadManagerTest extends DownloadManagerTestBase {
@Test
public void testDownload_onMediaStoreDownloadsDeleted() throws Exception {
- assumeFalse(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
- || mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH));
+ assumeDocumentsUiAvailableOnFormFactor();
+
// prepare file
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "cts" + System.nanoTime() + ".mp3");
diff --git a/tests/app/src/android/app/cts/DownloadManagerTestBase.java b/tests/app/src/android/app/cts/DownloadManagerTestBase.java
index 2c2b41cfb9d..d0a10d51ff0 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTestBase.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTestBase.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
import android.app.DownloadManager;
import android.app.Instrumentation;
@@ -467,6 +468,25 @@ public class DownloadManagerTestBase {
|| pm.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
}
+ /**
+ * Some non-mobile form factors ship a "stub" DocumentsUI package. Such stub packages may
+ * effectively declare "no-op" components similar to those in the "real" DocUI.
+ * For example, WearOS devices ship FrameworkPackageStubs that declares an Activity that should
+ * handle {@link Intent#ACTION_OPEN_DOCUMENT}, that when started will simply return
+ * {@link android.app.Activity#RESULT_CANCELED} right away.
+ * <p>
+ * This method "runs" a few {@link org.junit.Assume assumptions} to make sure we are not running
+ * on one of the form factors that ship with such stub packages.
+ * <p>
+ * For now, these form factors are: Auto (Android Automotive OS), TVs and wearables (Wear OS).
+ */
+ protected void assumeDocumentsUiAvailableOnFormFactor() {
+ final PackageManager pm = mContext.getPackageManager();
+ assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+ assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)); // TVs
+ assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
+ }
+
public static class DownloadCompleteReceiver extends BroadcastReceiver {
private HashSet<Long> mCompleteIds = new HashSet<>();
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
index d25fef79f49..720babebd75 100644
--- a/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -533,9 +533,12 @@ public class ServiceTest extends ActivityTestsBase {
private void assertNotification(int id, String expectedTitle, boolean shouldHaveFgsFlag) {
String packageName = getContext().getPackageName();
- String errorMessage = null;
- for (int i = 1; i<=2; i++) {
- errorMessage = null;
+ String titleErrorMsg = null;
+ String flagErrorMsg = null;
+ int i = 0;
+ while (true) {
+ titleErrorMsg = null;
+ flagErrorMsg = null;
StatusBarNotification[] sbns = getNotificationManager().getActiveNotifications();
for (StatusBarNotification sbn : sbns) {
if (sbn.getId() == id && sbn.getPackageName().equals(packageName)) {
@@ -543,30 +546,40 @@ public class ServiceTest extends ActivityTestsBase {
// check title first to make sure the update has propagated
String actualTitle = n.extras.getString(Notification.EXTRA_TITLE);
if (expectedTitle.equals(actualTitle)) {
+ titleErrorMsg = null;
// make sure notification and service state is in sync
if (shouldHaveFgsFlag ==
((n.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0)) {
+ flagErrorMsg = null;
+ // both title and flag matches.
return;
+ } else {
+ // title match, flag not match.
+ flagErrorMsg = String.format("Wrong flag for notification #%d: "
+ + " actual '%d'", id, n.flags);
}
- fail(String.format("Wrong flag for notification #%d: "
- + " actual '%d'", id, n.flags));
+ } else {
+ // It's possible the notification hasn't been updated yet, so save the error
+ // message to only fail after retrying.
+ titleErrorMsg = String.format("Wrong title for notification #%d: "
+ + "expected '%s', actual '%s'", id, expectedTitle, actualTitle);
}
- // It's possible the notification hasn't been updated yet, so save the error
- // message to only fail after retrying.
- errorMessage = String.format("Wrong title for notification #%d: "
- + "expected '%s', actual '%s'", id, expectedTitle, actualTitle);
- Log.w(TAG, errorMessage);
+ // id and packageName are found, break now.
+ break;
}
}
- // Notification might not be rendered yet, wait and try again...
- try {
- Thread.sleep(DELAY);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
+ // allow two more retries.
+ if (++i > 2) {
+ break;
}
+ // Notification might not be rendered yet, wait and try again...
+ SystemClock.sleep(DELAY); // 5 seconds delay
+ }
+ if (flagErrorMsg != null) {
+ fail(flagErrorMsg);
}
- if (errorMessage != null) {
- fail(errorMessage);
+ if (titleErrorMsg != null) {
+ fail(titleErrorMsg);
}
fail("No notification with id " + id + " for package " + packageName);
}
diff --git a/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/app/src/android/app/cts/SystemFeaturesTest.java
index f9d9fa8792a..d0caf69463b 100644
--- a/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -206,9 +206,9 @@ public class SystemFeaturesTest {
if (flashAvailable) {
hasFlash = true;
}
- float minFocusDistance =
+ Float minFocusDistance =
chars.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
- if (minFocusDistance > 0) {
+ if (minFocusDistance != null && minFocusDistance > 0) {
hasAutofocus = true;
}
}
@@ -534,8 +534,9 @@ public class SystemFeaturesTest {
*/
@Test
public void testTelephonyFeatures() {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) ||
- !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELECOM)) {
+ if (!(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ && mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELECOM)
+ && mTelephonyManager.isVoiceCapable())) {
return;
}
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 b8aa7ec4133..d5ec9ba3b21 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
@@ -467,7 +467,10 @@ public class AppSearchSchemaCtsTest {
+ " ]\n"
+ "}";
- assertThat(schemaString).isEqualTo(expectedString);
+ String[] lines = expectedString.split("\n");
+ for (String line : lines) {
+ assertThat(schemaString).contains(line);
+ }
}
@Test
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 ba76489068d..18f608b20c2 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
@@ -248,6 +248,148 @@ public abstract class AppSearchSessionCtsTestBase {
}
@Test
+ public void testSetSchema_addIndexedNestedDocumentProperty() throws Exception {
+ // Create schema with a nested document type
+ // SectionId assignment for 'Person':
+ // - "name": string type, indexed. Section id = 0.
+ // - "worksFor.name": string type, (nested) indexed. Section id = 1.
+ 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 DocumentPropertyConfig.Builder("worksFor", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(true)
+ .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())
+ .build();
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(personSchema, organizationSchema)
+ .build())
+ .get();
+
+ // Index documents and verify using getDocuments
+ GenericDocument person =
+ new GenericDocument.Builder<>("namespace", "person1", "Person")
+ .setPropertyString("name", "John")
+ .setPropertyDocument(
+ "worksFor",
+ new GenericDocument.Builder<>("namespace", "org1", "Organization")
+ .setPropertyString("name", "Google")
+ .build())
+ .build();
+
+ AppSearchBatchResult<String, Void> putResult =
+ checkIsBatchResultSuccess(
+ mDb1.putAsync(
+ new PutDocumentsRequest.Builder()
+ .addGenericDocuments(person)
+ .build()));
+ assertThat(putResult.getSuccesses()).containsExactly("person1", null);
+ assertThat(putResult.getFailures()).isEmpty();
+
+ GetByDocumentIdRequest getByDocumentIdRequest =
+ new GetByDocumentIdRequest.Builder("namespace").addIds("person1").build();
+ List<GenericDocument> outDocuments = doGet(mDb1, getByDocumentIdRequest);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(person);
+
+ // Verify search using property filter
+ SearchResultsShim searchResults =
+ mDb1.search(
+ "worksFor.name:Google",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(person);
+
+ // Change the schema to add another nested document property to 'Person'
+ // The added property has 'optional' cardinality, so this change is compatible and indexed
+ // documents should still be searchable.
+ //
+ // New section id assignment for 'Person':
+ // - "almaMater.name", string type, (nested) indexed. Section id = 0
+ // - "name": string type, indexed. Section id = 1
+ // - "worksFor.name": string type, (nested) indexed. Section id = 2
+ AppSearchSchema newPersonSchema =
+ 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 DocumentPropertyConfig.Builder("worksFor", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(true)
+ .build())
+ .addProperty(
+ new DocumentPropertyConfig.Builder("almaMater", "Organization")
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setShouldIndexNestedProperties(true)
+ .build())
+ .build();
+ mDb1.setSchemaAsync(
+ new SetSchemaRequest.Builder()
+ .addSchemas(newPersonSchema, organizationSchema)
+ .build())
+ .get();
+ Set<AppSearchSchema> outSchemaTypes = mDb1.getSchemaAsync().get().getSchemas();
+ assertThat(outSchemaTypes).containsExactly(newPersonSchema, organizationSchema);
+
+ getByDocumentIdRequest =
+ new GetByDocumentIdRequest.Builder("namespace").addIds("person1").build();
+ outDocuments = doGet(mDb1, getByDocumentIdRequest);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(person);
+
+ // Verify that index rebuild was triggered correctly. The same query "worksFor.name:Google"
+ // should still match the same result.
+ searchResults =
+ mDb1.search(
+ "worksFor.name:Google",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).hasSize(1);
+ assertThat(outDocuments).containsExactly(person);
+
+ // In new_schema the 'name' property is now indexed at section id 1. If searching for
+ // "name:Google" matched the document, this means that index rebuild was not triggered
+ // correctly and Icing is still searching the old index, where 'worksFor.name' was
+ // indexed at section id 1.
+ searchResults =
+ mDb1.search(
+ "name:Google",
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build());
+ outDocuments = convertSearchResultsToDocuments(searchResults);
+ assertThat(outDocuments).isEmpty();
+ }
+
+ @Test
public void testSetSchemaWithValidCycle_allowCircularReferences() throws Exception {
assumeTrue(mDb1.getFeatures().isFeatureSupported(Features.SET_SCHEMA_CIRCULAR_REFERENCES));
@@ -6617,295 +6759,6 @@ public abstract class AppSearchSessionCtsTestBase {
}
@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()
@@ -7560,4 +7413,41 @@ public abstract class AppSearchSessionCtsTestBase {
assertThat(outDocuments).hasSize(1);
assertThat(outDocuments).containsExactly(org2);
}
+
+ @Test
+ public void testSetSchema_toString_containsIndexableNestedPropsList() 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();
+ String expectedIndexableNestedPropertyMessage =
+ "indexableNestedProperties: [name, worksFor.notes, worksFor.name]";
+
+ assertThat(emailSchema.toString()).contains(expectedIndexableNestedPropertyMessage);
+ }
}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
index 0bfa6935634..dfbaf860ef4 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java
@@ -39,6 +39,7 @@ public class GenericDocumentCtsTest {
.build();
@Test
+ @SuppressWarnings("deprecation")
public void testMaxIndexedProperties() {
assertThat(GenericDocument.getMaxIndexedProperties()).isEqualTo(16);
}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
index a60dca7dab4..af38f5b6385 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
@@ -935,18 +935,24 @@ public abstract class GlobalSearchSessionCtsTestBase {
// Register observer. Note: the type does NOT exist yet!
mGlobalSearchSession.registerObserverCallback(
mContext.getPackageName(),
- new ObserverSpec.Builder().addFilterSchemas(AppSearchEmail.SCHEMA_TYPE).build(),
+ new ObserverSpec.Builder().addFilterSchemas("TestAddObserver-Type").build(),
EXECUTOR,
observer);
// Index a document
mDb1.setSchemaAsync(
- new SetSchemaRequest.Builder().addSchemas(AppSearchEmail.SCHEMA).build())
+ new SetSchemaRequest.Builder()
+ .addSchemas(
+ new AppSearchSchema.Builder("TestAddObserver-Type").build())
+ .build())
.get();
- AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build();
+ GenericDocument document =
+ new GenericDocument.Builder<GenericDocument.Builder<?>>(
+ "namespace", "testAddObserver-id1", "TestAddObserver-Type")
+ .build();
checkIsBatchResultSuccess(
mDb1.putAsync(
- new PutDocumentsRequest.Builder().addGenericDocuments(email1).build()));
+ new PutDocumentsRequest.Builder().addGenericDocuments(document).build()));
// Make sure the notification was received.
observer.waitForNotificationCount(2);
@@ -955,16 +961,15 @@ public abstract class GlobalSearchSessionCtsTestBase {
new SchemaChangeInfo(
mContext.getPackageName(),
DB_NAME_1,
- /*changedSchemaNames=*/ ImmutableSet.of(
- AppSearchEmail.SCHEMA_TYPE)));
+ /*changedSchemaNames=*/ ImmutableSet.of("TestAddObserver-Type")));
assertThat(observer.getDocumentChanges())
.containsExactly(
new DocumentChangeInfo(
mContext.getPackageName(),
DB_NAME_1,
"namespace",
- AppSearchEmail.SCHEMA_TYPE,
- /*changedDocumentIds=*/ ImmutableSet.of("id1")));
+ "TestAddObserver-Type",
+ /*changedDocumentIds=*/ ImmutableSet.of("testAddObserver-id1")));
}
@Test
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/SearchSpecCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/SearchSpecCtsTest.java
index d384327f889..d19df19f999 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/SearchSpecCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/SearchSpecCtsTest.java
@@ -69,10 +69,10 @@ public class SearchSpecCtsTest {
SearchSpec.GROUPING_TYPE_PER_NAMESPACE
| SearchSpec.GROUPING_TYPE_PER_PACKAGE,
/*limit=*/ 37)
- .addProjection("schemaType1", expectedPropertyPaths1)
- .addProjection("schemaType2", expectedPropertyPaths2)
- .setPropertyWeights("schemaType1", expectedPropertyWeights)
- .setPropertyWeightPaths("schemaType2", expectedPropertyWeightPaths)
+ .addProjection("schemaTypes1", expectedPropertyPaths1)
+ .addProjection("schemaTypes2", expectedPropertyPaths2)
+ .setPropertyWeights("schemaTypes1", expectedPropertyWeights)
+ .setPropertyWeightPaths("schemaTypes2", expectedPropertyWeightPaths)
.setNumericSearchEnabled(true)
.setVerbatimSearchEnabled(true)
.setListFilterQueryLanguageEnabled(true)
@@ -101,21 +101,21 @@ public class SearchSpecCtsTest {
| SearchSpec.GROUPING_TYPE_PER_PACKAGE);
assertThat(searchSpec.getProjections())
.containsExactly(
- "schemaType1",
+ "schemaTypes1",
expectedPropertyPaths1,
- "schemaType2",
+ "schemaTypes2",
expectedPropertyPaths2);
assertThat(searchSpec.getResultGroupingLimit()).isEqualTo(37);
assertThat(searchSpec.getPropertyWeights().keySet())
- .containsExactly("schemaType1", "schemaType2");
- assertThat(searchSpec.getPropertyWeights().get("schemaType1"))
+ .containsExactly("schemaTypes1", "schemaTypes2");
+ assertThat(searchSpec.getPropertyWeights().get("schemaTypes1"))
.containsExactly("property1", 1.0, "property2", 2.0);
- assertThat(searchSpec.getPropertyWeights().get("schemaType2"))
+ assertThat(searchSpec.getPropertyWeights().get("schemaTypes2"))
.containsExactly("property1.nested", 1.0);
- assertThat(searchSpec.getPropertyWeightPaths().get("schemaType1"))
+ assertThat(searchSpec.getPropertyWeightPaths().get("schemaTypes1"))
.containsExactly(
new PropertyPath("property1"), 1.0, new PropertyPath("property2"), 2.0);
- assertThat(searchSpec.getPropertyWeightPaths().get("schemaType2"))
+ assertThat(searchSpec.getPropertyWeightPaths().get("schemaTypes2"))
.containsExactly(new PropertyPath("property1.nested"), 1.0);
assertThat(searchSpec.isNumericSearchEnabled()).isTrue();
assertThat(searchSpec.isVerbatimSearchEnabled()).isTrue();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillAutoActivityLaunchTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillAutoActivityLaunchTestCase.java
index 7e8394995aa..46b8665d9f6 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillAutoActivityLaunchTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillAutoActivityLaunchTestCase.java
@@ -53,7 +53,7 @@ public abstract class AugmentedAutofillAutoActivityLaunchTestCase
new RequiredSystemResourceRule("config_defaultAugmentedAutofillService");
private static final RuleChain sRequiredFeatures = RuleChain
- .outerRule(sRequiredFeatureRule)
+ .outerRule(sRequiredFeaturesRule)
.around(sRequiredResource);
public AugmentedAutofillAutoActivityLaunchTestCase() {}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillManualActivityLaunchTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillManualActivityLaunchTestCase.java
index 341627fcd94..f98768d7cfb 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillManualActivityLaunchTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/AugmentedAutofillManualActivityLaunchTestCase.java
@@ -51,7 +51,7 @@ public abstract class AugmentedAutofillManualActivityLaunchTestCase
new RequiredSystemResourceRule("config_defaultAugmentedAutofillService");
private static final RuleChain sRequiredFeatures = RuleChain
- .outerRule(sRequiredFeatureRule)
+ .outerRule(sRequiredFeaturesRule)
.around(sRequiredResource);
@BeforeClass
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
index 39466c0f981..07cb853e660 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
@@ -282,9 +282,6 @@ public final class AutoFillServiceTestCase {
new ImeSettings.Builder().setInlineSuggestionsEnabled(true)
.setInlineSuggestionViewContentDesc(InlineUiBot.SUGGESTION_STRIP_DESC));
- protected static final RequiredFeatureRule sRequiredFeatureRule =
- new RequiredFeatureRule(PackageManager.FEATURE_AUTOFILL);
-
private final AutofillTestWatcher mTestWatcher = new AutofillTestWatcher();
private final RetryRule mRetryRule =
@@ -399,6 +396,10 @@ public final class AutoFillServiceTestCase {
protected final String mPackageName;
protected final UiBot mUiBot;
+ protected static final RuleChain sRequiredFeaturesRule = RuleChain
+ .outerRule(new RequiredFeatureRule(PackageManager.FEATURE_AUTOFILL))
+ .around(new RequiredFeatureRule(PackageManager.FEATURE_INPUT_METHODS));
+
public BaseTestCase() {
mPackageName = mContext.getPackageName();
mUiBot = sDefaultUiBot;
@@ -456,7 +457,7 @@ public final class AutoFillServiceTestCase {
*/
@NonNull
protected TestRule getRequiredFeaturesRule() {
- return sRequiredFeatureRule;
+ return sRequiredFeaturesRule;
}
/**
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
index dbd29107ed1..9bcbb8eac5c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/CheckoutActivityTest.java
@@ -473,13 +473,10 @@ public class CheckoutActivityTest
@Test
public void getEditTextAutoFillValue() throws Exception {
EditText editText = mActivity.getCcNumber();
+
mActivity.syncRunOnUiThread(() -> editText.setText("test"));
assertThat(editText.getAutofillValue()).isEqualTo(AutofillValue.forText("test"));
-
- mActivity.syncRunOnUiThread(() -> editText.setEnabled(false));
-
- assertThat(editText.getAutofillValue()).isNull();
}
// ============================================================================================
diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java
index fc7373c886d..1956514e118 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java
@@ -270,6 +270,7 @@ public class PccFieldClassificationTest extends
sClassificationReplier.getNextFieldClassificationRequest();
// Set expected value
+ // TODO: change it back to assert both username and password in next release
activity.expectPasswordAutoFill("sweet");
// Click on password field to trigger autofill
@@ -295,19 +296,6 @@ public class PccFieldClassificationTest extends
// Set expected value
activity.expectAutoFill("dude");
- // Click on username field to see presentation from previous autofill request.
- mUiBot.selectByRelativeId(ID_USERNAME);
- mUiBot.waitForIdleSync();
-
-
- // Auto-fill it.
- picker = mUiBot.assertDatasetsWithBorders(
- null /* expectedHeader */, null /* expectedFooter */, DROPDOWN_PRESENTATION);
- mUiBot.selectDataset(picker, DROPDOWN_PRESENTATION);
-
- // Check the results.
- activity.assertAutoFilled();
-
sClassificationReplier.assertNoUnhandledFieldClassificationRequests();
sReplier.assertNoUnhandledFillRequests();
}
diff --git a/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java b/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java
index a84d5f2cf19..92258354445 100644
--- a/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java
+++ b/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java
@@ -39,6 +39,7 @@ public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest {
private static final String BACKUP_APP_PACKAGE
= "android.cts.backup.backuprestoreeventloggerapp";
private static final int OPERATION_TIMEOUT_SECONDS = 30;
+ private static final int BACKUP_APP_RESTART_SLEEP_MS = 3_000;
// Copied from LoggingFullBackupAgent.java
@@ -84,6 +85,10 @@ public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest {
}
public void testBackupRestoreRoundTrip_logsSentToMonitor() throws Exception {
+ if (!isBackupSupported()) {
+ return;
+ }
+
// Ensure the app is not in stopped state.
createTestFileOfSize(BACKUP_APP_PACKAGE, /* size */ 1);
@@ -94,6 +99,9 @@ public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest {
boolean backupFinished = mOperationLatch.await(OPERATION_TIMEOUT_SECONDS,
TimeUnit.SECONDS);
+ // Sleep to allow the app to be killed, so that this doesn't disrupt the restore operation
+ Thread.sleep(BACKUP_APP_RESTART_SLEEP_MS);
+
// Run a restore.
mOperationLatch = new CountDownLatch(/* count */ 1);
mRestoreSession = mBackupManager.beginRestoreSession();
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index 6bcffae5632..06fd9e2f65c 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -4556,7 +4556,7 @@ testStillCaptureNative(
int64_t expectedDurationNs = (minFrameDurationNs + stallDurationNs) * NUM_TEST_IMAGES;
constexpr int64_t waitPerIterationUs = 100000;
constexpr int64_t usToNs = 1000;
- int totalWaitIteration = 50;
+ int totalWaitIteration = 60;
// Allow 1.5x margin
if (expectedDurationNs * 3 / 2 > totalWaitIteration * waitPerIterationUs * usToNs) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 7fbcc272b40..bcd829c0415 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -1113,7 +1113,6 @@ public class CameraDeviceTest extends Camera2AndroidTestCase {
*/
private void testCreateSessionWithParametersByCamera(String cameraId, boolean reprocessable)
throws Exception {
- final int SESSION_TIMEOUT_MS = 1000;
final int CAPTURE_TIMEOUT_MS = 3000;
int inputFormat = ImageFormat.YUV_420_888;
int outputFormat = inputFormat;
@@ -1121,6 +1120,15 @@ public class CameraDeviceTest extends Camera2AndroidTestCase {
Size inputSize = outputSize;
InputConfiguration inputConfig = null;
+ boolean reprocessSupported = mStaticInfo.isCapabilitySupported(
+ REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);
+ reprocessSupported |= mStaticInfo.isCapabilitySupported(
+ REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING);
+ if (reprocessable && !reprocessSupported) {
+ Log.v(TAG, "Reprocessing not supported for " + cameraId);
+ return;
+ }
+
if (VERBOSE) {
Log.v(TAG, "Testing creating session with parameters for camera " + cameraId);
}
@@ -1128,40 +1136,20 @@ public class CameraDeviceTest extends Camera2AndroidTestCase {
CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap config = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ List<OutputConfiguration> outputs = new ArrayList<>();
+ ImageReader reprocessInputReader = null;
if (reprocessable) {
- //Pick a supported i/o format and size combination.
- //Ideally the input format should match the output.
- boolean found = false;
- int inputFormats [] = config.getInputFormats();
- if (inputFormats.length == 0) {
- return;
- }
-
- for (int inFormat : inputFormats) {
- int outputFormats [] = config.getValidOutputFormatsForInput(inFormat);
- for (int outFormat : outputFormats) {
- if (inFormat == outFormat) {
- inputFormat = inFormat;
- outputFormat = outFormat;
- found = true;
- break;
- }
- }
- if (found) {
- break;
- }
- }
-
- //In case the above combination doesn't exist, pick the first first supported
- //pair.
- if (!found) {
- inputFormat = inputFormats[0];
- int outputFormats [] = config.getValidOutputFormatsForInput(inputFormat);
- assertTrue("No output formats supported for input format: " + inputFormat,
- (outputFormats.length > 0));
- outputFormat = outputFormats[0];
- }
+ // Setup the mandatory PRIV/YUV(input) + PRIV/YUV(output) + Jpeg(output) stream
+ // combination.
+ int inputFormats[] = config.getInputFormats();
+ assertNotNull(inputFormats);
+ assertArrayNotEmpty(inputFormats, "No input formats supported");
+ inputFormat = inputFormats[0];
+ int outputFormats[] = config.getValidOutputFormatsForInput(inputFormat);
+ assertNotNull(outputFormats);
+ assertTrue(contains(outputFormats, ImageFormat.JPEG));
+ outputFormat = ImageFormat.JPEG;
Size inputSizes[] = config.getInputSizes(inputFormat);
Size outputSizes[] = config.getOutputSizes(outputFormat);
@@ -1174,6 +1162,8 @@ public class CameraDeviceTest extends Camera2AndroidTestCase {
outputSize = outputSizes[0];
inputConfig = new InputConfiguration(inputSize.getWidth(),
inputSize.getHeight(), inputFormat);
+ reprocessInputReader = ImageReader.newInstance(inputSize.getWidth(),
+ inputSize.getHeight(), inputFormat, /*maxImages*/1);
} else {
if (config.isOutputSupportedFor(outputFormat)) {
outputSize = config.getOutputSizes(outputFormat)[0];
@@ -1188,8 +1178,10 @@ public class CameraDeviceTest extends Camera2AndroidTestCase {
try {
mSessionMockListener = spy(new BlockingSessionCallback());
mSessionWaiter = mSessionMockListener.getStateWaiter();
- List<OutputConfiguration> outputs = new ArrayList<>();
outputs.add(new OutputConfiguration(imageReader.getSurface()));
+ if (reprocessInputReader != null) {
+ outputs.add( new OutputConfiguration(reprocessInputReader.getSurface()));
+ }
SessionConfiguration sessionConfig = new SessionConfiguration(
SessionConfiguration.SESSION_REGULAR, outputs,
new HandlerExecutor(mHandler), mSessionMockListener);
@@ -1215,6 +1207,9 @@ public class CameraDeviceTest extends Camera2AndroidTestCase {
imageListener.getImage(CAPTURE_TIMEOUT_MS).close();
} finally {
imageReader.close();
+ if (reprocessInputReader != null) {
+ reprocessInputReader.close();
+ }
mSession.close();
}
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index b2da36177ba..1a82c5a351e 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -109,6 +109,8 @@ public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
private static final float FOCUS_DISTANCE_ERROR_PERCENT_UNCALIBRATED = 0.25f;
// 10 percent error margin for approximate device
private static final float FOCUS_DISTANCE_ERROR_PERCENT_APPROXIMATE = 0.10f;
+ // 1 percent boundary margin for focus range verify
+ private static final float FOCUS_RANGE_BOUNDARY_MARGIN_PERCENT = 0.01f;
private static final int ANTI_FLICKERING_50HZ = 1;
private static final int ANTI_FLICKERING_60HZ = 2;
// 5 percent error margin for resulting crop regions
@@ -1234,10 +1236,15 @@ public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
Pair<Float, Float> focusRange = result.get(CaptureResult.LENS_FOCUS_RANGE);
if (focusRange != null) {
+ // Prevent differences in floating point precision between manual request and HAL
+ // result, some margin need to be considered for focusRange.near and far check
+ float focusRangeNear = focusRange.first * (1.0f + FOCUS_RANGE_BOUNDARY_MARGIN_PERCENT);
+ float focusRangeFar = focusRange.second * (1.0f - FOCUS_RANGE_BOUNDARY_MARGIN_PERCENT);
+
mCollector.expectLessOrEqual("Focus distance should be less than or equal to "
- + "FOCUS_RANGE.near", focusRange.first, focusDistance);
+ + "FOCUS_RANGE.near (with margin)", focusRangeNear, focusDistance);
mCollector.expectGreaterOrEqual("Focus distance should be greater than or equal to "
- + "FOCUS_RANGE.far", focusRange.second, focusDistance);
+ + "FOCUS_RANGE.far (with margin)", focusRangeFar, focusDistance);
} else if (VERBOSE) {
Log.v(TAG, "FOCUS_RANGE undefined, skipping verification");
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
index 491a81bf90b..2ce590020ef 100644
--- a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -1148,6 +1148,8 @@ public class DngCreatorTest extends Camera2AndroidTestCase {
// Set up still capture template targeting JPEG/RAW outputs
CaptureRequest.Builder request =
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ request.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
+ CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF);
assertNotNull("Fail to get captureRequest", request);
for (Surface surface : outputSurfaces) {
request.addTarget(surface);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
index 1e14d8c3a49..a5314a3dabb 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -1876,7 +1876,7 @@ public class ImageReaderTest extends Camera2AndroidTestCase {
if (img != null) {
img.close();
}
- stopCapture(/*fast*/false);
+ stopCapture(/*fast*/true);
} finally {
closeDefaultImageReader();
}
@@ -2025,7 +2025,7 @@ public class ImageReaderTest extends Camera2AndroidTestCase {
if (VERBOSE) Log.v(TAG, "Waiting for an Image");
mListener.waitForAnyImageAvailable(CAPTURE_WAIT_TIMEOUT_MS);
if (repeating) {
- img = mReader.acquireLatestImage();
+ img = mReader.acquireNextImage();
if (img == null && retryCount < MAX_RETRY_COUNT) {
retryCount++;
continue;
diff --git a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
index e37e3117521..a9e0a58fa64 100644
--- a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
@@ -1035,9 +1035,16 @@ public final class LogicalCameraDeviceTest extends Camera2SurfaceViewTestCase {
Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
SizeF sensorSize = mStaticInfo.getValueFromKeyNonNull(
CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
+ Size logicalPixelArraySize = mStaticInfo.getValueFromKeyNonNull(
+ CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE);
+ Rect logicalPreCorrActiveArraySize = mStaticInfo.getValueFromKeyNonNull(
+ CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+ Float fovTransferRatio = logicalPreCorrActiveArraySize.width() * 1f /
+ logicalPixelArraySize.getWidth();
+ Float logicalSensorWidth = sensorSize.getWidth() * fovTransferRatio;
// Assume subject distance >> focal length, and subject distance >> camera baseline.
- double fov = 2 * Math.toDegrees(Math.atan2(sensorSize.getWidth() * cropRegion.width() /
+ double fov = 2 * Math.toDegrees(Math.atan2(logicalSensorWidth * cropRegion.width() /
(2 * zoomRatio * activeArraySize.width()), focalLength));
Map<String, CaptureResult> physicalResultsDual =
@@ -1052,15 +1059,23 @@ public final class LogicalCameraDeviceTest extends Camera2SurfaceViewTestCase {
SizeF physicalSensorSize = physicalStaticInfo.getValueFromKeyNonNull(
CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
+ Size physicalPixelArraySize = physicalStaticInfo.getValueFromKeyNonNull(
+ CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE);
+ Rect physicalPreCorrActiveArraySize = physicalStaticInfo.getValueFromKeyNonNull(
+ CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+ Float transferRatio = physicalPreCorrActiveArraySize.width() * 1f /
+ physicalPixelArraySize.getWidth();
+ Float physicalSensorWidth = physicalSensorSize.getWidth() * transferRatio;
+
// Physical result metadata's ZOOM_RATIO is 1.0f.
assertTrue("Physical result metadata ZOOM_RATIO should be 1.0f, but is " +
physicalZoomRatio, Math.abs(physicalZoomRatio - 1.0f) < ZOOM_RATIO_THRESHOLD);
double physicalFov = 2 * Math.toDegrees(Math.atan2(
- physicalSensorSize.getWidth() * physicalCropRegion.width() /
+ physicalSensorWidth * physicalCropRegion.width() /
(2 * physicalZoomRatio * physicalActiveArraySize.width()), physicalFocalLength));
- double maxPhysicalFov = 2 * Math.toDegrees(Math.atan2(physicalSensorSize.getWidth() / 2,
+ double maxPhysicalFov = 2 * Math.toDegrees(Math.atan2(physicalSensorWidth / 2,
physicalFocalLength));
double expectedPhysicalFov = Math.min(maxPhysicalFov, fov);
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 804682638c8..c2bdc929329 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -1383,7 +1383,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
private void startSlowMotionRecording(boolean useMediaRecorder, int videoFrameRate,
int captureRate, Range<Integer> fpsRange,
- CameraCaptureSession.CaptureCallback listener, boolean useHighSpeedSession)
+ SimpleCaptureCallback listener, boolean useHighSpeedSession)
throws Exception {
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
assertTrue("Both preview and recording surfaces should be valid",
@@ -1447,6 +1447,8 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
mSession.setRepeatingBurst(slowMoRequests, listener, mHandler);
if (useMediaRecorder) {
+ // Wait for the first capture start before starting mediaRecorder
+ listener.getCaptureStartTimestamps(1);
mMediaRecorder.start();
} else {
// TODO: need implement MediaCodec path.
@@ -2247,20 +2249,20 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
}
private void startRecording(boolean useMediaRecorder,
- CameraCaptureSession.CaptureCallback listener, boolean useVideoStab) throws Exception {
+ SimpleCaptureCallback listener, boolean useVideoStab) throws Exception {
startRecording(useMediaRecorder, listener, useVideoStab, /*variableFpsRange*/null,
/*useIntermediateSurface*/false);
}
private void startRecording(boolean useMediaRecorder,
- CameraCaptureSession.CaptureCallback listener, boolean useVideoStab,
+ SimpleCaptureCallback listener, boolean useVideoStab,
boolean useIntermediateSurface) throws Exception {
startRecording(useMediaRecorder, listener, useVideoStab, /*variableFpsRange*/null,
useIntermediateSurface);
}
private void startRecording(boolean useMediaRecorder,
- CameraCaptureSession.CaptureCallback listener, boolean useVideoStab,
+ SimpleCaptureCallback listener, boolean useVideoStab,
Range<Integer> variableFpsRange, boolean useIntermediateSurface) throws Exception {
if (!mStaticInfo.isVideoStabilizationSupported() && useVideoStab) {
throw new IllegalArgumentException("Video stabilization is not supported");
@@ -2309,6 +2311,8 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
mSession.setRepeatingRequest(recordingRequest, listener, mHandler);
if (useMediaRecorder) {
+ // Wait for the first capture start before starting mediaRecorder
+ listener.getCaptureStartTimestamps(1);
mMediaRecorder.start();
} else {
// TODO: need implement MediaCodec path.
@@ -2323,7 +2327,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
* @return true if success, false if sharing is not supported.
*/
private boolean startSharedRecording(boolean useMediaRecorder,
- CameraCaptureSession.CaptureCallback listener, boolean useVideoStab,
+ SimpleCaptureCallback listener, boolean useVideoStab,
Range<Integer> variableFpsRange) throws Exception {
if (!mStaticInfo.isVideoStabilizationSupported() && useVideoStab) {
throw new IllegalArgumentException("Video stabilization is not supported");
@@ -2363,6 +2367,8 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
mSession.setRepeatingRequest(recordingRequestBuilder.build(), listener, mHandler);
if (useMediaRecorder) {
+ // Wait for the first capture start before starting mediaRecorder
+ listener.getCaptureStartTimestamps(1);
mMediaRecorder.start();
} else {
// TODO: need implement MediaCodec path.
diff --git a/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
index 3b59f532663..269b25cf925 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ZoomCaptureTest.java
@@ -18,7 +18,7 @@ package android.hardware.camera2.cts;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.cts.CameraTestUtils;
+import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
import android.hardware.camera2.params.DynamicRangeProfiles;
@@ -29,7 +29,6 @@ import android.hardware.camera2.CaptureResult;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
-import android.os.ConditionVariable;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
@@ -179,9 +178,9 @@ public class ZoomCaptureTest extends Camera2AndroidTestCase {
physicalCameraIds = mStaticInfo.getCharacteristics().getPhysicalCameraIds();
}
try {
- mListener = new SimpleImageListener();
// Pick the largest image size:
Size maxSize = CameraTestUtils.getMaxSize(availableSizes);
+ mListener = new SimpleImageListener(format, maxSize);
createDefaultImageReader(maxSize, format, 1, mListener);
checkImageReaderSessionConfiguration(
@@ -199,6 +198,7 @@ public class ZoomCaptureTest extends Camera2AndroidTestCase {
boolean checkActivePhysicalIdConsistency =
PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.S;
+ List<CaptureRequest> requests = new ArrayList<CaptureRequest>();
for (Float zoomRatio : candidateZoomRatios) {
if (VERBOSE) {
Log.v(TAG, "Testing format " + format + " zoomRatio " + zoomRatio +
@@ -206,38 +206,36 @@ public class ZoomCaptureTest extends Camera2AndroidTestCase {
}
requestBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomRatio);
- CaptureRequest request = requestBuilder.build();
+ requests.add(requestBuilder.build());
+ }
- SimpleCaptureCallback listener = new SimpleCaptureCallback();
- startCapture(request, false /*repeating*/, listener, mHandler);
+ SimpleCaptureCallback listener = new SimpleCaptureCallback();
+ int seqId = mCameraSession.captureBurst(requests, listener, mHandler);
- // Validate images.
- mListener.waitForAnyImageAvailable(CAPTURE_WAIT_TIMEOUT_MS);
- Image img = mReader.acquireNextImage();
- assertNotNull("Unable to acquire the latest image", img);
- CameraTestUtils.validateImage(img, maxSize.getWidth(), maxSize.getHeight(), format,
- mDebugFileNameBase);
- img.close();
+ // onCaptureSequenceCompleted() trails all capture results. Upon its return,
+ // we make sure we've received all results/errors.
+ listener.getCaptureSequenceLastFrameNumber(
+ seqId, CAPTURE_WAIT_TIMEOUT_MS * candidateZoomRatios.size());
+ while (listener.hasMoreResults() && mStaticInfo.isActivePhysicalCameraIdSupported()) {
// Validate capture result.
- if (mStaticInfo.isActivePhysicalCameraIdSupported()) {
- CaptureResult result = listener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
- String activePhysicalId = result.get(
- CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
- if (checkActivePhysicalIdConsistency) {
- assertNotNull("Camera " + mCamera.getId() +
- " result metadata must contain ACTIVE_PHYSICAL_ID",
- activePhysicalId);
- assertTrue("Camera " + mCamera.getId() + " must be logical " +
- "camera if activePhysicalId exists in capture result",
- physicalCameraIds != null && physicalCameraIds.size() != 0);
- mCollector.expectTrue("Camera " + mCamera.getId() + " activePhysicalId " +
- activePhysicalId + "must be among valid physical Ids " +
- physicalCameraIds.toString(),
- physicalCameraIds.contains(activePhysicalId));
-
- activePhysicalIdsSeen.add(activePhysicalId);
- }
+ TotalCaptureResult result = listener.getTotalCaptureResult(
+ CAPTURE_RESULT_TIMEOUT_MS);
+ String activePhysicalId = result.get(
+ CaptureResult.LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID);
+ if (checkActivePhysicalIdConsistency) {
+ assertNotNull("Camera " + mCamera.getId() +
+ " result metadata must contain ACTIVE_PHYSICAL_ID",
+ activePhysicalId);
+ assertTrue("Camera " + mCamera.getId() + " must be logical " +
+ "camera if activePhysicalId exists in capture result",
+ physicalCameraIds != null && physicalCameraIds.size() != 0);
+ mCollector.expectTrue("Camera " + mCamera.getId() + " activePhysicalId " +
+ activePhysicalId + "must be among valid physical Ids " +
+ physicalCameraIds.toString(),
+ physicalCameraIds.contains(activePhysicalId));
+
+ activePhysicalIdsSeen.add(activePhysicalId);
}
}
// stop capture.
@@ -254,18 +252,21 @@ public class ZoomCaptureTest extends Camera2AndroidTestCase {
}
private final class SimpleImageListener implements ImageReader.OnImageAvailableListener {
- private final ConditionVariable imageAvailable = new ConditionVariable();
- @Override
- public void onImageAvailable(ImageReader reader) {
- imageAvailable.open();
+ private final int mImageFormat;
+ private final Size mMaxSize;
+ public SimpleImageListener(int imageFormat, Size maxSize) {
+ mImageFormat = imageFormat;
+ mMaxSize = maxSize;
}
- public void waitForAnyImageAvailable(long timeout) {
- if (imageAvailable.block(timeout)) {
- imageAvailable.close();
- } else {
- fail("wait for image available timed out after " + timeout + "ms");
- }
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ Image img = mReader.acquireNextImage();
+ assertNotNull("Unable to acquire the latest image", img);
+ CameraTestUtils.validateImage(img, mMaxSize.getWidth(), mMaxSize.getHeight(),
+ mImageFormat, mDebugFileNameBase);
+ Log.e(TAG, "Image verification done");
+ img.close();
}
}
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index ecc87d692b6..1234e2a3cff 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -673,7 +673,7 @@ public class Camera2SurfaceViewTestCase extends Camera2ParameterizedTestCase {
* @param size The preview size to be updated.
*/
protected void updatePreviewSurface(Size size) {
- if (size.equals(mPreviewSize) && mPreviewSurface != null) {
+ if (size.equals(mPreviewSize) && mPreviewSurface != null && mPreviewSurface.isValid()) {
Log.w(TAG, "Skipping update preview surface size...");
return;
}
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index a6d4131dc6d..ff0b1ede465 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -1986,7 +1986,7 @@ public class CameraTest extends Assert {
}
@UiThreadTest
- @Test(timeout=60*60*1000) // timeout = 60 mins for long running tests
+ @Test(timeout=120*60*1000) // timeout = 120 mins for long running tests
public void testPreviewPictureSizesCombination() throws Exception {
for (int id : mCameraIds) {
Log.v(TAG, "Camera id=" + id);
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultDialerApplicationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultDialerApplicationTest.java
index 74f2c61bdbb..6e216158dc2 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultDialerApplicationTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultDialerApplicationTest.java
@@ -17,6 +17,8 @@
package android.devicepolicy.cts;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
+
import static com.android.queryable.queries.ActivityQuery.activity;
import static com.android.queryable.queries.IntentFilterQuery.intentFilter;
@@ -36,6 +38,7 @@ import android.telephony.TelephonyManager;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.RequireFeature;
import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
import com.android.bedstead.harrier.annotations.enterprise.PolicyDoesNotApplyTest;
import com.android.bedstead.harrier.policies.DefaultDialerApplication;
@@ -51,6 +54,8 @@ import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.runner.RunWith;
+import java.time.Duration;
+
@RunWith(BedsteadJUnit4.class)
public final class DefaultDialerApplicationTest {
@ClassRule
@@ -82,6 +87,7 @@ public final class DefaultDialerApplicationTest {
// TODO(b/198588696): Add support is @RequireVoiceCapable and @RequireNotVoiceCapable
@Postsubmit(reason = "new test")
@CanSetPolicyTest(policy = DefaultDialerApplication.class)
+ @RequireFeature(FEATURE_TELEPHONY)
public void setDefaultDialerApplication_works() {
assumeTrue(mTelephonyManager.isVoiceCapable()
|| (mRoleManager != null && mRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER)));
@@ -167,6 +173,6 @@ public final class DefaultDialerApplicationTest {
throw new IllegalStateException(
"Error setting default dialer application. Relevant logcat: " + logcat);
}
- }).runAndWrapException();
+ }).timeout(Duration.ofMinutes(2)).runAndWrapException();
}
}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java
index 4dfee59f22a..3841b98eca4 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java
@@ -55,6 +55,7 @@ import com.android.bedstead.testapp.TestAppInstance;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.runner.RunWith;
@@ -221,6 +222,7 @@ public final class DefaultSmsApplicationTest {
}
}
+ @Ignore("b/300397938")
@Postsubmit(reason = "new test")
// We don't include non device admin states as passing a null admin is a NullPointerException
@CannotSetPolicyTest(policy = {
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java
index 9f4b3b70b76..00d3da65572 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java
@@ -25,16 +25,15 @@ import static org.junit.Assert.assertThrows;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.util.Log;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.UserType;
import com.android.bedstead.harrier.annotations.EnsureHasAccount;
-import com.android.bedstead.harrier.annotations.EnsureHasAccountAuthenticator;
import com.android.bedstead.harrier.annotations.EnsureHasAdditionalUser;
import com.android.bedstead.harrier.annotations.EnsureHasNoAccounts;
import com.android.bedstead.harrier.annotations.EnsureHasPermission;
+import com.android.bedstead.harrier.annotations.FailureMode;
import com.android.bedstead.harrier.annotations.Postsubmit;
import com.android.bedstead.harrier.annotations.RequireNotHeadlessSystemUserMode;
import com.android.bedstead.harrier.annotations.RequireRunOnSystemUser;
@@ -42,7 +41,6 @@ import com.android.bedstead.harrier.annotations.UserTest;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDpc;
import com.android.bedstead.nene.TestApis;
-import com.android.bedstead.nene.accounts.AccountReference;
import com.android.bedstead.nene.devicepolicy.DeviceOwner;
import com.android.bedstead.nene.exceptions.AdbException;
import com.android.bedstead.nene.packages.ComponentReference;
@@ -155,7 +153,8 @@ public final class DeviceOwnerTest {
@EnsureHasAdditionalUser
@EnsureHasNoDpc
- @EnsureHasNoAccounts(onUser = UserType.ANY)
+ @EnsureHasNoAccounts(onUser = UserType.ANY, allowPreCreatedAccounts = false,
+ failureMode = FailureMode.SKIP)
@RequireNotHeadlessSystemUserMode(reason = "No non-testonly dpc which supports headless")
@Test
public void setDeviceOwnerViaAdb_noAccounts_notTestOnly_sets() throws Exception {
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/ManagedSubscriptionsPolicyTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/ManagedSubscriptionsPolicyTest.java
index 39c77b1ee3f..2ab65d0ca0d 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/ManagedSubscriptionsPolicyTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/ManagedSubscriptionsPolicyTest.java
@@ -18,11 +18,8 @@ package android.devicepolicy.cts;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
-
import static com.android.bedstead.harrier.UserType.WORK_PROFILE;
-
import static com.google.common.truth.Truth.assertThat;
-
import static org.testng.Assert.assertThrows;
import android.app.admin.DevicePolicyManager;
@@ -67,7 +64,6 @@ import java.util.List;
@RequireFeature(FEATURE_TELEPHONY)
@RunWith(BedsteadJUnit4.class)
-@Ignore // because work profile telephony is disabled for Android U
public final class ManagedSubscriptionsPolicyTest {
@ClassRule
@Rule
@@ -85,6 +81,7 @@ public final class ManagedSubscriptionsPolicyTest {
@PolicyAppliesTest(policy = ManagedSubscriptions.class)
@ApiTest(apis = {"android.app.admin.DevicePolicyManager#setManagedSubscriptionsPolicy"})
@Postsubmit(reason = "new test")
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setManagedSubscriptionsPolicy_works() {
try {
sDeviceState
@@ -133,6 +130,7 @@ public final class ManagedSubscriptionsPolicyTest {
@CannotSetPolicyTest(policy = ManagedSubscriptions.class)
@ApiTest(apis = {"android.app.admin.DevicePolicyManager#setManagedSubscriptionsPolicy"})
@Postsubmit(reason = "new test")
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setManagedSubscriptionsPolicy_invalidAdmin_fails() {
assertThrows(
SecurityException.class, () -> sDeviceState
@@ -151,6 +149,7 @@ public final class ManagedSubscriptionsPolicyTest {
@ApiTest(apis = {"android.app.admin.DevicePolicyManager#setManagedSubscriptionsPolicy"})
@Postsubmit(reason = "new test")
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setManagedSubscriptionsPolicy_policySet_oemDialerAndSmsAppInstalledInWorkProfile() {
try (RemoteDpc dpc = RemoteDpc.createWorkProfile()) {
ProfileOwner profileOwner = (ProfileOwner) dpc.devicePolicyController();
@@ -174,6 +173,7 @@ public final class ManagedSubscriptionsPolicyTest {
@ApiTest(apis = {"android.app.admin.DevicePolicyManager#setManagedSubscriptionsPolicy"})
@Postsubmit(reason = "new test")
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setManagedSubscriptionsPolicy_callAndSmsIntent_resolvesToWorkProfileApps()
throws InterruptedException {
sDeviceState.dpc().devicePolicyManager().setManagedSubscriptionsPolicy(
@@ -208,6 +208,7 @@ public final class ManagedSubscriptionsPolicyTest {
@CanSetPolicyTest(policy = ManagedSubscriptions.class)
@ApiTest(apis = {"android.app.admin.DevicePolicyManager#setManagedSubscriptionsPolicy"})
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setManagedSubscriptionsPolicy_notEnabledForNonDPMRoleHolders_throwsException()
throws InterruptedException {
assertThrows(
@@ -228,6 +229,7 @@ public final class ManagedSubscriptionsPolicyTest {
@EnsureHasWorkProfile(isOrganizationOwned = true)
@Postsubmit(reason = "new test")
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setManagedSubscriptionsPolicy_enabledForNonDMPRoleHolders_works()
throws InterruptedException {
try {
@@ -257,6 +259,7 @@ public final class ManagedSubscriptionsPolicyTest {
@EnsureHasDevicePolicyManagerRoleHolder
@ApiTest(apis = {"android.app.admin.DevicePolicyManager#setManagedSubscriptionsPolicy"})
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setManagedSubscriptionsPolicy_fromDPMRoleHolder_works()
throws InterruptedException {
ProfileOwner profileOwner = TestApis.devicePolicy().setProfileOwner(
@@ -285,6 +288,7 @@ public final class ManagedSubscriptionsPolicyTest {
@CanSetPolicyTest(policy = AllowWorkProfileTelephonyForNonDPMRH.class)
@Postsubmit(reason = "new test")
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setGlobalSetting_allowWorkProfileTelephonyForNonDMPRH_fromDPMRH_works() {
try {
sDeviceState.dpmRoleHolder().devicePolicyManager().setGlobalSetting(null,
@@ -304,6 +308,7 @@ public final class ManagedSubscriptionsPolicyTest {
Settings.Global.ALLOW_WORK_PROFILE_TELEPHONY_FOR_NON_DPM_ROLE_HOLDERS, value = "0")
@Postsubmit(reason = "new test")
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void setGlobalSetting_allowWorkProfileTelephonyForNonDMPRH_fromNonDPMRH_fails() {
assertThrows(SecurityException.class,
() -> sDeviceState.dpc().devicePolicyManager().setGlobalSetting(null,
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java
index b1de6181e86..4fe81680666 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java
@@ -1053,6 +1053,7 @@ public final class PermissionGrantTest {
Settings.Global.ALLOW_WORK_PROFILE_TELEPHONY_FOR_NON_DPM_ROLE_HOLDERS, value = "1")
@RequireRunOnWorkProfile(isOrganizationOwned = true)
@Test
+ @Ignore("b/300397938")
public void grantSmsPermission_orgOwnedDeviceWithManagedSubscriptionsPolicySet_granted() {
RemoteDevicePolicyManager devicePolicyManager = sDeviceState.profileOwner(
WORK_PROFILE).devicePolicyManager();
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/ProfileOwnerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/ProfileOwnerTest.java
index 0fb1b8a8b79..04c84d7f141 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/ProfileOwnerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/ProfileOwnerTest.java
@@ -27,11 +27,10 @@ import static org.junit.Assert.assertThrows;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.annotations.EnsureHasAccount;
-import com.android.bedstead.harrier.annotations.EnsureHasAccountAuthenticator;
import com.android.bedstead.harrier.annotations.EnsureHasNoAccounts;
+import com.android.bedstead.harrier.annotations.FailureMode;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDpc;
import com.android.bedstead.nene.TestApis;
-import com.android.bedstead.nene.accounts.AccountReference;
import com.android.bedstead.nene.devicepolicy.ProfileOwner;
import com.android.bedstead.nene.exceptions.AdbException;
import com.android.bedstead.nene.packages.ComponentReference;
@@ -103,7 +102,8 @@ public final class ProfileOwnerTest {
}
@EnsureHasNoDpc
- @EnsureHasNoAccounts(onUser = ANY)
+ @EnsureHasNoAccounts(onUser = ANY, allowPreCreatedAccounts = false,
+ failureMode = FailureMode.SKIP)
@Test
public void setProfileOwnerViaAdb_noAccounts_notTestOnly_sets() throws Exception {
try (TestAppInstance dpcApp = NOT_TEST_ONLY_DPC.install()) {
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/ScreenCaptureDisabledTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/ScreenCaptureDisabledTest.java
index 24e7ba61a90..0e9903ed980 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/ScreenCaptureDisabledTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/ScreenCaptureDisabledTest.java
@@ -38,6 +38,7 @@ import android.app.admin.DevicePolicyManager;
import android.app.admin.NoArgsPolicyKey;
import android.app.admin.PolicyState;
import android.app.admin.PolicyUpdateResult;
+import android.content.pm.PackageManager;
import android.devicepolicy.cts.utils.PolicyEngineUtils;
import android.devicepolicy.cts.utils.PolicySetResultUtils;
import android.graphics.Bitmap;
@@ -597,10 +598,16 @@ public final class ScreenCaptureDisabledTest {
screenshot.getPixels(pixels, 0, width, 0, height / 4, width, height / 2);
for (int pixel : pixels) {
- if (!(pixel == Color.BLACK)) {
+ if (!(pixel == Color.BLACK || (pixel == Color.TRANSPARENT && isAutomotive()))) {
return false;
}
}
return true;
}
+
+ private static boolean isAutomotive() {
+ return TestApis.context().instrumentedContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
}
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 0d39eb2bbe4..a69a56cfcd8 100644
--- a/tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java
+++ b/tests/devicepolicy/telephony/src/android/devicepolicy/cts/telephony/WorkProfileTelephonyTest.java
@@ -26,7 +26,6 @@ import static android.Manifest.permission.WRITE_CALL_LOG;
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.permissions.CommonPermissions.MODIFY_PHONE_STATE;
@@ -34,9 +33,7 @@ import static com.android.bedstead.nene.permissions.CommonPermissions.READ_PRIVI
import static com.android.eventlib.truth.EventLogsSubject.assertThat;
import static com.android.queryable.queries.ActivityQuery.activity;
import static com.android.queryable.queries.IntentFilterQuery.intentFilter;
-
import static com.google.common.truth.Truth.assertThat;
-
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
@@ -105,7 +102,6 @@ import java.util.concurrent.TimeoutException;
@RequireFeature(FEATURE_TELEPHONY)
@RunWith(BedsteadJUnit4.class)
-@Ignore // because work profile telephony is disabled for Android U
public final class WorkProfileTelephonyTest {
@ClassRule @Rule
@@ -162,6 +158,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-3-1"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void sendTextMessage_fromWorkProfile_allManagedSubscriptions_smsSentSuccessfully()
throws ExecutionException, InterruptedException, TimeoutException {
assumeSmsCapableDevice();
@@ -201,6 +198,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-1-1", "7.4.1.4/C-3-2"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void sendTextMessage_fromPersonalProfile_allManagedSubscriptions_errorUserNotAllowed()
throws ExecutionException, InterruptedException, TimeoutException {
assumeSmsCapableDevice();
@@ -263,6 +261,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-3-1"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void allManagedSubscriptions_accessWorkMessageFromPersonalProfile_fails() {
assumeSmsCapableDevice();
assertValidSimCardPresent();
@@ -308,6 +307,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-3-1"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void allManagedSubscriptions_accessWorkMessageFromWorkProfile_works()
throws ExecutionException, InterruptedException, TimeoutException {
assumeSmsCapableDevice();
@@ -357,6 +357,7 @@ public final class WorkProfileTelephonyTest {
@RequireRunOnWorkProfile(isOrganizationOwned = true)
@Postsubmit(reason = "new test")
@Test
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void placeCall_fromWorkProfile_allManagedSubscriptions_works() throws Exception {
assumeCallCapableDevice();
assertValidSimCardPresent();
@@ -394,6 +395,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-1-1", "7.4.1.4/C-3-2"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void placeCall_fromPersonalProfile_allManagedSubscriptions_fails() throws Exception {
assumeCallCapableDevice();
assertValidSimCardPresent();
@@ -428,6 +430,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-3-3"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void getCallCapablePhoneAccounts_fromWorkProfile_allManagedSubscriptions_notEmpty()
throws Exception {
assumeCallCapableDevice();
@@ -459,6 +462,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-3-3"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void getCallCapablePhoneAccounts_fromPersonalProfile_allManagedSubscriptions_emptyList()
throws Exception {
assumeCallCapableDevice();
@@ -490,6 +494,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-2-1"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void allManagedSubscriptions_accessWorkCallLogFromWorkProfile_works() throws Exception {
assumeCallCapableDevice();
assertValidSimCardPresent();
@@ -535,6 +540,7 @@ public final class WorkProfileTelephonyTest {
@Postsubmit(reason = "new test")
@Test
@CddTest(requirements = {"7.4.1.4/C-2-1"})
+ @Ignore("TODO(298915118): Enable after work telephony requirements are re-added")
public void allManagedSubscriptions_accessWorkCallLogFromPersonalProfile_fails()
throws Exception {
assumeCallCapableDevice();
diff --git a/tests/devicestate/src/android/hardware/devicestate/cts/DeviceStateManagerTests.java b/tests/devicestate/src/android/hardware/devicestate/cts/DeviceStateManagerTests.java
index 451b55258fc..9374dde2dec 100644
--- a/tests/devicestate/src/android/hardware/devicestate/cts/DeviceStateManagerTests.java
+++ b/tests/devicestate/src/android/hardware/devicestate/cts/DeviceStateManagerTests.java
@@ -352,9 +352,12 @@ public class DeviceStateManagerTests extends DeviceStateManagerTestBase {
DeviceStateTestActivity.class,
DEFAULT_DISPLAY
);
- // verify that the overridden state is still active after finishing
- // and launching the second activity.
- assertEquals(nextState, callback.mCurrentState);
+ // Assumes that the overridden state is still active after finishing
+ // and launching the second activity. This due to some states may be cancelled
+ // if they have the FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP flag on them.
+ // TODO(b/305107721): Update this call when we can verify we're moving to a state
+ // that does not have the FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP flag.
+ assumeTrue(nextState == callback.mCurrentState);
final DeviceStateTestActivity activity2 = secondActivitySession.getActivity();
activity2.cancelOverriddenState();
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index bbbbe587ea5..5d753350698 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -408,7 +408,6 @@ public class Components extends ComponentsBase {
/** Extra key constants for {@link android.server.wm.app.FontScaleActivity}. */
public static class FontScaleActivity {
- public static final String EXTRA_FONT_SCALE = "fontScale";
public static final String EXTRA_FONT_PIXEL_SIZE = "fontPixelSize";
public static final String EXTRA_FONT_ACTIVITY_DPI = "fontActivityDpi";
}
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/FontScaleActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/FontScaleActivity.java
index c0c04494ce4..1cf71017b9b 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/FontScaleActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/FontScaleActivity.java
@@ -18,7 +18,6 @@ package android.server.wm.app;
import static android.server.wm.app.Components.FontScaleActivity.EXTRA_FONT_ACTIVITY_DPI;
import static android.server.wm.app.Components.FontScaleActivity.EXTRA_FONT_PIXEL_SIZE;
-import static android.server.wm.app.Components.FontScaleActivity.EXTRA_FONT_SCALE;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -63,7 +62,6 @@ public class FontScaleActivity extends AbstractLifecycleLogActivity {
Log.i(getTag(), "fontPixelSize=" + fontPixelSize + ", fontScale=" + fontScale);
TestJournalProvider.putExtras(this, bundle -> {
bundle.putInt(EXTRA_FONT_PIXEL_SIZE, fontPixelSize);
- bundle.putFloat(EXTRA_FONT_SCALE, fontScale);
});
} finally {
ta.recycle();
diff --git a/tests/framework/base/windowmanager/jetpack/Android.bp b/tests/framework/base/windowmanager/jetpack/Android.bp
index 9056e792bb2..aac83e2512d 100644
--- a/tests/framework/base/windowmanager/jetpack/Android.bp
+++ b/tests/framework/base/windowmanager/jetpack/Android.bp
@@ -60,6 +60,7 @@ java_library {
"cts_window-extensions",
"cts_window-extensions-core",
"cts_window-sidecar",
+ "cts-wm-window-manager-helper",
],
sdk_version: "test_current",
}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SdkAvailabilityTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SdkAvailabilityTest.java
index 5a3914740a8..53e16b36833 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SdkAvailabilityTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/SdkAvailabilityTest.java
@@ -63,7 +63,6 @@ public class SdkAvailabilityTest extends WindowManagerJetpackTestBase {
@Override
public void setUp() {
super.setUp();
- assumeHasLargeScreenDisplayOrExtensionEnabled();
assumeMultiWindowSupported();
}
@@ -74,6 +73,7 @@ public class SdkAvailabilityTest extends WindowManagerJetpackTestBase {
*/
@Test
public void testWindowExtensionsAvailability() {
+ assumeHasLargeScreenDisplayOrExtensionEnabled();
assertTrue("WindowExtension version is not latest",
ExtensionUtil.isExtensionVersionLatest());
assertTrue("Device must declared that the WindowExtension is enabled",
@@ -86,6 +86,7 @@ public class SdkAvailabilityTest extends WindowManagerJetpackTestBase {
*/
@Test
public void testActivityEmbeddingAvailability() {
+ assumeHasLargeScreenDisplay();
WindowExtensions windowExtensions = ExtensionUtil.getWindowExtensions();
assertNotNull("WindowExtensions is not available", windowExtensions);
ActivityEmbeddingComponent activityEmbeddingComponent =
@@ -100,17 +101,28 @@ public class SdkAvailabilityTest extends WindowManagerJetpackTestBase {
*/
@Test
public void testSidecarAvailability() {
+ assumeHasLargeScreenDisplayOrExtensionEnabled();
assertTrue("Sidecar is not available", SidecarUtil.isSidecarVersionValid());
}
- private void assumeHasLargeScreenDisplayOrExtensionEnabled() {
+ private boolean hasLargeScreenDisplay() {
final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
- boolean hasLargeScreenDisplay = Arrays.stream(displayManager.getDisplays())
+ return Arrays.stream(displayManager.getDisplays())
.filter(display -> display.getType() == Display.TYPE_INTERNAL)
.anyMatch(this::isLargeScreenDisplay);
+ }
+
+ private void assumeHasLargeScreenDisplay() {
assumeTrue("Device does not has a minimum screen dimension greater than or equal to "
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP + "dp",
- hasLargeScreenDisplay || WindowManager.hasWindowExtensionsEnabled());
+ hasLargeScreenDisplay());
+ }
+
+ private void assumeHasLargeScreenDisplayOrExtensionEnabled() {
+ assumeTrue("Device does not has a minimum screen dimension greater than or equal to "
+ + WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP + "dp and window "
+ + "extensions are not enabled.",
+ hasLargeScreenDisplay() || WindowManager.hasWindowExtensionsEnabled());
}
private void assumeMultiWindowSupported() {
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/area/ExtensionRearDisplayPresentationTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/area/ExtensionRearDisplayPresentationTest.java
index b7a4478ddd5..5e8127b2e59 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/area/ExtensionRearDisplayPresentationTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/area/ExtensionRearDisplayPresentationTest.java
@@ -47,6 +47,7 @@ import android.os.PowerManager;
import android.platform.test.annotations.LargeTest;
import android.platform.test.annotations.Presubmit;
import android.server.wm.DeviceStateUtils;
+import android.server.wm.jetpack.utils.ExtensionUtil;
import android.server.wm.jetpack.utils.TestActivity;
import android.server.wm.jetpack.utils.TestActivityLauncher;
import android.server.wm.jetpack.utils.TestRearDisplayActivity;
@@ -211,16 +212,20 @@ public class ExtensionRearDisplayPresentationTest extends WindowManagerJetpackTe
mDeviceStateManager.requestState(request, null, null));
waitAndAssert(() -> mCurrentDeviceState == newState);
+
// If the state does not put the device into the rear display presentation state,
// and the state is not one where the device is folded, the status should be
// available.
- if (!containsValue(mFoldedDeviceStates, mCurrentDeviceState)
- && mCurrentDeviceState != mRearDisplayPresentationState) {
+ if (ExtensionUtil.getWindowExtensions().getVendorApiLevel() >= 4
+ && mCurrentDeviceState == mRearDisplayPresentationState) {
waitAndAssert(() -> mWindowAreaPresentationStatus.getWindowAreaStatus()
- == WindowAreaComponent.STATUS_AVAILABLE);
- } else {
+ == WindowAreaComponent.STATUS_ACTIVE);
+ } else if (containsValue(mFoldedDeviceStates, mCurrentDeviceState)) {
waitAndAssert(() -> mWindowAreaPresentationStatus.getWindowAreaStatus()
== WindowAreaComponent.STATUS_UNAVAILABLE);
+ } else {
+ waitAndAssert(() -> mWindowAreaPresentationStatus.getWindowAreaStatus()
+ == WindowAreaComponent.STATUS_AVAILABLE);
}
}
}
@@ -318,8 +323,8 @@ public class ExtensionRearDisplayPresentationTest extends WindowManagerJetpackTe
presentation.getPresentationContext());
mActivity.runOnUiThread(() -> presentation.setPresentationView(presentationView));
waitAndAssert(() -> presentationView.mAttachedToWindow);
+ waitAndAssert(() -> presentationView.getDisplay().getState() != Display.STATE_OFF);
assertNotEquals(presentationView.getDisplay().getDisplayId(), DEFAULT_DISPLAY);
- assertTrue(presentationView.getDisplay().getState() != Display.STATE_OFF);
assertEquals(mWindowAreaSessionState, SESSION_STATE_CONTENT_VISIBLE);
pressHomeButton();
@@ -453,8 +458,8 @@ public class ExtensionRearDisplayPresentationTest extends WindowManagerJetpackTe
// Currently when ending rear display presentation session, the display turns off. If this
// expectation ever changes, we will probably also need to update KeyguardPresentation in
// SystemUI to ensure that the secondary keyguard is shown.
- assertNotEquals(Display.STATE_ON,
- presentation.getPresentationContext().getDisplay().getState());
+ waitAndAssert(() -> Display.STATE_ON
+ != presentation.getPresentationContext().getDisplay().getState());
}
/**
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingBoundsTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingBoundsTests.java
index cecf1d0d0d4..86640af07f2 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingBoundsTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingBoundsTests.java
@@ -23,11 +23,9 @@ import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.assertValidS
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createSplitPairRuleBuilder;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplitAttributes;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertNotVisible;
-import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitForFillsTask;
+import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumedAndFillsTask;
import static android.server.wm.jetpack.utils.TestActivityLauncher.KEY_ACTIVITY_ID;
-import static org.junit.Assert.assertTrue;
-
import android.app.Activity;
import android.content.Intent;
import android.platform.test.annotations.Presubmit;
@@ -71,7 +69,7 @@ public class ActivityEmbeddingBoundsTests extends ActivityEmbeddingTestBase {
* Tests that when two activities are in a split and the parent bounds shrink such that
* they can no longer support split activities, then the activities become stacked.
*/
- @ApiTest(apis = "androidx.window.extensions.embedding.SplitRule")
+ @ApiTest(apis = {"androidx.window.extensions.embedding.SplitRule#checkParentMetrics"})
@Test
public void testParentWindowMetricsPredicate() {
// Launch primary activity
@@ -105,13 +103,12 @@ public class ActivityEmbeddingBoundsTests extends ActivityEmbeddingTestBase {
// Shrink the display by 10% to make the activities stacked
mReportedDisplayMetrics.setSize(new Size((int) (originalDisplaySize.getWidth() * 0.9),
(int) (originalDisplaySize.getHeight() * 0.9)));
- waitForFillsTask(secondaryActivity);
+ waitAndAssertResumedAndFillsTask(secondaryActivity);
waitAndAssertNotVisible(primaryActivity);
// Return the display to its original size and verify that the activities are split
- secondaryActivity.resetBoundsChangeCounter();
mReportedDisplayMetrics.setSize(originalDisplaySize);
- assertTrue(secondaryActivity.waitForBoundsChange());
+ mInstrumentation.waitForIdleSync();
assertValidSplit(primaryActivity, secondaryActivity, splitPairRule);
}
}
@@ -223,7 +220,7 @@ public class ActivityEmbeddingBoundsTests extends ActivityEmbeddingTestBase {
* top-most activity split.
*/
@ApiTest(apis = "androidx.window.extensions.embedding.SplitAttributes"
- + ".SplitType.RatioSplitType")
+ + ".SplitType.RatioSplitType#getRatio")
@Test
public void testSplitRatio() {
final String activityAId = "activityA";
@@ -272,7 +269,8 @@ public class ActivityEmbeddingBoundsTests extends ActivityEmbeddingTestBase {
assertValidSplit(activityA, activityB, splitPairRuleAB);
}
- @ApiTest(apis = "androidx.window.extensions.embedding.SplitAttributes.HingeSplitType")
+ @ApiTest(apis = "androidx.window.extensions.embedding.SplitAttributes.HingeSplitType"
+ + "#HingeSplitType")
@Test
public void testHingeSplitType() {
TestConfigChangeHandlingActivity primaryActivity = startFullScreenActivityNewTask(
@@ -293,8 +291,8 @@ public class ActivityEmbeddingBoundsTests extends ActivityEmbeddingTestBase {
}
/** Verifies {@link SplitAttributes.SplitType.ExpandContainersSplitType} behavior. */
- @ApiTest(apis = "androidx.window.extensions.embedding.SplitAttributes"
- + ".ExpandContainersSplitType")
+ @ApiTest(apis = {"androidx.window.extensions.embedding.SplitAttributes"
+ + ".ExpandContainersSplitType#ExpandContainersSplitType"})
@Test
public void testExpandSplitType() {
SplitPairRule splitPairRule = createSplitPairRuleBuilder(
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingFinishTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingFinishTests.java
index bcdb27f8603..b72de287ae9 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingFinishTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingFinishTests.java
@@ -21,15 +21,14 @@ import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.DEFAULT_SPLI
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createWildcardSplitPairRule;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifyNotSplit;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplitAttributes;
-import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.verifyFillsTask;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertFinishing;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumed;
+import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumedAndFillsTask;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ADJACENT;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.app.Activity;
@@ -41,6 +40,7 @@ import android.util.Pair;
import android.view.WindowMetrics;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.window.extensions.embedding.SplitInfo;
import androidx.window.extensions.embedding.SplitPairRule;
@@ -67,6 +67,7 @@ public class ActivityEmbeddingFinishTests extends ActivityEmbeddingTestBase {
* Tests that finishing the primary activity results in the secondary activity resizing to fill
* the task.
*/
+ @FlakyTest(bugId = 302112669)
@Test
public void testFinishPrimary() throws InterruptedException {
SplitPairRule splitPairRule = createWildcardSplitPairRule();
@@ -81,9 +82,7 @@ public class ActivityEmbeddingFinishTests extends ActivityEmbeddingTestBase {
// Finishing the primary activity should cause the secondary activity to resize to fill the
// task.
primaryActivity.finish();
- assertTrue(secondaryActivity.waitForBoundsChange());
- assertEquals(getMaximumActivityBounds(secondaryActivity),
- getActivityBounds(secondaryActivity));
+ waitAndAssertResumedAndFillsTask(secondaryActivity);
// Verify that there are no split states
List<SplitInfo> splitInfoList = mSplitInfoConsumer.waitAndGet();
@@ -94,6 +93,7 @@ public class ActivityEmbeddingFinishTests extends ActivityEmbeddingTestBase {
* Tests that finishing the secondary activity results in the primary activity resizing to fill
* the task.
*/
+ @FlakyTest(bugId = 302192873)
@Test
public void testFinishSecondary() throws InterruptedException {
SplitPairRule splitPairRule = createWildcardSplitPairRule();
@@ -105,16 +105,10 @@ public class ActivityEmbeddingFinishTests extends ActivityEmbeddingTestBase {
primaryActivity, TestActivityWithId.class, splitPairRule, "secondaryActivity",
mSplitInfoConsumer);
- // Need to reset primary activity bounds change counter because entering the split already
- // triggered a bounds change.
- primaryActivity.resetBoundsChangeCounter();
-
// Finishing the secondary activity should cause the primary activity to resize to fill the
// task.
secondaryActivity.finish();
- assertTrue(primaryActivity.waitForBoundsChange());
- assertEquals(getMaximumActivityBounds(primaryActivity),
- getActivityBounds(primaryActivity));
+ waitAndAssertResumedAndFillsTask(primaryActivity);
// Verify that there are no split states
List<SplitInfo> splitInfoList = mSplitInfoConsumer.waitAndGet();
@@ -179,10 +173,8 @@ public class ActivityEmbeddingFinishTests extends ActivityEmbeddingTestBase {
Pair<TestActivity, TestActivity> activityPair = new PairedFinishBehaviorScenario()
.setFinishPrimaryWithSecondary(FINISH_NEVER).start();
// Verify the paired finish behavior
- activityPair.first.resetBoundsChangeCounter();
activityPair.second.finish();
- assertTrue(activityPair.first.waitForBoundsChange());
- verifyFillsTask(activityPair.first);
+ waitAndAssertResumedAndFillsTask(activityPair.first);
}
/**
@@ -274,10 +266,8 @@ public class ActivityEmbeddingFinishTests extends ActivityEmbeddingTestBase {
Pair<TestActivity, TestActivity> activityPair = new PairedFinishBehaviorScenario()
.setFinishSecondaryWithPrimary(FINISH_NEVER).start();
// Verify the paired finish behavior
- activityPair.second.resetBoundsChangeCounter();
activityPair.first.finish();
- assertTrue(activityPair.second.waitForBoundsChange());
- verifyFillsTask(activityPair.second);
+ waitAndAssertResumedAndFillsTask(activityPair.second);
}
/**
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingIntegrationTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingIntegrationTests.java
index 51d9910f8dd..2973fac944a 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingIntegrationTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingIntegrationTests.java
@@ -22,6 +22,7 @@ import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createSplitP
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifyNoCallback;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplitAttributes;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumed;
+import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumedAndFillsTask;
import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
import static android.server.wm.jetpack.utils.ExtensionUtil.assumeHasDisplayFeatures;
import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionWindowLayoutComponent;
@@ -60,7 +61,8 @@ import java.util.Collections;
* Build/Install/Run:
* atest CtsWindowManagerJetpackTestCases:ActivityEmbeddingIntegrationTests
*/
-@ApiTest(apis = {"androidx.window.extensions.embedding.SplitPairRule",
+@ApiTest(apis = {"androidx.window.extensions.embedding.SplitPairRule#checkParentMetrics",
+ "androidx.window.extensions.embedding.SplitPairRule#getDefaultSplitAttributes",
"androidx.window.extensions.layout.WindowLayoutComponent#addWindowLayoutInfoListener"})
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -108,16 +110,10 @@ public class ActivityEmbeddingIntegrationTests extends ActivityEmbeddingTestBase
assertEquals(windowLayoutInfo.getDisplayFeatures().size(),
newWindowLayoutInfo.getDisplayFeatures().size());
- // Need to reset primary activity bounds change counter because entering the split already
- // triggered a bounds change.
- primaryActivity.resetBoundsChangeCounter();
-
// Finish the secondary activity and verify that the primary activity still receives the
// display features
secondaryActivity.finish();
- assertTrue(primaryActivity.waitForBoundsChange());
- assertEquals(getMaximumActivityBounds(primaryActivity),
- getActivityBounds(primaryActivity));
+ waitAndAssertResumedAndFillsTask(primaryActivity);
newWindowLayoutInfo = getExtensionWindowLayoutInfo(primaryActivity);
assertEquals(windowLayoutInfo.getDisplayFeatures().size(),
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingLaunchTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingLaunchTests.java
index ec6de8b0f14..5dec077a3d4 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingLaunchTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityEmbeddingLaunchTests.java
@@ -37,7 +37,6 @@ import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
import android.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.FlakyTest;
import androidx.window.extensions.embedding.ActivityRule;
import androidx.window.extensions.embedding.SplitInfo;
import androidx.window.extensions.embedding.SplitPairRule;
@@ -266,12 +265,10 @@ public class ActivityEmbeddingLaunchTests extends ActivityEmbeddingTestBase {
alwaysExpandedActivityId);
// Verify that the always expanded activity is resumed and fills its parent
- waitAndAssertResumed(alwaysExpandedActivityId);
- Activity alwaysExpandedActivity = getResumedActivityById(alwaysExpandedActivityId);
- assertEquals(getMaximumActivityBounds(alwaysExpandedActivity),
- getActivityBounds(alwaysExpandedActivity));
+ ActivityEmbeddingUtil.waitAndAssertResumedAndFillsTask(alwaysExpandedActivityId);
// Finish the always expanded activity and verify that the split is resumed
+ final Activity alwaysExpandedActivity = getResumedActivityById(alwaysExpandedActivityId);
alwaysExpandedActivity.finish();
waitAndAssertResumed(Arrays.asList(primaryActivity, secondaryActivity));
assertValidSplit(primaryActivity, secondaryActivity, splitPairRule);
@@ -310,12 +307,10 @@ public class ActivityEmbeddingLaunchTests extends ActivityEmbeddingTestBase {
alwaysExpandedActivityId);
// Verify that the always expanded activity is resumed and fills its parent
- waitAndAssertResumed(alwaysExpandedActivityId);
- Activity alwaysExpandedActivity = getResumedActivityById(alwaysExpandedActivityId);
- assertEquals(getMaximumActivityBounds(alwaysExpandedActivity),
- getActivityBounds(alwaysExpandedActivity));
+ ActivityEmbeddingUtil.waitAndAssertResumedAndFillsTask(alwaysExpandedActivityId);
// Finish the always expanded activity and verify that the split is resumed
+ final Activity alwaysExpandedActivity = getResumedActivityById(alwaysExpandedActivityId);
alwaysExpandedActivity.finish();
waitAndAssertResumed(Arrays.asList(primaryActivity, secondaryActivity));
assertValidSplit(primaryActivity, secondaryActivity, splitPairRule);
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 96915507a7a..ca3b25ce1b6 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
@@ -18,17 +18,15 @@ package android.server.wm.jetpack.embedding;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.DEFAULT_SPLIT_ATTRS;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.assertValidSplit;
-import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.verifyFillsTask;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertFinishing;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertNotResumed;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumed;
+import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumedAndFillsTask;
import static android.server.wm.jetpack.utils.TestActivityLauncher.KEY_ACTIVITY_ID;
import static android.view.Surface.ROTATION_0;
import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
-import static org.junit.Assert.assertTrue;
-
import android.app.Activity;
import android.content.Intent;
import android.platform.test.annotations.Presubmit;
@@ -112,7 +110,7 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
Activity primaryActivity = startFullScreenActivityNewTask(TestActivityWithId.class,
PRIMARY_ACTIVITY_ID);
waitAndAssertNotResumed(PLACEHOLDER_ACTIVITY_ID);
- verifyFillsTask(primaryActivity);
+ waitAndAssertResumedAndFillsTask(primaryActivity);
}
/**
@@ -163,10 +161,8 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
// Finish the placeholder activity and verify that the primary activity does not finish
// and fills the task.
- primaryActivity.resetBoundsChangeCounter();
placeholderActivity.finish();
- assertTrue(primaryActivity.waitForBoundsChange());
- verifyFillsTask(primaryActivity);
+ waitAndAssertResumedAndFillsTask(primaryActivity);
}
/**
@@ -200,7 +196,6 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
final Activity placeholderActivity = activityPair.second;
// Shrink display size by 10% so that the primary and placeholder activities are stacked
- primaryActivity.resetBoundsChangeCounter();
final Size currentSize = mReportedDisplayMetrics.getSize();
mReportedDisplayMetrics.setSize(new Size((int) (currentSize.getWidth() * 0.9),
(int) (currentSize.getHeight() * 0.9)));
@@ -208,8 +203,7 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
// Verify that the placeholder activity was finished and that the primary activity now
// fills the task.
waitAndAssertFinishing(placeholderActivity);
- assertTrue(primaryActivity.waitForBoundsChange());
- verifyFillsTask(primaryActivity);
+ waitAndAssertResumedAndFillsTask(primaryActivity);
}
}
@@ -249,7 +243,7 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
// not launched
Activity primaryActivity = startFullScreenActivityNewTask(TestActivityWithId.class,
PRIMARY_ACTIVITY_ID);
- verifyFillsTask(primaryActivity);
+ waitAndAssertResumedAndFillsTask(primaryActivity);
waitAndAssertNotResumed(PLACEHOLDER_ACTIVITY_ID);
// Increase display size by 10% so that the primary and placeholder activities are
@@ -297,14 +291,12 @@ public class ActivityEmbeddingPlaceholderTests extends ActivityEmbeddingTestBase
// Shrink display width by 10% so that the primary and placeholder activities are
// stacked
- placeholderActivity.resetBoundsChangeCounter();
final Size currentSize = mReportedDisplayMetrics.getSize();
mReportedDisplayMetrics.setSize(new Size((int) (currentSize.getWidth() * 0.9),
(int) (currentSize.getHeight() * 0.9)));
// Verify that the placeholder was not finished and fills the task
- assertTrue(placeholderActivity.waitForBoundsChange());
- verifyFillsTask(placeholderActivity);
+ waitAndAssertResumedAndFillsTask(placeholderActivity);
waitAndAssertResumed(Arrays.asList(placeholderActivity));
}
}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityStackApisTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityStackApisTests.java
index f8906ab89c3..22f0f4b8538 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityStackApisTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/embedding/ActivityStackApisTests.java
@@ -22,7 +22,7 @@ import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createSplitP
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createWildcardSplitPairRule;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplitAttributes;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertFinishing;
-import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitForFillsTask;
+import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertResumedAndFillsTask;
import static android.server.wm.jetpack.utils.TestActivityLauncher.KEY_ACTIVITY_ID;
import static org.junit.Assert.assertEquals;
@@ -75,7 +75,7 @@ public class ActivityStackApisTests extends ActivityEmbeddingTestBase {
splitInfo.getPrimaryActivityStack().getToken()));
waitAndAssertFinishing(primaryActivity);
- waitForFillsTask(secondaryActivity);
+ waitAndAssertResumedAndFillsTask(secondaryActivity);
List<SplitInfo> splitInfoList = mSplitInfoConsumer.waitAndGet();
assertTrue(splitInfoList.isEmpty());
@@ -99,7 +99,7 @@ public class ActivityStackApisTests extends ActivityEmbeddingTestBase {
splitInfo.getSecondaryActivityStack().getToken()));
waitAndAssertFinishing(secondaryActivity);
- waitForFillsTask(primaryActivity);
+ waitAndAssertResumedAndFillsTask(primaryActivity);
List<SplitInfo> splitInfoList = mSplitInfoConsumer.waitAndGet();
assertTrue(splitInfoList.isEmpty());
@@ -170,7 +170,7 @@ public class ActivityStackApisTests extends ActivityEmbeddingTestBase {
waitAndAssertFinishing(activityB);
waitAndAssertFinishing(activityC);
- waitForFillsTask(activityA);
+ waitAndAssertResumedAndFillsTask(activityA);
List<SplitInfo> splitInfoList = mSplitInfoConsumer.waitAndGet();
assertTrue(splitInfoList.isEmpty());
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
index 93f226965a1..1db3e89137d 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
@@ -16,13 +16,13 @@
package android.server.wm.jetpack.utils;
+import static android.server.wm.WindowManagerState.STATE_RESUMED;
import static android.server.wm.jetpack.utils.ExtensionUtil.EXTENSION_VERSION_2;
import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionWindowLayoutInfo;
import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
import static android.server.wm.jetpack.utils.ExtensionUtil.isExtensionVersionAtLeast;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityBounds;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getMaximumActivityBounds;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getResumedActivityById;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.isActivityResumed;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.startActivityFromActivity;
@@ -39,6 +39,7 @@ import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
+import android.server.wm.WindowManagerStateHelper;
import android.util.Log;
import android.util.Pair;
import android.view.WindowMetrics;
@@ -151,7 +152,7 @@ public class ActivityEmbeddingUtil {
assertFalse(isActivityResumed(activityLaunchingFrom));
TestActivity secondActivity = getResumedActivityById(secondActivityId);
// Verify the second activity is not split with the first
- verifyFillsTask(secondActivity);
+ waitAndAssertResumedAndFillsTask(secondActivity);
return secondActivity;
}
@@ -367,13 +368,37 @@ public class ActivityEmbeddingUtil {
}
}
- public static void verifyFillsTask(Activity activity) {
- assertEquals(getMaximumActivityBounds(activity), getActivityBounds(activity));
+ /**
+ * Waits for the activity specified in {@code activityId} to be in resumed state and verifies
+ * if it fills the task.
+ */
+ public static void waitAndAssertResumedAndFillsTask(@NonNull String activityId) {
+ waitAndAssertResumed(activityId);
+ final Activity activity = getResumedActivityById(activityId);
+ final Rect taskBounds = getTaskBounds(activity, false /* shouldWaitForResume */);
+ PollingCheck.waitFor(WAIT_FOR_LIFECYCLE_TIMEOUT_MS, () ->
+ getActivityBounds(activity).equals(taskBounds));
+ assertEquals(taskBounds, getActivityBounds(activity));
}
- public static void waitForFillsTask(Activity activity) {
+ /** Waits for the {@code activity} to be in resumed state and verifies if it fills the task. */
+ public static void waitAndAssertResumedAndFillsTask(@NonNull Activity activity) {
+ final Rect taskBounds = getTaskBounds(activity, true /* shouldWaitForResume */);
PollingCheck.waitFor(WAIT_FOR_LIFECYCLE_TIMEOUT_MS, () ->
- getActivityBounds(activity).equals(getMaximumActivityBounds(activity)));
+ getActivityBounds(activity).equals(taskBounds));
+ assertEquals(taskBounds, getActivityBounds(activity));
+ }
+
+ @NonNull
+ private static Rect getTaskBounds(@NonNull Activity activity, boolean shouldWaitForResume) {
+ final WindowManagerStateHelper wmState = new WindowManagerStateHelper();
+ final ComponentName activityName = activity.getComponentName();
+ if (shouldWaitForResume) {
+ wmState.waitAndAssertActivityState(activityName, STATE_RESUMED);
+ } else {
+ wmState.waitForValidState(activityName);
+ }
+ return wmState.getTaskByActivity(activityName).getBounds();
}
private static void waitForActivityBoundsEquals(@NonNull Activity activity,
@@ -492,9 +517,10 @@ public class ActivityEmbeddingUtil {
@NonNull SplitAttributes splitAttributes) {
SplitType splitType = splitAttributes.getSplitType();
- final Rect parentBounds = getMaximumActivityBounds(primaryActivity);
+ final Rect parentTaskBounds = getTaskBounds(primaryActivity,
+ false /* shouldWaitForResume */);
if (splitType instanceof SplitType.ExpandContainersSplitType) {
- return new Pair<>(new Rect(parentBounds), new Rect(parentBounds));
+ return new Pair<>(new Rect(parentTaskBounds), new Rect(parentTaskBounds));
}
int layoutDir = (splitAttributes.getLayoutDirection() == LayoutDirection.LOCALE)
@@ -513,14 +539,14 @@ public class ActivityEmbeddingUtil {
// The split pair should be split by hinge if there's exactly one hinge
// at the current device state.
final Rect hingeArea = foldingFeature.getBounds();
- final Rect leftContainer = new Rect(parentBounds.left, parentBounds.top,
- hingeArea.left, parentBounds.bottom);
- final Rect topContainer = new Rect(parentBounds.left, parentBounds.top,
- parentBounds.right, hingeArea.top);
- final Rect rightContainer = new Rect(hingeArea.right, parentBounds.top,
- parentBounds.right, parentBounds.bottom);
- final Rect bottomContainer = new Rect(parentBounds.left, hingeArea.bottom,
- parentBounds.right, parentBounds.bottom);
+ final Rect leftContainer = new Rect(parentTaskBounds.left, parentTaskBounds.top,
+ hingeArea.left, parentTaskBounds.bottom);
+ final Rect topContainer = new Rect(parentTaskBounds.left, parentTaskBounds.top,
+ parentTaskBounds.right, hingeArea.top);
+ final Rect rightContainer = new Rect(hingeArea.right, parentTaskBounds.top,
+ parentTaskBounds.right, parentTaskBounds.bottom);
+ final Rect bottomContainer = new Rect(parentTaskBounds.left, hingeArea.bottom,
+ parentTaskBounds.right, parentTaskBounds.bottom);
switch (layoutDir) {
case LayoutDirection.LEFT_TO_RIGHT: {
return new Pair<>(leftContainer, rightContainer);
@@ -557,27 +583,27 @@ public class ActivityEmbeddingUtil {
final boolean isHorizontal = isHorizontal(layoutDir);
final Rect leftOrTopContainerBounds = isHorizontal
? new Rect(
- parentBounds.left,
- parentBounds.top,
- parentBounds.right,
- (int) (parentBounds.top + parentBounds.height() * splitRatio)
+ parentTaskBounds.left,
+ parentTaskBounds.top,
+ parentTaskBounds.right,
+ (int) (parentTaskBounds.top + parentTaskBounds.height() * splitRatio)
) : new Rect(
- parentBounds.left,
- parentBounds.top,
- (int) (parentBounds.left + parentBounds.width() * splitRatio),
- parentBounds.bottom);
+ parentTaskBounds.left,
+ parentTaskBounds.top,
+ (int) (parentTaskBounds.left + parentTaskBounds.width() * splitRatio),
+ parentTaskBounds.bottom);
final Rect rightOrBottomContainerBounds = isHorizontal
? new Rect(
- parentBounds.left,
- (int) (parentBounds.top + parentBounds.height() * splitRatio),
- parentBounds.right,
- parentBounds.bottom
+ parentTaskBounds.left,
+ (int) (parentTaskBounds.top + parentTaskBounds.height() * splitRatio),
+ parentTaskBounds.right,
+ parentTaskBounds.bottom
) : new Rect(
- (int) (parentBounds.left + parentBounds.width() * splitRatio),
- parentBounds.top,
- parentBounds.right,
- parentBounds.bottom);
+ (int) (parentTaskBounds.left + parentTaskBounds.width() * splitRatio),
+ parentTaskBounds.top,
+ parentTaskBounds.right,
+ parentTaskBounds.bottom);
// Assign the primary and secondary bounds depending on layout direction
if (isPrimaryRightOrBottomContainer) {
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java
index 948f6a4b6ff..e515baed57c 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java
@@ -16,12 +16,7 @@
package android.server.wm.jetpack.utils;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityBounds;
-
import android.app.Activity;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;
@@ -35,34 +30,17 @@ import java.util.concurrent.TimeUnit;
* androidx.window.TestActivity.
*/
public class TestActivity extends Activity implements View.OnLayoutChangeListener {
-
- private int mRootViewId;
private CountDownLatch mLayoutLatch;
- private CountDownLatch mBoundsChangeLatch;
- private final Rect mPreviousBounds = new Rect();
private static CountDownLatch sResumeLatch = new CountDownLatch(1);
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final View contentView = new TestContentViewForConfigurationChange(this);
- mRootViewId = View.generateViewId();
- contentView.setId(mRootViewId);
- setContentView(contentView);
resetLayoutCounter();
- resetBoundsChangeCounter();
getWindow().getDecorView().addOnLayoutChangeListener(this);
}
- int getWidth() {
- return findViewById(mRootViewId).getWidth();
- }
-
- int getHeight() {
- return findViewById(mRootViewId).getHeight();
- }
-
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
@@ -84,15 +62,6 @@ public class TestActivity extends Activity implements View.OnLayoutChangeListene
}
/**
- * Resets bounds change counter when waiting for a bounds change to happen before calling
- * {@link #waitForBoundsChange()}.
- */
- public void resetBoundsChangeCounter() {
- mPreviousBounds.set(getActivityBounds(this));
- mBoundsChangeLatch = new CountDownLatch(1);
- }
-
- /**
* Blocks and waits for the next layout to happen. {@link #resetLayoutCounter()} must be called
* before calling this method.
* @return {@code true} if the layout happened before the timeout count reached zero and
@@ -107,20 +76,6 @@ public class TestActivity extends Activity implements View.OnLayoutChangeListene
}
/**
- * Blocks and waits for the next bounds change to happen. {@link #resetBoundsChangeCounter()}
- * must be called before calling this method.
- * @return {@code true} if the bounds change happened before the timeout count reached zero and
- * {@code false} if the waiting time elapsed before the bounds change happened.
- */
- public boolean waitForBoundsChange() {
- try {
- return mBoundsChangeLatch.await(3, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- return false;
- }
- }
-
- /**
* Resets layout counter when waiting for a layout to happen before calling
* {@link #waitForOnResume()}.
*/
@@ -141,24 +96,4 @@ public class TestActivity extends Activity implements View.OnLayoutChangeListene
return false;
}
}
-
- /**
- * Sometimes activity configuration change does not trigger when embedding status change, need
- * to use View's instead.
- */
- class TestContentViewForConfigurationChange extends View {
- public TestContentViewForConfigurationChange(Context context) {
- super(context);
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- final Rect newActivityBounds = getActivityBounds(TestActivity.this);
- if (!newActivityBounds.equals(mPreviousBounds)) {
- mPreviousBounds.set(newActivityBounds);
- mBoundsChangeLatch.countDown();
- }
- }
- }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java
index ed432dcac9f..6b2aa2397ab 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java
@@ -311,17 +311,14 @@ public class ActivityMetricsLoggerTests extends ActivityManagerTestBase {
final String startTestActivityCmd = "am start -W " + TEST_ACTIVITY.flattenToShortString();
SystemUtil.runShellCommand(startTestActivityCmd);
- mWmState.computeState();
- // On multiple screen devices, tasks may be launched in different task display areas. Make
- // sure the tasks will be launched in the same TDA.
- int targetDisplayAreaId = mWmState.getTaskDisplayAreaFeatureId(TEST_ACTIVITY);
-
- launchAndWaitForActivity(SECOND_ACTIVITY, targetDisplayAreaId);
- separateTestJournal();
+ launchHomeActivityNoWait();
+ waitAndAssertActivityState(TEST_ACTIVITY, STATE_STOPPED, "Activity should be stopped");
+ final float originalFontScale = mContext.getResources().getConfiguration().fontScale;
final FontScaleSession fontScaleSession = createManagedFontScaleSession();
fontScaleSession.set(fontScaleSession.get() + 0.1f);
- assertActivityLifecycle(SECOND_ACTIVITY, true /* relaunched */);
+ Condition.waitFor("font scale changed", () ->
+ originalFontScale != mContext.getResources().getConfiguration().fontScale);
// Move the task of test activity to front.
final String amStartOutput = SystemUtil.runShellCommand(startTestActivityCmd);
@@ -460,22 +457,12 @@ public class ActivityMetricsLoggerTests extends ActivityManagerTestBase {
}
private void launchAndWaitForActivity(ComponentName activity) {
- getLaunchActivityBuilder(activity)
- .execute();
- }
-
- private void launchAndWaitForActivity(ComponentName activity, int targetDisplayAreaId) {
- getLaunchActivityBuilder(activity)
- .setLaunchTaskDisplayAreaFeatureId(targetDisplayAreaId)
- .execute();
- }
-
- private LaunchActivityBuilder getLaunchActivityBuilder(ComponentName activity) {
- return getLaunchActivityBuilder()
+ getLaunchActivityBuilder()
.setUseInstrumentation()
.setTargetActivity(activity)
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
- .setWaitForLaunched(true);
+ .setWaitForLaunched(true)
+ .execute();
}
@NonNull
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
index e608b6c5e05..1bc31c11a35 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
@@ -19,6 +19,7 @@ package android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.server.wm.CliIntentExtra.extraString;
@@ -91,8 +92,13 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
launchHomeActivity();
launchActivity(TRANSLUCENT_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
+ int expectedWindowingMode = hasAutomotiveSplitscreenMultitaskingFeature()
+ // On auto devices with this feature enabled, the system is in a permanent
+ // split-screen UI where every app opens in MULTI_WINDOW mode.
+ ? WINDOWING_MODE_MULTI_WINDOW
+ : WINDOWING_MODE_FULLSCREEN;
mWmState.assertFrontStack("Fullscreen stack must be the front stack.",
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
mWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
mWmState.assertHomeActivityVisible(true);
}
@@ -726,6 +732,8 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
lockScreenSession.sleepDevice();
separateTestJournal();
launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
+ // wait for the UI to be stable.
+ mInstrumentation.getUiAutomation().syncInputTransactions();
mWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
assertSingleLaunch(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
@@ -737,12 +745,21 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
"Activity should be stopped");
separateTestJournal();
launchActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
+ mInstrumentation.getUiAutomation().syncInputTransactions();
mWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
// Wait more for display state change since turning the display ON may take longer
// and reported after the activity launch.
waitForDefaultDisplayState(true /* wantOn */);
assertTrue("Display turns on", isDisplayOn(DEFAULT_DISPLAY));
- assertSingleStart(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
+ if (hasAutomotiveSplitscreenMultitaskingFeature()) {
+ // In the scenario when the Launcher HOME activity hosts the TaskView, the HOME activity
+ // itself will be resumed first before the Test activity resulting in 2 calls to
+ // ON_RESUME rather than 1. Is such case just check if the Test activity is resumed.
+ // TODO(b/300009006): assertSingleStart when fixed.
+ waitAndAssertResumedActivity(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
+ } else {
+ assertSingleStart(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY);
+ }
}
@Test
@@ -838,4 +855,13 @@ public class ActivityVisibilityTests extends ActivityManagerTestBase {
mWmState.waitForWindowSurfaceShown(getWindowName(activityBehind), visible);
mWmState.assertVisibility(activityBehind, visible);
}
+
+ /**
+ * Checks whether the device has automotive split-screen multitasking feature enabled
+ */
+ private boolean hasAutomotiveSplitscreenMultitaskingFeature() {
+ return mContext.getPackageManager()
+ .hasSystemFeature(/* PackageManager.FEATURE_CAR_SPLITSCREEN_MULTITASKING */
+ "android.software.car.splitscreen_multitasking") && isCar();
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index 2396f4bc59d..22141a71efc 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -904,10 +904,18 @@ public class AppConfigurationTests extends MultiDisplayTestBase {
assumeTrue("Skipping test: no rotation support", supportsRotation());
assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
- // Launch activities in split screen.
- launchActivitiesInSplitScreen(
- getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
- getLaunchActivityBuilder().setTargetActivity(activity));
+ // Launch activity and move it to primary split-screen.
+ launchActivityInPrimarySplit(LAUNCHING_ACTIVITY);
+
+ // Launch target activity in secondary split-screen.
+ mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
+ getLaunchActivityBuilder()
+ .setTargetActivity(activity)
+ .setUseInstrumentation()
+ .setWaitForLaunched(true)
+ .setNewTask(true)
+ .setMultipleTask(true)
+ .execute();
mWmState.assertVisibility(activity, true /* visible */);
// Rotate the device and it should always rotate regardless orientation app requested.
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 104c07a1978..e13157c23d1 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BackGestureInvokedTest.java
@@ -77,13 +77,17 @@ public class BackGestureInvokedTest extends ActivityManagerTestBase {
@Test
public void popupWindowDismissedOnBackGesture() {
mActivitySession.runOnMainSyncAndWait(mActivity::addPopupWindow);
- mWmState.waitAndAssertWindowShown(TYPE_APPLICATION_PANEL, true);
+ final int taskId = mWmState.getTaskByActivity(mActivity.getComponentName()).getTaskId();
+ assertTrue("Popup window must show", mWmState.waitFor(state ->
+ mWmState.getMatchingWindows(ws -> ws.getType() == TYPE_APPLICATION_PANEL
+ && ws.getStackId() == taskId && ws.isSurfaceShown())
+ .findAny().isPresent(), "popup window show"));
triggerBackEventByGesture(DEFAULT_DISPLAY);
- assertTrue("Popup window must be removed",
- mWmState.waitForWithAmState(
- state -> state.getMatchingWindowType(TYPE_APPLICATION_PANEL).isEmpty(),
- "popup window to dismiss"));
+ assertTrue("Popup window must be removed", mWmState.waitFor(state ->
+ mWmState.getMatchingWindows(ws -> ws.getType() == TYPE_APPLICATION_PANEL
+ && ws.getStackId() == taskId).findAny().isEmpty(),
+ "popup window removed"));
// activity remain focused
mWmState.assertFocusedActivity("Top activity must be focused",
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
index da85c3214a2..71b82ae1272 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java
@@ -54,7 +54,6 @@ import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.mockito.Mockito;
-import java.util.Optional;
import java.util.function.Consumer;
@Presubmit
@@ -95,12 +94,8 @@ public class BlurTests extends WindowManagerTestBase {
WindowManagerState.WindowState windowState = mWmState.getWindowState(cn);
WindowManagerState.Activity act = mWmState.getActivity(cn);
mBackgroundActivityBounds = act.getBounds();
- Optional<WindowManagerState.InsetsSource> captionInsetsOptional =
- windowState.getMergedLocalInsetsSources().stream().filter(
- insets -> insets.isCaptionBar()).findFirst();
- captionInsetsOptional.ifPresent(captionInsets -> {
- captionInsets.insetGivenFrame(mBackgroundActivityBounds);
- });
+ insetGivenFrame(windowState, WindowManagerState.InsetsSource::isCaptionBar,
+ mBackgroundActivityBounds);
// Wait for the first frame *after* the splash screen is removed to take screenshots.
// We don't currently have a definite event / callback for this.
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index b94e0d35f72..cfbdeef61f7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -88,6 +88,7 @@ import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
@@ -335,6 +336,7 @@ public final class CompatChangeTests extends MultiDisplayTestBase {
}
@Test
+ @Ignore("b/295873734 flaky")
public void testOverrideIgnoreRequestedOrientation_propertyIsFalse_overrideNotApplied() {
assumeTrue("Skipping test: "
+ "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled not enabled",
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
index fc3aef324b2..5287c2c133b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
@@ -25,7 +25,6 @@ import static android.server.wm.app.Components.FONT_SCALE_ACTIVITY;
import static android.server.wm.app.Components.FONT_SCALE_NO_RELAUNCH_ACTIVITY;
import static android.server.wm.app.Components.FontScaleActivity.EXTRA_FONT_ACTIVITY_DPI;
import static android.server.wm.app.Components.FontScaleActivity.EXTRA_FONT_PIXEL_SIZE;
-import static android.server.wm.app.Components.FontScaleActivity.EXTRA_FONT_SCALE;
import static android.server.wm.app.Components.NO_RELAUNCH_ACTIVITY;
import static android.server.wm.app.Components.TEST_ACTIVITY;
import static android.server.wm.app.Components.TestActivity.EXTRA_CONFIG_ASSETS_SEQ;
@@ -257,39 +256,27 @@ public class ConfigChangeTests extends ActivityManagerTestBase {
}
final int densityDpi = extras.getInt(EXTRA_FONT_ACTIVITY_DPI);
- // Retry set font scale if needed, but with a maximum retry count to prevent infinite loop.
- int retrySetFontScale = 5;
- final float step = 0.15f;
- for (float fontScale = 0.85f; fontScale <= 1.3f; fontScale += step) {
- separateTestJournal();
- fontScaleSession.set(fontScale);
- mWmState.computeState(activityName);
- // The number of config changes could be greater than expected as there may have
- // other configuration change events triggered after font scale changed, such as
- // NavigationBar recreated.
- new ActivityLifecycleCounts(activityName).assertCountWithRetry(
- "relaunch or config changed",
- countSpec(ActivityCallback.ON_DESTROY, CountSpec.EQUALS, relaunch ? 1 : 0),
- countSpec(ActivityCallback.ON_CREATE, CountSpec.EQUALS, relaunch ? 1 : 0),
- countSpec(ActivityCallback.ON_RESUME, CountSpec.EQUALS, relaunch ? 1 : 0),
- countSpec(ActivityCallback.ON_CONFIGURATION_CHANGED,
- CountSpec.GREATER_THAN_OR_EQUALS, relaunch ? 0 : 1));
-
- // Verify that the display metrics are updated, and therefore the text size is also
- // updated accordingly.
- final Bundle changedExtras = TestJournalContainer.get(activityName).extras;
- if (changedExtras.getFloat(EXTRA_FONT_SCALE) == fontScale) {
- final float scale = fontScale;
- waitForOrFail("reported fontPixelSize from " + activityName,
- () -> scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, scale, densityDpi)
- == changedExtras.getInt(EXTRA_FONT_PIXEL_SIZE));
- } else if (retrySetFontScale-- > 0) {
- logE("retry set font scale " + fontScale + ", currently is "
- + changedExtras.getFloat(EXTRA_FONT_SCALE) + " session="
- + fontScaleSession.get());
- fontScale -= step;
- }
- }
+ final float fontScale = 0.85f;
+ separateTestJournal();
+ fontScaleSession.set(fontScale);
+ mWmState.computeState(activityName);
+ // The number of config changes could be greater than expected as there may have
+ // other configuration change events triggered after font scale changed, such as
+ // NavigationBar recreated.
+ new ActivityLifecycleCounts(activityName).assertCountWithRetry(
+ "relaunch or config changed",
+ countSpec(ActivityCallback.ON_DESTROY, CountSpec.EQUALS, relaunch ? 1 : 0),
+ countSpec(ActivityCallback.ON_CREATE, CountSpec.EQUALS, relaunch ? 1 : 0),
+ countSpec(ActivityCallback.ON_RESUME, CountSpec.EQUALS, relaunch ? 1 : 0),
+ countSpec(ActivityCallback.ON_CONFIGURATION_CHANGED,
+ CountSpec.GREATER_THAN_OR_EQUALS, relaunch ? 0 : 1));
+
+ // Verify that the display metrics are updated, and therefore the text size is also
+ // updated accordingly.
+ waitForOrFail("reported fontPixelSize from " + activityName,
+ () -> scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, fontScale, densityDpi)
+ == TestJournalContainer.get(activityName).extras.getInt(
+ EXTRA_FONT_PIXEL_SIZE));
}
/**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java
index d74294148fa..ab60f050747 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java
@@ -181,8 +181,9 @@ public class DisplayCutoutTests {
public void setUp() throws Exception {
final Context context = getInstrumentation().getContext();
mMaximumSizeForNoLetterbox =
- (context.getResources().getConfiguration().densityDpi / DENSITY_DEFAULT)
- * MAXIMUM_SIZE_FOR_NO_LETTERBOX_IF_DEFAULT_OR_SHORT_EDGE_DP;
+ (int) ((context.getResources().getConfiguration().densityDpi
+ / (float) DENSITY_DEFAULT)
+ * MAXIMUM_SIZE_FOR_NO_LETTERBOX_IF_DEFAULT_OR_SHORT_EDGE_DP);
}
@Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java
index 590dd45e1bc..09b253c51b6 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayHashManagerTest.java
@@ -289,6 +289,8 @@ public class DisplayHashManagerTest {
} catch (InterruptedException e) {
}
+ waitForAllActivitiesResumed();
+
generateDisplayHash(null);
mInstrumentation.runOnMainSync(() -> {
@@ -414,6 +416,7 @@ public class DisplayHashManagerTest {
committedCallbackLatch.await(WAIT_TIME_S, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
+ waitForAllActivitiesResumed();
byte[] expectedImageHash = new byte[]{-1, -1, 127, -1, -1, -1, 127, 127};
@@ -472,6 +475,7 @@ public class DisplayHashManagerTest {
committedCallbackLatch.await(WAIT_TIME_S, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
+ waitForAllActivitiesResumed();
}
public static class TestActivity extends Activity {
@@ -539,4 +543,13 @@ public class DisplayHashManagerTest {
mCountDownLatch.countDown();
}
}
+
+ /**
+ * Waits for all activities to be resumed since image hash could be calculated before the
+ * activity is resumed due to slower activity transitions.
+ */
+ private void waitForAllActivitiesResumed() {
+ mWmState.waitForWithAmState(WindowManagerState::allActivitiesResumed,
+ "All activities should be resumed");
+ }
}
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 f10fe84c432..af63b3ef52f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DockConfigChangeTests.java
@@ -28,6 +28,7 @@ import static org.junit.Assume.assumeTrue;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.platform.test.annotations.Presubmit;
import android.view.Surface;
@@ -47,13 +48,15 @@ public class DockConfigChangeTests extends ActivityManagerTestBase {
// enabled.
assumeTrue(getConfigSkipRelaunchOnDock());
- // 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();
- rotateToDockRotation(rotationSession);
launchActivity(TEST_ACTIVITY);
waitAndAssertResumedActivity(TEST_ACTIVITY, "Activity must be resumed");
+
+ // 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.
+ rotateToDockRotation(rotationSession);
+ waitAndAssertResumedActivity(TEST_ACTIVITY, "Activity must be resumed");
separateTestJournal();
final DockTestSession dockTestSession = mObjectTracker.manage(new DockTestSession());
@@ -80,13 +83,15 @@ public class DockConfigChangeTests extends ActivityManagerTestBase {
// enabled.
assumeTrue(getConfigSkipRelaunchOnDock());
- // 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();
- rotateToDockRotation(rotationSession);
launchActivity(DESK_RESOURCES_ACTIVITY);
waitAndAssertResumedActivity(DESK_RESOURCES_ACTIVITY, "Activity must be resumed");
+
+ // 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.
+ rotateToDockRotation(rotationSession);
+ waitAndAssertResumedActivity(DESK_RESOURCES_ACTIVITY, "Activity must be resumed");
separateTestJournal();
final DockTestSession dockTestSession = mObjectTracker.manage(new DockTestSession());
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 40a11b146fd..4ae4604d654 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
@@ -149,7 +149,8 @@ public class DragDropTest extends WindowManagerTestBase {
}
final LogEntry other = (LogEntry) obj;
return view == other.view && action == other.action
- && x == other.x && y == other.y
+ // Use tolerance in case mInvCompatScale is not 1.
+ && Math.abs(x - other.x) < 1f && Math.abs(y - other.y) < 1f
&& compareParcelables(clipData, other.clipData)
&& compareParcelables(clipDescription, other.clipDescription)
&& localState == other.localState
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java
index 6a556288f2e..b03c52b58c4 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java
@@ -47,10 +47,12 @@ public class KeepScreenOnTests extends MultiDisplayTestBase {
private int mInitialStayOnWhilePluggedInSetting;
private PowerManager mPowerManager;
private ContentResolver mContentResolver;
+ private boolean mIsTv;
@Before
public void setUp() throws Exception {
super.setUp();
+ mIsTv = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
mContentResolver = mContext.getContentResolver();
mInitialDisplayTimeout =
Settings.System.getString(mContentResolver, SCREEN_OFF_TIMEOUT);
@@ -86,6 +88,8 @@ public class KeepScreenOnTests extends MultiDisplayTestBase {
@ApiTest(apis = "android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON")
@Test
public void testKeepScreenOn_activityNotForeground_screenTurnsOff() {
+ assumeFalse("TVs may start screen saver instead of turning screen off - skipping test",
+ mIsTv);
setScreenOffTimeoutMs("500");
launchActivity(TURN_SCREEN_ON_ACTIVITY);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
index 8f8b9f68e74..0002f3e5c88 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
@@ -55,6 +55,7 @@ import static org.mockito.Mockito.verify;
import android.Manifest;
import android.app.KeyguardManager.KeyguardLockedStateListener;
+import android.app.WallpaperManager;
import android.content.ComponentName;
import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
@@ -73,6 +74,12 @@ import org.junit.Test;
@Presubmit
@android.server.wm.annotation.Group2
public class KeyguardTests extends KeyguardTestBase {
+
+ boolean isLockscreenLiveWpEnabled() {
+ WallpaperManager mWallpaperManager = mContext.getSystemService(WallpaperManager.class);
+ return mWallpaperManager != null && mWallpaperManager.isLockscreenLiveWallpaperEnabled();
+ }
+
@Before
@Override
public void setUp() throws Exception {
@@ -190,7 +197,12 @@ public class KeyguardTests extends KeyguardTestBase {
waitAndAssertResumedActivity(SHOW_WHEN_LOCKED_TRANSLUCENT_ACTIVITY);
lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_TRANSLUCENT_ACTIVITY);
waitAndAssertResumedActivity(SHOW_WHEN_LOCKED_TRANSLUCENT_ACTIVITY);
- mWmState.waitAndAssertWindowShown(TYPE_WALLPAPER, true);
+ if (isLockscreenLiveWpEnabled()) {
+ // When the flag is not enabled, the behavior of this test is not well-defined.
+ // This check would pass with a shared wallpaper, but not with a separate lock screen
+ // wallpaper.
+ mWmState.waitAndAssertWindowShown(TYPE_WALLPAPER, true);
+ }
mWmState.assertKeyguardShowingAndOccluded();
}
@@ -219,7 +231,12 @@ public class KeyguardTests extends KeyguardTestBase {
waitAndAssertResumedActivity(SHOW_WHEN_LOCKED_DIALOG_ACTIVITY);
lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_DIALOG_ACTIVITY);
waitAndAssertResumedActivity(SHOW_WHEN_LOCKED_DIALOG_ACTIVITY);
- mWmState.waitAndAssertWindowShown(TYPE_WALLPAPER, true);
+ if (isLockscreenLiveWpEnabled()) {
+ // When the flag is not enabled, the behavior of this test is not well-defined.
+ // This check would pass with a shared wallpaper, but not with a separate lock screen
+ // wallpaper.
+ mWmState.waitAndAssertWindowShown(TYPE_WALLPAPER, true);
+ }
mWmState.assertKeyguardShowingAndOccluded();
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
index a0f7c9fa49d..5511c36cb06 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
@@ -191,6 +191,7 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
waitAndAssertTopResumedActivity(BROADCAST_RECEIVER_ACTIVITY, newDisplay.mId,
"Activity should be resumed on secondary display");
+ mayLaunchHomeActivityForCar();
mBroadcastActionTrigger.launchActivityNewTask(getActivityName(TEST_ACTIVITY));
waitAndAssertTopResumedActivity(TEST_ACTIVITY, newDisplayId,
"Activity should be resumed on secondary display");
@@ -296,6 +297,7 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
// can get the callbacks which are related to the reparenting.
nonResizeableSession.takeCallbackHistory();
+ mayLaunchHomeActivityForCar();
// Try to move the non-resizeable activity to the top of the root task on secondary display.
moveActivityToRootTaskOrOnTop(NON_RESIZEABLE_ACTIVITY, externalFrontRootTaskId);
// Wait for a while to check that it will move.
@@ -960,6 +962,7 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
"Activity launched on primary display and on top");
+ mayLaunchHomeActivityForCar();
// Activity should be moved to target display.
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(displayContent.mId);
@@ -997,6 +1000,7 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
.setSimulateDisplay(true)
.createDisplay();
+ mayLaunchHomeActivityForCar();
// Launch activity on new secondary display.
getLaunchActivityBuilder()
.setUseInstrumentation()
@@ -1059,6 +1063,7 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
.setSimulateDisplay(true)
.createDisplay();
+ mayLaunchHomeActivityForCar();
// Start LAUNCHING_ACTIVITY on secondary display with target flags, verify the task
// be reparented to secondary display
getLaunchActivityBuilder()
@@ -1071,6 +1076,15 @@ public class MultiDisplayActivityLaunchTests extends MultiDisplayTestBase {
"Activity launched on secondary display and on top");
}
+ private void mayLaunchHomeActivityForCar() {
+ if (isCar()) {
+ // CarLauncher has a TaskView, and which launches the embedded task when it becomes
+ // visible and this can disrupt the top focused state of the test activity.
+ // So we'd like to make Home visible in advance to prevent that.
+ launchHomeActivity();
+ }
+ }
+
private PendingIntent getPendingIntentActivity(ComponentName activity) {
final Intent intent = new Intent();
intent.setClassName(activity.getPackageName(), activity.getClassName());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java
index ee11d08b7b9..9721bad39a0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiWindowTests.java
@@ -588,8 +588,11 @@ public class MultiWindowTests extends ActivityManagerTestBase {
final WindowContainerTransaction wct = new WindowContainerTransaction()
.reorder(token, true /* onTop */);
mTaskOrganizer.applyTransaction(wct);
- waitForOrFail("Fail to reorder", () ->
- mTaskOrganizer.getTaskInfo(taskId2).isVisible());
+
+ final WindowManagerState.Task topTask = mWmState
+ .getStandardRootTaskByWindowingMode(WINDOWING_MODE_FULLSCREEN)
+ .getTopTask();
+ waitForOrFail("Fail to reorder", () -> (topTask.mTaskId == taskId2));
});
} catch (AssertionError e) {
gotAssertionError = true;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index e3fbf67c952..bb01bbbe86f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -296,12 +296,14 @@ public class PinnedStackTests extends ActivityManagerTestBase {
@Test
public void testEnterPipToOtherOrientation() {
+ assumeTrue("Skipping test: no orientation request support", supportsOrientationRequest());
// Launch a portrait only app on the fullscreen stack
launchActivity(TEST_ACTIVITY,
extraString(EXTRA_FIXED_ORIENTATION, String.valueOf(SCREEN_ORIENTATION_PORTRAIT)));
// Launch the PiP activity fixed as landscape
launchActivity(PIP_ACTIVITY,
extraString(EXTRA_PIP_ORIENTATION, String.valueOf(SCREEN_ORIENTATION_LANDSCAPE)));
+ mWmState.waitForActivityOrientation(PIP_ACTIVITY, Configuration.ORIENTATION_LANDSCAPE);
// Enter PiP, and assert that the PiP is within bounds now that the device is back in
// portrait
mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index d943e39c876..929a42f0482 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -217,6 +217,10 @@ public class SplashscreenTests extends ActivityManagerTestBase {
} else {
appBounds = new Rect(startingWindow.getFrame());
}
+
+ insetGivenFrame(startingWindow, WindowManagerState.InsetsSource::isCaptionBar,
+ appBounds);
+
assertFalse("Couldn't find splash screen bounds. Impossible to assert the colors",
appBounds.isEmpty());
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 8ed33a692f8..ab34530b804 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
@@ -53,6 +53,7 @@ import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
+import android.graphics.Point;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -64,6 +65,7 @@ import android.server.wm.shared.ICrossProcessSurfaceControlViewHostTestService;
import android.util.ArrayMap;
import android.view.Gravity;
import android.view.MotionEvent;
+import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@@ -613,7 +615,7 @@ public class SurfaceControlViewHostTests extends ActivityManagerTestBase impleme
assertTrue("Failed to tap on embedded parent",
tapOnWindow(mInstrumentation, () -> mEmbeddedView.getWindowToken(),
- null /* offset */));
+ new Point(1, 1) /* offset */));
// When tapping on the parent embedded window, it should gain focus.
assertWindowFocused(mEmbeddedView, true);
// assert child embedded window does not have focus.
@@ -787,13 +789,23 @@ public class SurfaceControlViewHostTests extends ActivityManagerTestBase impleme
mVr.setView(mEmbeddedView, mEmbeddedViewWidth, mEmbeddedViewHeight);
});
- surfaceCreated.await();
+ assertTrue("Failed to wait for SurfaceView created",
+ surfaceCreated.await(5, TimeUnit.SECONDS));
// Make a copy of the SurfacePackage and release the original package.
SurfacePackage surfacePackage = mVr.getSurfacePackage();
SurfacePackage copy = new SurfacePackage(surfacePackage);
surfacePackage.release();
- mSurfaceView.setChildSurfacePackage(copy);
+
+ CountDownLatch surfacePackageReparented = new CountDownLatch(1);
+ mActivityRule.runOnUiThread(() -> {
+ mSurfaceView.setChildSurfacePackage(copy);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ t.addTransactionCommittedListener(Runnable::run, surfacePackageReparented::countDown);
+ mSurfaceView.getRootSurfaceControl().applyTransactionOnDraw(t);
+ });
+ assertTrue("Failed to wait for surface package to get reparented",
+ surfacePackageReparented.await(5, TimeUnit.SECONDS));
mInstrumentation.waitForIdleSync();
waitUntilEmbeddedViewDrawn();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
index 29e9dc3ba9f..202d2b09b1f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
@@ -108,7 +108,7 @@ public class WindowInsetsAnimationImeTests extends WindowInsetsAnimationTestBase
getInstrumentation().runOnMainSync(
() -> mRootView.getWindowInsetsController().show(ime()));
- waitForOrFail("Waiting until IME animation starts", () -> callback.imeAnim != null);
+ waitForOrFail("Waiting until IME animation starts", () -> callback.imeAnimStarted);
waitForOrFail("Waiting until animation done", () -> callback.runningAnims.isEmpty());
WindowInsets after = mActivity.mLastWindowInsets;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
index a403eb7dc60..47ef2cef998 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
@@ -53,7 +53,6 @@ import com.android.compatibility.common.util.OverrideAnimationScaleRule;
import org.junit.Assert;
import org.junit.Rule;
-import org.junit.rules.TestRule;
import org.mockito.InOrder;
import java.util.ArrayList;
@@ -233,6 +232,7 @@ public class WindowInsetsAnimationTestBase extends WindowManagerTestBase {
WindowInsetsAnimation statusBarAnim;
WindowInsetsAnimation navBarAnim;
WindowInsetsAnimation imeAnim;
+ volatile boolean imeAnimStarted;
volatile boolean animationDone;
final ArrayList<AnimationStep> statusAnimSteps = new ArrayList<>();
final ArrayList<AnimationStep> navAnimSteps = new ArrayList<>();
@@ -264,6 +264,9 @@ public class WindowInsetsAnimationTestBase extends WindowManagerTestBase {
startRunnable.run();
}
runningAnims.add(animation);
+ if (animation.equals(imeAnim)) {
+ imeAnimStarted = true;
+ }
return bounds;
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java
index 2fed7aa7c04..f0c2858ed2f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java
@@ -19,6 +19,7 @@ package android.server.wm;
import static android.Manifest.permission.ACCESS_SURFACE_FLINGER;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW;
+import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
import static android.server.wm.UiDeviceUtils.pressUnlockButton;
import static android.server.wm.UiDeviceUtils.pressWakeupButton;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
@@ -958,10 +959,9 @@ public class WindowUntrustedTouchTest {
WindowManagerState.WindowState focusedWindowState = mWmState.getWindowState(component);
Rect expectedBounds = mWmState.getActivity(component).getBounds();
SystemUtil.runWithShellPermissionIdentity(() -> {
- if (!CtsWindowInfoUtils.waitForWindowInfos(windows -> windows.stream().anyMatch(w ->
- w.name.contains(focusedWindowState.getToken())
- && w.name.contains(focusedWindowState.getName())
- && w.bounds.equals(expectedBounds)), 3, TimeUnit.SECONDS)) {
+ if (!CtsWindowInfoUtils.waitForWindowOnTop(5 * HW_TIMEOUT_MULTIPLIER, TimeUnit.SECONDS,
+ window -> window.name.contains(focusedWindowState.getToken())
+ && window.name.contains(focusedWindowState.getName()))) {
fail("Window " + focusedWindowState.getName() + " did not appear in InputFlinger "
+ "with an expected bounds " + expectedBounds);
}
diff --git a/tests/framework/base/windowmanager/util/Android.bp b/tests/framework/base/windowmanager/util/Android.bp
index 54ac015adf7..a6f89761317 100644
--- a/tests/framework/base/windowmanager/util/Android.bp
+++ b/tests/framework/base/windowmanager/util/Android.bp
@@ -39,6 +39,28 @@ filegroup {
}
java_test_helper_library {
+ name: "cts-wm-window-manager-helper",
+
+ srcs: [
+ "src/android/server/wm/Condition.java",
+ "src/android/server/wm/ComponentNameUtils.java",
+ "src/android/server/wm/ProtoExtractors.java",
+ "src/android/server/wm/StateLogger.java",
+ "src/android/server/wm/WaitForValidActivityState.java",
+ "src/android/server/wm/WindowManagerState.java",
+ "src/android/server/wm/WindowManagerStateHelper.java",
+ ],
+
+ static_libs: [
+ "compatibility-device-util-axt",
+ "platformprotosnano",
+ "hamcrest-library",
+ ],
+
+ sdk_version: "test_current",
+}
+
+java_test_helper_library {
name: "cts-wm-util",
srcs: [
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 5f6215d9bc4..fdcd640585d 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -207,12 +207,14 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -1741,6 +1743,11 @@ public abstract class ActivityManagerTestBase {
}
LockScreenSession disableLockScreen() {
+ // Lock credentials need to be cleared before disabling the lock.
+ if (mLockCredentialSet) {
+ removeLockCredential();
+ mLockCredentialSet = false;
+ }
setLockDisabled(true);
return this;
}
@@ -1864,7 +1871,7 @@ public abstract class ActivityManagerTestBase {
* @param lockDisabled true if should disable, false otherwise.
*/
protected void setLockDisabled(boolean lockDisabled) {
- runCommandAndPrintOutput("locksettings set-disabled " + oldIfNeeded() + lockDisabled);
+ runCommandAndPrintOutput("locksettings set-disabled " + lockDisabled);
}
@NonNull
@@ -3459,4 +3466,19 @@ public abstract class ActivityManagerTestBase {
mWmState.computeState(new WaitForValidActivityState(activityName));
return mWmState.getActivity(activityName);
}
+
+ /**
+ * Inset given frame if the insets source exist.
+ *
+ * @param windowState The window which have the insets source.
+ * @param predicate Inset source predicate.
+ * @param inOutBounds In/out the given frame from the inset source.
+ */
+ public static void insetGivenFrame(WindowManagerState.WindowState windowState,
+ Predicate<WindowManagerState.InsetsSource> predicate, Rect inOutBounds) {
+ Optional<WindowManagerState.InsetsSource> insetsOptional =
+ windowState.getMergedLocalInsetsSources().stream().filter(
+ predicate).findFirst();
+ insetsOptional.ifPresent(insets -> insets.insetGivenFrame(inOutBounds));
+ }
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/CtsWindowInfoUtils.java b/tests/framework/base/windowmanager/util/src/android/server/wm/CtsWindowInfoUtils.java
index 46ba1bc73c3..78dc2f2df9a 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/CtsWindowInfoUtils.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/CtsWindowInfoUtils.java
@@ -27,6 +27,7 @@ import android.os.SystemProperties;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
+import android.view.Display;
import android.window.WindowInfosListenerForTest;
import android.window.WindowInfosListenerForTest.WindowInfo;
@@ -127,7 +128,9 @@ public class CtsWindowInfoUtils {
if (!windowInfo.isVisible) {
continue;
}
- if (windowInfo.windowToken == windowToken) {
+ // only wait for default display.
+ if (windowInfo.windowToken == windowToken
+ && windowInfo.displayId == Display.DEFAULT_DISPLAY) {
return predicate.test(windowInfo);
}
}
@@ -165,7 +168,7 @@ public class CtsWindowInfoUtils {
}
/**
- * Waits until the window specified by windowTokenSupplier is present, not occluded, and hasn't
+ * Waits until the window specified by the predicate is present, not occluded, and hasn't
* had geometry changes for 200ms.
*
* The window is considered occluded if any part of another window is above it, excluding
@@ -186,7 +189,7 @@ public class CtsWindowInfoUtils {
* reached. False otherwise.
*/
public static boolean waitForWindowOnTop(int timeout, @NonNull TimeUnit unit,
- @NonNull Supplier<IBinder> windowTokenSupplier)
+ @NonNull Predicate<WindowInfo> predicate)
throws InterruptedException {
var latch = new CountDownLatch(1);
var satisfied = new AtomicBoolean();
@@ -210,15 +213,10 @@ public class CtsWindowInfoUtils {
return;
}
- IBinder windowToken = windowTokenSupplier.get();
- if (windowToken == null) {
- return;
- }
-
WindowInfo targetWindowInfo = null;
ArrayList<WindowInfo> aboveWindowInfos = new ArrayList<>();
for (var windowInfo : windowInfos) {
- if (windowInfo.windowToken == windowToken) {
+ if (predicate.test(windowInfo)) {
targetWindowInfo = windowInfo;
break;
}
@@ -263,7 +261,7 @@ public class CtsWindowInfoUtils {
latch.countDown();
}
};
- mTimer.schedule(mTask, 200);
+ mTimer.schedule(mTask, 200L * HW_TIMEOUT_MULTIPLIER);
}
};
@@ -298,6 +296,36 @@ public class CtsWindowInfoUtils {
}
/**
+ * Waits until the window specified by windowTokenSupplier is present, not occluded, and hasn't
+ * had geometry changes for 200ms.
+ *
+ * The window is considered occluded if any part of another window is above it, excluding
+ * trusted overlays.
+ *
+ * <p>
+ * <strong>Note:</strong>If the caller has any adopted shell permissions, they must include
+ * android.permission.ACCESS_SURFACE_FLINGER.
+ * </p>
+ *
+ * @param timeout The amount of time to wait for the window to be visible.
+ * @param unit The units associated with timeout.
+ * @param windowTokenSupplier Supplies the window token for the window to wait on. The
+ * supplier is called each time window infos change. If the
+ * supplier returns null, the window is assumed not visible
+ * yet.
+ * @return True if the window satisfies the visibility requirements before the timeout is
+ * reached. False otherwise.
+ */
+ public static boolean waitForWindowOnTop(int timeout, @NonNull TimeUnit unit,
+ @NonNull Supplier<IBinder> windowTokenSupplier)
+ throws InterruptedException {
+ return waitForWindowOnTop(timeout, unit, windowInfo -> {
+ IBinder windowToken = windowTokenSupplier.get();
+ return windowToken != null && windowInfo.windowToken == windowToken;
+ });
+ }
+
+ /**
* Tap on the center coordinates of the specified window.
* </p>
* @param instrumentation Instrumentation object to use for tap.
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 f133224fc1e..71d2c08ba07 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
@@ -26,7 +26,7 @@ import static android.server.wm.ComponentNameUtils.getActivityName;
import static android.server.wm.ProtoExtractors.extract;
import static android.server.wm.StateLogger.log;
import static android.server.wm.StateLogger.logE;
-import static android.server.wm.TestTaskOrganizer.INVALID_TASK_ID;
+import static android.server.wm.WindowManagerState.Task.INVALID_TASK_ID;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_IME;
@@ -1432,6 +1432,8 @@ public class WindowManagerState {
}
public static class Task extends ActivityContainer {
+ // TODO(b/292187837): Use the one in ActivityTaskManager instead.
+ public static final int INVALID_TASK_ID = -1;
int mTaskId;
int mRootTaskId;
public int mDisplayId;
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
index 913b039646d..b2a85208d23 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
@@ -379,9 +379,10 @@ public class WindowManagerStateHelper extends WindowManagerState {
}, message);
}
- public void waitForFocusedActivity(final String msg, final ComponentName activityName) {
+ public boolean waitForFocusedActivity(final String msg, final ComponentName activityName) {
final String activityComponentName = getActivityName(activityName);
- waitFor(msg, wmState -> Objects.equals(activityComponentName, wmState.getFocusedActivity())
+ return waitFor(msg, wmState ->
+ Objects.equals(activityComponentName, wmState.getFocusedActivity())
&& Objects.equals(activityComponentName, wmState.getFocusedApp()));
}
diff --git a/tests/input/src/android/input/cts/UinputTouchDevice.kt b/tests/input/src/android/input/cts/UinputTouchDevice.kt
index 709c922f43e..ceb4506a5db 100644
--- a/tests/input/src/android/input/cts/UinputTouchDevice.kt
+++ b/tests/input/src/android/input/cts/UinputTouchDevice.kt
@@ -20,6 +20,7 @@ import android.app.Instrumentation
import android.content.Context
import android.graphics.Point
import android.hardware.input.InputManager
+import android.server.wm.WindowManagerStateHelper
import android.util.Size
import android.view.Display
import android.view.InputDevice
@@ -45,6 +46,8 @@ class UinputTouchDevice(
uinputDevice = createDevice(instrumentation, size)
inputManager = instrumentation.targetContext.getSystemService(InputManager::class.java)!!
associateWith(display)
+ WindowManagerStateHelper().waitForAppTransitionIdleOnDisplay(display.displayId)
+ instrumentation.uiAutomation.syncInputTransactions()
}
private fun injectEvent(events: IntArray) {
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
index d172e0f73af..4d83f06f8e9 100644
--- a/tests/inputmethod/AndroidManifest.xml
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -19,6 +19,8 @@
package="android.view.inputmethod.cts"
android:targetSandboxVersion="2">
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
+
<queries>
<intent>
<action android:name="android.view.InputMethod" />
@@ -30,6 +32,7 @@
</queries>
<application android:label="CtsInputMethodTestCases"
+ android:requestLegacyExternalStorage="true"
android:multiArch="true"
android:supportsRtl="true"
android:debuggable="true"
diff --git a/tests/inputmethod/AndroidTest.xml b/tests/inputmethod/AndroidTest.xml
index c356dd09c8e..d66112cde49 100644
--- a/tests/inputmethod/AndroidTest.xml
+++ b/tests/inputmethod/AndroidTest.xml
@@ -144,6 +144,17 @@
<!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
<option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
+
+ <!-- Create a place to store files for DumpOnFailure -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /sdcard/DumpOnFailure" />
+ </target_preparer>
+ <!-- Collect the files from DumpOnFailure. -->
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/sdcard/DumpOnFailure" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.view.inputmethod.cts" />
<option name="runtime-hint" value="1m0s" />
diff --git a/tests/inputmethod/mockime/Android.bp b/tests/inputmethod/mockime/Android.bp
index aeb1e099bfc..8b7f73e9490 100644
--- a/tests/inputmethod/mockime/Android.bp
+++ b/tests/inputmethod/mockime/Android.bp
@@ -41,8 +41,9 @@ android_test_helper_app {
optimize: {
enabled: false,
},
+ dxflags: ["--multi-dex"],
sdk_version: "test_current",
- min_sdk_version: "19",
+ min_sdk_version: "21",
// tag this module as a cts test artifact
test_suites: [
"cts",
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
index 8855dee537b..199e798fe52 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
@@ -32,7 +32,7 @@ public final class Watermark {
*
* <p>See Bug 174534092 about why we ended up having this.</p>
*/
- private static final int TOLERANCE = 6;
+ private static final int TOLERANCE = 8;
/**
* A utility class that represents A8R8G8B bitmap as an integer array.
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index 167e9f62a2d..aefa3277aba 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -335,7 +335,7 @@ public class InputMethodManagerTest {
return condition.canProceed();
});
} catch (AssertionError e) {
- File heap = new File(mContext.getExternalFilesDir(null), "dump.hprof");
+ File heap = new File("/sdcard/DumpOnFailure", "inputmethod-dump.hprof");
Debug.dumpHprofData(heap.getAbsolutePath());
throw new AssertionError("Dumped heap in device at " + heap.getAbsolutePath(), e);
}
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
index 0885fcfc767..4ef76ae632c 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -76,6 +76,7 @@ import android.util.Pair;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
+import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.view.WindowManager;
@@ -97,7 +98,6 @@ import android.widget.TextView;
import android.window.OnBackInvokedDispatcher;
import androidx.annotation.ColorInt;
-import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -1308,11 +1308,18 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
*/
@Test
public void testRotateScreenWithKeyboardShownImplicitly() throws Exception {
+ // Test only when both portrait and landscape mode are supported.
+ final PackageManager pm = mInstrumentation.getTargetContext().getPackageManager();
+ assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT));
+ assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE));
+
final InputMethodManager imm = mInstrumentation
.getTargetContext().getSystemService(InputMethodManager.class);
// Disable auto-rotate screen and set the screen orientation to portrait mode.
setAutoRotateScreen(false);
- rotateScreen(0);
+ final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation);
+ uiDevice.setOrientationPortrait();
+ mInstrumentation.waitForIdleSync();
// Set FullscreenModePolicy as OS_DEFAULT to call the original
// InputMethodService#onEvaluateFullscreenMode()
@@ -1344,14 +1351,9 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
View.VISIBLE, TIMEOUT);
expectImeVisible(TIMEOUT);
- // Rotate screen right
- rotateScreen(3);
- expectImeVisible(TIMEOUT);
- assertTrue("IME should be in fullscreen mode",
- getOnMainSync(() -> imm.isFullscreenMode()));
-
- // Rotate screen left
- rotateScreen(1);
+ // Rotate screen to landscape.
+ uiDevice.setOrientationLandscape();
+ mInstrumentation.waitForIdleSync();
expectImeVisible(TIMEOUT);
assertTrue("IME should be in fullscreen mode",
getOnMainSync(() -> imm.isFullscreenMode()));
@@ -1524,6 +1526,18 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
return new LinearLayout(activity);
}, TestActivity2.class);
+ View decor = splitPrimaryActivity.getWindow().getDecorView();
+ CountDownLatch latch = new CountDownLatch(1);
+ ViewTreeObserver observer = decor.getViewTreeObserver();
+ observer.addOnDrawListener(() -> {
+ if (splitPrimaryActivity.isInMultiWindowMode()) {
+ // check activity in multi-window mode after relayoutWindow.
+ latch.countDown();
+ }
+ });
+
+ latch.await(LAYOUT_STABLE_THRESHOLD, TimeUnit.MILLISECONDS);
+
// Tap on the first activity to change focus
mCtsTouchUtils.emulateTapOnViewCenter(mInstrumentation,
null, splitPrimaryActivity.getWindow().getDecorView());
@@ -1653,17 +1667,6 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
}
}
- private void rotateScreen(@IntRange(from = 0, to = 3) int rotation) {
- try {
- final Instrumentation instrumentation = mInstrumentation;
- SystemUtil.runShellCommand(instrumentation, "settings put system user_rotation "
- + rotation);
- instrumentation.waitForIdleSync();
- } catch (IOException io) {
- fail("Couldn't rotate screen");
- }
- }
-
private static ImeSettings.Builder getFloatingImeSettings(@ColorInt int navigationBarColor) {
final ImeSettings.Builder builder = new ImeSettings.Builder();
builder.setWindowFlags(0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
index b14354a79b5..e3e2469aed7 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
@@ -1978,7 +1978,12 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
private static int getTouchSlop() {
final Context context = InstrumentationRegistry.getInstrumentation().getContext();
- return ViewConfiguration.get(context).getScaledTouchSlop();
+ // Some tests require stylus movements to exceed the touch slop so that they are not
+ // interpreted as clicks. Other tests require the movements to exceed the handwriting slop
+ // to trigger handwriting initiation. Using the larger value allows all tests to pass.
+ return Math.max(
+ ViewConfiguration.get(context).getScaledTouchSlop(),
+ ViewConfiguration.get(context).getScaledHandwritingSlop());
}
private Pair<EditText, EditText> launchTestActivity(@NonNull String focusedMarker,
@@ -2014,7 +2019,12 @@ public class StylusHandwritingTest extends EndToEndImeTestBase {
HANDWRITING_BOUNDS_OFFSET_PX,
HANDWRITING_BOUNDS_OFFSET_PX,
HANDWRITING_BOUNDS_OFFSET_PX);
- layout.addView(nonFocusedEditText);
+ // Leave margin between the EditTexts so that their extended handwriting bounds do not
+ // overlap.
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ layoutParams.topMargin = 3 * HANDWRITING_BOUNDS_OFFSET_PX;
+ layout.addView(nonFocusedEditText, layoutParams);
return layout;
});
return new Pair<>(focusedEditTextRef.get(), nonFocusedEditTextRef.get());
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
index 33a80f0b35b..b35128ca9b6 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
@@ -18,12 +18,11 @@ package android.location.cts.fine;
import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeTrue;
-import static org.mockito.ArgumentMatchers.anyList;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.location.Address;
import android.location.Geocoder;
import android.location.Geocoder.GeocodeListener;
import android.os.Build.VERSION;
@@ -33,28 +32,33 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.compatibility.common.util.ApiTest;
-import com.android.compatibility.common.util.RetryRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
@RunWith(AndroidJUnit4.class)
public class GeocoderTest {
- // retry just in case of network failure
- @Rule
- public final RetryRule mRetryRule = new RetryRule(2);
+ @Rule public final MockitoRule mocks = MockitoJUnit.rule();
private Context mContext;
private Geocoder mGeocoder;
+ private @Mock Runnable mCallbackRunnable;
+ private GeocodeListener mListener;
+
@Before
public void setUp() {
+ mListener = new TestGeocodeListener(mCallbackRunnable);
mContext = ApplicationProvider.getApplicationContext();
mGeocoder = new Geocoder(mContext, Locale.US);
@@ -63,14 +67,36 @@ public class GeocoderTest {
!mContext.getPackageManager().isInstantApp() || VERSION.SDK_INT >= VERSION_CODES.S);
}
+ /**
+ * GeocodeListener for tests. For the purposes of this test class, we don't care whether the
+ * request succeeds or fails. Invokes the runnable so we can verify that the callback is invoked
+ * in either case.
+ */
+ private static class TestGeocodeListener implements GeocodeListener {
+ private Runnable mCallbackRunnable;
+
+ TestGeocodeListener(Runnable callbackRunnable) {
+ this.mCallbackRunnable = callbackRunnable;
+ }
+
+ @Override
+ public void onGeocode(List<Address> addresses) {
+ mCallbackRunnable.run();
+ }
+
+ @Override
+ public void onError(String errorMessage) {
+ mCallbackRunnable.run();
+ }
+ }
+
@ApiTest(apis = "android.location.Geocoder#getFromLocation")
@Test
public void testGetFromLocation() {
assumeTrue(Geocoder.isPresent());
- GeocodeListener listener = mock(GeocodeListener.class);
- mGeocoder.getFromLocation(60, 30, 5, listener);
- verify(listener, timeout(10000)).onGeocode(anyList());
+ mGeocoder.getFromLocation(60, 30, 5, mListener);
+ verify(mCallbackRunnable, timeout(10000)).run();
}
@ApiTest(apis = "android.location.Geocoder#getFromLocation")
@@ -84,15 +110,18 @@ public class GeocoderTest {
@ApiTest(apis = "android.location.Geocoder#getFromLocation")
@Test
public void testGetFromLocation_badInput() {
- GeocodeListener listener = mock(GeocodeListener.class);
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocation(-91, 30, 5, listener));
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocation(91, 30, 5, listener));
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocation(10, -181, 5, listener));
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocation(10, 181, 5, listener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocation(-91, 30, 5, mListener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocation(91, 30, 5, mListener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocation(10, -181, 5, mListener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocation(10, 181, 5, mListener));
}
@ApiTest(apis = "android.location.Geocoder#getFromLocationName")
@@ -100,9 +129,8 @@ public class GeocoderTest {
public void testGetFromLocationName() {
assumeTrue(Geocoder.isPresent());
- GeocodeListener listener = mock(GeocodeListener.class);
- mGeocoder.getFromLocationName("Dalvik,Iceland", 5, listener);
- verify(listener, timeout(10000)).onGeocode(anyList());
+ mGeocoder.getFromLocationName("Dalvik,Iceland", 5, mListener);
+ verify(mCallbackRunnable, timeout(10000)).run();
}
@ApiTest(apis = "android.location.Geocoder#getFromLocationName")
@@ -116,27 +144,31 @@ public class GeocoderTest {
@ApiTest(apis = "android.location.Geocoder#getFromLocationName")
@Test
public void testGetFromLocationName_badInput() {
- GeocodeListener listener = mock(GeocodeListener.class);
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocationName(null, 5, listener));
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocationName("Beijing", 5, -91, 100, 45, 130, listener));
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocationName("Beijing", 5, 25, 190, 45, 130, listener));
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocationName("Beijing", 5, 25, 100, 91, 130, listener));
- assertThrows(IllegalArgumentException.class,
- () -> mGeocoder.getFromLocationName("Beijing", 5, 25, 100, 45, -181, listener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocationName(null, 5, mListener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocationName("Beijing", 5, -91, 100, 45, 130, mListener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocationName("Beijing", 5, 25, 190, 45, 130, mListener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocationName("Beijing", 5, 25, 100, 91, 130, mListener));
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> mGeocoder.getFromLocationName("Beijing", 5, 25, 100, 45, -181, mListener));
}
- @ApiTest(apis = {
- "android.location.Geocoder.GeocodeListener#onGeocode",
- "android.location.Geocoder.GeocodeListener#onError",
- })
+ @ApiTest(
+ apis = {
+ "android.location.Geocoder.GeocodeListener#onGeocode",
+ "android.location.Geocoder.GeocodeListener#onError",
+ })
@Test
public void testGeocodeListener() {
- GeocodeListener listener = mock(GeocodeListener.class);
- listener.onGeocode(new ArrayList<>());
- listener.onError(null);
+ mListener.onGeocode(new ArrayList<>());
+ mListener.onError(null);
}
}
diff --git a/tests/media/AndroidTest.xml b/tests/media/AndroidTest.xml
index afb4861c438..9056d6dcf12 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.5" />
+ <option name="media-folder-name" value="CtsMediaV2TestCases-3.6" />
<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 e3643d73789..3ab84f67812 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.5.zip</value>
+ <value>https://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.6.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/media/README.md b/tests/media/README.md
index 5601ad3d379..fc25fe57b2a 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.5.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.6.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/CompareStreams.java b/tests/media/common/src/android/mediav2/common/cts/CompareStreams.java
index 76745363f67..b6b906864a8 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CompareStreams.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CompareStreams.java
@@ -16,7 +16,9 @@
package android.mediav2.common.cts;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
import static android.mediav2.common.cts.DecodeStreamToYuv.findDecoderForStream;
+import static android.mediav2.common.cts.DecodeStreamToYuv.getFormatInStream;
import static android.mediav2.common.cts.DecodeStreamToYuv.getImage;
import static android.mediav2.common.cts.VideoErrorManager.computeMSE;
import static android.mediav2.common.cts.VideoErrorManager.computePSNR;
@@ -31,6 +33,10 @@ import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
+import com.android.compatibility.common.util.MediaUtils;
+
+import org.junit.Assume;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -260,6 +266,21 @@ public class CompareStreams extends CodecDecoderTestBase {
private void generateErrorStats() throws IOException, InterruptedException {
if (!mGenerateStats) {
+ if (MediaUtils.isTv()) {
+ // Some TV devices support HDR10 display with VO instead of GPU. In this case,
+ // COLOR_FormatYUVP010 may not be supported.
+ MediaFormat format = mStreamFormat != null ? mStreamFormat :
+ getFormatInStream(mMediaType, mTestFile);
+ ArrayList<MediaFormat> formatList = new ArrayList<>();
+ formatList.add(format);
+ boolean isHBD = doesAnyFormatHaveHDRProfile(mMediaType, formatList);
+ if (isHBD || mTestFile.contains("10bit")) {
+ if (!hasSupportForColorFormat(mCodecName, mMediaType, COLOR_FormatYUVP010)) {
+ Assume.assumeTrue("Could not validate the encoded output as"
+ + " COLOR_FormatYUVP010 is not supported by the decoder", false);
+ }
+ }
+ }
if (mStreamFormat != null) {
decodeToMemory(mStreamBuffer, mStreamBufferInfos, mStreamFormat, mCodecName);
} else {
diff --git a/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java b/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java
index 1d01b8623c6..5c3b741f1da 100644
--- a/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java
+++ b/tests/media/common/src/android/mediav2/common/cts/DecodeStreamToYuv.java
@@ -108,7 +108,7 @@ public class DecodeStreamToYuv extends CodecDecoderTestBase {
.build();
}
- static String findDecoderForStream(String mediaType, String file) throws IOException {
+ static MediaFormat getFormatInStream(String mediaType, String file) throws IOException {
File tmp = new File(file);
if (!tmp.exists()) {
throw new FileNotFoundException("Test Setup Error, missing file: " + file);
@@ -128,7 +128,11 @@ public class DecodeStreamToYuv extends CodecDecoderTestBase {
throw new IllegalArgumentException(
"No track with mediaType: " + mediaType + " found in file: " + file);
}
- return findDecoderForFormat(format);
+ return format;
+ }
+
+ static String findDecoderForStream(String mediaType, String file) throws IOException {
+ return findDecoderForFormat(getFormatInStream(mediaType, file));
}
static String findDecoderForFormat(MediaFormat format) {
@@ -147,8 +151,8 @@ public class DecodeStreamToYuv extends CodecDecoderTestBase {
writeImage(img);
if (mOutputCount == 0) {
MediaFormat format = mCodec.getOutputFormat();
- mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
- mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
+ mWidth = getWidth(format);
+ mHeight = getHeight(format);
int imgFormat = img.getFormat();
mBytesPerSample = (ImageFormat.getBitsPerPixel(imgFormat) * 2) / (8 * 3);
}
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 34627bc232a..7ae24200474 100644
--- a/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
@@ -153,13 +153,18 @@ public class HDREncoderTestBase extends CodecEncoderTestBase {
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);
+ if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+ assertTrue("At timestamp : " + pts + " application queued hdr10+ metadata,"
+ + " during dequeue application did not receive it in output format",
+ mHdrDynamicInfoReceived.containsKey(pts));
+ }
+ if (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);
+ }
}
}
diff --git a/tests/media/copy_media.sh b/tests/media/copy_media.sh
index b0850ad64d1..c402f156e7d 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.5
+resLabel=CtsMediaV2TestCases-3.6
srcDir="/tmp/$resLabel"
tgtDir="/sdcard/test"
usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/media/src/android/mediav2/cts/WorkDir.java b/tests/media/src/android/mediav2/cts/WorkDir.java
index de9f200d7a8..9584c741198 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.5");
+ return getMediaDirString("CtsMediaV2TestCases-3.6");
}
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index a283ec38c46..cd5f0f33af7 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -369,16 +369,18 @@ public class PerformanceClassEvaluator {
* ms or less for a 1080p or smaller video encoding session for all hardware video
* encoders when under load. Load here is defined as a concurrent 1080p to 720p
* video-only transcoding session using hardware video codecs together with the 1080p
- * audio-video recording initialization.
+ * audio-video recording initialization. For Dolby vision codec, the codec initialization
+ * latency MUST be 50 ms or less.
*/
- public static CodecInitLatencyRequirement createR5_1__H_1_7() {
+ public static CodecInitLatencyRequirement createR5_1__H_1_7(String mediaType) {
+ long latency = mediaType.equals(MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION) ? 50L : 40L;
RequiredMeasurement<Long> codec_init_latency =
RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY)
.setPredicate(RequirementConstants.LONG_LTE)
.addRequiredValue(Build.VERSION_CODES.R, 65L)
.addRequiredValue(Build.VERSION_CODES.S, 50L)
- .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 40L)
- .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, 40L)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, latency)
+ .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, latency)
.build();
return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_7,
@@ -2206,8 +2208,8 @@ public class PerformanceClassEvaluator {
return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_6_4k());
}
- public CodecInitLatencyRequirement addR5_1__H_1_7() {
- return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_7());
+ public CodecInitLatencyRequirement addR5_1__H_1_7(String mediaType) {
+ return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_7(mediaType));
}
public CodecInitLatencyRequirement addR5_1__H_1_8() {
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 258b30f7cc9..55955913b96 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
@@ -123,7 +123,9 @@ public class Utils {
final double diagonalInch = Math.sqrt(widthInch * widthInch + heightInch * heightInch);
final double maxDiagonalPixels =
Math.sqrt(maxWidthPixels * maxWidthPixels + maxHeightPixels * maxHeightPixels);
- DISPLAY_DPI = (int) (maxDiagonalPixels / diagonalInch);
+ // Use max of computed dpi and advertised dpi as these values differ in some devices.
+ DISPLAY_DPI = Math.max((int) (maxDiagonalPixels / diagonalInch),
+ context.getResources().getConfiguration().densityDpi);
ActivityManager activityManager = context.getSystemService(ActivityManager.class);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
diff --git a/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java b/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java
index 6ae69665ebc..e668ddb310f 100644
--- a/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java
+++ b/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java
@@ -126,13 +126,7 @@ class AudioPlaybackLoad extends CodecDecoderTestBase {
}
@Override
- void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- mSawOutputEOS = true;
- }
- if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
- mOutputCount++;
- }
+ void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) {
final ByteBuffer buffer = mCodec.getOutputBuffer(bufferIndex);
final byte[] audio = new byte[info.size];
buffer.clear(); // prepare buffer for reading
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
index 4ff5f6b71fc..020ddeb0905 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
@@ -350,8 +350,8 @@ public class CodecInitializationLatencyTest {
PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
PerformanceClassEvaluator.CodecInitLatencyRequirement r5_1__H_1_Latency =
- isEncoder ? isAudio ? pce.addR5_1__H_1_8() : pce.addR5_1__H_1_7()
- : isAudio ? pce.addR5_1__H_1_13() : pce.addR5_1__H_1_12();
+ isEncoder ? isAudio ? pce.addR5_1__H_1_8() : pce.addR5_1__H_1_7(mMime)
+ : isAudio ? pce.addR5_1__H_1_13() : pce.addR5_1__H_1_12();
r5_1__H_1_Latency.setCodecInitLatencyMs(initializationLatency);
@@ -533,6 +533,13 @@ public class CodecInitializationLatencyTest {
public long calculateInitLatency() throws Exception {
MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
MediaFormat format = setUpSource(mTestFile);
+ ArrayList<MediaFormat> formats = new ArrayList<>();
+ formats.add(format);
+ // If the decoder doesn't support the formats, then return Integer.MAX_VALUE to
+ // indicate that all decode was not successful
+ if (!areFormatsSupported(mDecoderName, formats)) {
+ return Integer.MAX_VALUE;
+ }
long enqueueTimeStamp = 0;
long dequeueTimeStamp = 0;
long baseTimeStamp = SystemClock.elapsedRealtimeNanos();
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
index 29ed734acb9..53dbce6ebd6 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
@@ -57,6 +57,7 @@ import java.util.concurrent.Callable;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
class CodecAsyncHandler extends MediaCodec.Callback {
private static final String LOG_TAG = CodecAsyncHandler.class.getSimpleName();
@@ -214,7 +215,49 @@ abstract class CodecTestBase {
abstract void enqueueInput(int bufferIndex) throws IOException;
- abstract void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info);
+ // Callback for each time the output count changes.
+ // This can be used to measure codec performance.
+ Consumer<Integer> mOutputCountListener;
+
+ // must not be called during doWork
+ void setOutputCountListener(Consumer<Integer> listener) {
+ mOutputCountListener = listener;
+ }
+
+ /**
+ * Called to handle a dequeued output buffer.
+ *
+ * We account for EOS and the number of full output frames.
+ */
+ protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ mSawOutputEOS = true;
+ }
+ int outputCount = mOutputCount;
+ // handle output count prior to releasing the buffer as that can take time
+ if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+ mOutputCount++;
+ if (mOutputCountListener != null) {
+ mOutputCountListener.accept(mOutputCount);
+ }
+ }
+ releaseOutput(outputCount, bufferIndex, info);
+ }
+
+ /**
+ * Called to handle releasing an output buffer.
+ */
+ abstract void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info);
+
+ /**
+ * Called to handle releasing an output buffer.
+ *
+ * @param outputCount total count of full output frames prior to
+ * this point (not including this buffer).
+ */
+ protected void releaseOutput(int outputCount, int bufferIndex, MediaCodec.BufferInfo info) {
+ releaseOutput(bufferIndex, info);
+ }
void configureCodec(MediaFormat format, boolean isAsync, boolean signalEOSWithLastFrame,
boolean isEncoder) throws Exception {
@@ -627,13 +670,7 @@ class CodecDecoderTestBase extends CodecTestBase {
}
}
- void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- mSawOutputEOS = true;
- }
- if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
- mOutputCount++;
- }
+ void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) {
mCodec.releaseOutputBuffer(bufferIndex, false);
}
}
@@ -819,13 +856,7 @@ class CodecEncoderTestBase extends CodecTestBase {
}
}
- void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- mSawOutputEOS = true;
- }
- if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
- mOutputCount++;
- }
+ void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) {
mCodec.releaseOutputBuffer(bufferIndex, false);
}
}
@@ -844,6 +875,9 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> {
String.format("%s?video_id=%s&provider=%s", WIDEVINE_LICENSE_SERVER_URL,
"GTS_HW_SECURE_ALL", PROVIDER);
final boolean mIsAsync;
+ private int mInitialFramesToIgnoreCount = 1;
+ private long mStartTimeMillis = 0;
+ private long mEndTimeMillis = 0;
Decode(String mime, String testFile, String decoderName, boolean isAsync) {
this(mime, testFile,decoderName, isAsync, false);
@@ -857,8 +891,29 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> {
mSecureMode = secureMode;
}
+ public void setInitialFramesToIgnoreCount(int count) {
+ mInitialFramesToIgnoreCount = count;
+ }
+
+ // measure throughput at the output port
+ private void onOutputCountListener(int count) {
+ // keep the timestamp of the last output frame
+ mEndTimeMillis = System.currentTimeMillis();
+
+ // don't count the time for the initial frames that are ignored
+ if (count == mInitialFramesToIgnoreCount) {
+ mStartTimeMillis = mEndTimeMillis;
+ }
+ }
+
public Double doDecode() throws Exception {
MediaFormat format = setUpSource(mTestFile);
+ ArrayList<MediaFormat> formats = new ArrayList<>();
+ formats.add(format);
+ // If the decoder doesn't support the formats, then return 0 to indicate that decode failed
+ if (!areFormatsSupported(mDecoderName, formats)) {
+ return (Double) 0.0;
+ }
mCodec = MediaCodec.createByCodecName(mDecoderName);
mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
configureCodec(format, mIsAsync, false, false, mServerURL);
@@ -870,11 +925,14 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> {
mCodec.release();
return (Double) 0.0;
}
- long start = System.currentTimeMillis();
+
+ // capture timestamps at receipt of output buffers
+ setOutputCountListener(i -> onOutputCountListener(i));
+
doWork(Integer.MAX_VALUE);
queueEOS();
waitForAllOutputs();
- long end = System.currentTimeMillis();
+
mCodec.stop();
mCodec.release();
mExtractor.release();
@@ -884,7 +942,8 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> {
if (mDrm != null) {
mDrm.close();
}
- double fps = mOutputCount / ((end - start) / 1000.0);
+ double fps = (mOutputCount - mInitialFramesToIgnoreCount) /
+ ((mEndTimeMillis - mStartTimeMillis) / 1000.0);
Log.d(LOG_TAG, "Decode Mime: " + mMime + " Decoder: " + mDecoderName +
" Achieved fps: " + fps);
return fps;
@@ -908,13 +967,7 @@ class DecodeToSurface extends Decode {
mSurface = surface;
}
- void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- mSawOutputEOS = true;
- }
- if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
- mOutputCount++;
- }
+ void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) {
mCodec.releaseOutputBuffer(bufferIndex, true);
}
}
@@ -930,6 +983,10 @@ class Encode extends CodecEncoderTestBase implements Callable<Double> {
private final boolean mIsAsync;
private final int mBitrate;
+ private int mInitialFramesToIgnoreCount = 1;
+ private long mStartTimeMillis = 0;
+ private long mEndTimeMillis = 0;
+
Encode(String mime, String encoderName, boolean isAsync, int height, int width, int frameRate,
int bitrate) {
super(mime);
@@ -941,6 +998,21 @@ class Encode extends CodecEncoderTestBase implements Callable<Double> {
mWidth = width;
}
+ public void setInitialFramesToIgnoreCount(int count) {
+ mInitialFramesToIgnoreCount = count;
+ }
+
+ // measure throughput at the output port
+ private void onOutputCountListener(int count) {
+ // keep the timestamp of the last output frame
+ mEndTimeMillis = System.currentTimeMillis();
+
+ // don't count the time for the initial frames that are ignored
+ if (count == mInitialFramesToIgnoreCount) {
+ mStartTimeMillis = mEndTimeMillis;
+ }
+ }
+
private MediaFormat setUpFormat() {
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, mMime);
@@ -964,14 +1036,18 @@ class Encode extends CodecEncoderTestBase implements Callable<Double> {
mCodec = MediaCodec.createByCodecName(mEncoderName);
configureCodec(format, mIsAsync, false, true);
mCodec.start();
- long start = System.currentTimeMillis();
+
+ // capture timestamps at receipt of output buffers
+ setOutputCountListener(i -> onOutputCountListener(i));
+
doWork(Integer.MAX_VALUE);
queueEOS();
waitForAllOutputs();
- long end = System.currentTimeMillis();
+
mCodec.stop();
mCodec.release();
- double fps = mOutputCount / ((end - start) / 1000.0);
+ double fps = (mOutputCount - mInitialFramesToIgnoreCount) /
+ ((mEndTimeMillis - mStartTimeMillis) / 1000.0);
Log.d(LOG_TAG, "Encode Mime: " + mMime + " Encoder: " + mEncoderName +
" Achieved fps: " + fps);
return fps;
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java
index 37267b275d3..cfd1b5d9749 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java
@@ -17,6 +17,7 @@
package android.mediapc.cts;
import static android.mediav2.common.cts.CodecTestBase.PROFILE_HLG_MAP;
+import static android.mediapc.cts.CodecTestBase.areFormatsSupported;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -31,6 +32,7 @@ import android.view.Surface;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.Callable;
@@ -383,6 +385,13 @@ class Transcode extends CodecTranscoderTestBase implements Callable<Double> {
public Double doTranscode() throws Exception {
MediaFormat decoderFormat = setUpSource(mTestFile);
+ ArrayList<MediaFormat> formats = new ArrayList<>();
+ formats.add(decoderFormat);
+ // If the decoder doesn't support the formats, then return 0 to indicate that decode failed
+ if (!areFormatsSupported(mDecoderName, formats)) {
+ return (Double) 0.0;
+ }
+
mDecoder = MediaCodec.createByCodecName(mDecoderName);
MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat);
mEncoder = MediaCodec.createByCodecName(mEncoderName);
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
index aad1c621f97..9fffb349568 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
@@ -95,7 +95,8 @@ public class FrameDropTestBase {
m2160p60FpsTestFiles.put(HEVC, "bbb_3840x2160_18mbps_60fps_hevc.mkv");
m2160p60FpsTestFiles.put(VP8, "bbb_3840x2160_24mbps_60fps_vp8.webm");
m2160p60FpsTestFiles.put(VP9, "bbb_3840x2160_18mbps_60fps_vp9.webm");
- m2160p60FpsTestFiles.put(AV1, "bbb_3840x2160_18mbps_60fps_av1.mp4");
+ // Limit AV1 4k tests to 1080p as per PC14 requirements
+ m2160p60FpsTestFiles.put(AV1, "bbb_1920x1080_6mbps_60fps_av1.mp4");
m540p30FpsTestFiles.put(AVC, "bbb_960x540_2mbps_30fps_avc.mp4");
m540p30FpsTestFiles.put(HEVC, "bbb_960x540_2mbps_30fps_hevc.mp4");
diff --git a/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
index 393d9044b76..c7d100e736b 100644
--- a/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
+++ b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java
@@ -27,7 +27,6 @@ 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;
@@ -40,7 +39,7 @@ 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;
+ private final long mEachFrameTimeIntervalUs;
private final boolean mIsAsync;
private int mFrameDropCount;
@@ -60,33 +59,48 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
private Thread mThread;
class OutputHandler implements Runnable {
- private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mQueue = new LinkedList<>();
+ class BufferData {
+ public final int frameCount; // total count of full frames up to this point
+ public final int bufferIndex;
+ public final MediaCodec.BufferInfo info;
+
+ public BufferData(int frameCount, int bufferIndex, MediaCodec.BufferInfo info) {
+ this.frameCount = frameCount;
+ this.bufferIndex = bufferIndex;
+ this.info = info;
+ }
+ };
+
+ private final ArrayList<BufferData> mQueue = new ArrayList<>();
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;
+ private BufferData getOutput() throws InterruptedException {
+ BufferData output = null;
mLock.lock();
- while (!mStop) {
- if (mQueue.isEmpty()) {
- mCondition.await();
- } else {
- element = mQueue.remove(0);
- break;
+ try {
+ while (!mStop) {
+ if (mQueue.isEmpty()) {
+ mCondition.await();
+ } else {
+ output = mQueue.remove(0);
+ break;
+ }
}
+ } finally {
+ mLock.unlock();
}
- mLock.unlock();
- return element;
+ return output;
}
@Override
public void run() {
try {
while (true) {
- Pair<Integer, MediaCodec.BufferInfo> element = getOutput();
- if (element != null) {
- releaseOutput(element.first, element.second);
+ BufferData output = getOutput();
+ if (output != null) {
+ delayedReleaseOutput(output.frameCount, output.bufferIndex, output.info);
} else {
break;
}
@@ -96,18 +110,24 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
}
}
- public void add(int bufferIndex, MediaCodec.BufferInfo info) {
+ public void add(int outputCount, int bufferIndex, MediaCodec.BufferInfo info) {
mLock.lock();
- mQueue.add(new Pair<>(bufferIndex, info));
- mCondition.signal();
- mLock.unlock();
+ try {
+ mQueue.add(new BufferData(outputCount, bufferIndex, info));
+ mCondition.signal();
+ } finally {
+ mLock.unlock();
+ }
}
public void stop() throws Exception {
mLock.lock();
- mStop = true;
- mCondition.signal();
- mLock.unlock();
+ try {
+ mStop = true;
+ mCondition.signal();
+ } finally {
+ mLock.unlock();
+ }
}
}
@@ -260,27 +280,25 @@ 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;
- }
+ protected void releaseOutput(int outputCount, int bufferIndex, MediaCodec.BufferInfo info) {
+ mOutputHandler.add(outputCount, bufferIndex, info);
}
- void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) {
+
+ void delayedReleaseOutput(int outputCount, 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) {
+ if (outputCount == 0) {
// delay rendering the first frame by the specific delay
mRenderStartTimeUs = nowUs + mInitialDelay * mEachFrameTimeIntervalUs;
}
- if (nowUs > getRenderTimeUs(mOutputCount + 1)) {
+ if (nowUs > getRenderTimeUs(outputCount + 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++;
mCodec.releaseOutputBuffer(bufferIndex, false);
- } else if (nowUs > getRenderTimeUs(mOutputCount)) {
+ } else if (nowUs > getRenderTimeUs(outputCount)) {
// If the current sample timeStamp is greater than the actual presentation timeStamp
// of the current sample, we can render it.
mCodec.releaseOutputBuffer(bufferIndex, true);
@@ -289,9 +307,9 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
// We are okay with directly rendering the sample if we are less by not more than
// half of one sample duration. Otherwise we sleep for how much more we are less
// than the half of one sample duration.
- if ((getRenderTimeUs(mOutputCount) - nowUs) > (mEachFrameTimeIntervalUs / 2)) {
+ if ((getRenderTimeUs(outputCount) - nowUs) > (mEachFrameTimeIntervalUs / 2)) {
try {
- Thread.sleep(((getRenderTimeUs(mOutputCount) - nowUs) -
+ Thread.sleep(((getRenderTimeUs(outputCount) - nowUs) -
(mEachFrameTimeIntervalUs / 2)) / 1000);
} catch (InterruptedException e) {
// Do nothing.
@@ -299,8 +317,5 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase {
}
mCodec.releaseOutputBuffer(bufferIndex, true);
}
- if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
- mOutputCount++;
- }
}
}
diff --git a/tests/openglperf2/AndroidTest.xml b/tests/openglperf2/AndroidTest.xml
index d7fc0d2d3f5..f9975c13fc7 100644
--- a/tests/openglperf2/AndroidTest.xml
+++ b/tests/openglperf2/AndroidTest.xml
@@ -28,7 +28,7 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.opengl2.cts" />
<option name="runtime-hint" value="4m" />
- <!-- test-timeout unit is ms, value = 100 min -->
- <option name="test-timeout" value="6000000" />
+ <!-- test-timeout unit is ms, value = 10 min -->
+ <option name="test-timeout" value="600000" />
</test>
</configuration>
diff --git a/tests/signature/api-check/shared-libs-api/Android.bp b/tests/signature/api-check/shared-libs-api/Android.bp
index 607df480758..6a53a7502e3 100644
--- a/tests/signature/api-check/shared-libs-api/Android.bp
+++ b/tests/signature/api-check/shared-libs-api/Android.bp
@@ -123,8 +123,8 @@ genrule {
" apiLevel=$${apiLevel%_api.txt} && " +
" if [ -z $${apiLevel} ]; then apiLevel=public; fi && " +
// Convert the .txt file into its XML representation.
- " $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED --no-banner " +
- " -convert2xmlnostrip $${f} $(genDir)/list/$${fileName}-current-$${apiLevel}.api; " +
+ " $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED " +
+ " signature-to-jdiff $${f} $(genDir)/list/$${fileName}-current-$${apiLevel}.api; " +
"done && " +
"$(location soong_zip) -o $(out) -C $(genDir)/list -D $(genDir)/list",
}
@@ -150,8 +150,8 @@ genrule {
" platformSdkVersion=$$(echo $${f} | awk -F/ '{print $$(3)}') && " +
" if [ $${platformSdkVersion} -lt 28 ]; then continue; fi && " +
" apiLevel=$$(echo $${f} | awk -F/ '{print $$(4)}') && " +
- " $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED --no-banner " +
- " -convert2xmlnostrip $${f} $(genDir)/list/$${fileName}-$${platformSdkVersion}-$${apiLevel}.api; " +
+ " $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED " +
+ " signature-to-jdiff $${f} $(genDir)/list/$${fileName}-$${platformSdkVersion}-$${apiLevel}.api; " +
"done && " +
"$(location soong_zip) -o $(out) -C $(genDir)/list -D $(genDir)/list",
}
diff --git a/tests/signature/api-check/system-api/Android.bp b/tests/signature/api-check/system-api/Android.bp
index 7263c8464d4..3ddba35627f 100644
--- a/tests/signature/api-check/system-api/Android.bp
+++ b/tests/signature/api-check/system-api/Android.bp
@@ -56,8 +56,8 @@ genrule {
" platformSdkVersion=$$(echo $${f} | awk -F/ '{print $$(3)}') && " +
" if [ $${platformSdkVersion} -lt 28 ]; then continue; fi && " +
" apiLevel=$$(echo $${f} | awk -F/ '{print $$(4)}') && " +
- " $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED --no-banner " +
- " -convert2xmlnostrip $${f} $(genDir)/list/$${platformSdkVersion}-$${apiLevel}.api; " +
+ " $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED " +
+ " signature-to-jdiff $${f} $(genDir)/list/$${platformSdkVersion}-$${apiLevel}.api; " +
"done &&" +
"$(location soong_zip) -o $(out) -C $(genDir)/list -D $(genDir)/list",
}
diff --git a/tests/signature/api/Android.bp b/tests/signature/api/Android.bp
index 3f24355a619..a746726982f 100644
--- a/tests/signature/api/Android.bp
+++ b/tests/signature/api/Android.bp
@@ -18,7 +18,7 @@ package {
genrule_defaults {
name: "signature-cts-api-api-gz",
- cmd: "$(location metalava) --no-banner -convert2xmlnostrip $(in) $(genDir)/api.xml && gzip -c $(genDir)/api.xml > $(out)",
+ cmd: "$(location metalava) signature-to-jdiff $(in) $(genDir)/api.xml && gzip -c $(genDir)/api.xml > $(out)",
tools: ["metalava"],
visibility: [
"//cts/tests/signature/api-check:__subpackages__",
diff --git a/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java b/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java
index e6d721a0e88..9cc12279367 100644
--- a/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java
+++ b/tests/signature/lib/common/src/android/signature/cts/ReflectionHelper.java
@@ -17,6 +17,7 @@ package android.signature.cts;
import android.signature.cts.JDiffClassDescription.JDiffConstructor;
import android.signature.cts.JDiffClassDescription.JDiffMethod;
+
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
@@ -611,7 +612,11 @@ public class ReflectionHelper {
public static boolean isOverridingAnnotatedMethod(Method method, String annotationSpec) {
Class<?> clazz = method.getDeclaringClass();
- while (!(clazz = clazz.getSuperclass()).equals(Object.class)) {
+ while (true) {
+ clazz = clazz.getSuperclass();
+ if (clazz == null || Object.class.equals(clazz)) {
+ break;
+ }
try {
Method overriddenMethod;
overriddenMethod = clazz.getDeclaredMethod(method.getName(),
diff --git a/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java b/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java
index edfd5ff9737..c34a344aa03 100644
--- a/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java
+++ b/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java
@@ -41,6 +41,7 @@ import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
+import android.view.ViewTreeObserver;
import android.view.cts.surfacevalidator.BitmapPixelChecker;
import android.widget.FrameLayout;
@@ -234,7 +235,7 @@ public class AttachedSurfaceControlTest {
if (firstCallback[0] != null) {
Assert.assertTrue(firstCallback[0].await(3, TimeUnit.SECONDS));
scenario.onActivity(activity -> Assert.assertEquals(transformHintResult[0],
- activity.getWindow().getRootSurfaceControl().getBufferTransformHint()));
+ activity.getWindow().getRootSurfaceControl().getBufferTransformHint()));
}
scenario.onActivity(activity -> {
@@ -266,6 +267,8 @@ public class AttachedSurfaceControlTest {
private final CountDownLatch mDrawCompleteLatch = new CountDownLatch(1);
+ private boolean mChildScAttached;
+
GreenAnchorViewWithInsets(Context c, Rect insets) {
super(c, null, 0, 0);
mSurfaceControl = new SurfaceControl.Builder()
@@ -277,21 +280,46 @@ public class AttachedSurfaceControlTest {
canvas.drawColor(Color.GREEN);
mSurface.unlockCanvasAndPost(canvas);
mChildBoundingInsets = insets;
+
+ getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ attachChildSc();
+ getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
+ });
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ attachChildSc();
+ }
+
+ private void attachChildSc() {
+ if (mChildScAttached) {
+ return;
+ }
+ // This should be called even if buildReparentTransaction fails the first time since
+ // the second call will come from preDrawListener which is called after bounding insets
+ // are updated in VRI.
+ getRootSurfaceControl().setChildBoundingInsets(mChildBoundingInsets);
+
SurfaceControl.Transaction t =
getRootSurfaceControl().buildReparentTransaction(mSurfaceControl);
- getRootSurfaceControl().setChildBoundingInsets(mChildBoundingInsets);
- t.setLayer(mSurfaceControl, 1)
- .setVisibility(mSurfaceControl, true)
- .apply();
+ if (t == null) {
+ // TODO (b/286406553) SurfaceControl was not yet setup. Wait until the draw request
+ // to attach since the SurfaceControl will be created by that point. This can be
+ // cleaned up when the bug is fixed.
+ return;
+ }
+ t.setLayer(mSurfaceControl, 1).setVisibility(mSurfaceControl, true);
t.addTransactionCommittedListener(Runnable::run, mDrawCompleteLatch::countDown);
getRootSurfaceControl().applyTransactionOnDraw(t);
+ mChildScAttached = true;
}
@Override
@@ -299,6 +327,7 @@ public class AttachedSurfaceControlTest {
new SurfaceControl.Transaction().reparent(mSurfaceControl, null).apply();
mSurfaceControl.release();
mSurface.release();
+ mChildScAttached = false;
super.onDetachedFromWindow();
}
@@ -335,7 +364,7 @@ public class AttachedSurfaceControlTest {
countDownLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
view[0].waitForDrawn();
- // Do not include system insets because the child SC is not layed out in the system
+ // Do not include system insets because the child SC is not laid out in the system
// insets
validateScreenshot(mName, activity[0],
new BitmapPixelChecker(Color.GREEN, new Rect(0, 10, 100, 100)),
diff --git a/tests/surfacecontrol/src/android/view/surfacecontrol/cts/SurfaceViewSyncTest.java b/tests/surfacecontrol/src/android/view/surfacecontrol/cts/SurfaceViewSyncTest.java
index 0c80ed506f6..ad28177b4a9 100644
--- a/tests/surfacecontrol/src/android/view/surfacecontrol/cts/SurfaceViewSyncTest.java
+++ b/tests/surfacecontrol/src/android/view/surfacecontrol/cts/SurfaceViewSyncTest.java
@@ -39,7 +39,6 @@ import android.view.cts.surfacevalidator.ViewFactory;
import android.widget.FrameLayout;
import androidx.test.filters.LargeTest;
-import androidx.test.filters.RequiresDevice;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -52,7 +51,6 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@LargeTest
@SuppressLint("RtlHardcoded")
-@RequiresDevice
public class SurfaceViewSyncTest {
private static final String TAG = "SurfaceViewSyncTests";
diff --git a/tests/tests/appwidget/Android.bp b/tests/tests/appwidget/Android.bp
index 9fc1a0d054d..89b1e106a80 100644
--- a/tests/tests/appwidget/Android.bp
+++ b/tests/tests/appwidget/Android.bp
@@ -37,6 +37,7 @@ android_test {
"ctstestrunner-axt",
"junit",
"compatibility-device-util-axt",
+ "cts-wm-util",
],
libs: ["android.test.base"],
// Tag this module as a cts test artifact
@@ -51,6 +52,7 @@ android_test {
":CtsAppWidgetProvider1",
":CtsAppWidgetLauncher1",
":CtsAppWidgetProvider2",
+ ":CtsAppWidgetTestCasesBalApp",
],
per_testcase_directory: true,
}
diff --git a/tests/tests/appwidget/AndroidManifest.xml b/tests/tests/appwidget/AndroidManifest.xml
index b99f9084099..5d8b055522c 100644
--- a/tests/tests/appwidget/AndroidManifest.xml
+++ b/tests/tests/appwidget/AndroidManifest.xml
@@ -22,6 +22,7 @@
<queries>
<!-- UpdateProviderInfoTest queries widget providers. -->
<package android:name="android.appwidget.cts.widgetprovider"/>
+ <package android:name="android.appwidget.cts.appbal" />
</queries>
<application>
diff --git a/tests/tests/appwidget/AndroidTest.xml b/tests/tests/appwidget/AndroidTest.xml
index db4aa66a936..96c6a1e0ec5 100644
--- a/tests/tests/appwidget/AndroidTest.xml
+++ b/tests/tests/appwidget/AndroidTest.xml
@@ -26,8 +26,8 @@
<option name="test-file-name" value="CtsAppWidgetLauncher2.apk" />
<option name="test-file-name" value="CtsAppWidgetLauncher3.apk" />
<option name="test-file-name" value="CtsAppWidgetTestCases.apk" />
+ <option name="test-file-name" value="CtsAppWidgetTestCasesBalApp.apk" />
</target_preparer>
-
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="mkdir -p /data/local/tmp/cts/widgetprovider/" />
<option name="teardown-command" value="rm -rf /data/local/tmp/cts/widgetprovider"/>
diff --git a/tests/tests/appwidget/AppBal/Android.bp b/tests/tests/appwidget/AppBal/Android.bp
new file mode 100644
index 00000000000..5c4b2732778
--- /dev/null
+++ b/tests/tests/appwidget/AppBal/Android.bp
@@ -0,0 +1,41 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsAppWidgetTestCasesBalApp",
+ defaults: ["cts_defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+
+ target_sdk_version: "32",
+
+ static_libs: [
+ "mockito-target-minus-junit4",
+ "ctstestrunner-axt",
+ "junit",
+ "compatibility-device-util-axt",
+ "cts-wm-util",
+ ],
+ libs: ["android.test.base"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ ],
+}
diff --git a/tests/tests/appwidget/AppBal/AndroidManifest.xml b/tests/tests/appwidget/AppBal/AndroidManifest.xml
new file mode 100755
index 00000000000..e0c4ed11dd3
--- /dev/null
+++ b/tests/tests/appwidget/AppBal/AndroidManifest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.appwidget.cts.appbal">
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+
+ <queries>
+ <!-- UpdateProviderInfoTest queries widget providers. -->
+ <package android:name="android.appwidget.cts.widgetprovider"/>
+ <package android:name="android.appwidget.cts" />
+ </queries>
+ <application>
+ <activity
+ android:name="android.appwidget.cts.appbal.BalActivity"
+ android:label="BalActivity"
+ android:visibleToInstantApps="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="android.appwidget.cts.appbal.EmptyActivity"
+ android:exported="true" />
+
+ <service
+ android:name="android.appwidget.cts.appbal.BalService"
+ android:exported="true" />
+
+ <receiver android:name="android.appwidget.cts.appbal.BalAppWidgetProvider"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
+ </intent-filter>
+ <meta-data android:name="android.appwidget.provider"
+ android:resource="@xml/widget_info" />
+ </receiver>
+ </application>
+</manifest>
diff --git a/tests/tests/appwidget/AppBal/res/xml/widget_info.xml b/tests/tests/appwidget/AppBal/res/xml/widget_info.xml
new file mode 100644
index 00000000000..b0e66eda9eb
--- /dev/null
+++ b/tests/tests/appwidget/AppBal/res/xml/widget_info.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+<appwidget-provider
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="180dp"
+ android:minHeight="110dp"
+ android:updatePeriodMillis="86400000"
+ android:resizeMode="horizontal|vertical"
+ android:widgetCategory="home_screen">
+</appwidget-provider> \ No newline at end of file
diff --git a/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalActivity.java b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalActivity.java
new file mode 100644
index 00000000000..353b751d423
--- /dev/null
+++ b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 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.appwidget.cts.appbal;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class BalActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ requestAppWidget();
+ }
+
+ private void requestAppWidget() {
+ try {
+ // pinResult tries to launch a service which launches a background activity.
+ PendingIntent pinResult = PendingIntent.getService(this, 0,
+ new Intent(this, BalService.class),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
+ AppWidgetManager appWidgetManager = this.getSystemService(AppWidgetManager.class);
+ android.content.ComponentName firstWidgetProvider =
+ new android.content.ComponentName(this, BalAppWidgetProvider.class);
+ appWidgetManager.requestPinAppWidget(firstWidgetProvider, null, pinResult);
+ Log.i("BalActivity", "requested pin App widget");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalAppWidgetProvider.java b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalAppWidgetProvider.java
new file mode 100644
index 00000000000..97eab2d4081
--- /dev/null
+++ b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalAppWidgetProvider.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 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.appwidget.cts.appbal;
+
+import android.appwidget.AppWidgetProvider;
+
+public class BalAppWidgetProvider extends AppWidgetProvider {
+}
diff --git a/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalService.java b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalService.java
new file mode 100644
index 00000000000..c529681e424
--- /dev/null
+++ b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/BalService.java
@@ -0,0 +1,62 @@
+/*
+ * 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.appwidget.cts.appbal;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+
+public class BalService extends Service {
+
+ Handler mHandler;
+
+ public BalService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ Log.i("BalService", "Service started");
+ mHandler = new Handler();
+ mHandler.postDelayed(this::startBackgroundActivity, 1000 * 30);
+ super.onCreate();
+ }
+
+ void startBackgroundActivity() {
+ try {
+ Log.e("BalService", "Start background activity called");
+ Intent intent = new Intent(this, EmptyActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ this.startActivity(intent);
+
+ } catch (Exception e) {
+ Log.e("BalService", "startBackgroundActivity throws exception." + e);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.i("BalService", "Service destroyed!");
+ super.onDestroy();
+ }
+}
diff --git a/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/EmptyActivity.java b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/EmptyActivity.java
new file mode 100644
index 00000000000..5b57d2cec55
--- /dev/null
+++ b/tests/tests/appwidget/AppBal/src/android.appwidget.cts.appbal/EmptyActivity.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 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.appwidget.cts.appbal;
+
+import android.app.Activity;
+
+public class EmptyActivity extends Activity { }
diff --git a/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.java b/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.java
index 7fc72114cef..a8ac2eee609 100644
--- a/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.java
+++ b/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.java
@@ -30,10 +30,10 @@ public class AppWidgetConfirmPin extends Activity {
private PinItemRequest mRequest;
private BroadcastReceiver mReceiver;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
try {
final LauncherApps launcherApps = getSystemService(LauncherApps.class);
mRequest = launcherApps.getPinItemRequest(getIntent());
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java b/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
index 4e68779020e..6e9d7885df1 100644
--- a/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
+++ b/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
@@ -16,20 +16,30 @@
package android.appwidget.cts;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.server.wm.UiDeviceUtils.pressHomeButton;
+
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.ActivityManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
+import android.appwidget.cts.activity.EmptyActivity;
import android.appwidget.cts.common.Constants;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.os.Bundle;
import android.platform.test.annotations.AppModeFull;
+import android.server.wm.WindowManagerStateHelper;
+import android.util.Log;
import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.SystemUtil;
import org.junit.After;
import org.junit.Before;
@@ -46,6 +56,8 @@ public class RequestPinAppWidgetTest extends AppWidgetTestCase {
private String mDefaultLauncher;
+ protected WindowManagerStateHelper mWmState = new WindowManagerStateHelper();
+
@Before
public void setUpLauncher() throws Exception {
mDefaultLauncher = getDefaultLauncher();
@@ -57,7 +69,7 @@ public class RequestPinAppWidgetTest extends AppWidgetTestCase {
setLauncher(mDefaultLauncher);
}
- @CddTest(requirement="3.8.2/C-2-2")
+ @CddTest(requirement = "3.8.2/C-2-2")
private void runPinWidgetTest(final String launcherPkg) throws Exception {
setLauncher(launcherPkg + "/" + LAUNCHER_CLASS);
@@ -103,7 +115,7 @@ public class RequestPinAppWidgetTest extends AppWidgetTestCase {
assertEquals("dummy-2", resultReceiver.result.getStringExtra("dummy"));
}
- @Ignore("b/265187199")
+ //@Ignore("b/265187199")
@Test
public void testPinWidget_launcher1() throws Exception {
runPinWidgetTest("android.appwidget.cts.packages.launcher1");
@@ -115,9 +127,9 @@ public class RequestPinAppWidgetTest extends AppWidgetTestCase {
runPinWidgetTest("android.appwidget.cts.packages.launcher2");
}
- @CddTest(requirement="3.8.2/C-2-1")
+ @CddTest(requirement = "3.8.2/C-2-1")
public void verifyIsRequestPinAppWidgetSupported(String launcherPkg, boolean expectedSupport)
- throws Exception {
+ throws Exception {
setLauncher(launcherPkg + "/" + LAUNCHER_CLASS);
Context context = getInstrumentation().getContext();
@@ -155,7 +167,52 @@ public class RequestPinAppWidgetTest extends AppWidgetTestCase {
}
private void setLauncher(String component) throws Exception {
- runShellCommand("cmd package set-home-activity --user "
+ Log.i("BalActivity", "cmd package set-home-activity --user "
+ getInstrumentation().getContext().getUserId() + " " + component);
+ /*runShellCommand("cmd package set-home-activity --user "
+ + getInstrumentation().getContext().getUserId() + " " + component);*/
+ runShellCommand("cmd package set-home-activity "
+ + component);
}
+
+ @Test
+ public void testRequestPinAppWidgetNotAllBal() throws Exception {
+ String launcherPkg = "android.appwidget.cts.packages.launcher1";
+ setLauncher(launcherPkg + "/" + LAUNCHER_CLASS);
+ Context context = getInstrumentation().getContext();
+ // Request to pin widget
+ BlockingBroadcastReceiver setupReceiver = new BlockingBroadcastReceiver()
+ .register(Constants.ACTION_SETUP_REPLY);
+
+ // starts the BalActivity in the test app AppBal.
+ context.startActivity(new Intent(Intent.ACTION_MAIN)
+ .setPackage("android.appwidget.cts.appbal")
+ .addFlags(FLAG_ACTIVITY_NEW_TASK));
+
+ setupReceiver.await();
+ // Verify that the confirmation dialog was opened
+ assertTrue(setupReceiver.result.getBooleanExtra(Constants.EXTRA_SUCCESS, false));
+
+ // Accept the request
+ context.sendBroadcast(new Intent(Constants.ACTION_CONFIRM_PIN)
+ .setPackage(launcherPkg));
+
+ // Press home key to ensure stopAppSwitches is called because the last-stop-app-switch-time
+ // is a criteria of allowing background start.
+ pressHomeButton();
+ SystemUtil.runWithShellPermissionIdentity(ActivityManager::resumeAppSwitches);
+ mWmState.waitForHomeActivityVisible();
+ SystemUtil.runWithShellPermissionIdentity(ActivityManager::resumeAppSwitches);
+
+ boolean result = false;
+ // The background activity will be launched 30s after the BalService starts. The
+ // waitForFocusedActivity only waits for 5s. So put it in a for loop.
+ for (int i = 0; i < 10; i++) {
+ result = mWmState.waitForFocusedActivity(
+ "Empty Activity is launched", new ComponentName(context, EmptyActivity.class));
+ if (result) break;
+ }
+ assertFalse("Should not able to launch background activity", result);
+ }
+
}
diff --git a/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java b/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java
index 74468ff75db..8db12e3e136 100644
--- a/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java
+++ b/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java
@@ -17,6 +17,10 @@ package android.assist.cts;
import static android.assist.common.Utils.SHOW_SESSION_FLAGS_TO_SET;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeFalse;
+
import android.assist.common.AutoResetLatch;
import android.assist.common.Utils;
import android.content.Intent;
@@ -25,7 +29,6 @@ import android.util.Log;
import org.junit.Test;
-import static com.google.common.truth.Truth.assertWithMessage;
public class ExtraAssistDataTest extends AssistTestBase {
private static final String TAG = "ExtraAssistDataTest";
private static final String TEST_CASE_TYPE = Utils.EXTRA_ASSIST;
@@ -37,10 +40,7 @@ public class ExtraAssistDataTest extends AssistTestBase {
@Test
public void testAssistContentAndAssistData() throws Exception {
- if (mActivityManager.isLowRamDevice()) {
- Log.d(TAG, "Not running assist tests on low-RAM device.");
- return;
- }
+ assumeIsNotLowRamDevice();
startTest(TEST_CASE_TYPE);
waitForAssistantToBeReady();
start3pApp(TEST_CASE_TYPE);
@@ -72,10 +72,12 @@ public class ExtraAssistDataTest extends AssistTestBase {
@Test
public void testAssistContentAndDataNullWhenNoFlagsToShowSession() throws Exception {
- if (mActivityManager.isLowRamDevice()) {
- Log.d(TAG, "Not running assist tests on low-RAM device.");
- return;
- }
+ assumeIsNotLowRamDevice();
+ // TODO(b/299988169): Fix multi/secure displays for automotive
+ // Currently automotive uses multi-display and/or secure displays
+ // and sending null data is not supported due to the lack of information in main voice
+ // interaction service.
+ assumeIsNotAutomotive();
startTest(TEST_CASE_TYPE);
waitForAssistantToBeReady();
start3pApp(TEST_CASE_TYPE);
@@ -88,4 +90,12 @@ public class ExtraAssistDataTest extends AssistTestBase {
verifyActivityIdNullness(/* isActivityIdNull = */ false);
verifyAssistDataNullness(true, true, true, true);
}
+
+ private void assumeIsNotAutomotive() {
+ assumeFalse("Test not supported in automotive", Utils.isAutomotive(mContext));
+ }
+
+ private void assumeIsNotLowRamDevice() {
+ assumeFalse("Test not supported for low-RAM devices", mActivityManager.isLowRamDevice());
+ }
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
index a55df67a9bc..9701bbdbd6a 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
@@ -33,6 +33,7 @@ import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothSinkAudioPolicy;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.OobData;
@@ -391,8 +392,10 @@ public class BluetoothDeviceTest extends AndroidTestCase {
}
public void test_messageAccessPermission() {
- if (!mHasBluetooth || !mHasCompanionDevice) {
- // Skip the test if bluetooth or companion device are not present.
+ if (!mHasBluetooth || !mHasCompanionDevice
+ || !TestUtils.isProfileEnabled(BluetoothProfile.MAP)) {
+ // Skip the test if bluetooth or companion device are not present,
+ // or if MAP is not enabled.
return;
}
@@ -416,8 +419,10 @@ public class BluetoothDeviceTest extends AndroidTestCase {
}
public void test_phonebookAccessPermission() {
- if (!mHasBluetooth || !mHasCompanionDevice) {
- // Skip the test if bluetooth or companion device are not present.
+ if (!mHasBluetooth || !mHasCompanionDevice
+ || !TestUtils.isProfileEnabled(BluetoothProfile.PBAP)) {
+ // Skip the test if bluetooth or companion device are not present,
+ // of if PBAP is not enabled.
return;
}
@@ -441,8 +446,10 @@ public class BluetoothDeviceTest extends AndroidTestCase {
}
public void test_simAccessPermission() {
- if (!mHasBluetooth || !mHasCompanionDevice) {
- // Skip the test if bluetooth or companion device are not present.
+ if (!mHasBluetooth || !mHasCompanionDevice
+ || !TestUtils.isProfileEnabled(BluetoothProfile.SAP)) {
+ // Skip the test if bluetooth or companion device are not present,
+ // or if SAP is not enabled.
return;
}
diff --git a/tests/tests/car/AndroidManifest.xml b/tests/tests/car/AndroidManifest.xml
index 9b561baa5e0..0dfa316a6b4 100644
--- a/tests/tests/car/AndroidManifest.xml
+++ b/tests/tests/car/AndroidManifest.xml
@@ -17,12 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.car.cts">
<uses-feature android:name="android.hardware.type.automotive" />
- <uses-permission android:name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID" />
- <uses-permission android:name="android.car.permission.CAR_POWER" />
- <uses-permission android:name="android.car.permission.CAR_TEST_SERVICE" />
- <!-- for CarRemoteDeviceManagerTest and CarOccupantConnectionManagerTest-->
- <uses-permission android:name="android.car.permission.MANAGE_REMOTE_DEVICE" />
- <uses-permission android:name="android.car.permission.MANAGE_OCCUPANT_CONNECTION" />
<uses-permission android:name="android.car.permission.READ_CAR_POWER_POLICY" />
<uses-permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/tests/tests/car/src/android/car/app/cts/CarActivityManagerTest.java b/tests/tests/car/src/android/car/app/cts/CarActivityManagerTest.java
index 47358d47b13..f17a4fd377f 100644
--- a/tests/tests/car/src/android/car/app/cts/CarActivityManagerTest.java
+++ b/tests/tests/car/src/android/car/app/cts/CarActivityManagerTest.java
@@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.Manifest;
@@ -188,6 +189,10 @@ public class CarActivityManagerTest {
@ApiTest(apis = {"android.car.app.CarActivityManager#moveRootTaskToDisplay(int,int)",
"android.car.builtin.app.ActivityManagerHelper#moveRootTaskToDisplay(int,int)"})
public void testMoveRootTaskToDisplay() throws Exception {
+ // TODO(b/300466988): Create a new API that can move a leaf task to display even when there
+ // are extra nested root tasks in the hierarchy.
+ assumeFalse(hasSplitscreenMultitaskingFeature());
+
try (VirtualDisplaySession session = new VirtualDisplaySession()) {
// create a secondary virtual display
Display secondaryDisplay = session.createDisplay(mContext,
@@ -323,4 +328,13 @@ public class CarActivityManagerTest {
public static final class BlankActivity extends Activity {
}
+
+ /**
+ * Checks whether the device has automotive split-screen multitasking feature enabled
+ */
+ private boolean hasSplitscreenMultitaskingFeature() {
+ return mContext.getPackageManager()
+ .hasSystemFeature(/* PackageManager.FEATURE_CAR_SPLITSCREEN_MULTITASKING */
+ "android.software.car.splitscreen_multitasking");
+ }
}
diff --git a/tests/tests/car/src/android/car/cts/CarDisplayInputLockTest.java b/tests/tests/car/src/android/car/cts/CarDisplayInputLockTest.java
index 210cde28b53..6163592b9c7 100644
--- a/tests/tests/car/src/android/car/cts/CarDisplayInputLockTest.java
+++ b/tests/tests/car/src/android/car/cts/CarDisplayInputLockTest.java
@@ -33,12 +33,14 @@ import android.car.Car;
import android.car.CarOccupantZoneManager;
import android.car.annotation.ApiRequirements;
import android.car.settings.CarSettings;
+import android.car.test.PermissionsCheckerRule.EnsureHasPermission;
import android.content.ContentResolver;
import android.graphics.Color;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.SystemClock;
+import android.os.UserManager;
import android.provider.Settings;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.Display;
@@ -80,6 +82,10 @@ public class CarDisplayInputLockTest extends AbstractCarTestCase {
@Before
public void setUp() throws Exception {
+ UserManager userManager = mContext.getSystemService(UserManager.class);
+ assumeTrue("This test is enabled only in multi-user/multi-display devices",
+ userManager.isVisibleBackgroundUsersSupported());
+
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContentResolver = mContext.getContentResolver();
mCarOccupantZoneManager =
@@ -90,7 +96,9 @@ public class CarDisplayInputLockTest extends AbstractCarTestCase {
@After
public void tearDown() {
- writeDisplayInputLockSetting(mContentResolver, mInitialSettingValue);
+ if (mContentResolver != null) {
+ writeDisplayInputLockSetting(mContentResolver, mInitialSettingValue);
+ }
}
@CddTest(requirements = {"TODO(b/262236403)"})
@@ -158,6 +166,7 @@ public class CarDisplayInputLockTest extends AbstractCarTestCase {
@ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0,
minPlatformVersion = ApiRequirements.PlatformVersion.UPSIDE_DOWN_CAKE_0)
@Test
+ @EnsureHasPermission(Car.ACCESS_PRIVATE_DISPLAY_ID)
public void testPassengerDisplayInputLockDoesNotAffectDriverDisplay() throws Exception {
int driverDisplayId = mCarOccupantZoneManager.getDisplayIdForDriver(
CarOccupantZoneManager.DISPLAY_TYPE_MAIN);
diff --git a/tests/tests/car/src/android/car/cts/CarOccupantConnectionManagerTest.java b/tests/tests/car/src/android/car/cts/CarOccupantConnectionManagerTest.java
index 429be37de7d..ea49be41185 100644
--- a/tests/tests/car/src/android/car/cts/CarOccupantConnectionManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarOccupantConnectionManagerTest.java
@@ -29,6 +29,7 @@ import android.car.occupantconnection.CarOccupantConnectionManager;
import android.car.occupantconnection.CarOccupantConnectionManager.ConnectionRequestCallback;
import android.car.occupantconnection.Payload;
import android.car.test.ApiCheckerRule;
+import android.car.test.PermissionsCheckerRule.EnsureHasPermission;
import android.car.test.mocks.JavaMockitoHelper;
import android.content.ComponentName;
import android.content.Context;
@@ -60,6 +61,8 @@ import java.util.concurrent.Executor;
@RunWith(AndroidJUnit4.class)
@AppModeFull(reason = "Test relies on other server to connect to.")
+@EnsureHasPermission({Car.PERMISSION_MANAGE_REMOTE_DEVICE,
+ Car.PERMISSION_MANAGE_OCCUPANT_CONNECTION})
public final class CarOccupantConnectionManagerTest extends AbstractCarTestCase {
private static final String TAG = CarOccupantConnectionManagerTest.class.getSimpleName();
diff --git a/tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java b/tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java
index 7a30991d7b1..e82ec1e8dc6 100644
--- a/tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarOccupantZoneManagerTest.java
@@ -368,7 +368,8 @@ public final class CarOccupantZoneManagerTest extends AbstractCarTestCase {
public void testClusterDisplayIsPrivate() {
assumeDriverZone();
- mUiAutomation.adoptShellPermissionIdentity(Car.PERMISSION_MANAGE_OCCUPANT_ZONE);
+ mUiAutomation.adoptShellPermissionIdentity(Car.PERMISSION_MANAGE_OCCUPANT_ZONE,
+ Car.ACCESS_PRIVATE_DISPLAY_ID);
int clusterDisplayId = mCarOccupantZoneManager.getDisplayIdForDriver(
CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER);
diff --git a/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java b/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
index a484964a3bb..830bca6f356 100644
--- a/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPowerManagerTest.java
@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeTrue;
+import android.app.UiAutomation;
import android.car.Car;
import android.car.CarOccupantZoneManager;
import android.car.CarOccupantZoneManager.OccupantZoneInfo;
@@ -39,6 +40,7 @@ import android.util.Log;
import android.view.Display;
import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
import com.android.compatibility.common.util.PollingCheck;
@@ -68,6 +70,7 @@ public final class CarPowerManagerTest extends AbstractCarTestCase {
private static String sDefaultDisplayPowerModeValue;
+ private UiAutomation mUiAutomation;
private CarPowerManager mCarPowerManager;
private CarOccupantZoneManager mCarOccupantZoneManager;
private String mInitialPowerPolicyId;
@@ -82,6 +85,8 @@ public final class CarPowerManagerTest extends AbstractCarTestCase {
@Before
public void setUp() throws Exception {
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity(Car.PERMISSION_CAR_POWER);
mCarPowerManager = (CarPowerManager) getCar().getCarManager(Car.POWER_SERVICE);
mCarOccupantZoneManager = (CarOccupantZoneManager) getCar().getCarManager(
Car.CAR_OCCUPANT_ZONE_SERVICE);
@@ -94,6 +99,7 @@ public final class CarPowerManagerTest extends AbstractCarTestCase {
if (!mInitialPowerPolicyId.equals(policy.getPolicyId())) {
applyPowerPolicy(mInitialPowerPolicyId);
}
+ mUiAutomation.dropShellPermissionIdentity();
}
@BeforeClass
diff --git a/tests/tests/car/src/android/car/cts/CarRemoteDeviceManagerTest.java b/tests/tests/car/src/android/car/cts/CarRemoteDeviceManagerTest.java
index 17a5b05ae10..b842b926635 100644
--- a/tests/tests/car/src/android/car/cts/CarRemoteDeviceManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarRemoteDeviceManagerTest.java
@@ -23,11 +23,13 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;
+import android.car.Car;
import android.car.CarOccupantZoneManager;
import android.car.CarOccupantZoneManager.OccupantZoneInfo;
import android.car.CarRemoteDeviceManager;
import android.car.CarRemoteDeviceManager.StateCallback;
import android.car.test.ApiCheckerRule;
+import android.car.test.PermissionsCheckerRule.EnsureHasPermission;
import android.content.pm.PackageInfo;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
@@ -53,6 +55,7 @@ import java.util.List;
@SmallTest
@RunWith(AndroidJUnit4.class)
@AppModeFull(reason = "Test relies on other server to connect to.")
+@EnsureHasPermission(Car.PERMISSION_MANAGE_REMOTE_DEVICE)
public final class CarRemoteDeviceManagerTest extends AbstractCarTestCase {
private static final String TAG = CarRemoteDeviceManagerTest.class.getSimpleName();
@@ -152,6 +155,8 @@ public final class CarRemoteDeviceManagerTest extends AbstractCarTestCase {
@Test
@ApiTest(apis = {"android.car.CarRemoteDeviceManager#setOccupantZonePower",
"android.car.CarRemoteDeviceManager#isOccupantZonePowerOn"})
+ @EnsureHasPermission({Car.PERMISSION_MANAGE_REMOTE_DEVICE,
+ Car.PERMISSION_CAR_POWER})
public void testSetOccupantZonePower() {
for (OccupantZoneInfo zone : mAllZones) {
if (zone.equals(mMyZone)
diff --git a/tests/tests/car/src/android/car/cts/OemCarServiceImplTest.java b/tests/tests/car/src/android/car/cts/OemCarServiceImplTest.java
index 3efc7465ae7..c8c366ab851 100644
--- a/tests/tests/car/src/android/car/cts/OemCarServiceImplTest.java
+++ b/tests/tests/car/src/android/car/cts/OemCarServiceImplTest.java
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeTrue;
import android.car.Car;
-import android.car.oem.OemCarService;
import android.car.test.CarTestManager;
import android.car.test.PermissionsCheckerRule;
import android.car.test.PermissionsCheckerRule.EnsureHasPermission;
@@ -43,14 +42,8 @@ import java.util.concurrent.CountDownLatch;
public final class OemCarServiceImplTest extends AbstractCarTestCase {
- private static final String TAG = OemCarServiceImplTest.class.getSimpleName();
-
- private final Object mLock = new Object();
-
private CarTestManager mManager;
private String mOemServiceName;
- private OemCarService mOemCarService;
- private boolean mIsOemServiceConnected;
private CountDownLatch mLatch = new CountDownLatch(1);
@Rule
@@ -64,7 +57,8 @@ public final class OemCarServiceImplTest extends AbstractCarTestCase {
// Test should run for TIRAMISU_0. As it is not testing API or CDD, using
// android.car.oem.OemCarService#getSupportedCarVersion so that test run for TIRAMISU_0.
@Test
- @EnsureHasPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ @EnsureHasPermission({android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Car.PERMISSION_CAR_TEST_SERVICE})
@ApiTest(apis = "android.car.oem.OemCarService#getSupportedCarVersion")
public void testOemServicePermissionInManifest() throws Exception {
Intent intent = (new Intent())
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
index 0d277ed5f80..d4c9880ac4b 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
@@ -23,6 +23,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assume.assumeFalse;
+
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -51,6 +53,7 @@ import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.SystemUtil;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -158,6 +161,9 @@ public final class ActivityManagerHelperTest extends ActivityManagerTestBase {
@Test
public void testSetFocusedRootTask() throws Exception {
+ // Don't run this test on automotive targets with splitscreen multitasking enabled due to
+ // it having root tasks which are not the leaf nodes in the view hierarchy.
+ assumeFalse(hasAutomotiveSplitscreenMultitaskingFeature());
// setup
ActivityA task1BottomActivity = launchTestActivity(ActivityA.class);
ActivityB task1TopActivity = launchTestActivity(ActivityB.class);
@@ -278,7 +284,7 @@ public final class ActivityManagerHelperTest extends ActivityManagerTestBase {
.isEqualTo(expectedLaunchAllowed);
}
- @FlakyTest(bugId = 242066634)
+ @Ignore("b/304870066")
@Test
public void testStopAllTasksForUser() throws Exception {
int initialCurrentUserId = getCurrentUserId();
@@ -554,4 +560,12 @@ public final class ActivityManagerHelperTest extends ActivityManagerTestBase {
return foundSimpleActivity;
}
+
+ /**
+ * Checks whether the device has automotive splitscreen multitasking feature enabled
+ */
+ private boolean hasAutomotiveSplitscreenMultitaskingFeature() {
+ PackageManager pm = mContext.getPackageManager();
+ return isCar() && pm.hasSystemFeature("android.software.car.splitscreen_multitasking");
+ }
}
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/Constants.kt b/tests/tests/companion/common/src/android/companion/cts/common/Constants.kt
index a343d997153..37743fa34eb 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/Constants.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/Constants.kt
@@ -66,3 +66,6 @@ val BACKGROUND_THREAD_EXECUTOR: Executor by lazy {
Executor { threadHandler.post(it) }
}
}
+
+val PRIMARY_PROCESS_NAME = ":primary"
+val SECONDARY_PROCESS_NAME = ":secondary"
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
index d288e53f1cf..0190be81833 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
@@ -35,6 +35,7 @@ import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.SystemUtil
import java.io.IOException
+import java.util.Locale
import kotlin.test.assertContains
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
@@ -354,11 +355,17 @@ fun Instrumentation.runShellCommand(cmd: String): String {
fun Instrumentation.setSystemProp(name: String, value: String) =
runShellCommand("setprop $name $value")
-fun MacAddress.toUpperCaseString() = toString().toUpperCase()
+fun MacAddress.toUpperCaseString() = toString().uppercase(Locale.ROOT)
fun sleepFor(duration: Duration) = sleep(duration.inWholeMilliseconds)
fun killProcess(name: String) {
- val pid = SystemUtil.runShellCommand("pgrep -A $name").trim()
- Process.killProcess(Integer.valueOf(pid))
+ val pids = SystemUtil.runShellCommand("pgrep $name").trim().split("\\s+".toRegex())
+ for (pid: String in pids) {
+ // Make sure that it is the intended process before killing it.
+ val process = SystemUtil.runShellCommand("ps $pid")
+ if (process.contains("android.companion.cts.multiprocess")) {
+ Process.killProcess(Integer.valueOf(pid))
+ }
+ }
}
diff --git a/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/BinderLifecycleTest.kt b/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/BinderLifecycleTest.kt
index 6e8d8cf5937..ce350a215e7 100644
--- a/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/BinderLifecycleTest.kt
+++ b/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/BinderLifecycleTest.kt
@@ -17,6 +17,8 @@
package android.companion.cts.multiprocess
import android.companion.cts.common.DEVICE_DISPLAY_NAME_A
+import android.companion.cts.common.PRIMARY_PROCESS_NAME
+import android.companion.cts.common.SECONDARY_PROCESS_NAME
import android.companion.cts.common.TestBase
import android.companion.cts.common.assertApplicationBinds
import android.companion.cts.common.assertApplicationRemainsBound
@@ -46,7 +48,7 @@ class BinderLifecycleTest : TestBase() {
assertApplicationBinds(cdm)
// Kill primary process
- killProcess(":primary")
+ killProcess(PRIMARY_PROCESS_NAME)
assertApplicationUnbinds(cdm)
}
@@ -63,7 +65,7 @@ class BinderLifecycleTest : TestBase() {
SystemClock.sleep(2000)
// Kill secondary process
- killProcess(":secondary")
+ killProcess(SECONDARY_PROCESS_NAME)
assertApplicationRemainsBound(cdm)
}
}
diff --git a/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/RebindServiceTest.kt b/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/RebindServiceTest.kt
index cede5164e21..0684fc0b1e0 100644
--- a/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/RebindServiceTest.kt
+++ b/tests/tests/companion/multiprocess/src/android/companion/cts/multiprocess/RebindServiceTest.kt
@@ -17,6 +17,8 @@ package android.companion.cts.multiprocess
import android.companion.cts.common.DEVICE_DISPLAY_NAME_A
import android.companion.cts.common.DEVICE_DISPLAY_NAME_B
+import android.companion.cts.common.PRIMARY_PROCESS_NAME
+import android.companion.cts.common.SECONDARY_PROCESS_NAME
import android.companion.cts.common.TestBase
import android.companion.cts.common.assertApplicationBinds
import android.companion.cts.common.killProcess
@@ -44,8 +46,8 @@ class RebindServiceTest : TestBase() {
// Wait for secondary service to start.
SystemClock.sleep(2000)
// Kill both primary and secondary processes.
- killProcess(":primary")
- killProcess(":secondary")
+ killProcess(PRIMARY_PROCESS_NAME)
+ killProcess(SECONDARY_PROCESS_NAME)
// Schedule rebind in 10 seconds but give it 11 seconds.
SystemClock.sleep(11000)
@@ -72,7 +74,7 @@ class RebindServiceTest : TestBase() {
// Wait for secondary service to start.
SystemClock.sleep(2000)
// Kill secondary process.
- killProcess(":secondary")
+ killProcess(SECONDARY_PROCESS_NAME)
// Schedule rebind in 10 seconds but give it 11 seconds.
SystemClock.sleep(11000)
@@ -96,8 +98,8 @@ class RebindServiceTest : TestBase() {
// Wait for secondary service to start.
SystemClock.sleep(2000)
// Kill the primary process.
- killProcess(":primary")
- killProcess(":secondary")
+ killProcess(PRIMARY_PROCESS_NAME)
+ killProcess(SECONDARY_PROCESS_NAME)
// Primary service should be unbound.
assertServiceNotBound("PrimaryCompanionService")
diff --git a/tests/tests/companion/uicommon/src/android/companion/cts/uicommon/CompanionDeviceManagerUi.kt b/tests/tests/companion/uicommon/src/android/companion/cts/uicommon/CompanionDeviceManagerUi.kt
index 64e53a82125..0716cefee7c 100644
--- a/tests/tests/companion/uicommon/src/android/companion/cts/uicommon/CompanionDeviceManagerUi.kt
+++ b/tests/tests/companion/uicommon/src/android/companion/cts/uicommon/CompanionDeviceManagerUi.kt
@@ -20,6 +20,7 @@ import android.os.SystemClock
import android.os.SystemClock.sleep
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.Direction
import androidx.test.uiautomator.SearchCondition
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
@@ -78,8 +79,20 @@ open class CompanionDeviceManagerUi(private val ui: UiDevice) {
fun clickNegativeButton() = click(NEGATIVE_BUTTON, "Negative button")
- fun clickNegativeButtonMultipleDevices() = click(
- NEGATIVE_BUTTON_MULTIPLE_DEVICES, "Negative button for multiple devices")
+ fun clickNegativeButtonMultipleDevices() {
+ ui.wait(Until.findObject(CONFIRMATION_UI), 2.seconds.inWholeMilliseconds)?.let {
+ // swipe up (or scroll down) until cancel button is enabled
+ val startTime = SystemClock.uptimeMillis()
+ var elapsedTime = 0L
+ // UiDevice.hasObject() takes a long time for some reason so wait at least 10 seconds
+ while (!ui.hasObject(NEGATIVE_BUTTON_MULTIPLE_DEVICES)
+ && elapsedTime < 10.seconds.inWholeMilliseconds) {
+ it.swipe(Direction.UP, 1.0F)
+ elapsedTime = SystemClock.uptimeMillis() - startTime
+ }
+ }
+ click(NEGATIVE_BUTTON_MULTIPLE_DEVICES, "Negative button for multiple devices")
+ }
fun waitUntilAppAppeared() = ui.wait(Until.hasObject(ASSOCIATION_REVOKE_APP_UI),
"The test app has not appeared.")
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index dc89b8c6a7a..aecf00ed26a 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -40,6 +40,7 @@ import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.Telephony;
import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import com.android.compatibility.common.util.CddTest;
@@ -179,7 +180,10 @@ public class AvailableIntentsTest extends AndroidTestCase {
*/
public void testDialPhoneNumber() {
PackageManager packageManager = mContext.getPackageManager();
- if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ TelephonyManager telephonyManager =
+ mContext.getSystemService(TelephonyManager.class);
+ if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ && telephonyManager.isVoiceCapable()) {
Uri uri = Uri.parse("tel:(212)5551212");
Intent intent = new Intent(Intent.ACTION_DIAL, uri);
assertCanBeHandled(intent);
@@ -191,7 +195,10 @@ public class AvailableIntentsTest extends AndroidTestCase {
*/
public void testDialVoicemail() {
PackageManager packageManager = mContext.getPackageManager();
- if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ TelephonyManager telephonyManager =
+ mContext.getSystemService(TelephonyManager.class);
+ if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ && telephonyManager.isVoiceCapable()) {
Uri uri = Uri.parse("voicemail:");
Intent intent = new Intent(Intent.ACTION_DIAL, uri);
assertCanBeHandled(intent);
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderClientTest.java b/tests/tests/content/src/android/content/cts/ContentProviderClientTest.java
index a6218b1d91d..1bbfa3e249c 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderClientTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderClientTest.java
@@ -17,6 +17,7 @@
package android.content.cts;
import static org.mockito.Mockito.RETURNS_DEFAULTS;
+import static org.mockito.Mockito.after;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -128,7 +129,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.query(URI, null, ARGS, mCancellationSignal));
- verify(mIContentProvider).query(mAttributionSource, URI, null, ARGS,
+ verify(mIContentProvider, after(150)).query(mAttributionSource, URI, null, ARGS,
mICancellationSignal);
}
@@ -149,7 +150,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.getType(URI));
- verify(mIContentProvider).getType(mAttributionSource, URI);
+ verify(mIContentProvider, after(150)).getType(mAttributionSource, URI);
}
public void testGetStreamTypes() throws RemoteException {
@@ -163,7 +164,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.getStreamTypes(URI, ""));
- verify(mIContentProvider).getStreamTypes(mAttributionSource, URI, "");
+ verify(mIContentProvider, after(150)).getStreamTypes(mAttributionSource, URI, "");
}
public void testCanonicalize() throws RemoteException {
@@ -176,7 +177,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.canonicalize(URI));
- verify(mIContentProvider).canonicalize(mAttributionSource, URI);
+ verify(mIContentProvider, after(150)).canonicalize(mAttributionSource, URI);
}
public void testUncanonicalize() throws RemoteException {
@@ -189,7 +190,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.uncanonicalize(URI));
- verify(mIContentProvider).uncanonicalize(mAttributionSource, URI);
+ verify(mIContentProvider, after(150)).uncanonicalize(mAttributionSource, URI);
}
public void testRefresh() throws RemoteException {
@@ -204,7 +205,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.refresh(URI, ARGS, mCancellationSignal));
- verify(mIContentProvider).refresh(mAttributionSource, URI, ARGS,
+ verify(mIContentProvider, after(150)).refresh(mAttributionSource, URI, ARGS,
mICancellationSignal);
}
@@ -225,7 +226,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.insert(URI, VALUES, EXTRAS));
- verify(mIContentProvider).insert(mAttributionSource, URI, VALUES, EXTRAS);
+ verify(mIContentProvider, after(150)).insert(mAttributionSource, URI, VALUES, EXTRAS);
}
public void testBulkInsert() throws RemoteException {
@@ -239,7 +240,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.bulkInsert(URI, VALUES_ARRAY));
- verify(mIContentProvider).bulkInsert(mAttributionSource, URI, VALUES_ARRAY);
+ verify(mIContentProvider, after(150)).bulkInsert(mAttributionSource, URI, VALUES_ARRAY);
}
public void testDelete() throws RemoteException {
@@ -252,7 +253,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.delete(URI, EXTRAS));
- verify(mIContentProvider).delete(mAttributionSource, URI, EXTRAS);
+ verify(mIContentProvider, after(150)).delete(mAttributionSource, URI, EXTRAS);
}
public void testUpdate() throws RemoteException {
@@ -266,7 +267,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.update(URI, VALUES, EXTRAS));
- verify(mIContentProvider).update(mAttributionSource, URI, VALUES, EXTRAS);
+ verify(mIContentProvider, after(150)).update(mAttributionSource, URI, VALUES, EXTRAS);
}
public void testOpenFile() throws RemoteException, FileNotFoundException {
@@ -282,7 +283,8 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.openFile(URI, MODE, mCancellationSignal));
- verify(mIContentProvider).openFile(mAttributionSource, URI, MODE, mICancellationSignal);
+ verify(mIContentProvider, after(150)).openFile(mAttributionSource, URI, MODE,
+ mICancellationSignal);
}
public void testOpenFileAlreadyCancelled() throws Exception {
@@ -305,7 +307,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.openAssetFile(URI, MODE, mCancellationSignal));
- verify(mIContentProvider).openAssetFile(mAttributionSource, URI, MODE,
+ verify(mIContentProvider, after(150)).openAssetFile(mAttributionSource, URI, MODE,
mICancellationSignal);
}
@@ -339,8 +341,8 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.openTypedAssetFile(URI, MODE, ARGS,
mCancellationSignal));
- verify(mIContentProvider).openTypedAssetFile(mAttributionSource, URI, MODE, ARGS,
- mICancellationSignal);
+ verify(mIContentProvider, after(150)).openTypedAssetFile(mAttributionSource, URI, MODE,
+ ARGS, mICancellationSignal);
}
public void testOpenTypedAssetFileAlreadyCancelled() throws Exception {
@@ -365,7 +367,7 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.applyBatch(AUTHORITY, OPS));
- verify(mIContentProvider).applyBatch(mAttributionSource, AUTHORITY, OPS);
+ verify(mIContentProvider, after(150)).applyBatch(mAttributionSource, AUTHORITY, OPS);
}
public void testCall() throws RemoteException {
@@ -380,7 +382,8 @@ public class ContentProviderClientTest extends AndroidTestCase {
testTimeout(() -> mContentProviderClient.call(AUTHORITY, METHOD, ARG, ARGS));
- verify(mIContentProvider).call(mAttributionSource, AUTHORITY, METHOD, ARG, ARGS);
+ verify(mIContentProvider, after(150)).call(mAttributionSource, AUTHORITY, METHOD, ARG,
+ ARGS);
}
private void testTimeout(Function function) throws InterruptedException {
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
index 14df6139415..11f739f377c 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
@@ -2015,10 +2015,15 @@ public class SQLiteDatabaseTest extends AndroidTestCase {
"Unexpected version format, expected MAJOR.MINOR.PATCH but was " + fullVersionStr,
lastDot > 0);
String majorMinor = fullVersionStr.substring(0, lastDot);
+ int patchLevel = Integer.valueOf(fullVersionStr.substring(lastDot + 1));
+ // Temporarily allow 3.42.0.
+ if (majorMinor.equals("3.42") && patchLevel >= 0) {
+ // Okay. No further testing required.
+ return;
+ }
assertEquals(
"Expected SQLite library version " + EXPECTED_MAJOR_MINOR_VERSION + ", but was "
+ fullVersionStr, EXPECTED_MAJOR_MINOR_VERSION, majorMinor);
- int patchLevel = Integer.valueOf(fullVersionStr.substring(lastDot + 1));
assertTrue("Expected minimum patch level " + EXPECTED_MIN_PATCH_LEVEL + ", but was "
+ patchLevel, patchLevel >= EXPECTED_MIN_PATCH_LEVEL);
}
diff --git a/tests/tests/display/src/android/display/cts/BrightnessTest.java b/tests/tests/display/src/android/display/cts/BrightnessTest.java
index 016a0a21bce..ef647bd0944 100644
--- a/tests/tests/display/src/android/display/cts/BrightnessTest.java
+++ b/tests/tests/display/src/android/display/cts/BrightnessTest.java
@@ -92,6 +92,14 @@ public class BrightnessTest extends TestBase {
assumeTrue(
numberOfSystemAppsWithPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE) > 0);
+ assumeTrue(
+ numberOfSystemAppsWithPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
+ > 0);
+ grantPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS);
+ BrightnessConfiguration defaultConfig = mDisplayManager.getDefaultBrightnessConfiguration();
+ // This might be null, meaning that the device doesn't support autobrightness
+ assumeNotNull(defaultConfig);
+
int previousBrightness = getSystemSetting(Settings.System.SCREEN_BRIGHTNESS);
int previousBrightnessMode =
getSystemSetting(Settings.System.SCREEN_BRIGHTNESS_MODE);
@@ -145,6 +153,14 @@ public class BrightnessTest extends TestBase {
assumeTrue(
numberOfSystemAppsWithPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE) > 0);
+ assumeTrue(
+ numberOfSystemAppsWithPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
+ > 0);
+ grantPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS);
+ BrightnessConfiguration defaultConfig = mDisplayManager.getDefaultBrightnessConfiguration();
+ // This might be null, meaning that the device doesn't support autobrightness
+ assumeNotNull(defaultConfig);
+
int previousBrightness = getSystemSetting(Settings.System.SCREEN_BRIGHTNESS);
int previousBrightnessMode =
getSystemSetting(Settings.System.SCREEN_BRIGHTNESS_MODE);
@@ -235,6 +251,11 @@ public class BrightnessTest extends TestBase {
Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) > 0);
grantPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS);
+
+ BrightnessConfiguration defaultConfig = mDisplayManager.getDefaultBrightnessConfiguration();
+ // This might be null, meaning that the device doesn't support autobrightness
+ assumeNotNull(defaultConfig);
+
int previousBrightness = getSystemSetting(Settings.System.SCREEN_BRIGHTNESS);
int previousBrightnessMode =
getSystemSetting(Settings.System.SCREEN_BRIGHTNESS_MODE);
@@ -395,6 +416,11 @@ public class BrightnessTest extends TestBase {
// Don't run as there is no app that has permission to push curves.
assumeTrue(numberOfSystemAppsWithPermission(
Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) > 0);
+ grantPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS);
+
+ BrightnessConfiguration defaultConfig = mDisplayManager.getDefaultBrightnessConfiguration();
+ // This might be null, meaning that the device doesn't support autobrightness
+ assumeNotNull(defaultConfig);
BrightnessConfiguration config =
new BrightnessConfiguration.Builder(
@@ -411,7 +437,6 @@ public class BrightnessTest extends TestBase {
assertEquals(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC, mode);
grantPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE);
- grantPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS);
// Setup and remember some initial state.
recordSliderEvents();
@@ -492,6 +517,11 @@ public class BrightnessTest extends TestBase {
Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) > 0);
grantPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS);
+
+ BrightnessConfiguration defaultConfig = mDisplayManager.getDefaultBrightnessConfiguration();
+ // This might be null, meaning that the device doesn't support autobrightness
+ assumeNotNull(defaultConfig);
+
grantPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE);
BrightnessConfiguration previousConfig = mDisplayManager.getBrightnessConfiguration();
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index 4e2fd60fa01..6cd292ac771 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -17,6 +17,7 @@
package android.dpi.cts;
import android.content.Context;
+import android.os.Build;
import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
import android.util.DisplayMetrics;
@@ -25,6 +26,7 @@ import android.view.WindowManager;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.FeatureUtil;
+import com.android.compatibility.common.util.PropertyUtil;
import java.util.HashSet;
import java.util.Set;
@@ -52,6 +54,9 @@ public class ConfigurationTest extends AndroidTestCase {
double yInches = (double) mMetrics.heightPixels / mMetrics.ydpi;
double diagonalInches = Math.sqrt(Math.pow(xInches, 2) + Math.pow(yInches, 2));
double minSize = 2.5d;
+ if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.R) {
+ minSize = 3.3d;
+ }
if (FeatureUtil.isWatch()) {
// Watches have a different minimum diagonal.
minSize = 1.0d;
diff --git a/tests/tests/media/audio/Android.bp b/tests/tests/media/audio/Android.bp
index cf27b8435ff..abe42eebb60 100644
--- a/tests/tests/media/audio/Android.bp
+++ b/tests/tests/media/audio/Android.bp
@@ -101,7 +101,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-media",
],
target_sdk_version: "31",
}
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioCommunicationDeviceTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioCommunicationDeviceTest.java
index dec698ae236..aa40d3852c0 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioCommunicationDeviceTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioCommunicationDeviceTest.java
@@ -16,9 +16,12 @@
package android.media.audio.cts;
+import android.Manifest;
import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
+import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import androidx.test.filters.SdkSuppress;
@@ -35,53 +38,160 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
private final static String TAG = "AudioCommunicationDeviceTest";
private AudioManager mAudioManager;
+ private int mOriginalMode;
+ private MyOnModeChangedListener mModelistener;
+
+ private MyOnCommunicationDeviceChangedListener mCommunicationDeviceListener;
@Override
protected void setUp() throws Exception {
super.setUp();
+
mAudioManager = getInstrumentation().getContext().getSystemService(AudioManager.class);
+
+ mOriginalMode = mAudioManager.getMode();
+ mModelistener = new MyOnModeChangedListener(mAudioManager);
+ mAudioManager.addOnModeChangedListener(
+ Executors.newSingleThreadExecutor(), mModelistener);
+
+ mCommunicationDeviceListener = new MyOnCommunicationDeviceChangedListener(mAudioManager);
+ mAudioManager.addOnCommunicationDeviceChangedListener(
+ Executors.newSingleThreadExecutor(), mCommunicationDeviceListener);
}
- public void testSetValidCommunicationDevice() {
+ @Override
+ protected void tearDown() throws Exception {
+ mAudioManager.clearCommunicationDevice();
+ // This will time out if the communication device is already the default one but as there
+ // is no way to tell what the default communication device should be it is the only way to
+ // safely return to the default device before next test
+ mCommunicationDeviceListener.waitForDeviceUpdate();
+ mAudioManager.removeOnCommunicationDeviceChangedListener(mCommunicationDeviceListener);
+
+ mModelistener.setAudioMode(mOriginalMode);
+ mAudioManager.removeOnModeChangedListener(mModelistener);
+
+ super.tearDown();
+ }
+
+ public void testGetCommunicationDevice() {
if (!isValidPlatform("testSetValidCommunicationDevice")) return;
AudioDeviceInfo commDevice = null;
+ try {
+ commDevice = mAudioManager.getCommunicationDevice();
+ } catch (Exception e) {
+ fail("getCommunicationDevice failed with exception: " + e);
+ }
+ if (commDevice == null) {
+ fail("platform has no default communication device");
+ }
+ }
+
+ public void testClearCommunicationDevice() {
+ if (!isValidPlatform("testSetValidCommunicationDevice")) return;
+
+ try {
+ mAudioManager.clearCommunicationDevice();
+ } catch (Exception e) {
+ fail("clearCommunicationDevice failed with exception: " + e);
+ }
+ }
+
+ @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
+ public void testSetCommunicationDeviceSuccessModeOwner() {
+ if (!isValidPlatform("testSetValidCommunicationDevice")) return;
+
+ mModelistener.setAudioMode(AudioManager.MODE_IN_COMMUNICATION);
+
+ doSetCommunicationDeviceSuccessTest();
+ }
+
+ public void testSetCommunicationDeviceSuccessPrivileged() {
+ if (!isValidPlatform("testSetValidCommunicationDevice")) return;
+
+ try {
+ getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.MODIFY_PHONE_STATE);
+
+ doSetCommunicationDeviceSuccessTest();
+ } finally {
+ getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ private void doSetCommunicationDeviceSuccessTest() {
List<AudioDeviceInfo> devices = mAudioManager.getAvailableCommunicationDevices();
for (AudioDeviceInfo device : devices) {
+ AudioDeviceInfo commDevice = null;
try {
- mAudioManager.setCommunicationDevice(device);
+ mCommunicationDeviceListener.setCommunicationDevice(device);
try {
commDevice = mAudioManager.getCommunicationDevice();
+ assertNotNull("Platform has no default communication device", commDevice);
} catch (Exception e) {
fail("getCommunicationDevice failed with exception: " + e);
}
- if (commDevice == null || commDevice.getType() != device.getType()) {
+ if (commDevice.getType() != device.getType()) {
fail("setCommunicationDevice failed, expected device: "
- + device.getType() + " but got: "
- + ((commDevice == null)
- ? AudioDeviceInfo.TYPE_UNKNOWN : commDevice.getType()));
+ + device.getType() + " but got: " + commDevice.getType());
}
} catch (Exception e) {
fail("setCommunicationDevice failed with exception: " + e);
}
}
+ }
- try {
- mAudioManager.clearCommunicationDevice();
- } catch (Exception e) {
- fail("clearCommunicationDevice failed with exception: " + e);
- }
- try {
- commDevice = mAudioManager.getCommunicationDevice();
- } catch (Exception e) {
- fail("getCommunicationDevice failed with exception: " + e);
- }
- if (commDevice == null) {
- fail("platform has no default communication device");
+ public void testSetCommunicationDeviceDeniedNotModeOwnerNotPrivileged() {
+ final long kDeviceListenerIdleWaitTimeoutMs = 10000;
+
+ if (!isValidPlatform("testSetValidCommunicationDevice")) return;
+
+ AudioDeviceInfo originalCommDevice = mAudioManager.getCommunicationDevice();
+ assertNotNull("Platform has no default communication device", originalCommDevice);
+
+ List<AudioDeviceInfo> devices = mAudioManager.getAvailableCommunicationDevices();
+ for (AudioDeviceInfo device : devices) {
+ if (device.getType() == originalCommDevice.getType()) {
+ continue;
+ }
+ MyOnCommunicationDeviceChangedListener listener =
+ new MyOnCommunicationDeviceChangedListener(mAudioManager);
+ try {
+ mAudioManager.addOnCommunicationDeviceChangedListener(
+ Executors.newSingleThreadExecutor(), listener);
+
+ listener.setCommunicationDevice(device);
+ // The following behaviors are acceptable:
+ // - U: the communication device changes: log a warning to
+ // track migration to post U QPR1 behavior
+ // - U QPR1 and after:
+ // - the communication device does not change OR
+ // - the communication device changes temporarily and comes back to
+ // the initial device after the inactivity grace period.
+ AudioDeviceInfo listenerDevice = listener.getDevice();
+ if (listenerDevice != null
+ && listenerDevice.getType() != originalCommDevice.getType()) {
+ listener.waitForDeviceUpdate(
+ originalCommDevice, kDeviceListenerIdleWaitTimeoutMs);
+ listenerDevice = listener.getDevice();
+ if (listenerDevice == null
+ || listenerDevice.getType() != originalCommDevice.getType()) {
+ Log.w(TAG, "setCommunicationDevice not denied, expected device: "
+ + originalCommDevice.getType()
+ + " but got: " + (listenerDevice == null
+ ? AudioDeviceInfo.TYPE_UNKNOWN : listenerDevice.getType()));
+ }
+ }
+ } catch (Exception e) {
+ fail("AudioManager call failed with exception: " + e);
+ } finally {
+ mAudioManager.removeOnCommunicationDeviceChangedListener(listener);
+ }
}
}
- public void testSetInvalidCommunicationDevice() {
+ public void testSetInvalidCommunicationDeviceFail() {
if (!isValidPlatform("testSetInvalidCommunicationDevice")) return;
AudioDeviceInfo[] alldevices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
@@ -102,13 +212,16 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
static class MyOnCommunicationDeviceChangedListener implements
AudioManager.OnCommunicationDeviceChangedListener {
+ private static final long LISTENER_WAIT_TIMEOUT_MS = 3000;
+
private final Object mCbLock = new Object();
@GuardedBy("mCbLock")
private boolean mCalled;
@GuardedBy("mCbLock")
private AudioDeviceInfo mDevice;
- private static final int LISTENER_WAIT_TIMEOUT_MS = 3000;
+ private final AudioManager mAudioManager;
+
void reset() {
synchronized (mCbLock) {
mCalled = false;
@@ -117,24 +230,49 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
}
AudioDeviceInfo waitForDeviceUpdate() {
+ return waitForDeviceUpdateTo(null, LISTENER_WAIT_TIMEOUT_MS);
+ }
+
+ AudioDeviceInfo waitForDeviceUpdate(AudioDeviceInfo device) {
+ return waitForDeviceUpdateTo(device, LISTENER_WAIT_TIMEOUT_MS);
+ }
+
+ AudioDeviceInfo waitForDeviceUpdate(AudioDeviceInfo device, long timeoutMs) {
+ return waitForDeviceUpdateTo(device, timeoutMs);
+ }
+
+ // Waits for the communication device to be the one passed as argument.
+ // If the device passed is null, it will wait unconditionally for the listener to be called
+ private AudioDeviceInfo waitForDeviceUpdateTo(AudioDeviceInfo device,
+ long timeoutMs) {
synchronized (mCbLock) {
- while (!mCalled) {
+ long endTimeMillis = SystemClock.uptimeMillis() + timeoutMs;
+ long waiTimeMillis = endTimeMillis - SystemClock.uptimeMillis();
+ while (((device != null && !device.equals(mAudioManager.getCommunicationDevice()))
+ || !mCalled) && (waiTimeMillis > 0)) {
try {
- mCbLock.wait(LISTENER_WAIT_TIMEOUT_MS);
+ mCbLock.wait(waiTimeMillis);
} catch (InterruptedException e) {
}
+ waiTimeMillis = endTimeMillis - SystemClock.uptimeMillis();
}
return mDevice;
}
}
+ void setCommunicationDevice(AudioDeviceInfo device) {
+ mAudioManager.setCommunicationDevice(device);
+ waitForDeviceUpdateTo(device, LISTENER_WAIT_TIMEOUT_MS);
+ }
+
AudioDeviceInfo getDevice() {
synchronized (mCbLock) {
return mDevice;
}
}
- MyOnCommunicationDeviceChangedListener() {
+ MyOnCommunicationDeviceChangedListener(AudioManager audioManager) {
+ mAudioManager = audioManager;
reset();
}
@@ -148,11 +286,14 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
}
}
+ @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
public void testCommunicationDeviceListener() {
if (!isValidPlatform("testCommunicationDeviceListener")) return;
+ mModelistener.setAudioMode(AudioManager.MODE_IN_COMMUNICATION);
+
MyOnCommunicationDeviceChangedListener listener =
- new MyOnCommunicationDeviceChangedListener();
+ new MyOnCommunicationDeviceChangedListener(mAudioManager);
try {
mAudioManager.addOnCommunicationDeviceChangedListener(null, listener);
@@ -189,7 +330,7 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
}
AudioDeviceInfo originalDevice = mAudioManager.getCommunicationDevice();
- assertNotNull("Platform as no default communication device", originalDevice);
+ assertNotNull("Platform has no default communication device", originalDevice);
AudioDeviceInfo requestedDevice = null;
List<AudioDeviceInfo> devices = mAudioManager.getAvailableCommunicationDevices();
@@ -205,6 +346,7 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
+" no valid decice to test");
return;
}
+
mAudioManager.setCommunicationDevice(requestedDevice);
AudioDeviceInfo listenerDevice = listener.waitForDeviceUpdate();
if (listenerDevice == null || listenerDevice.getType() != requestedDevice.getType()) {
@@ -214,11 +356,12 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
? AudioDeviceInfo.TYPE_UNKNOWN : listenerDevice.getType()));
}
AudioDeviceInfo getterDevice = mAudioManager.getCommunicationDevice();
- if (getterDevice == null || getterDevice.getType() != listenerDevice.getType()) {
+ assertNotNull("Platform has no default communication device", getterDevice);
+
+ if (getterDevice.getType() != listenerDevice.getType()) {
fail("listener and getter device mismatch, expected device: "
+ listenerDevice.getType() + " but got: "
- + ((getterDevice == null)
- ? AudioDeviceInfo.TYPE_UNKNOWN : getterDevice.getType()));
+ + getterDevice.getType());
}
listener.reset();
@@ -226,7 +369,7 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
mAudioManager.setCommunicationDevice(originalDevice);
listenerDevice = listener.waitForDeviceUpdate();
- assertNotNull("Platform as no default communication device", listenerDevice);
+ assertNotNull("Platform has no default communication device", listenerDevice);
if (listenerDevice.getType() != originalDevice.getType()) {
fail("communication device listener failed on clear, expected device: "
@@ -241,6 +384,64 @@ public class AudioCommunicationDeviceTest extends CtsAndroidTestCase {
}
}
+ static class MyOnModeChangedListener implements AudioManager.OnModeChangedListener {
+
+ private final Object mCbLock = new Object();
+ @GuardedBy("mCbLock")
+ private boolean mCalled;
+ @GuardedBy("mCbLock")
+ private int mMode;
+ private final AudioManager mAudioManager;
+
+ private static final int LISTENER_WAIT_TIMEOUT_MS = 3000;
+ void reset() {
+ synchronized (mCbLock) {
+ mCalled = false;
+ mMode = AudioManager.MODE_INVALID;
+ }
+ }
+
+ private int waitForModeUpdateTo(int mode) {
+ synchronized (mCbLock) {
+ long endTimeMillis = SystemClock.uptimeMillis() + LISTENER_WAIT_TIMEOUT_MS;
+ long waiTimeMillis = endTimeMillis - SystemClock.uptimeMillis();
+ while ((mAudioManager.getMode() != mode || !mCalled) && waiTimeMillis > 0) {
+ try {
+ mCbLock.wait(waiTimeMillis);
+ } catch (InterruptedException e) {
+ }
+ waiTimeMillis = endTimeMillis - SystemClock.uptimeMillis();
+ }
+ return mMode;
+ }
+ }
+
+ void setAudioMode(int mode) {
+ mAudioManager.setMode(mode);
+ waitForModeUpdateTo(mode);
+ }
+
+ int getMode() {
+ synchronized (mCbLock) {
+ return mMode;
+ }
+ }
+
+ MyOnModeChangedListener(AudioManager audioManager) {
+ mAudioManager = audioManager;
+ reset();
+ }
+
+ @Override
+ public void onModeChanged(int mode) {
+ synchronized (mCbLock) {
+ mCalled = true;
+ mMode = mode;
+ mCbLock.notifyAll();
+ }
+ }
+ }
+
private boolean isValidPlatform(String testName) {
PackageManager pm = getInstrumentation().getContext().getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
index 6ce5bcab86f..2f20324bbcf 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
@@ -300,10 +300,14 @@ public class AudioManagerTest extends InstrumentationTestCase {
if (!hasBuiltinSpeaker()) {
return;
}
+
final MyBlockingIntentReceiver receiver = new MyBlockingIntentReceiver(
AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED);
final boolean initialSpeakerphoneState = mAudioManager.isSpeakerphoneOn();
try {
+ getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.MODIFY_PHONE_STATE);
+
mContext.registerReceiver(receiver,
new IntentFilter(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED));
// change the speakerphone state
@@ -319,6 +323,7 @@ public class AudioManagerTest extends InstrumentationTestCase {
} finally {
mContext.unregisterReceiver(receiver);
mAudioManager.setSpeakerphoneOn(initialSpeakerphoneState);
+ getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
}
}
@@ -586,9 +591,9 @@ public class AudioManagerTest extends InstrumentationTestCase {
// setBluetoothA2dpOn is a no-op, and getRouting should always return -1
boolean oldA2DP = mAudioManager.isBluetoothA2dpOn();
mAudioManager.setBluetoothA2dpOn(true);
- assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn());
+ assertEquals(oldA2DP, mAudioManager.isBluetoothA2dpOn());
mAudioManager.setBluetoothA2dpOn(false);
- assertEquals(oldA2DP , mAudioManager.isBluetoothA2dpOn());
+ assertEquals(oldA2DP, mAudioManager.isBluetoothA2dpOn());
assertEquals(-1, mAudioManager.getRouting(MODE_RINGTONE));
assertEquals(-1, mAudioManager.getRouting(MODE_NORMAL));
@@ -607,13 +612,22 @@ public class AudioManagerTest extends InstrumentationTestCase {
if (isAutomotive()) {
return;
}
- mAudioManager.setSpeakerphoneOn(true);
- assertTrueCheckTimeout(mAudioManager, p -> p.isSpeakerphoneOn(),
- DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned false");
- mAudioManager.setSpeakerphoneOn(false);
- assertTrueCheckTimeout(mAudioManager, p -> !p.isSpeakerphoneOn(),
- DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned true");
+ try {
+ getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.MODIFY_PHONE_STATE);
+
+ mAudioManager.setSpeakerphoneOn(true);
+ assertTrueCheckTimeout(mAudioManager, p -> p.isSpeakerphoneOn(),
+ DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned false");
+
+ mAudioManager.setSpeakerphoneOn(false);
+ assertTrueCheckTimeout(mAudioManager, p -> !p.isSpeakerphoneOn(),
+ DEFAULT_ASYNC_CALL_TIMEOUT_MS, "isSpeakerPhoneOn() returned true");
+
+ } finally {
+ getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
+ }
}
public void testVibrateNotification() throws Exception {
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioModeListenerTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioModeListenerTest.java
index 738f77ed870..3c4b994ab3a 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioModeListenerTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioModeListenerTest.java
@@ -18,6 +18,7 @@ package android.media.audio.cts;
import android.content.pm.PackageManager;
import android.media.AudioManager;
+import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
@@ -66,11 +67,14 @@ public class AudioModeListenerTest extends CtsAndroidTestCase {
int waitForModeUpdate() {
synchronized (mCbLock) {
- while (!mCalled) {
+ long endTimeMillis = SystemClock.uptimeMillis() + LISTENER_WAIT_TIMEOUT_MS;
+ long waiTimeMillis = endTimeMillis - SystemClock.uptimeMillis();
+ while (!mCalled && waiTimeMillis > 0) {
try {
- mCbLock.wait(LISTENER_WAIT_TIMEOUT_MS);
+ mCbLock.wait(waiTimeMillis);
} catch (InterruptedException e) {
}
+ waiTimeMillis = endTimeMillis - SystemClock.uptimeMillis();
}
return mMode;
}
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 5eb881eb1e4..2d60d0230dc 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
@@ -17,12 +17,12 @@ package android.media.audio.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.Instrumentation;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -83,8 +83,9 @@ public class RingtoneManagerTest {
mRingtoneManager = new RingtoneManager(mActivity);
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
// backup ringer settings
- mDefaultUri = RingtoneManager.getActualDefaultRingtoneUri(mContext,
- RingtoneManager.TYPE_RINGTONE);
+ mDefaultUri = ContentProvider.maybeAddUserId(
+ RingtoneManager.getActualDefaultRingtoneUri(
+ mContext, RingtoneManager.TYPE_RINGTONE), mContext.getUserId());
mOriginalRingerMode = mAudioManager.getRingerMode();
if (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
@@ -144,10 +145,15 @@ public class RingtoneManagerTest {
Uri uri = mRingtoneManager.getRingtoneUri(expectedPosition);
assertEquals(expectedPosition, mRingtoneManager.getRingtonePosition(uri));
assertNotNull(RingtoneManager.getValidRingtoneUri(mContext));
+ uri = ContentProvider.maybeAddUserId(uri, mContext.getUserId());
RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, uri);
- assertEquals(uri, RingtoneManager.getActualDefaultRingtoneUri(mContext,
- RingtoneManager.TYPE_RINGTONE));
+
+ Uri actualDefaultRingtoneUri = ContentProvider.maybeAddUserId(
+ RingtoneManager.getActualDefaultRingtoneUri(
+ mContext, RingtoneManager.TYPE_RINGTONE), mContext.getUserId());
+
+ assertEquals(uri, actualDefaultRingtoneUri);
try (AssetFileDescriptor afd = RingtoneManager.openDefaultRingtoneUri(
mActivity, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE))) {
diff --git a/tests/tests/media/bettertogether/src/android/media/bettertogether/cts/MediaSessionManagerTest.java b/tests/tests/media/bettertogether/src/android/media/bettertogether/cts/MediaSessionManagerTest.java
index 409008d6de7..ca36e57ec2b 100644
--- a/tests/tests/media/bettertogether/src/android/media/bettertogether/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/bettertogether/src/android/media/bettertogether/cts/MediaSessionManagerTest.java
@@ -48,11 +48,9 @@ import android.view.KeyEvent;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SdkSuppress;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
-import com.android.compatibility.common.util.MediaUtils;
import com.android.compatibility.common.util.NonMainlineTest;
import com.android.compatibility.common.util.SystemUtil;
@@ -104,6 +102,7 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testGetActiveSessions() throws Exception {
assertThrows("Expected security exception for unauthorized call to getActiveSessions",
SecurityException.class,
@@ -112,26 +111,24 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testGetMediaKeyEventSession_throwsSecurityException() {
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
assertThrows("Expected security exception for call to getMediaKeyEventSession",
SecurityException.class,
() -> mSessionManager.getMediaKeyEventSession());
}
@Test
+ @NonMainlineTest
public void testGetMediaKeyEventSessionPackageName_throwsSecurityException() {
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
assertThrows("Expected security exception for call to getMediaKeyEventSessionPackageName",
SecurityException.class,
() -> mSessionManager.getMediaKeyEventSessionPackageName());
}
@Test
+ @NonMainlineTest
public void testOnMediaKeyEventSessionChangedListener() throws Exception {
- // The permission can be held only on S+
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
-
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.MANAGE_EXTERNAL_STORAGE);
@@ -159,10 +156,8 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testOnMediaKeyEventSessionChangedListener_whenSessionIsReleased() throws Exception {
- // The permission can be held only on S+
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
-
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.MANAGE_EXTERNAL_STORAGE);
@@ -181,9 +176,7 @@ public class MediaSessionManagerTest {
assertThat(keyEventSessionListener.mCountDownLatch
.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue();
assertThat(keyEventSessionListener.mSessionToken).isNull();
- if (sIsAtLeastU) {
- assertThat(keyEventSessionListener.mPackageName).isEmpty();
- }
+ assertThat(keyEventSessionListener.mPackageName).isEmpty();
assertThat(mSessionManager.getMediaKeyEventSession()).isNull();
assertThat(mSessionManager.getMediaKeyEventSessionPackageName()).isEqualTo("");
@@ -191,10 +184,8 @@ public class MediaSessionManagerTest {
@Test
@NonMainlineTest
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testOnMediaKeyEventSessionChangedListener_noSession_passesEmptyPackageAndNullToken()
throws InterruptedException {
- // The permission can be held only on S+
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.MEDIA_CONTENT_CONTROL);
@@ -226,8 +217,8 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testOnMediaKeyEventSessionChangedListener_noPermission_throwsSecurityException() {
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
MediaKeyEventSessionListener keyEventSessionListener = new MediaKeyEventSessionListener();
assertThrows("Expected security exception for call to"
+ " addOnMediaKeyEventSessionChangedListener",
@@ -237,10 +228,8 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testOnMediaKeyEventDispatchedListener() throws Exception {
- // The permission can be held only on S+
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
-
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.MANAGE_EXTERNAL_STORAGE);
@@ -283,8 +272,8 @@ public class MediaSessionManagerTest {
@Test
@UiThreadTest
+ @NonMainlineTest
public void testAddOnActiveSessionsListener() throws Exception {
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
assertThrows("Expected NPE for call to addOnActiveSessionsChangedListener",
NullPointerException.class,
() -> mSessionManager.addOnActiveSessionsChangedListener(null, null));
@@ -310,6 +299,7 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testSetOnVolumeKeyLongPressListener() throws Exception {
Context context = getInstrumentation().getTargetContext();
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
@@ -352,6 +342,7 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testSetOnMediaKeyListener() throws Exception {
Handler handler = createHandler();
MediaSession session = null;
@@ -418,6 +409,7 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testRemoteUserInfo() throws Exception {
final Context context = getInstrumentation().getTargetContext();
Handler handler = createHandler();
@@ -608,9 +600,9 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testCustomClassConfigValuesAreValid() throws Exception {
- if (!MediaUtils.check(sIsAtLeastS, "test invalid before Android 12")) return;
- final Context context = getInstrumentation().getTargetContext();
+ Context context = getInstrumentation().getTargetContext();
String customMediaKeyDispatcher = context.getString(
android.R.string.config_customMediaKeyDispatcher);
String customMediaSessionPolicyProvider = context.getString(
@@ -629,6 +621,7 @@ public class MediaSessionManagerTest {
}
@Test
+ @NonMainlineTest
public void testIsTrustedForMediaControl_withEnabledNotificationListener() throws Exception {
List<String> packageNames = getEnabledNotificationListenerPackages();
for (String packageName : packageNames) {
diff --git a/tests/tests/media/common/src/android/media/cts/CodecState.java b/tests/tests/media/common/src/android/media/cts/CodecState.java
index 9fda728f9cf..d34e4f433a9 100644
--- a/tests/tests/media/common/src/android/media/cts/CodecState.java
+++ b/tests/tests/media/common/src/android/media/cts/CodecState.java
@@ -85,12 +85,6 @@ public class CodecState {
private volatile OnFirstTunnelFrameReadyListener mOnFirstTunnelFrameReadyListener;
/** If true, starves the underlying {@link MediaCodec} to simulate an underrun. */
private boolean mShouldStopDrainingOutputBuffers;
- /**
- * An offset (in nanoseconds) to add to presentation timestamps fed to the {@link AudioTrack}.
- *
- * This is used to simulate desynchronization between tracks.
- */
- private long mAudioOffsetNs;
private static boolean mIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
@@ -136,8 +130,6 @@ public class CodecState {
mIsFirstTunnelFrameReady = false;
mShouldStopDrainingOutputBuffers = false;
- mAudioOffsetNs = 0;
-
String mime = mFormat.getString(MediaFormat.KEY_MIME);
Log.d(TAG, "CodecState::CodecState " + mime);
mIsAudio = mime.startsWith("audio/");
@@ -467,7 +459,7 @@ public class CodecState {
buffer.clear();
mAudioTrack.write(ByteBuffer.wrap(audioArray), info.size,
- info.presentationTimeUs * 1000 + mAudioOffsetNs);
+ info.presentationTimeUs * 1000);
mCodec.releaseOutputBuffer(index, false /* render */);
@@ -632,16 +624,21 @@ public class CodecState {
/**
* Stop draining output buffers which can simulate underrun condition.
*/
- public void stopDrainingOutputBuffers(boolean enable) {
- mShouldStopDrainingOutputBuffers = enable;
+ public void stopDrainingOutputBuffers(boolean stop) {
+ mShouldStopDrainingOutputBuffers = stop;
+ if (mAudioTrack != null) {
+ mAudioTrack.setStopWriting(stop);
+ }
}
/**
- * Option to introduce an offset (positive or negative, in ms) to content queued to the
+ * Option to introduce an offset (positive or negative, in Ns) to content queued to the
* {@link AudioTrack}.
*/
- public void setAudioOffsetMs(int audioOffsetMs) {
- mAudioOffsetNs = audioOffsetMs * 1000000;
+ public void setAudioOffsetNs(long audioOffsetNs) {
+ if (mAudioTrack != null) {
+ mAudioTrack.setAudioOffsetNs(audioOffsetNs);
+ }
}
/** Returns the underlying {@code AudioTrack}, if any. */
diff --git a/tests/tests/media/common/src/android/media/cts/MediaCodecCryptoAsyncHelper.java b/tests/tests/media/common/src/android/media/cts/MediaCodecCryptoAsyncHelper.java
index 2ecd83addd5..c6d14795362 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaCodecCryptoAsyncHelper.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaCodecCryptoAsyncHelper.java
@@ -192,7 +192,7 @@ public class MediaCodecCryptoAsyncHelper {
slotQueue = new LinkedBlockingQueue<>();
boolean isSecureDecodeASuccess = false;
try {
- outputSurface = new OutputSurface(1, 1);
+ outputSurface = new OutputSurface(1, 1, false, secure);
MediaFormat mediaFormat = mediaExtractor.getTrackFormat(
mediaExtractor.getSampleTrackIndex());
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
@@ -310,7 +310,7 @@ public class MediaCodecCryptoAsyncHelper {
final LinkedBlockingQueue<MediaCodecAsyncHelper.SlotEvent>
slotQueue = new LinkedBlockingQueue<>();
try {
- outputSurface = new OutputSurface(1, 1);
+ outputSurface = new OutputSurface(1, 1, false, secure);
MediaFormat mediaFormat = mediaExtractor.getTrackFormat(
mediaExtractor.getSampleTrackIndex());
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
@@ -438,7 +438,7 @@ public class MediaCodecCryptoAsyncHelper {
final LinkedBlockingQueue<MediaCodec.CryptoInfo>
cryptoInfoQueue = new LinkedBlockingQueue<>();
try {
- outputSurface = new OutputSurface(1, 1);
+ outputSurface = new OutputSurface(1, 1, false, secure);
MediaFormat mediaFormat = mediaExtractor.getTrackFormat(
mediaExtractor.getSampleTrackIndex());
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
diff --git a/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java b/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
index d4a8250a1ac..1877566c362 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
@@ -737,16 +737,16 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
}
/** Configure underrun simulation on audio codecs. */
- public void stopDrainingAudioOutputBuffers(boolean enabled) {
+ public void stopDrainingAudioOutputBuffers(boolean stop) {
for (CodecState state: mAudioCodecStates.values()) {
- state.stopDrainingOutputBuffers(enabled);
+ state.stopDrainingOutputBuffers(stop);
}
}
- /** Configure an offset (in ms) to audio content to simulate track desynchronization. */
- public void setAudioTrackOffsetMs(int audioOffsetMs) {
+ /** Configure an offset (in Ns) to audio content to simulate track desynchronization. */
+ public void setAudioTrackOffsetNs(long audioOffsetNs) {
if (mAudioTrackState != null) {
- mAudioTrackState.setAudioOffsetMs(audioOffsetMs);
+ mAudioTrackState.setAudioOffsetNs(audioOffsetNs);
}
}
diff --git a/tests/tests/media/common/src/android/media/cts/NonBlockingAudioTrack.java b/tests/tests/media/common/src/android/media/cts/NonBlockingAudioTrack.java
index ce31607898d..6589cc568f0 100644
--- a/tests/tests/media/common/src/android/media/cts/NonBlockingAudioTrack.java
+++ b/tests/tests/media/common/src/android/media/cts/NonBlockingAudioTrack.java
@@ -23,7 +23,9 @@ import android.media.AudioTrack;
import java.nio.ByteBuffer;
import java.util.LinkedList;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
/**
* Class for playing audio by using audio track.
@@ -47,6 +49,13 @@ public class NonBlockingAudioTrack {
private LinkedList<QueueElement> mQueue = new LinkedList<QueueElement>();
private boolean mStopped;
private int mBufferSizeInBytes;
+ private AtomicBoolean mStopWriting = new AtomicBoolean(false);
+
+ /**
+ * An offset (in nanoseconds) to add to presentation timestamps fed to the {@link AudioTrack}.
+ * This is used to simulate desynchronization between tracks.
+ */
+ private AtomicLong mAudioOffsetNs = new AtomicLong(0);
public NonBlockingAudioTrack(int sampleRate, int channelCount, boolean hwAvSync,
int audioSessionId) {
@@ -130,6 +139,14 @@ public class NonBlockingAudioTrack {
}
}
+ public void setStopWriting(boolean stop) {
+ mStopWriting.set(stop);
+ }
+
+ public void setAudioOffsetNs(long audioOffsetNs) {
+ mAudioOffsetNs.set(audioOffsetNs);
+ }
+
public void pause() {
mAudioTrack.pause();
}
@@ -155,8 +172,12 @@ public class NonBlockingAudioTrack {
public void process() {
while (!mQueue.isEmpty()) {
QueueElement element = mQueue.peekFirst();
+ if (mStopWriting.get()) {
+ break;
+ }
+
int written = mAudioTrack.write(element.data, element.size,
- AudioTrack.WRITE_NON_BLOCKING, element.pts);
+ AudioTrack.WRITE_NON_BLOCKING, element.pts + mAudioOffsetNs.get());
if (written < 0) {
throw new RuntimeException("Audiotrack.write() failed.");
}
diff --git a/tests/tests/media/common/src/android/media/cts/OutputSurface.java b/tests/tests/media/common/src/android/media/cts/OutputSurface.java
index a25f2ba44c5..efd464d9bcc 100644
--- a/tests/tests/media/common/src/android/media/cts/OutputSurface.java
+++ b/tests/tests/media/common/src/android/media/cts/OutputSurface.java
@@ -27,6 +27,8 @@ import android.opengl.EGLSurface;
import android.util.Log;
import android.view.Surface;
+import org.junit.Assume;
+
/**
* Holds state associated with a Surface used for MediaCodec decoder output.
@@ -47,6 +49,11 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private static final String TAG = "OutputSurface";
private static final boolean VERBOSE = false;
+ public static int EGL_PROTECTED_CONTENT_EXT = 0x32C0;
+
+ // https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_protected_content.txt
+ private static final String EXTENSION_PROTECTED_CONTENT = "EGL_EXT_protected_content";
+
private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
@@ -56,6 +63,7 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private Object mFrameSyncObject = new Object(); // guards mFrameAvailable
private boolean mFrameAvailable;
+ private boolean mSecureMode = false;
private TextureRender mTextureRender;
@@ -65,13 +73,18 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
* to MediaCodec.configure().
*/
public OutputSurface(int width, int height) {
- this(width, height, false);
+ this(width, height, false, false);
}
public OutputSurface(int width, int height, boolean useHighBitDepth) {
+ this(width, height, useHighBitDepth, false);
+ }
+
+ public OutputSurface(int width, int height, boolean useHighBitDepth, boolean secure) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException();
}
+ mSecureMode = secure;
eglSetup(width, height, useHighBitDepth);
makeCurrent();
@@ -91,12 +104,18 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
setup(listener);
}
+ private boolean isSecureSurfaceSupported() {
+ EGLDisplay display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+ String eglExtensions = EGL14.eglQueryString(display, EGL14.EGL_EXTENSIONS);
+ return eglExtensions != null && eglExtensions.contains(EXTENSION_PROTECTED_CONTENT);
+ }
+
/**
* Creates instances of TextureRender and SurfaceTexture, and a Surface associated
* with the SurfaceTexture.
*/
private void setup(SurfaceTexture.OnFrameAvailableListener listener) {
- mTextureRender = new TextureRender();
+ mTextureRender = new TextureRender(mSecureMode);
mTextureRender.surfaceCreated();
// Even if we don't access the SurfaceTexture after the constructor returns, we
@@ -135,6 +154,11 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
mEGLDisplay = null;
throw new RuntimeException("unable to initialize EGL14");
}
+ if (mSecureMode) {
+ Assume.assumeTrue("EGL_PROTECTED_CONTENT_EXT not supported",
+ isSecureSurfaceSupported());
+ checkEglError("EGL_PROTECTED_CONTENT_EXT not supported");
+ }
// Configure EGL for pbuffer and OpenGL ES 2.0. We want enough RGB bits
// to be able to tell if the frame is reasonable.
@@ -163,10 +187,19 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
}
// Configure context for OpenGL ES 2.0.
- int[] contextAttribList = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL14.EGL_NONE
- };
+ int[] contextAttribList;
+ if (!mSecureMode) {
+ contextAttribList = new int [] {
+ EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL14.EGL_NONE
+ };
+ } else {
+ contextAttribList = new int [] {
+ EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_PROTECTED_CONTENT_EXT, EGL14.EGL_TRUE,
+ EGL14.EGL_NONE
+ };
+ }
mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
contextAttribList, 0);
checkEglError("eglCreateContext");
@@ -176,11 +209,22 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
// Create a pbuffer surface. By using this for output, we can use glReadPixels
// to test values in the output.
- int[] surfaceAttribs = {
- EGL14.EGL_WIDTH, width,
- EGL14.EGL_HEIGHT, height,
- EGL14.EGL_NONE
- };
+ int[] surfaceAttribs;
+
+ if (!mSecureMode) {
+ surfaceAttribs = new int[] {
+ EGL14.EGL_WIDTH, width,
+ EGL14.EGL_HEIGHT, height,
+ EGL14.EGL_NONE
+ };
+ } else {
+ surfaceAttribs = new int[] {
+ EGL14.EGL_WIDTH, width,
+ EGL14.EGL_HEIGHT, height,
+ EGL_PROTECTED_CONTENT_EXT, EGL14.EGL_TRUE,
+ EGL14.EGL_NONE
+ };
+ }
mEGLSurface = EGL14.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs, 0);
checkEglError("eglCreatePbufferSurface");
if (mEGLSurface == null) {
diff --git a/tests/tests/media/common/src/android/media/cts/TextureRender.java b/tests/tests/media/common/src/android/media/cts/TextureRender.java
index daf589268b1..1d02be95f79 100644
--- a/tests/tests/media/common/src/android/media/cts/TextureRender.java
+++ b/tests/tests/media/common/src/android/media/cts/TextureRender.java
@@ -79,8 +79,16 @@ public class TextureRender {
private int muSTMatrixHandle;
private int maPositionHandle;
private int maTextureHandle;
+ private boolean mSecureMode = false;
+
+ private static int GL_TEXTURE_PROTECTED_EXT = 0x8BFA;
public TextureRender() {
+ this(false);
+ }
+
+ public TextureRender(boolean secure) {
+ mSecureMode = secure;
mTriangleVertices = ByteBuffer.allocateDirect(
mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
@@ -176,6 +184,10 @@ public class TextureRender {
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
+ if (mSecureMode) {
+ GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_PROTECTED_EXT,
+ GLES20.GL_TRUE);
+ }
checkGlError("glTexParameter");
}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeOnlyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeOnlyTest.java
index 8b25bcde25e..93ab0d1c8bd 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeOnlyTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeOnlyTest.java
@@ -37,6 +37,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
+import android.os.SystemProperties;
import android.platform.test.annotations.AppModeFull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -72,6 +73,10 @@ import java.util.function.Supplier;
@RunWith(AndroidJUnit4.class)
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public class DecodeOnlyTest extends MediaTestBase {
+ public static final boolean IS_BOARD_AT_LEAST_U =
+ SystemProperties.getInt("ro.board.api_level", Build.VERSION_CODES.CUR_DEVELOPMENT)
+ >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+
private static final String MEDIA_DIR_STRING = WorkDir.getMediaDirString();
private static final String HEVC_VIDEO =
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv";
@@ -102,36 +107,48 @@ public class DecodeOnlyTest extends MediaTestBase {
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledPerfectSeekInitialPeekOnAvc() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledPerfectSeek(AVC_VIDEO, true);
}
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledPerfectSeekInitialPeekOnVp9() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledPerfectSeek(VP9_VIDEO, true);
}
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledPerfectSeekInitialPeekOnHevc() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledPerfectSeek(HEVC_VIDEO, true);
}
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledPerfectSeekInitialPeekOffAvc() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledPerfectSeek(AVC_VIDEO, false);
}
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledPerfectSeekInitialPeekOffVp9() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledPerfectSeek(VP9_VIDEO, false);
}
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledPerfectSeekInitialPeekOffHevc() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledPerfectSeek(HEVC_VIDEO, false);
}
@@ -141,18 +158,24 @@ public class DecodeOnlyTest extends MediaTestBase {
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledTrickPlayHevc() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledTrickPlay(HEVC_VIDEO);
}
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledTrickPlayAvc() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledTrickPlay(AVC_VIDEO);
}
@Test
@ApiTest(apis = {"android.media.MediaCodec#BUFFER_FLAG_DECODE_ONLY"})
public void testTunneledTrickPlayVp9() throws Exception {
+ // Tunnel mode requires vendor support of the DECODE_ONLY feature
+ Assume.assumeTrue("Board API level is not Android 14 or later.", IS_BOARD_AT_LEAST_U);
testTunneledTrickPlay(VP9_VIDEO);
}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
index df497b66025..b6d428327f8 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
@@ -59,6 +59,7 @@ import android.media.cts.TestUtils;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.view.Surface;
@@ -107,10 +108,14 @@ import java.util.zip.CRC32;
public class DecoderTest extends MediaTestBase {
private static final String TAG = "DecoderTest";
private static final String REPORT_LOG_NAME = "CtsMediaDecoderTestCases";
- private static boolean mIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
- private static boolean sIsBeforeS = ApiLevelUtil.isBefore(Build.VERSION_CODES.S);
- private static boolean sIsAfterT = ApiLevelUtil.isAfter(Build.VERSION_CODES.TIRAMISU)
- || ApiLevelUtil.codenameEquals("UpsideDownCake");
+
+ private static final int BOARD_SDK_LEVEL =
+ SystemProperties.getInt("ro.board.api_level", Build.VERSION_CODES.CUR_DEVELOPMENT);
+ public static final boolean IS_BOARD_AT_LEAST_S = BOARD_SDK_LEVEL >= Build.VERSION_CODES.S;
+
+ private static boolean IS_AT_LEAST_R = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
+ private static boolean IS_BEFORE_S = ApiLevelUtil.isBefore(Build.VERSION_CODES.S);
+ private static boolean IS_AFTER_T = ApiLevelUtil.isAfter(Build.VERSION_CODES.TIRAMISU);
private static final int RESET_MODE_NONE = 0;
private static final int RESET_MODE_RECONFIGURE = 1;
@@ -369,7 +374,7 @@ public class DecoderTest extends MediaTestBase {
private void verifyChannelsAndRates(String[] mimetypes, int[] sampleRates,
int[] channelMasks) throws Exception {
- if (!MediaUtils.check(mIsAtLeastR, "test invalid before Android 11")) return;
+ if (!MediaUtils.check(IS_AT_LEAST_R, "test invalid before Android 11")) return;
for (String mimetype : mimetypes) {
// ensure we find a codec for all listed mime/channel/rate combinations
@@ -1487,7 +1492,7 @@ public class DecoderTest extends MediaTestBase {
throws IOException {
// CODEC_DEFAULT behaviors started with S
- if (sIsBeforeS) {
+ if (IS_BEFORE_S) {
codecSupportMode = CODEC_ALL;
}
MediaExtractor ex = new MediaExtractor();
@@ -1515,7 +1520,7 @@ public class DecoderTest extends MediaTestBase {
continue;
}
if (codecSupportMode == CODEC_ALL) {
- if (sIsAfterT) {
+ if (IS_AFTER_T) {
// This is an extractor failure as often as it is a codec failure
assertTrue(info.getName() + " does not declare support for "
+ format.toString(),
@@ -3525,6 +3530,8 @@ public class DecoderTest extends MediaTestBase {
@ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTunneledVideoPeekOnHevc() throws Exception {
+ // Requires vendor support of the TUNNEL_PEEK feature
+ Assume.assumeTrue("Board API level is not Android 12 or later.", IS_BOARD_AT_LEAST_S);
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv", 25);
}
@@ -3536,6 +3543,8 @@ public class DecoderTest extends MediaTestBase {
@ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTunneledVideoPeekOnAvc() throws Exception {
+ // Requires vendor support of the TUNNEL_PEEK feature
+ Assume.assumeTrue("Board API level is not Android 12 or later.", IS_BOARD_AT_LEAST_S);
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 25);
}
@@ -3547,12 +3556,13 @@ public class DecoderTest extends MediaTestBase {
@ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTunneledVideoPeekOnVp9() throws Exception {
+ // Requires vendor support of the TUNNEL_PEEK feature
+ Assume.assumeTrue("Board API level is not Android 12 or later.", IS_BOARD_AT_LEAST_S);
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm",
30);
}
-
/**
* Test that peek off doesn't render the first frame until turned on in tunneled mode.
*
@@ -3618,6 +3628,8 @@ public class DecoderTest extends MediaTestBase {
@ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTunneledVideoPeekOffHevc() throws Exception {
+ // Requires vendor support of the TUNNEL_PEEK feature
+ Assume.assumeTrue("Board API level is not Android 12 or later.", IS_BOARD_AT_LEAST_S);
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv", 25);
}
@@ -3629,6 +3641,8 @@ public class DecoderTest extends MediaTestBase {
@ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTunneledVideoPeekOffAvc() throws Exception {
+ // Requires vendor support of the TUNNEL_PEEK feature
+ Assume.assumeTrue("Board API level is not Android 12 or later.", IS_BOARD_AT_LEAST_S);
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 25);
}
@@ -3640,6 +3654,8 @@ public class DecoderTest extends MediaTestBase {
@ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTunneledVideoPeekOffVp9() throws Exception {
+ // Requires vendor support of the TUNNEL_PEEK feature
+ Assume.assumeTrue("Board API level is not Android 12 or later.", IS_BOARD_AT_LEAST_S);
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm",
30);
@@ -3682,7 +3698,7 @@ public class DecoderTest extends MediaTestBase {
// After 100 ms of playback, simulate a PTS gap of 100 ms
Thread.sleep(100);
- mMediaCodecPlayer.setAudioTrackOffsetMs(100);
+ mMediaCodecPlayer.setAudioTrackOffsetNs(100L * 1000000);
// Verify that at some point in time in the future, the framePosition stopped advancing.
// This should happen when the PTS gap is encountered - silence is rendered to fill the
@@ -4229,7 +4245,7 @@ public class DecoderTest extends MediaTestBase {
// Resume audio playback with a negative offset, in order to simulate a desynchronisation.
// TODO(b/202710709): Use timestamp relative to last played video frame before pause
- mMediaCodecPlayer.setAudioTrackOffsetMs(-100);
+ mMediaCodecPlayer.setAudioTrackOffsetNs(-100L * 1000000);
mMediaCodecPlayer.stopDrainingAudioOutputBuffers(false);
// Wait until audio playback resumes
diff --git a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
index 19d8035b252..5180acc3ea0 100644
--- a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
@@ -32,6 +32,7 @@ import android.media.cts.TestUtils.Monitor;
import android.net.Uri;
import android.os.Build;
import android.os.Looper;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.util.Base64;
import android.util.Log;
@@ -60,6 +61,7 @@ import java.util.Vector;
/**
* Tests of MediaPlayer streaming capabilities.
*/
+@AppModeFull(reason = "Instant apps cannot access the SD card")
public class MediaDrmClearkeyTest extends MediaCodecPlayerTestBase<MediaStubActivity> {
private static final String TAG = MediaDrmClearkeyTest.class.getSimpleName();
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
index cbfb26d00fd..0a4d19ee337 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
@@ -69,7 +69,7 @@ public class EncoderTest {
static final String mInpPrefix = WorkDir.getMediaDirString();
private static final int kNumInputBytes = 512 * 1024;
private static final long kTimeoutUs = 100;
- public static final int PER_TEST_TIMEOUT_SMALL_TEST_MS = 60000;
+ public static final int PER_TEST_TIMEOUT_SMALL_TEST_MS = 120000;
// not all combinations are valid
private static final int MODE_SILENT = 0;
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
index 110ad390870..e20cc3306ac 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
@@ -135,6 +135,7 @@ public class ResourceManagerTestActivityBase extends Activity {
Bundle extras = getIntent().getExtras();
int type = TYPE_NONSECURE;
boolean highResolution = false;
+ boolean isResolutionSet = true;
if (extras != null) {
type = extras.getInt("test-type", type);
// Check if mime has been passed.
@@ -144,7 +145,8 @@ public class ResourceManagerTestActivityBase extends Activity {
mHeight = extras.getInt("height");
if (mWidth == 0 || mHeight == 0) {
// Either no resolution has been passed or its invalid.
- // So, look for high-resolution flag.
+ isResolutionSet = false;
+ // See if the high-resolution flag has been set.
highResolution = extras.getBoolean("high-resolution", highResolution);
} else if (mHeight >= 1080) {
highResolution = true;
@@ -167,6 +169,12 @@ public class ResourceManagerTestActivityBase extends Activity {
if (!shouldSkip) {
if (type == TYPE_SECURE || type == TYPE_MIX) {
+ if (!isResolutionSet && type == TYPE_MIX) {
+ // clear previously set resolutions by the unsecure codecs,
+ // so that we read the secure codec resolutions again.
+ mWidth = 0;
+ mHeight = 0;
+ }
securePlayback = true;
MediaCodecInfo info = getTestCodecInfo(securePlayback);
if (info != null) {
diff --git a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
index 9505f3ef760..6f479a296fc 100644
--- a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
+++ b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderTest.java
@@ -595,7 +595,7 @@ public class MediaRecorderTest extends MediaTestBase {
FileOutputStream fos = new FileOutputStream(OUTPUT_PATH2);
FileDescriptor fd = fos.getFD();
mMediaRecorder.setOutputFile(fd);
- long maxFileSize = MAX_FILE_SIZE * 10;
+ long maxFileSize = mVideoHeight >= 720 ? MAX_FILE_SIZE * 50 : MAX_FILE_SIZE * 10;
recordMedia(maxFileSize, mOutFile2);
assertFalse(checkLocationInFile(OUTPUT_PATH2));
fos.close();
@@ -628,7 +628,11 @@ public class MediaRecorderTest extends MediaTestBase {
}
mMediaRecorder.setVideoSize(width, height);
mMediaRecorder.setOutputFile(mOutFile);
- long maxFileSize = MAX_FILE_SIZE * 10;
+
+ // For some devices, the QUALITY_LOW profile can be as high as 720p. In that case use
+ // the bigger max file size to make sure the file will be able to contain at least single
+ // valid frame.
+ long maxFileSize = height >= 720 ? MAX_FILE_SIZE * 50 : MAX_FILE_SIZE * 10;
recordMedia(maxFileSize, mOutFile);
}
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java
index 4117a5c4d36..2a0403ee4d4 100644
--- a/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java
@@ -64,18 +64,7 @@ public class NfcAntennaLocationApiTest {
public void testGetNfcAntennaInfo() {
NfcAntennaInfo nfcAntennaInfo = mAdapter.getNfcAntennaInfo();
- if (nfcAntennaInfo == null) {
- return;
- }
-
- assertEquals("Device widths do not match", 0,
- nfcAntennaInfo.getDeviceWidth());
- assertEquals("Device heights do not match", 0,
- nfcAntennaInfo.getDeviceHeight());
- assertEquals("Device foldable do not match", false,
- nfcAntennaInfo.isDeviceFoldable());
- assertEquals("Wrong number of available antennas", 0,
- nfcAntennaInfo.getAvailableNfcAntennas().size());
+ assertNotNull(nfcAntennaInfo);
AvailableNfcAntenna availableNfcAntenna = new AvailableNfcAntenna(ANTENNA_X, ANTENNA_Y);
diff --git a/tests/tests/notification/src/android/app/notification/current/cts/NotificationManagerTest.java b/tests/tests/notification/src/android/app/notification/current/cts/NotificationManagerTest.java
index e1cfbca5636..c56fadd878b 100755
--- a/tests/tests/notification/src/android/app/notification/current/cts/NotificationManagerTest.java
+++ b/tests/tests/notification/src/android/app/notification/current/cts/NotificationManagerTest.java
@@ -2413,16 +2413,20 @@ public class NotificationManagerTest extends BaseNotificationManagerTest {
List<String> allowedPackages = Arrays.asList(
mPackageManager.getPermissionControllerPackageName(),
"com.android.shell");
+ StringBuilder sb = new StringBuilder();
for (PackageInfo pkg : allPackages) {
if (!pkg.applicationInfo.isSystemApp()
&& mPackageManager.checkPermission(
Manifest.permission.MANAGE_NOTIFICATION_LISTENERS, pkg.packageName)
== PackageManager.PERMISSION_GRANTED
&& !allowedPackages.contains(pkg.packageName)) {
- fail(pkg.packageName + " can't hold "
- + Manifest.permission.MANAGE_NOTIFICATION_LISTENERS);
+ sb.append(pkg.packageName + " can't hold "
+ + Manifest.permission.MANAGE_NOTIFICATION_LISTENERS + "\n");
}
}
+ if (sb.length() > 0) {
+ fail(sb.toString());
+ }
}
public void testChannelDeletion_cancelReason() throws Exception {
diff --git a/tests/tests/os/assets/minijail/isolated-common.policy b/tests/tests/os/assets/minijail/isolated-common.policy
index 11205aee06b..f7bb1e8ce7f 100644
--- a/tests/tests/os/assets/minijail/isolated-common.policy
+++ b/tests/tests/os/assets/minijail/isolated-common.policy
@@ -94,7 +94,7 @@ pipe2: 1
ppoll: 1
# prctl: PR_SET_VMA=0x53564d41, PR_SET_TIMERSLACK_PID={41,43,127} depending on kernel version
-prctl: arg0 == PR_GET_NAME || arg0 == PR_SET_NAME || arg0 == PR_GET_DUMPABLE || arg0 == PR_SET_DUMPABLE || arg0 == PR_SET_PTRACER || arg0 == PR_SET_TIMERSLACK || arg0 == 0x53564d41 || arg0 == 41 || arg0 == 43 || arg0 == 127
+prctl: arg0 == PR_GET_NAME || arg0 == PR_SET_NAME || arg0 == PR_GET_DUMPABLE || arg0 == PR_SET_DUMPABLE || arg0 == PR_SET_PTRACER || arg0 == PR_SET_TIMERSLACK || arg0 == 0x53564d41 || arg0 == 41 || arg0 == 43 || arg0 == 127 || arg0 == PR_PAC_RESET_KEYS
pread64: 1
pselect6: 1
diff --git a/tests/tests/os/src/android/os/cts/FileObserverTest.java b/tests/tests/os/src/android/os/cts/FileObserverTest.java
index 1ae870622a1..26ea8952bc0 100644
--- a/tests/tests/os/src/android/os/cts/FileObserverTest.java
+++ b/tests/tests/os/src/android/os/cts/FileObserverTest.java
@@ -129,6 +129,11 @@ public class FileObserverTest extends AndroidTestCase {
*
* On emulated storage, there may be additional operations related to case insensitivity, so
* we just check that the expected ones are present.
+ *
+ * On internal storage, there may also be additional operations - the art runtime creates a
+ * folder called 'oat_primary' in the cache folder, for instance. So it is best just to
+ * always check that the expected ones are present, since we cannot stop other components
+ * from performing extra actions.
*/
public void helpTestFileObserver(File dir, boolean isEmulated) throws Exception {
MockFileObserver fileObserver = null;
@@ -153,10 +158,7 @@ public class FileObserverTest extends AndroidTestCase {
// should not get any event
expected = new int[] {UNDEFINED};
moveEvents = waitForEvent(fileObserver);
- if (isEmulated)
- assertEventsContains(testFile, expected, moveEvents);
- else
- assertEventsEquals(testFile, expected, moveEvents);
+ assertEventsContains(testFile, expected, moveEvents);
} finally {
fileObserver.stopWatching();
if (out != null)
@@ -192,11 +194,7 @@ public class FileObserverTest extends AndroidTestCase {
FileObserver.MOVE_SELF,
};
moveEvents = waitForEvent(movedFileObserver);
- if (isEmulated) {
- assertEventsContains(testFile, expected, moveEvents);
- } else {
- assertEventsEquals(testFile, expected, moveEvents);
- }
+ assertEventsContains(testFile, expected, moveEvents);
} finally {
movedFileObserver.stopWatching();
}
@@ -220,11 +218,7 @@ public class FileObserverTest extends AndroidTestCase {
};
final FileEvent[] moveEvents = waitForEvent(fileObserver);
- if (isEmulated) {
- assertEventsContains(testFile, expected, moveEvents);
- } else {
- assertEventsEquals(testFile, expected, moveEvents);
- }
+ assertEventsContains(testFile, expected, moveEvents);
}
private void verifyTriggeredEventsOnDir(MockFileObserver fileObserver,
@@ -245,11 +239,7 @@ public class FileObserverTest extends AndroidTestCase {
};
final FileEvent[] moveEvents = waitForEvent(fileObserver);
- if (isEmulated) {
- assertEventsContains(testFile, expected, moveEvents);
- } else {
- assertEventsEquals(testFile, expected, moveEvents);
- }
+ assertEventsContains(testFile, expected, moveEvents);
}
public void testFileObserver() throws Exception {
@@ -319,21 +309,6 @@ public class FileObserverTest extends AndroidTestCase {
}
}
- private void assertEventsEquals(
- File testFile, final int[] expected, final FileEvent[] moveEvents) {
- List<Integer> expectedEvents = new ArrayList<Integer>();
- for (int i = 0; i < expected.length; i++) {
- expectedEvents.add(expected[i]);
- }
- List<FileEvent> actualEvents = Arrays.asList(moveEvents);
- String message = "For test file [" + testFile.getAbsolutePath()
- + "] expected: " + expectedEvents + " Actual: " + actualEvents;
- assertEquals(message, expected.length, moveEvents.length);
- for (int i = 0; i < expected.length; i++) {
- assertEquals(message, expected[i], moveEvents[i].event);
- }
- }
-
private void assertEventsContains(
File testFile, final int[] expected, final FileEvent[] moveEvents) {
List<Integer> expectedEvents = new ArrayList<Integer>();
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java
index 5c5327037c7..57287081fa4 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java
@@ -32,11 +32,15 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
final class StorageManagerHelper {
+ private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);
+ private static final long POLLING_SLEEP_MILLIS = 100;
+
/**
* Creates a virtual disk that simulates SDCard on a device. It is
* mounted as a public visible disk.
@@ -96,11 +100,11 @@ final class StorageManagerHelper {
private static void pollForCondition(Supplier<Boolean> condition, String errorMessage)
throws Exception {
Thread.sleep(2000);
- for (int i = 0; i < 20; i++) {
+ for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) {
if (condition.get()) {
return;
}
- Thread.sleep(100);
+ Thread.sleep(POLLING_SLEEP_MILLIS);
}
throw new TimeoutException(errorMessage);
}
diff --git a/tests/tests/permission/src/android/permission/cts/ShellCommandPermissionTest.java b/tests/tests/permission/src/android/permission/cts/ShellCommandPermissionTest.java
index e70f07bcea0..54562d5ee3a 100644
--- a/tests/tests/permission/src/android/permission/cts/ShellCommandPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ShellCommandPermissionTest.java
@@ -16,7 +16,8 @@
package android.permission.cts;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.fail;
import androidx.test.runner.AndroidJUnit4;
@@ -24,36 +25,23 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-
/**
* Test shell command capability enforcement
*/
@RunWith(AndroidJUnit4.class)
public class ShellCommandPermissionTest {
- private void executeShellCommandAndRequireError(String command, String required)
+ static final int EXPECTED_ERROR_CODE = 255;
+
+ /**
+ * Runs the given command, waits for it to exit, and verifies the return
+ * code indicates failure.
+ */
+ private void executeShellCommandAndWaitForError(String command)
throws Exception {
try {
java.lang.Process proc = Runtime.getRuntime().exec(command);
-
- // read output of command
- BufferedReader reader =
- new BufferedReader(new InputStreamReader(proc.getErrorStream()));
- StringBuilder stderr = new StringBuilder();
- String line = reader.readLine();
- while (line != null) {
- stderr.append(line);
- line = reader.readLine();
- }
- reader.close();
- proc.waitFor();
-
- String stderrString = stderr.toString();
- assertTrue("Expected command stderr '" + stderrString
- + " to contain '" + required + "'",
- stderrString.contains(required));
+ assertThat(proc.waitFor()).isEqualTo(EXPECTED_ERROR_CODE);
} catch (InterruptedException e) {
fail("Unsuccessful shell command");
}
@@ -61,15 +49,13 @@ public class ShellCommandPermissionTest {
@Test
public void testTraceIpc() throws Exception {
- executeShellCommandAndRequireError(
- "cmd activity trace-ipc stop --dump-file /data/system/last-fstrim",
- "Error:");
+ executeShellCommandAndWaitForError(
+ "cmd activity trace-ipc stop --dump-file /data/system/last-fstrim");
}
@Test
public void testDumpheap() throws Exception {
- executeShellCommandAndRequireError(
- "cmd activity dumpheap system_server /data/system/last-fstrim",
- "Error:");
+ executeShellCommandAndWaitForError(
+ "cmd activity dumpheap system_server /data/system/last-fstrim");
}
}
diff --git a/tests/tests/permission3/ImplicitUserSelectStorageApp/Android.bp b/tests/tests/permission3/ImplicitUserSelectStorageApp/Android.bp
index 88e82a15ad3..6d7036e524f 100644
--- a/tests/tests/permission3/ImplicitUserSelectStorageApp/Android.bp
+++ b/tests/tests/permission3/ImplicitUserSelectStorageApp/Android.bp
@@ -27,6 +27,6 @@ android_test_helper_app {
"kotlin-stdlib",
],
certificate: ":cts-testkey2",
- target_sdk_version: "33",
- min_sdk_version: "33",
+ target_sdk_version: "34",
+ min_sdk_version: "34",
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/CameraMicIndicatorsPermissionTest.kt
index 35252e50514..3d52a695e49 100644
--- a/tests/tests/permission3/src/android/permission3/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/CameraMicIndicatorsPermissionTest.kt
@@ -221,7 +221,7 @@ class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase {
@CddTest(requirement = "9.8.2/H-5-1,T-5-1,A-2-1")
fun testCameraIndicator() {
// If camera is not available skip the test
- assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA))
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY))
val manager = context.getSystemService(CameraManager::class.java)!!
assumeTrue(manager.cameraIdList.isNotEmpty())
changeSafetyCenterFlag(false.toString())
@@ -262,7 +262,7 @@ class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase {
// TODO(b/218788634): enable this test for car once the new camera indicator is implemented.
assumeFalse(isCar)
// If camera is not available skip the test
- assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA))
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY))
changeSafetyCenterFlag(false.toString())
testCameraAndMicIndicator(useMic = false, useCamera = true, chainUsage = true)
}
@@ -330,7 +330,7 @@ class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase {
) {
// If camera is not available skip the test
if (useCamera) {
- assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA))
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY))
}
var chainAttribution: AttributionSource? = null
openApp(useMic, useCamera, useHotword, finishEarly)
diff --git a/tests/tests/permission3/src/android/permission3/cts/ReviewAccessibilityServicesTest.kt b/tests/tests/permission3/src/android/permission3/cts/ReviewAccessibilityServicesTest.kt
index e42cc748912..c1fe8671833 100644
--- a/tests/tests/permission3/src/android/permission3/cts/ReviewAccessibilityServicesTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/ReviewAccessibilityServicesTest.kt
@@ -51,6 +51,7 @@ class ReviewAccessibilityServicesTest {
private val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
private val testService1String = context.getString(R.string.test_accessibility_service)
private val testService2String = context.getString(R.string.test_accessibility_service_2)
+ private val packageName = context.packageManager.permissionControllerPackageName
companion object {
private const val EXPECTED_TIMEOUT_MS = 500L
@@ -171,7 +172,10 @@ class ReviewAccessibilityServicesTest {
private fun waitForSettingsButtonToDisappear() {
SystemUtil.eventually {
- findObjectByText(false, "Settings")
+ findPCObjectByClassAndText(false,
+ "android.widget.Button",
+ "Settings"
+ )
}
}
@@ -196,6 +200,21 @@ class ReviewAccessibilityServicesTest {
return findObjectByTextWithoutRetry(expected, text)
}
}
+
+ private fun findPCObjectByClassAndText(
+ shouldBePresent: Boolean,
+ className: String,
+ text: String
+ ): UiObject2? {
+ val selector = By.pkg(packageName)
+ .clazz(className)
+ .text(text)
+ val view = waitFindObjectOrNull(selector)
+ assertEquals(
+ "Expected to find view with packageName '$packageName' className '$className' " +
+ "text '$text' : $shouldBePresent", shouldBePresent, view != null)
+ return view
+ }
}
/** Test Accessibility Services */
diff --git a/tests/tests/permissionmultiuser/AndroidTest.xml b/tests/tests/permissionmultiuser/AndroidTest.xml
index a72b9151d2e..850799b3cdb 100644
--- a/tests/tests/permissionmultiuser/AndroidTest.xml
+++ b/tests/tests/permissionmultiuser/AndroidTest.xml
@@ -55,6 +55,8 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.permissionmultiuser.cts" />
+ <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" />
+ <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser" />
<option name="runtime-hint" value="5m" />
</test>
diff --git a/tests/tests/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt b/tests/tests/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt
index c0469291f6b..2b6707492d1 100644
--- a/tests/tests/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt
+++ b/tests/tests/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt
@@ -412,11 +412,8 @@ class AppDataSharingUpdatesTest {
private fun assertNoUpdatesPresent() {
findView(By.descContains(DATA_SHARING_UPDATES), true)
- findView(By.textContains(DATA_SHARING_UPDATES_SUBTITLE), true)
findView(By.textContains(DATA_SHARING_NO_UPDATES_MESSAGE), true)
findView(By.textContains(LOCATION_PACKAGE_NAME_SUBSTRING), false)
- findView(By.textContains(UPDATES_IN_LAST_30_DAYS), false)
- findView(By.textContains(DATA_SHARING_UPDATES_FOOTER_MESSAGE), true)
}
private fun grantLocationPermission(packageName: String) {
@@ -444,7 +441,7 @@ class AppDataSharingUpdatesTest {
private fun findView(selector: BySelector, expected: Boolean) {
val timeoutMillis =
if (expected) {
- 10000L
+ 20000L
} else {
1000L
}
@@ -467,7 +464,13 @@ class AppDataSharingUpdatesTest {
} catch (e: Exception) {
e
}
- Assert.assertTrue("Expected to find view: $expected", (exception == null) == expected)
+ val actual = exception == null
+ val message = if (expected) {
+ "Expected view $selector not found"
+ } else {
+ "Unexpected view found: $selector"
+ }
+ Assert.assertTrue(message, actual == expected)
}
}
}
diff --git a/tests/tests/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java b/tests/tests/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java
index a2d9c32eacb..c3a29ccb30b 100644
--- a/tests/tests/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java
+++ b/tests/tests/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java
@@ -43,6 +43,7 @@ import java.util.concurrent.TimeUnit;
@SystemUserOnly(reason = "Secondary users have the DISALLOW_SMS user restriction")
public class NoReceiveSmsPermissionTest extends AndroidTestCase {
+ private static final int SMS_DELIVERED_WAIT_TIME_MILLIS = 4000;
private static final String TELEPHONY_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String MESSAGE_STATUS_RECEIVED_ACTION =
"com.android.cts.permission.sms.MESSAGE_STATUS_RECEIVED_ACTION";
@@ -128,7 +129,7 @@ public class NoReceiveSmsPermissionTest extends AndroidTestCase {
private boolean waitForForEvents(Semaphore semaphore, int expectedNumberOfEvents) {
for (int i = 0; i < expectedNumberOfEvents; i++) {
try {
- if (!semaphore.tryAcquire(2000, TimeUnit.MILLISECONDS)) {
+ if (!semaphore.tryAcquire(SMS_DELIVERED_WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS)) {
return false;
}
} catch (Exception ex) {
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 ef5c67b9f4e..cb62b1bc924 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
@@ -64,11 +64,11 @@ public class Settings_MemoryUsageTest {
@Test
public void testMemoryUsageExceeded() {
- expectThrows(IllegalStateException.class,
+ expectThrows(Exception.class,
() -> Settings.System.putString(
mContentResolver, STRING_SETTING, Strings.repeat("A", 65535)));
// Repeated calls should throw as well
- expectThrows(IllegalStateException.class,
+ expectThrows(Exception.class,
() -> Settings.System.putString(
mContentResolver, STRING_SETTING, Strings.repeat("A", 65535)));
}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_39738.java b/tests/tests/security/src/android/security/cts/CVE_2021_39738.java
new file mode 100644
index 00000000000..7d8daea9f89
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_39738.java
@@ -0,0 +1,64 @@
+/*
+ * 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.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+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_2021_39738 extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 216190509)
+ @Test
+ public void testPocCVE_2021_39738() {
+ try {
+ Context context = getApplicationContext();
+ PackageManager pm = context.getPackageManager();
+
+ // Skip test for non-automotive builds
+ assumeTrue(
+ "Skipping test: " + PackageManager.FEATURE_AUTOMOTIVE + " missing",
+ pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+
+ // BluetoothPairingDialog activity should require BLUETOOTH_PRIVILEGED permission
+ final String pkgName = "com.android.car.settings";
+ ComponentName component =
+ new ComponentName(pkgName, pkgName + ".bluetooth.BluetoothPairingDialog");
+ String permission = pm.getActivityInfo(component, 0 /* flags */).permission;
+ assertTrue(
+ "Vulnerable to b/216190509",
+ permission.contains(android.Manifest.permission.BLUETOOTH_PRIVILEGED));
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/PersistableBundleTest.java b/tests/tests/security/src/android/security/cts/PersistableBundleTest.java
new file mode 100644
index 00000000000..e7780e49b64
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/PersistableBundleTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.Assert.assertFalse;
+
+import android.os.PersistableBundle;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+
+@RunWith(AndroidJUnit4.class)
+public class PersistableBundleTest extends StsExtraBusinessLogicTestCase {
+
+ @AsbSecurityTest(cveBugId = 247513680)
+ @Test
+ public void testReadFromStream_invalidType() throws Exception {
+ String input = "<bundle><string name=\"key\">value</string>"
+ + "<byte-array name=\"invalid\" num=\"2\">ffff</byte-array></bundle>";
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(input.getBytes());
+
+ // Reading from the stream with invalid type should not throw an exception
+ PersistableBundle restoredBundle = PersistableBundle.readFromStream(inputStream);
+
+ // verify invalid type is ignored
+ assertFalse(restoredBundle.containsKey("invalid"));
+ // verify valid type exists
+ assertEquals("value", restoredBundle.getString("key"));
+ }
+}
diff --git a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java
index 869b7e42c8d..97c0c8ad4f0 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java
@@ -15,21 +15,30 @@
*/
package android.speech.tts.cts;
+import android.content.Context;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Bundle;
import android.os.ConditionVariable;
-import android.os.Environment;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.ServiceManager;
+import android.speech.tts.ITextToSpeechManager;
+import android.speech.tts.ITextToSpeechSession;
+import android.speech.tts.ITextToSpeechSessionCallback;
import android.speech.tts.TextToSpeech;
import android.test.AndroidTestCase;
+import com.google.common.util.concurrent.SettableFuture;
+
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
-import java.util.Map;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link android.speech.tts.TextToSpeechService} using StubTextToSpeechService.
@@ -60,6 +69,37 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
return mTts.getTts();
}
+ public void testNullEngine() throws Exception {
+ IBinder binder = ServiceManager.getService(Context.TEXT_TO_SPEECH_MANAGER_SERVICE);
+ ITextToSpeechManager manager =
+ Objects.requireNonNull(ITextToSpeechManager.Stub.asInterface(binder));
+ // could use a spy instead but we run into "cannot proxy inaccessible class" issues
+ final SettableFuture<String> errorMsg = SettableFuture.create();
+ final SettableFuture<Void> connected = SettableFuture.create();
+ final SettableFuture<Void> disconnected = SettableFuture.create();
+ ITextToSpeechSessionCallback callback =
+ new ITextToSpeechSessionCallback.Stub() {
+ @Override
+ public void onConnected(ITextToSpeechSession session, IBinder serviceBinder) {
+ connected.set(null);
+ }
+
+ @Override
+ public void onDisconnected() {
+ disconnected.set(null);
+ }
+
+ @Override
+ public void onError(String errorInfo) {
+ errorMsg.set(errorInfo);
+ }
+ };
+ manager.createSession(null, callback);
+ assertFalse(connected.isDone());
+ assertFalse(disconnected.isDone());
+ assertEquals("Engine cannot be null", errorMsg.get(1, TimeUnit.SECONDS));
+ }
+
public void testSynthesizeToFile() throws Exception {
File sampleFile = new File(getContext().getExternalFilesDir(null), SAMPLE_FILE_NAME);
try {
@@ -67,7 +107,7 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
int result =
getTts().synthesizeToFile(
- UTTERANCE, createParams("mocktofile"), sampleFile.getPath());
+ UTTERANCE, createParams("mocktofile"), sampleFile.getPath());
verifySynthesisFile(result, mTts, sampleFile);
} finally {
sampleFile.delete();
@@ -84,10 +124,10 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
int result =
getTts().synthesizeToFile(
- UTTERANCE,
- params,
- sampleFile,
- params.getString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID));
+ UTTERANCE,
+ params,
+ sampleFile,
+ params.getString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID));
verifySynthesisFile(result, mTts, sampleFile);
} finally {
sampleFile.delete();
@@ -101,16 +141,16 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
assertFalse(sampleFile.exists());
ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(sampleFile,
- ParcelFileDescriptor.MODE_WRITE_ONLY
- | ParcelFileDescriptor.MODE_CREATE
- | ParcelFileDescriptor.MODE_TRUNCATE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY
+ | ParcelFileDescriptor.MODE_CREATE
+ | ParcelFileDescriptor.MODE_TRUNCATE);
Bundle params = createParamsBundle("mocktofile");
int result =
- getTts().synthesizeToFile(
- UTTERANCE, params, fileDescriptor,
- params.getString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID));
+ getTts().synthesizeToFile(
+ UTTERANCE, params, fileDescriptor,
+ params.getString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID));
verifySynthesisFile(result, mTts, sampleFile);
} finally {
sampleFile.delete();
@@ -119,29 +159,30 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
}
public void testMaxSpeechInputLength() {
- File sampleFile = new File(getContext().getExternalFilesDir(null), SAMPLE_FILE_NAME);
- try {
- assertFalse(sampleFile.exists());
- TextToSpeech tts = getTts();
-
- int maxLength = tts.getMaxSpeechInputLength();
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < maxLength; i++) {
+ File sampleFile = new File(getContext().getExternalFilesDir(null), SAMPLE_FILE_NAME);
+ try {
+ assertFalse(sampleFile.exists());
+ TextToSpeech tts = getTts();
+
+ int maxLength = tts.getMaxSpeechInputLength();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < maxLength; i++) {
+ sb.append("c");
+ }
+ String valid = sb.toString();
sb.append("c");
- }
- String valid = sb.toString();
- sb.append("c");
- String invalid = sb.toString();
-
- assertEquals(maxLength, valid.length());
- assertTrue(invalid.length() > maxLength);
- assertEquals(TextToSpeech.ERROR,
- tts.synthesizeToFile(invalid, createParams("mockToFile"), sampleFile.getPath()));
- assertEquals(TextToSpeech.SUCCESS,
- tts.synthesizeToFile(valid, createParams("mockToFile"), sampleFile.getPath()));
- } finally {
- sampleFile.delete();
- }
+ String invalid = sb.toString();
+
+ assertEquals(maxLength, valid.length());
+ assertTrue(invalid.length() > maxLength);
+ assertEquals(TextToSpeech.ERROR,
+ tts.synthesizeToFile(invalid, createParams("mockToFile"),
+ sampleFile.getPath()));
+ assertEquals(TextToSpeech.SUCCESS,
+ tts.synthesizeToFile(valid, createParams("mockToFile"), sampleFile.getPath()));
+ } finally {
+ sampleFile.delete();
+ }
}
public void testSpeak() throws Exception {
@@ -203,7 +244,7 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
try {
assertFalse(TextToSpeechWrapper.isSoundFile(sampleFile.getPath()));
FileOutputStream out = new FileOutputStream(sampleFile);
- out.write(new byte[] { 0x01, 0x02 });
+ out.write(new byte[]{0x01, 0x02});
out.close();
assertFalse(TextToSpeechWrapper.isSoundFile(sampleFile.getPath()));
} finally {
@@ -212,79 +253,81 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
}
public void testAddPlayEarcon() throws Exception {
- File sampleFile = new File(getContext().getExternalFilesDir(null), SAMPLE_FILE_NAME);
- try {
- generateSampleAudio(sampleFile);
+ File sampleFile = new File(getContext().getExternalFilesDir(null), SAMPLE_FILE_NAME);
+ try {
+ generateSampleAudio(sampleFile);
- Uri sampleUri = Uri.fromFile(sampleFile);
- assertEquals(getTts().addEarcon(EARCON_UTTERANCE, sampleFile), TextToSpeech.SUCCESS);
+ Uri sampleUri = Uri.fromFile(sampleFile);
+ assertEquals(getTts().addEarcon(EARCON_UTTERANCE, sampleFile), TextToSpeech.SUCCESS);
- int result = getTts().playEarcon(EARCON_UTTERANCE,
- TextToSpeech.QUEUE_FLUSH, createParamsBundle(EARCON_UTTERANCE), EARCON_UTTERANCE);
+ int result = getTts().playEarcon(EARCON_UTTERANCE,
+ TextToSpeech.QUEUE_FLUSH, createParamsBundle(EARCON_UTTERANCE),
+ EARCON_UTTERANCE);
- verifyAddPlay(result, mTts, EARCON_UTTERANCE);
- } finally {
- sampleFile.delete();
- }
+ verifyAddPlay(result, mTts, EARCON_UTTERANCE);
+ } finally {
+ sampleFile.delete();
+ }
}
public void testAddPlaySpeech() throws Exception {
- File sampleFile = new File(getContext().getExternalFilesDir(null), SAMPLE_FILE_NAME);
- try {
- generateSampleAudio(sampleFile);
+ File sampleFile = new File(getContext().getExternalFilesDir(null), SAMPLE_FILE_NAME);
+ try {
+ generateSampleAudio(sampleFile);
- Uri sampleUri = Uri.fromFile(sampleFile);
- assertEquals(getTts().addSpeech(SPEECH_UTTERANCE, sampleFile), TextToSpeech.SUCCESS);
+ Uri sampleUri = Uri.fromFile(sampleFile);
+ assertEquals(getTts().addSpeech(SPEECH_UTTERANCE, sampleFile), TextToSpeech.SUCCESS);
- int result = getTts().speak(SPEECH_UTTERANCE,
- TextToSpeech.QUEUE_FLUSH, createParamsBundle(SPEECH_UTTERANCE), SPEECH_UTTERANCE);
+ int result = getTts().speak(SPEECH_UTTERANCE,
+ TextToSpeech.QUEUE_FLUSH, createParamsBundle(SPEECH_UTTERANCE),
+ SPEECH_UTTERANCE);
- verifyAddPlay(result, mTts, SPEECH_UTTERANCE);
- } finally {
- sampleFile.delete();
- }
+ verifyAddPlay(result, mTts, SPEECH_UTTERANCE);
+ } finally {
+ sampleFile.delete();
+ }
}
public void testSetLanguage() {
- TextToSpeech tts = getTts();
+ TextToSpeech tts = getTts();
- assertEquals(tts.setLanguage(null), TextToSpeech.LANG_NOT_SUPPORTED);
- assertEquals(tts.setLanguage(new Locale("en", "US")), TextToSpeech.LANG_COUNTRY_AVAILABLE);
- assertEquals(tts.setLanguage(new Locale("en")), TextToSpeech.LANG_AVAILABLE);
- assertEquals(tts.setLanguage(new Locale("es", "US")), TextToSpeech.LANG_NOT_SUPPORTED);
+ assertEquals(tts.setLanguage(null), TextToSpeech.LANG_NOT_SUPPORTED);
+ assertEquals(tts.setLanguage(new Locale("en", "US")), TextToSpeech.LANG_COUNTRY_AVAILABLE);
+ assertEquals(tts.setLanguage(new Locale("en")), TextToSpeech.LANG_AVAILABLE);
+ assertEquals(tts.setLanguage(new Locale("es", "US")), TextToSpeech.LANG_NOT_SUPPORTED);
}
public void testAddAudioAttributes() {
- TextToSpeech tts = getTts();
- AudioAttributes attr =
- new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+ TextToSpeech tts = getTts();
+ AudioAttributes attr =
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
- assertEquals(tts.setAudioAttributes(null), TextToSpeech.ERROR);
- assertEquals(tts.setAudioAttributes(attr), TextToSpeech.SUCCESS);
+ assertEquals(tts.setAudioAttributes(null), TextToSpeech.ERROR);
+ assertEquals(tts.setAudioAttributes(attr), TextToSpeech.SUCCESS);
}
private void generateSampleAudio(File sampleFile) throws Exception {
- assertFalse(sampleFile.exists());
+ assertFalse(sampleFile.exists());
- ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(sampleFile,
- ParcelFileDescriptor.MODE_WRITE_ONLY
- | ParcelFileDescriptor.MODE_CREATE
- | ParcelFileDescriptor.MODE_TRUNCATE);
+ ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(sampleFile,
+ ParcelFileDescriptor.MODE_WRITE_ONLY
+ | ParcelFileDescriptor.MODE_CREATE
+ | ParcelFileDescriptor.MODE_TRUNCATE);
- Bundle params = createParamsBundle("mocktofile");
+ Bundle params = createParamsBundle("mocktofile");
- int result =
- getTts().synthesizeToFile(
- UTTERANCE, params, fileDescriptor,
- params.getString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID));
+ int result =
+ getTts().synthesizeToFile(
+ UTTERANCE, params, fileDescriptor,
+ params.getString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID));
- verifySynthesisFile(result, mTts, sampleFile);
+ verifySynthesisFile(result, mTts, sampleFile);
}
private void verifyAddPlay(int result, TextToSpeechWrapper mTts, String utterance)
- throws Exception {
- assertEquals(TextToSpeech.SUCCESS, result);
- assertTrue(mTts.waitForComplete(utterance));
+ throws Exception {
+ assertEquals(TextToSpeech.SUCCESS, result);
+ assertTrue(mTts.waitForComplete(utterance));
}
private HashMap<String, String> createParams(String utteranceId) {
@@ -300,7 +343,7 @@ public class TextToSpeechServiceTest extends AndroidTestCase {
}
private void verifySynthesisFile(int result, TextToSpeechWrapper mTts, File file)
- throws InterruptedException {
+ throws InterruptedException {
assertEquals("synthesizeToFile() failed", TextToSpeech.SUCCESS, result);
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index c09cb536d3c..c8a42febc2d 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -57,6 +57,7 @@ import com.android.compatibility.common.util.ThrowingRunnable;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
@@ -246,11 +247,12 @@ public class LightBarTests extends LightBarTestBase {
Thread.sleep(WAIT_TIME);
Bitmap bitmap = takeStatusBarScreenshot(activity);
- Stats s = evaluateDarkBarBitmap(bitmap, Color.BLACK, 0);
+ Stats s = evaluateDarkBarBitmap(bitmap, Color.TRANSPARENT, 0);
assertStats(bitmap, s, false /* light */);
});
}
+ @Ignore
@Test
@AppModeFull // Instant apps cannot create notifications
public void testLightBarIsNotAllowed_fitDisplayCutout() throws Throwable {
diff --git a/tests/tests/telephony/current/AndroidTest.xml b/tests/tests/telephony/current/AndroidTest.xml
index 8fcbc6098e1..947443bb32d 100644
--- a/tests/tests/telephony/current/AndroidTest.xml
+++ b/tests/tests/telephony/current/AndroidTest.xml
@@ -65,4 +65,8 @@
<option name="run-command" value="setprop persist.radio.allow_mock_modem true" />
<option name="teardown-command" value="setprop persist.radio.allow_mock_modem false" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.FeatureFlagTargetPreparer" >
+ <option name="flag-value" value="telephony/com.android.internal.telephony.flags.oem_enabled_satellite_flag=true" />
+ <option name="flag-value" value="telephony/com.android.internal.telephony.flags.carrier_enabled_satellite_flag=true" />
+ </target_preparer>
</configuration>
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockDataService.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockDataService.java
index 4e20314cb24..f4f93c537f3 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockDataService.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockDataService.java
@@ -111,19 +111,24 @@ public class MockDataService {
mPhoneId = instanceId;
initializeParameter();
+ Log.d(TAG, "MockDataService(): enter");
try {
setDataCallListFromNetworkAgent();
} catch (Exception e) {
Log.e(TAG, "Exception error: " + e);
}
+ Log.d(TAG, "MockDataService(): initialized");
}
private void setDataCallListFromNetworkAgent() throws Exception {
+ Log.d(TAG, "setDataCallListFromNetworkAgent(): enter");
String result =
TelephonyUtils.executeShellCommand(
InstrumentationRegistry.getInstrumentation(),
sQueryTelephonyDebugServiceCommand);
+ Log.d(TAG, "setDataCallListFromNetworkAgent(): query finished");
setBridgeTheDataConnection(result);
+ Log.d(TAG, "setDataCallListFromNetworkAgent(): exit");
}
/* Default value definition */
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigBase.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigBase.java
index 5642a5fbe16..7a462d17538 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigBase.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigBase.java
@@ -227,6 +227,9 @@ public class MockModemConfigBase implements MockModemConfigInterface {
case 1:
imei = new String(MockModemConfigInterface.DEFAULT_PHONE2_IMEI);
break;
+ case 2:
+ imei = new String(MockModemConfigInterface.DEFAULT_PHONE3_IMEI);
+ break;
default:
imei = new String(MockModemConfigInterface.DEFAULT_PHONE1_IMEI);
break;
@@ -243,6 +246,9 @@ public class MockModemConfigBase implements MockModemConfigInterface {
case 1:
imeisv = new String(MockModemConfigInterface.DEFAULT_PHONE2_IMEISV);
break;
+ case 2:
+ imeisv = new String(MockModemConfigInterface.DEFAULT_PHONE3_IMEISV);
+ break;
default:
imeisv = new String(MockModemConfigInterface.DEFAULT_PHONE1_IMEISV);
break;
@@ -259,6 +265,9 @@ public class MockModemConfigBase implements MockModemConfigInterface {
case 1:
esn = new String(MockModemConfigInterface.DEFAULT_PHONE2_ESN);
break;
+ case 2:
+ esn = new String(MockModemConfigInterface.DEFAULT_PHONE3_ESN);
+ break;
default:
esn = new String(MockModemConfigInterface.DEFAULT_PHONE1_ESN);
break;
@@ -275,6 +284,9 @@ public class MockModemConfigBase implements MockModemConfigInterface {
case 1:
meid = new String(MockModemConfigInterface.DEFAULT_PHONE2_MEID);
break;
+ case 2:
+ meid = new String(MockModemConfigInterface.DEFAULT_PHONE3_MEID);
+ break;
default:
meid = new String(MockModemConfigInterface.DEFAULT_PHONE1_MEID);
break;
@@ -523,6 +535,13 @@ public class MockModemConfigBase implements MockModemConfigInterface {
mMeid[i] = MockModemConfigInterface.DEFAULT_PHONE2_MEID;
mImeiType[i] = MockModemConfigInterface.DEFAULT_PHONE2_IMEITYPE;
break;
+ case 2:
+ mImei[i] = MockModemConfigInterface.DEFAULT_PHONE3_IMEI;
+ mImeiSv[i] = MockModemConfigInterface.DEFAULT_PHONE3_IMEISV;
+ mEsn[i] = MockModemConfigInterface.DEFAULT_PHONE3_ESN;
+ mMeid[i] = MockModemConfigInterface.DEFAULT_PHONE3_MEID;
+ mImeiType[i] = MockModemConfigInterface.DEFAULT_PHONE3_IMEITYPE;
+ break;
default:
mImei[i] = MockModemConfigInterface.DEFAULT_PHONE1_IMEI;
mImeiSv[i] = MockModemConfigInterface.DEFAULT_PHONE1_IMEISV;
@@ -554,6 +573,7 @@ public class MockModemConfigBase implements MockModemConfigInterface {
MockModemConfigInterface.DEFAULT_IS_INTERNAL_LINGERING_SUPPORTED;
phoneCapability.logicalModemIds[0] = MockModemConfigInterface.DEFAULT_LOGICAL_MODEM1_ID;
phoneCapability.logicalModemIds[1] = MockModemConfigInterface.DEFAULT_LOGICAL_MODEM2_ID;
+ phoneCapability.logicalModemIds[2] = MockModemConfigInterface.DEFAULT_LOGICAL_MODEM3_ID;
}
private void updateSimSlotStatus() {
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigInterface.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigInterface.java
index afead886278..cd76dc1d77c 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigInterface.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemConfigInterface.java
@@ -27,7 +27,7 @@ public interface MockModemConfigInterface {
// ***** Constants
int MAX_NUM_OF_SIM_SLOT = 3; // Change this needs to add more SIM SLOT NVs.
- int MAX_NUM_OF_LOGICAL_MODEM = 2; // Change this needs to add more MODEM NVs.
+ int MAX_NUM_OF_LOGICAL_MODEM = 3; // Change this needs to add more MODEM NVs.
int RADIO_STATE_UNAVAILABLE = 0;
int RADIO_STATE_OFF = 1;
int RADIO_STATE_ON = 2;
@@ -46,6 +46,12 @@ public interface MockModemConfigInterface {
String DEFAULT_PHONE2_ESN = "987654321";
String DEFAULT_PHONE2_MEID = "987654321543210";
int DEFAULT_PHONE2_IMEITYPE = ImeiInfo.ImeiType.SECONDARY;
+ // PHONE3
+ String DEFAULT_PHONE3_IMEI = "987654321012345";
+ String DEFAULT_PHONE3_IMEISV = "03";
+ String DEFAULT_PHONE3_ESN = "192837465";
+ String DEFAULT_PHONE3_MEID = "987654321012345";
+ int DEFAULT_PHONE3_IMEITYPE = ImeiInfo.ImeiType.SECONDARY;
int DEFAULT_RADIO_STATE = RADIO_STATE_UNAVAILABLE;
int DEFAULT_NUM_OF_LIVE_MODEM = 1; // Should <= MAX_NUM_OF_MODEM
@@ -54,6 +60,7 @@ public interface MockModemConfigInterface {
boolean DEFAULT_IS_INTERNAL_LINGERING_SUPPORTED = false;
int DEFAULT_LOGICAL_MODEM1_ID = 0;
int DEFAULT_LOGICAL_MODEM2_ID = 1;
+ int DEFAULT_LOGICAL_MODEM3_ID = 2;
// ***** Methods
void destroy();
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java
index b11003292d7..caa9224238f 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockModemService.java
@@ -64,6 +64,8 @@ public class MockModemService extends Service {
public static final byte PHONE_ID_0 = 0x00;
public static final byte PHONE_ID_1 = 0x01;
+ public static final byte PHONE_ID_2 = 0x02;
+ public static final byte MAX_PHONE_NUM = 3;
public static final int LATCH_MOCK_MODEM_SERVICE_READY = 0;
public static final int LATCH_RADIO_INTERFACES_READY = 1;
@@ -99,6 +101,10 @@ public class MockModemService extends Service {
mNumOfPhone = mTelephonyManager.getActiveModemCount();
Log.d(TAG, "Support number of phone = " + mNumOfPhone + ", number of SIM = " + mNumOfSim);
+ if (mNumOfPhone > MAX_PHONE_NUM) {
+ mNumOfPhone = MAX_PHONE_NUM;
+ }
+
// Number of physical Sim slot should be equals to or greater than number of phone.
if (mNumOfSim < mNumOfPhone) {
mNumOfSim = mNumOfPhone;
@@ -181,7 +187,7 @@ public class MockModemService extends Service {
byte phoneId = intent.getByteExtra(PHONE_ID, PHONE_ID_0);
- if (phoneId > PHONE_ID_1) {
+ if (phoneId >= MAX_PHONE_NUM) {
Log.e(TAG, "Not suuport for phone " + phoneId);
return null;
}
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 48ca465d5f6..c5ff62221f0 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ConnectivityManagerTestOnMockModem.java
@@ -70,6 +70,7 @@ public class ConnectivityManagerTestOnMockModem {
private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem";
private static final boolean DEBUG = !"user".equals(Build.TYPE);
+ private static final String RESOURCE_PACKAGE_NAME = "android";
private static boolean sIsMultiSimDevice;
private static class CMNetworkCallback extends NetworkCallback {
@@ -216,6 +217,24 @@ public class ConnectivityManagerTestOnMockModem {
return tm != null && tm.getPhoneCount() > 1;
}
+ private static boolean isSimHotSwapCapable() {
+ boolean isSimHotSwapCapable = false;
+ int resourceId =
+ getContext()
+ .getResources()
+ .getIdentifier("config_hotswapCapable", "bool", RESOURCE_PACKAGE_NAME);
+
+ if (resourceId > 0) {
+ isSimHotSwapCapable = getContext().getResources().getBoolean(resourceId);
+ } else {
+ Log.d(TAG, "Fail to get the resource Id, using default.");
+ }
+
+ Log.d(TAG, "isSimHotSwapCapable = " + (isSimHotSwapCapable ? "true" : "false"));
+
+ return isSimHotSwapCapable;
+ }
+
private static Context getContext() {
return InstrumentationRegistry.getInstrumentation().getContext();
}
@@ -311,6 +330,8 @@ public class ConnectivityManagerTestOnMockModem {
public void testNetworkValidated() throws Throwable {
Log.d(TAG, "ConnectivityManagerTestOnMockModem#testNetworkValidated");
+ assumeTrue(isSimHotSwapCapable());
+
int slotId = 0;
// Insert a SIM
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MmsTest.java b/tests/tests/telephony/current/src/android/telephony/cts/MmsTest.java
index 301db2aa004..4e2b80820fe 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/MmsTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/MmsTest.java
@@ -215,7 +215,7 @@ public class MmsTest {
DefaultSmsAppHelper.stopBeingDefaultSmsApp();
}
- @Test(timeout = 30000) // b/232461746: reduce test timeout to 30s for CF
+ @Test
@ApiTest(apis = "android.telephony.SmsManager#sendMultimediaMessage")
public void testSendMmsMessage() {
Log.i("MmsTest", "testSendMmsMessage");
@@ -229,7 +229,7 @@ public class MmsTest {
DefaultSmsAppHelper.stopBeingDefaultSmsApp();
}
- @Test(timeout = 30000) // b/232461746: reduce test timeout to 30s for CF
+ @Test
@ApiTest(apis = "android.telephony.SmsManager#sendMultimediaMessage")
public void testSendMmsMessageWithInactiveSubscriptionId() {
int inactiveSubId = 127;
@@ -245,7 +245,7 @@ public class MmsTest {
DefaultSmsAppHelper.stopBeingDefaultSmsApp();
}
- @Test(timeout = 30000) // b/232461746: reduce test timeout to 30s for CF
+ @Test
@ApiTest(apis = "android.telephony.SmsManager#sendMultimediaMessage")
public void testSendMmsMessageWithMessageId() {
// Test non-default SMS app
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 51b8d7fcc44..2f9e68d7193 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -1149,14 +1149,14 @@ public class TelephonyManagerTest {
@ApiTest(apis = {"android.telephony.TelephonyManager#getPhoneAccountHandle"})
public void testGetPhoneAccountHandle() {
TelecomManager telecomManager = getContext().getSystemService(TelecomManager.class);
- PhoneAccountHandle defaultAccount = telecomManager
- .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
+ List<PhoneAccountHandle> callCapableAccounts = telecomManager
+ .getCallCapablePhoneAccounts();
try {
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.adoptShellPermissionIdentity(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
PhoneAccountHandle phoneAccountHandle = mTelephonyManager.getPhoneAccountHandle();
- assertEquals(phoneAccountHandle, defaultAccount);
+ assertTrue(callCapableAccounts.contains(phoneAccountHandle));
} catch (SecurityException e) {
fail("TelephonyManager#getPhoneAccountHandle requires READ_PRIVILEGED_PHONE_STATE");
} finally {
@@ -3550,7 +3550,7 @@ public class TelephonyManagerTest {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
// test without permission: verify SecurityException
- long allowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_NR;
+ long allowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
try {
mTelephonyManager.setAllowedNetworkTypes(allowedNetworkTypes);
fail("testSetAllowedNetworkTypes: SecurityException expected");
@@ -3580,8 +3580,7 @@ public class TelephonyManagerTest {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
long allowedNetworkTypes = ~TelephonyManager.NETWORK_TYPE_BITMASK_NR;
- long networkTypeBitmask = TelephonyManager.NETWORK_TYPE_BITMASK_NR
- | TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+ long networkTypeBitmask = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
try {
@@ -3625,7 +3624,7 @@ public class TelephonyManagerTest {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
// test without permission: verify SecurityException
- long allowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_NR;
+ long allowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
try {
mIsAllowedNetworkTypeChanged = true;
mTelephonyManager.setAllowedNetworkTypesForReason(
@@ -3664,7 +3663,7 @@ public class TelephonyManagerTest {
() -> {
mTelephonyManager.setAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER,
- TelephonyManager.NETWORK_TYPE_BITMASK_NR);
+ TelephonyManager.NETWORK_TYPE_BITMASK_LTE);
}
);
} catch (SecurityException se) {
@@ -3684,7 +3683,7 @@ public class TelephonyManagerTest {
() -> {
mTelephonyManager.setAllowedNetworkTypesForReason(
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G,
- TelephonyManager.NETWORK_TYPE_BITMASK_NR);
+ TelephonyManager.NETWORK_TYPE_BITMASK_LTE);
}
);
});
@@ -3695,14 +3694,14 @@ public class TelephonyManagerTest {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
// test without permission: verify SecurityException
- long allowedNetworkTypes1 = TelephonyManager.NETWORK_TYPE_BITMASK_NR
+ long allowedNetworkTypes1 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
long allowedNetworkTypes2 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
- long allowedNetworkTypes3 = TelephonyManager.NETWORK_TYPE_BITMASK_NR
- | TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+ long allowedNetworkTypes3 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+ | TelephonyManager.NETWORK_TYPE_BITMASK_HSPA
| TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
- long allowedNetworkTypes4 = TelephonyManager.NETWORK_TYPE_LTE
- | TelephonyManager.NETWORK_TYPE_EVDO_B;
+ long allowedNetworkTypes4 = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+ | TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
try {
mIsAllowedNetworkTypeChanged = true;
@@ -5764,10 +5763,9 @@ public class TelephonyManagerTest {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
// NETWORK_TYPE_BITMASK_LTE_CA is invalid, should be converted into NETWORK_TYPE_BITMASK_LTE
- long invalidAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_NR
+ long invalidAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE
| TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
- long expectedAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_NR
- | TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
+ long expectedAllowedNetworkTypes = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
try {
mIsAllowedNetworkTypeChanged = true;
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
@@ -5826,7 +5824,7 @@ public class TelephonyManagerTest {
implements TelephonyCallback.ServiceStateListener,
TelephonyCallback.RadioPowerStateListener {
private static final long TIMEOUT_TO_WAIT_FOR_DESIRED_STATE =
- TimeUnit.SECONDS.toMillis(15);
+ TimeUnit.SECONDS.toMillis(20);
private final Object mPowerStateLock = new Object();
private final Object mServiceStateLock = new Object();
ServiceState mServiceState;
@@ -5869,7 +5867,7 @@ public class TelephonyManagerTest {
mDesireRadioPowerState = desiredRadioState;
/**
* Since SST sets waiting time up to 10 seconds for the power off radio, the
- * RadioStateIntent timer extends the wait time up to 15 seconds here as well.
+ * RadioStateIntent timer extends the wait time up to 20 seconds here as well.
*/
waitForDesiredState(mPowerStateLock, desiredRadioState,
() -> mRadioPowerState, true);
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
index 77e1c969df3..e22db02e333 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
@@ -27,8 +27,10 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
+
import android.Manifest;
import android.app.Instrumentation;
import android.content.BroadcastReceiver;
@@ -44,6 +46,7 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.provider.Telephony.Sms;
import android.provider.Telephony.Sms.Intents;
import android.telecom.PhoneAccount;
@@ -105,7 +108,8 @@ public class VisualVoicemailServiceTest {
public void setUp() throws Exception {
mContext = getInstrumentation().getContext();
assumeTrue(hasFeatureSupported(mContext));
-
+ // The tests run on real modem with visual voicemail SMS.
+ assumeFalse(isEmulator());
mPreviousDefaultDialer = getDefaultDialer(getInstrumentation());
setDefaultDialer(getInstrumentation(), PACKAGE);
@@ -714,4 +718,9 @@ public class VisualVoicemailServiceTest {
}
}
}
+
+ private static boolean isEmulator() {
+ return SystemProperties.getBoolean("ro.boot.qemu", false)
+ || SystemProperties.getBoolean("ro.kernel.qemu", false);
+ }
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index 3374b249a51..6ee9d59f701 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -21,12 +21,10 @@ import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK_WITH_TIMEOUT;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
-
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
-
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -965,9 +963,10 @@ public class ImsServiceTest {
}
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.adoptShellPermissionIdentity("android.permission.MODIFY_PHONE_STATE");
- Resources mResource = Resources.getSystem();
- boolean sendSmmaViaIms = mResource.getBoolean(
- com.android.internal.R.bool.config_smma_notification_supported_over_ims);
+ boolean sendSmmaViaIms = getContext().getResources().getBoolean(
+ Resources.getSystem().getIdentifier("config_smma_notification_supported_over_ims",
+ "bool",
+ "android"));
if (!sendSmmaViaIms) {
return;
}
@@ -1022,9 +1021,9 @@ public class ImsServiceTest {
return;
}
- Resources mResource = Resources.getSystem();
- boolean isViaIms = mResource.getBoolean(
- com.android.internal.R.bool.config_smppsim_response_via_ims);
+ boolean isViaIms = getContext().getResources().getBoolean(
+ Resources.getSystem().getIdentifier("config_smppsim_response_via_ims", "bool",
+ "android"));
if (!isViaIms) {
return;
}
diff --git a/tests/tests/text/src/android/text/method/cts/TouchTest.java b/tests/tests/text/src/android/text/method/cts/TouchTest.java
index 127b87cb72b..8e80d42a7f6 100644
--- a/tests/tests/text/src/android/text/method/cts/TouchTest.java
+++ b/tests/tests/text/src/android/text/method/cts/TouchTest.java
@@ -26,7 +26,6 @@ import android.text.Layout;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.method.Touch;
-import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
@@ -115,19 +114,17 @@ public class TouchTest {
@Test
public void testOnTouchEvent() throws Throwable {
// Create a string that is wider than the screen.
- DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
- int screenWidth = metrics.widthPixels;
+ int rootViewWidth = mActivity.getWindow().getDecorView().getWidth();
TextPaint paint = mTextView.getPaint();
String text = LONG_TEXT;
int textWidth = Math.round(paint.measureText(text));
- while (textWidth < screenWidth) {
+ while (textWidth < rootViewWidth) {
text += LONG_TEXT;
textWidth = Math.round(paint.measureText(text));
}
// Drag the difference between the text width and the screen width.
- int dragAmount = Math.min(screenWidth, textWidth - screenWidth);
- assertTrue(dragAmount > 0);
+ int dragAmount = Math.min(rootViewWidth, textWidth - rootViewWidth);
final String finalText = text;
final SpannableString spannable = new SpannableString(finalText);
mActivityRule.runOnUiThread(() -> {
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index c30f9ca1027..38516f07d06 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -633,7 +633,7 @@ public class LinkifyTest {
@Test
public void testAddLinks_doesNotMatchUrlsWithoutProtocolAndWithUnknownTld() {
- String url = "thank.you";
+ String url = "thank.unknowntld";
verifyAddLinksWithWebUrlFails("Should not match URL that does not start with a protocol " +
"and does not contain a known TLD", url);
}
@@ -647,7 +647,7 @@ public class LinkifyTest {
@Test
public void testAddLinks_doesNotMatchUrlsWithEmojiWithoutProtocolAndWithoutKnownTld()
{
- String url = "Thank\u263A.you";
+ String url = "Thank\u263A.unknowntld";
verifyAddLinksWithWebUrlFails("Should not match URLs containing emoji and with unknown " +
"TLD", url);
}
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerFrontendTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerFrontendTest.java
index 1a65c659d6c..6644d1f20f8 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerFrontendTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerFrontendTest.java
@@ -644,7 +644,6 @@ public class TunerFrontendTest {
assertEquals(1, settings.getFrequencyLong());
assertEquals(AnalogFrontendSettings.SIGNAL_TYPE_NTSC, settings.getSignalType());
assertEquals(AnalogFrontendSettings.SIF_BG_NICAM, settings.getSifStandard());
- assertEquals(AnalogFrontendSettings.AFT_FLAG_TRUE, settings.getAftFlag());
if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) {
assertEquals(AnalogFrontendSettings.AFT_FLAG_TRUE, settings.getAftFlag());
assertEquals(FrontendSettings.FRONTEND_SPECTRAL_INVERSION_NORMAL,
@@ -776,11 +775,11 @@ public class TunerFrontendTest {
assertEquals(3, settings.getSymbolRate());
assertEquals(DvbcFrontendSettings.OUTER_FEC_OUTER_FEC_RS, settings.getOuterFec());
assertEquals(DvbcFrontendSettings.ANNEX_B, settings.getAnnex());
- assertEquals(DvbcFrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
- settings.getTimeInterleaveMode());
assertEquals(FrontendSettings.FRONTEND_SPECTRAL_INVERSION_NORMAL,
settings.getSpectralInversion());
if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) {
+ assertEquals(DvbcFrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
+ settings.getTimeInterleaveMode());
assertEquals(100, settings.getEndFrequencyLong());
assertEquals(DvbcFrontendSettings.BANDWIDTH_5MHZ, settings.getBandwidth());
} else {
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 353c5a4263e..72093a961de 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
@@ -1159,6 +1159,7 @@ public class TunerTest {
// TODO: get real CiCam id from MediaCas
res = mTuner.connectFrontendToCiCam(0);
} else {
+ res = mTuner.connectFrontendToCiCam(0);
assertEquals(Tuner.INVALID_LTS_ID, mTuner.connectFrontendToCiCam(0));
}
@@ -1403,12 +1404,12 @@ public class TunerTest {
assertNotEquals(Tuner.INVALID_FILTER_ID, f.getId());
DownloadSettings.Builder builder = DownloadSettings.builder(Filter.TYPE_MMTP);
- if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) {
+ if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) {
builder.setUseDownloadId(true);
}
builder.setDownloadId(2);
DownloadSettings settings = builder.build();
- if (!TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1)) {
+ if (TunerVersionChecker.isHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_2_0)) {
assertEquals(settings.useDownloadId(), true);
} else {
assertEquals(settings.useDownloadId(), false);
diff --git a/tests/tests/uiautomation/AndroidManifest.xml b/tests/tests/uiautomation/AndroidManifest.xml
index 34d8defc6c9..edf730d5662 100644
--- a/tests/tests/uiautomation/AndroidManifest.xml
+++ b/tests/tests/uiautomation/AndroidManifest.xml
@@ -34,10 +34,6 @@
android:exported="true">
</activity>
- <activity android:name="android.app.uiautomation.cts.UiAutomationTestSecondActivity"
- android:exported="true">
- </activity>
-
<service android:name="android.app.uiautomation.cts.UiAutomationTestA11yService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
diff --git a/tests/tests/uiautomation/res/values/strings.xml b/tests/tests/uiautomation/res/values/strings.xml
index 4f215f18910..970bbc5d96a 100644
--- a/tests/tests/uiautomation/res/values/strings.xml
+++ b/tests/tests/uiautomation/res/values/strings.xml
@@ -16,42 +16,5 @@
-->
<resources>
-
- <string name="uiautomation_test_activity">Cheeses</string>
-
- <string-array name="some_cheeses">
- <item>Abbaye de Belloc</item>
- <item>Abbaye de Belval</item>
- <item>Abbaye de Citeaux</item>
- <item>Abbaye du Mont des Cats</item>
- <item>Abbot’s Gold</item>
- <item>Acapella</item>
- <item>Acorn</item>
- <item>Adelost</item>
- <item>Affidelice au Chablis</item>
- <item>Afuega\'l Pitu</item>
- <item>Aged Gouda</item>
- <item>Airag</item>
- <item>Airedale</item>
- <item>Aisy Cendre</item>
- <item>Allgauer Emmentaler</item>
- <item>Babybel</item>
- <item>Baby Swiss</item>
- <item>Baguette Laonnaise</item>
- <item>Bakers</item>
- <item>Balaton</item>
- <item>Bandal</item>
- <item>Banon</item>
- <item>Barry\'s Bay Cheddar</item>
- <item>Basing</item>
- <item>Basket Cheese</item>
- <item>Bath Cheese</item>
- <item>Bavarian Bergkase</item>
- <item>Baylough</item>
- <item>Beauvoorde</item>
- <item>Beemster 2% Milk</item>
- </string-array>
-
<string name="uiautomation_a11y_service_description">com.android.app.uiautomation.cts.UiAutomationTestAccessibilityService</string>
-
</resources>
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
index 8686e456129..b239494c958 100644
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
@@ -23,6 +23,8 @@ import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.ListView;
+import java.util.Arrays;
+
/**
* Activity for testing the UiAutomation APIs.
*/
@@ -40,11 +42,13 @@ public class UiAutomationTestFirstActivity extends Activity {
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- String[] cheeses = getResources().getStringArray(R.array.some_cheeses);
- ArrayAdapter<String> cheeseAdapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, cheeses);
+ final String[] list = new String[100];
+ Arrays.setAll(list, Integer::toString);
+ ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_1, list);
ListView listView = (ListView) findViewById(R.id.list_view);
- listView.setAdapter(cheeseAdapter);
+ listView.setAdapter(listAdapter);
}
}
+
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
deleted file mode 100644
index 6c4b04c882d..00000000000
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
+++ /dev/null
@@ -1,47 +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.app.uiautomation.cts;
-
-import android.app.Activity;
-import android.app.uiautomation.cts.R;
-import android.os.Bundle;
-import android.view.WindowManager;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-/**
-* Activity for testing the UiAutomation APIs.
-*/
-public class UiAutomationTestSecondActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
- setContentView(R.layout.ui_automation_test);
-
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
-
- String[] cheeses = getResources().getStringArray(R.array.some_cheeses);
- ArrayAdapter<String> cheeseAdapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, cheeses);
-
- ListView listView = (ListView) findViewById(R.id.list_view);
- listView.setAdapter(cheeseAdapter);
- }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GainmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GainmapTests.java
index 11d109b24f5..2505dec662f 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GainmapTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GainmapTests.java
@@ -99,9 +99,20 @@ public class GainmapTests {
return mapWhiteWithGain(sTestImage.getGainmap(), gain);
}
- private static void assertTestImageResult(Bitmap result) {
+ private static float toleranceForResult(Bitmap result) {
// 8888 precision ain't so great
- final float delta = result.getConfig() == Bitmap.Config.ARGB_8888 ? 0.02f : 0.002f;
+ if (result.getConfig() == Bitmap.Config.ARGB_8888) {
+ // PQ math on GLES2.0 is very poor
+ if (result.getColorSpace().getId() == ColorSpace.Named.BT2020_PQ.ordinal()) {
+ return 0.06f;
+ }
+ return 0.02f;
+ }
+ return 0.002f;
+ }
+
+ private static void assertTestImageResult(Bitmap result) {
+ final float delta = toleranceForResult(result);
assertChannels(result.getColor(0, 0), Color.pack(Color.WHITE), delta);
assertChannels(result.getColor(2, 2), mapWhiteWithGain(0x40 / 255.f), delta);
assertChannels(result.getColor(4, 2), mapWhiteWithGain(0x80 / 255.f), delta);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
index 08666e20809..110061d5cad 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
@@ -26,6 +26,7 @@ import android.uirendering.cts.R
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.view.WindowManager
import androidx.annotation.Nullable
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
@@ -88,6 +89,8 @@ class DrawActivity : Activity() {
mHandler = RenderSpecHandler()
setContentView(R.layout.test_container)
+ window.attributes.layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
mTestContainer = findViewById(R.id.test_content_wrapper)
}
diff --git a/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java b/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java
index a8818880097..088b70e7e63 100644
--- a/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java
+++ b/tests/tests/view/src/android/view/cts/AutoHandwritingTest.java
@@ -74,4 +74,12 @@ public class AutoHandwritingTest {
view.setAutoHandwritingEnabled(true);
assertTrue(view.isAutoHandwritingEnabled());
}
+
+ @Test
+ public void autoHandwriting_textView_defaultValueIsTrue() {
+ Activity activity = mActivityRule.getActivity();
+ View view = activity.findViewById(R.id.default_textview);
+
+ assertTrue(view.isAutoHandwritingEnabled());
+ }
}
diff --git a/tests/tests/view/src/android/view/cts/SDRTestActivity.java b/tests/tests/view/src/android/view/cts/SDRTestActivity.java
index 6bb3075bc69..2e8eafca845 100644
--- a/tests/tests/view/src/android/view/cts/SDRTestActivity.java
+++ b/tests/tests/view/src/android/view/cts/SDRTestActivity.java
@@ -23,9 +23,12 @@ import android.view.SurfaceView;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets.Type;
import android.widget.FrameLayout;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
public class SDRTestActivity extends Activity
implements SurfaceHolder.Callback, SurfaceTextureListener {
private static final long TIME_OUT_MS = 1000;
@@ -34,6 +37,8 @@ public class SDRTestActivity extends Activity
private TextureView mTextureView;
private SurfaceTexture mSurface;
+ private CountDownLatch mEnterAnimationFence = new CountDownLatch(1);
+
@Override
public void surfaceCreated(SurfaceHolder holder) {}
@@ -59,8 +64,6 @@ public class SDRTestActivity extends Activity
mSurfaceView.getHolder().addCallback(this);
setContentView(content);
- getWindow().getInsetsController().hide(Type.statusBars());
- getWindow().getInsetsController().hide(Type.navigationBars());
}
@Override
@@ -71,6 +74,13 @@ public class SDRTestActivity extends Activity
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
+ mEnterAnimationFence.countDown();
+ }
+
+ public void waitForEnterAnimationComplete() throws TimeoutException, InterruptedException {
+ if (!mEnterAnimationFence.await(TIME_OUT_MS, TimeUnit.MILLISECONDS)) {
+ throw new TimeoutException();
+ }
}
public TextureView getTextureView() {
diff --git a/tests/tests/view/src/android/view/cts/TextureViewTest.java b/tests/tests/view/src/android/view/cts/TextureViewTest.java
index 17b22c72ace..14b8797975e 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewTest.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewTest.java
@@ -23,6 +23,8 @@ import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glEnable;
import static android.opengl.GLES20.glScissor;
import static android.view.WindowInsets.Type.captionBar;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -53,6 +55,7 @@ import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.view.WindowInsets;
import android.view.cts.util.BitmapDumper;
import androidx.test.InstrumentationRegistry;
@@ -286,7 +289,7 @@ public class TextureViewTest {
final SDRTestActivity activity =
mSDRActivityRule.launchActivity(/*startIntent*/ null);
- activity.waitForSurface();
+ activity.waitForEnterAnimationComplete();
TextureView textureView = activity.getTextureView();
// SurfaceView and TextureView dimensions are the same so we reuse variables
@@ -382,25 +385,40 @@ public class TextureViewTest {
WidgetTestUtils.runOnMainAndDrawSync(
mSDRActivityRule, textureView, () -> textureView.getBitmap(textureViewScreenshot));
+ WindowInsets rootWindowInsets = activity.getWindow().getDecorView().getRootWindowInsets();
+ int extraSurfaceTopOffset = rootWindowInsets.getInsets(captionBar()).top;
// If the caption bar is present, the surface top edge in the screenshot is shifted.
- int extraSurfaceOffset = activity.getWindow().getDecorView().getRootWindowInsets()
- .getInsets(captionBar()).top;
+ extraSurfaceTopOffset += rootWindowInsets.getInsets(statusBars()).top;
+
+ int extraSurfaceBottomOffset = rootWindowInsets.getInsets(navigationBars()).bottom;
// sample 5 pixels on the edge for bitmap comparison.
// TextureView and SurfaceView use different shaders, so compare these two with tolerance.
// TODO(b/229173479): These shaders shouldn't be very different. Figure out why we need
// this tolerance in the first place.
final int threshold = 3;
- assertPixelsAreSame(surfaceViewScreenshot.getPixel(width / 2, extraSurfaceOffset),
- textureViewScreenshot.getPixel(width / 2, 0), threshold);
- assertPixelsAreSame(surfaceViewScreenshot.getPixel(0, height / 2),
- textureViewScreenshot.getPixel(0, height / 2), threshold);
- assertPixelsAreSame(surfaceViewScreenshot.getPixel(width / 2, height / 2),
- textureViewScreenshot.getPixel(width / 2, height / 2), threshold);
- assertPixelsAreSame(surfaceViewScreenshot.getPixel(width / 2, height - 1),
- textureViewScreenshot.getPixel(width / 2, height - 1), threshold);
- assertPixelsAreSame(surfaceViewScreenshot.getPixel(width - 1, height / 2),
- textureViewScreenshot.getPixel(width - 1, height / 2), threshold);
+ try {
+ assertPixelsAreSame(surfaceViewScreenshot.getPixel(width / 2, extraSurfaceTopOffset),
+ textureViewScreenshot.getPixel(width / 2, 0), threshold);
+ assertPixelsAreSame(surfaceViewScreenshot.getPixel(0, height / 2),
+ textureViewScreenshot.getPixel(0, height / 2), threshold);
+ assertPixelsAreSame(surfaceViewScreenshot.getPixel(width / 2, height / 2),
+ textureViewScreenshot.getPixel(width / 2, height / 2), threshold);
+ assertPixelsAreSame(
+ surfaceViewScreenshot.getPixel(width / 2,
+ height - 1 - extraSurfaceBottomOffset),
+ textureViewScreenshot.getPixel(width / 2,
+ height - 1),
+ threshold);
+ assertPixelsAreSame(surfaceViewScreenshot.getPixel(width - 1, height / 2),
+ textureViewScreenshot.getPixel(width - 1, height / 2), threshold);
+ } catch (AssertionError err) {
+ BitmapDumper.dumpBitmap(textureViewScreenshot,
+ mTestName.getMethodName() + "_textureView", "TextureViewTest");
+ BitmapDumper.dumpBitmap(surfaceViewScreenshot,
+ mTestName.getMethodName() + "_surfaceView", "TextureViewTest");
+ throw err;
+ }
}
@Test
diff --git a/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java b/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
index a58c03c2ca8..0882211be89 100644
--- a/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
@@ -257,18 +257,21 @@ public class ViewTreeObserverTest {
@LargeTest
@Test
- public void testRemoveOnPreDrawListener() {
+ public void testRemoveOnPreDrawListener() throws Throwable {
mViewTreeObserver = mLinearLayout.getViewTreeObserver();
final ViewTreeObserver.OnPreDrawListener listener =
mock(ViewTreeObserver.OnPreDrawListener.class);
- mViewTreeObserver.addOnPreDrawListener(listener);
- mViewTreeObserver.dispatchOnPreDraw();
- verify(listener, times(1)).onPreDraw();
-
- reset(listener);
- mViewTreeObserver.removeOnPreDrawListener(listener);
- mViewTreeObserver.dispatchOnPreDraw();
+ mActivityRule.runOnUiThread(() -> {
+ reset(listener); // in case draw happened before now.
+ mViewTreeObserver.addOnPreDrawListener(listener);
+ mViewTreeObserver.dispatchOnPreDraw();
+ verify(listener, times(1)).onPreDraw();
+
+ reset(listener);
+ mViewTreeObserver.removeOnPreDrawListener(listener);
+ mViewTreeObserver.dispatchOnPreDraw();
+ });
// Since we've unregistered our listener, we expect it to not be called even after
// we've waited for a couple of seconds
SystemClock.sleep(TIMEOUT_MS);
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppClipboardTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppClipboardTest.java
index d43f6caa524..cfe1545f22a 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppClipboardTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppClipboardTest.java
@@ -182,8 +182,6 @@ public class StreamedAppClipboardTest {
@After
public void tearDown() {
- // Avoid crash in sysui showing toasts on closed VirtualDisplay (b/265325338).
- waitForNoToasts();
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
}
@@ -272,9 +270,7 @@ public class StreamedAppClipboardTest {
eq(RESULT_CODE_CLIP_LISTENER_READY), any());
ClipData clipToSet = ClipData.newPlainText("some label", "Hello World");
- waitForNoToasts();
deviceClipboard.setPrimaryClip(clipToSet);
- waitForToastToAppearAndDisappear();
ArgumentCaptor<Bundle> bundle = ArgumentCaptor.forClass(Bundle.class);
verify(mOnReceiveResultListener, timeout(EVENT_TIMEOUT_MS)).onReceiveResult(
@@ -372,10 +368,8 @@ public class StreamedAppClipboardTest {
CLIPBOARD_TEST_ACTIVITY_2)
.putExtra(EXTRA_RESULT_RECEIVER, createResultReceiver(secondResultReceiver));
- waitForNoToasts();
launchAndAwaitActivityOnVirtualDisplay(secondAppIntent);
tapOnDisplay(mVirtualDisplay.getDisplay());
- waitForToastToAppearAndDisappear();
// Make sure that the second activity now running on top of the VirtualDisplay reads the
// value which was set by the first activity.
@@ -590,7 +584,6 @@ public class StreamedAppClipboardTest {
verify(secondDeviceClipboardListener,
timeout(EVENT_TIMEOUT_MS).atLeastOnce()).onPrimaryClipChanged();
assertThat(secondDeviceClipboard.hasPrimaryClip()).isTrue();
- waitForNoToasts();
readClip = secondDeviceClipboard.getPrimaryClip();
assertThat(readClip.getItemCount()).isEqualTo(1);
assertThat(readClip.getDescription().getLabel().toString()).isEqualTo(
@@ -629,8 +622,7 @@ public class StreamedAppClipboardTest {
verify(deviceClipboardListener,
timeout(EVENT_TIMEOUT_MS).atLeastOnce()).onPrimaryClipChanged();
assertThat(deviceClipboard.hasPrimaryClip()).isTrue();
- waitForNoToasts();
- ClipData clipData = deviceClipboard.getPrimaryClip();
+ ClipData unused = deviceClipboard.getPrimaryClip();
// Since we set the DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS_FOR_VD_OWNER flag to false
// above, there should be no Toast windows.
@@ -681,33 +673,6 @@ public class StreamedAppClipboardTest {
virtualDevice.removeActivityListener(activityListener);
}
- private void waitForNoToasts() {
- boolean observedToast = true;
- // The default timeout for mWmState.waitFor is a little low so we try a few times.
- for (int i = 0; i < 5; i++) {
- if (mWmState.waitFor(state -> state.getMatchingWindowType(
- WindowManager.LayoutParams.TYPE_TOAST).isEmpty(), "No Toast appears")) {
- observedToast = false;
- break;
- }
- }
- assertThat(observedToast).isFalse();
- }
-
- private void waitForToastToAppearAndDisappear() {
- boolean observedToast = false;
- // The default timeout for mWmState.waitFor is a little low so we try a few times.
- for (int i = 0; i < 5; i++) {
- if (mWmState.waitFor(state -> !state.getMatchingWindowType(
- WindowManager.LayoutParams.TYPE_TOAST).isEmpty(), "Toast appears")) {
- observedToast = true;
- break;
- }
- }
- assertThat(observedToast).isTrue();
- waitForNoToasts();
- }
-
/**
* Tap in the center of the given Display, to give focus to the top activity there.
*/
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java
index 8b1f360e456..0df780945ea 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/AbstractRecognitionServiceTest.java
@@ -63,6 +63,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@@ -220,47 +221,41 @@ abstract class AbstractRecognitionServiceTest {
}
@Test
- public void testCanTriggerModelDownloadWithListener() throws Throwable {
+ @Parameters(method = "modelDownloadScenarios")
+ @TestCaseName("{method}_{0}")
+ public void testCanTriggerModelDownloadWithListener(
+ ModelDownloadExecutionInfo.Scenario scenario) {
mUiDevice.waitForIdle();
SpeechRecognizer recognizer = mActivity.getRecognizerInfoDefault().mRecognizer;
assertThat(recognizer).isNotNull();
setCurrentRecognizer(recognizer, IN_PACKAGE_RECOGNITION_SERVICE);
mUiDevice.waitForIdle();
+ ModelDownloadExecutionInfo mdei = ModelDownloadExecutionInfo.fromScenario(scenario);
CtsRecognitionService.sDownloadTriggers.clear();
+ CtsRecognitionService.sInstructedModelDownloadCallbacks =
+ new ArrayDeque<>(mdei.mInstructedCallbacks);
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
- List<String> callbackCalls = new ArrayList<>();
- ModelDownloadListener listener = new ModelDownloadListener() {
- @Override
- public void onProgress(int completedPercent) {
- callbackCalls.add("progress");
- }
-
- @Override
- public void onSuccess() {
- callbackCalls.add("success");
- }
+ ModelDownloadCallbackLogger listener = new ModelDownloadCallbackLogger();
- @Override
- public void onScheduled() {
- callbackCalls.add("scheduled");
- }
-
- @Override
- public void onError(int error) {
- callbackCalls.add("error");
- }
- };
mActivity.triggerModelDownloadWithListenerDefault(intent, listener);
PollingCheck.waitFor(SEQUENCE_TEST_WAIT_TIMEOUT_MS,
() -> CtsRecognitionService.sDownloadTriggers.size() > 0);
- PollingCheck.waitFor(SEQUENCE_TEST_WAIT_TIMEOUT_MS,
- () -> callbackCalls.size() > 0);
- assertThat(callbackCalls)
- .containsExactly("progress", "scheduled", "success", "error")
+
+ mUiDevice.waitForIdle();
+ assertThat(listener.mCallbacks)
+ .containsExactlyElementsIn(mdei.mExpectedCallbacks)
.inOrder();
}
+ static ModelDownloadExecutionInfo.Scenario[] modelDownloadScenarios() {
+ return new ModelDownloadExecutionInfo.Scenario[] {
+ ModelDownloadExecutionInfo.Scenario.PROGRESS_PROGRESS_PROGRESS};
+
+ // TODO(b/297309890): Other scenarios should be added for the CTS 15 release,
+ // as they are failing on non-QPR Android U platform.
+ }
+
@Test
@Parameters(method = "singleScenarios")
@TestCaseName("{method}_{0}")
@@ -789,4 +784,95 @@ abstract class AbstractRecognitionServiceTest {
}
}
}
+
+ /**
+ * Data class containing information about model download listener callback sequence:
+ * <ul>
+ * <li> {@link ModelDownloadExecutionInfo#mInstructedCallbacks} - list of {@link
+ * ModelDownloadCallback}s instructed to be invoked by the service on the given listener;
+ * <li> {@link ModelDownloadExecutionInfo#mExpectedCallbacks} - list of {@link
+ * ModelDownloadCallback}s expected to be received at the client's end by the given listener.
+ */
+ private static class ModelDownloadExecutionInfo {
+ private final List<ModelDownloadCallback> mInstructedCallbacks;
+ private final List<ModelDownloadCallback> mExpectedCallbacks;
+
+ private ModelDownloadExecutionInfo(
+ List<ModelDownloadCallback> instructedCallbacks,
+ List<ModelDownloadCallback> expectedCallbacks) {
+ mInstructedCallbacks = instructedCallbacks;
+ mExpectedCallbacks = expectedCallbacks;
+ }
+
+ enum Scenario {
+ PROGRESS_PROGRESS_PROGRESS,
+ PROGRESS_SUCCESS_PROGRESS,
+ SCHEDULED_ERROR,
+ ERROR_SCHEDULED
+ }
+
+ private static ModelDownloadExecutionInfo fromScenario(Scenario scenario) {
+ switch (scenario) {
+ case PROGRESS_PROGRESS_PROGRESS:
+ return new ModelDownloadExecutionInfo(
+ /* callbacks to be invoked by the service: */ ImmutableList.of(
+ ModelDownloadCallback.ON_PROGRESS,
+ ModelDownloadCallback.ON_PROGRESS,
+ ModelDownloadCallback.ON_PROGRESS),
+ /* callbacks to be received by the client: */ ImmutableList.of(
+ ModelDownloadCallback.ON_PROGRESS,
+ ModelDownloadCallback.ON_PROGRESS,
+ ModelDownloadCallback.ON_PROGRESS));
+ case PROGRESS_SUCCESS_PROGRESS:
+ return new ModelDownloadExecutionInfo(
+ /* callbacks to be invoked by the service: */ ImmutableList.of(
+ ModelDownloadCallback.ON_PROGRESS,
+ ModelDownloadCallback.ON_SUCCESS,
+ ModelDownloadCallback.ON_PROGRESS),
+ /* callbacks to be received by the client: */ ImmutableList.of(
+ ModelDownloadCallback.ON_PROGRESS,
+ ModelDownloadCallback.ON_SUCCESS));
+ case SCHEDULED_ERROR:
+ return new ModelDownloadExecutionInfo(
+ /* callbacks to be invoked by the service: */ ImmutableList.of(
+ ModelDownloadCallback.ON_SCHEDULED,
+ ModelDownloadCallback.ON_ERROR),
+ /* callbacks to be received by the client: */ ImmutableList.of(
+ ModelDownloadCallback.ON_SCHEDULED));
+ case ERROR_SCHEDULED:
+ return new ModelDownloadExecutionInfo(
+ /* callbacks to be invoked by the service: */ ImmutableList.of(
+ ModelDownloadCallback.ON_ERROR,
+ ModelDownloadCallback.ON_SCHEDULED),
+ /* callbacks to be received by the client: */ ImmutableList.of(
+ ModelDownloadCallback.ON_ERROR));
+ default:
+ return new ModelDownloadExecutionInfo(ImmutableList.of(), ImmutableList.of());
+ }
+ }
+ }
+
+ private static class ModelDownloadCallbackLogger implements ModelDownloadListener {
+ private List<ModelDownloadCallback> mCallbacks = new ArrayList<>();
+
+ @Override
+ public void onProgress(int completedPercent) {
+ mCallbacks.add(ModelDownloadCallback.ON_PROGRESS);
+ }
+
+ @Override
+ public void onSuccess() {
+ mCallbacks.add(ModelDownloadCallback.ON_SUCCESS);
+ }
+
+ @Override
+ public void onScheduled() {
+ mCallbacks.add(ModelDownloadCallback.ON_SCHEDULED);
+ }
+
+ @Override
+ public void onError(int error) {
+ mCallbacks.add(ModelDownloadCallback.ON_ERROR);
+ }
+ }
}
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/CtsRecognitionService.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/CtsRecognitionService.java
index 728e76e2b74..f2a0c9edc85 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/CtsRecognitionService.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/CtsRecognitionService.java
@@ -64,6 +64,15 @@ public class CtsRecognitionService extends RecognitionService {
public static Queue<Pair<Integer, CallbackMethod>> sInstructedCallbackMethods =
new ArrayDeque<>();
+ /**
+ * Queue of instructions for callbacks on the model download task - {@link
+ * CtsRecognitionService#onTriggerModelDownload(
+ * Intent, AttributionSource, ModelDownloadListener)}.
+ *
+ * <p> Each instruction represents the callback to be run on the given listener.
+ */
+ public static Queue<ModelDownloadCallback> sInstructedModelDownloadCallbacks = null;
+
public static AtomicBoolean sIsActive = new AtomicBoolean(false);
public static Queue<Consumer<SupportCallback>> sConsumerQueue = new ArrayDeque<>();
public static List<Intent> sDownloadTriggers = new ArrayList<>();
@@ -128,10 +137,26 @@ public class CtsRecognitionService extends RecognitionService {
@NonNull AttributionSource attributionSource,
@NonNull ModelDownloadListener listener) {
assertThat(attributionSource.getUid()).isEqualTo(android.os.Process.myUid());
- listener.onProgress(50);
- listener.onScheduled();
- listener.onSuccess();
- listener.onError(0);
+
+ while (!sInstructedModelDownloadCallbacks.isEmpty()) {
+ ModelDownloadCallback callback = sInstructedModelDownloadCallbacks.poll();
+ switch (callback) {
+ case ON_PROGRESS:
+ listener.onProgress(50);
+ break;
+ case ON_SUCCESS:
+ listener.onSuccess();
+ break;
+ case ON_SCHEDULED:
+ listener.onScheduled();
+ break;
+ case ON_ERROR:
+ listener.onError(0);
+ break;
+ default:
+ break;
+ }
+ }
sDownloadTriggers.add(recognizerIntent);
}
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/ModelDownloadCallback.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/ModelDownloadCallback.java
new file mode 100644
index 00000000000..e984160d27c
--- /dev/null
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/ModelDownloadCallback.java
@@ -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.voicerecognition.cts;
+
+enum ModelDownloadCallback {
+ ON_PROGRESS,
+ ON_SUCCESS,
+ ON_SCHEDULED,
+ ON_ERROR
+}
diff --git a/tests/tests/voiceinteraction/AndroidTest.xml b/tests/tests/voiceinteraction/AndroidTest.xml
index 6191ac9a462..a69379fb04f 100644
--- a/tests/tests/voiceinteraction/AndroidTest.xml
+++ b/tests/tests/voiceinteraction/AndroidTest.xml
@@ -49,4 +49,11 @@
<option name="package" value="android.voiceinteraction.cts" />
<option name="runtime-hint" value="11m" />
</test>
+
+ <!-- This test is included as part of GTS 11 but is built against U SDK.
+ Skip on non-U devices. -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MinApiLevelModuleController">
+ <option name="min-api-level" value="34" />
+ </object>
</configuration>
diff --git a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
index 1271e92b7bf..a7370bbd2ed 100644
--- a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
+++ b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
@@ -26,6 +26,7 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import android.os.SystemProperties;
import android.service.voice.HotwordAudioStream;
import android.service.voice.HotwordDetectedResult;
import android.util.Log;
@@ -264,6 +265,9 @@ public class Utils {
new HotwordDetectedResult.Builder().setAudioStreams(
List.of(HOTWORD_AUDIO_STREAM_WRONG_COPY_BUFFER_SIZE)).build();
+ public static final boolean SYSPROP_VISUAL_QUERY_SERVICE_ENABLED =
+ SystemProperties.getBoolean("ro.hotword.visual_query_service_enabled", false);
+
/**
* Returns the PersistableBundle data that is used for testing.
*/
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceNonSharedIsolatedTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceNonSharedIsolatedTest.java
index b0a6c94f7f6..2e3d81a371b 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceNonSharedIsolatedTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceNonSharedIsolatedTest.java
@@ -25,8 +25,10 @@ import static com.google.common.truth.Truth.assertThat;
import android.platform.test.annotations.AppModeFull;
import android.service.voice.HotwordDetectionService;
import android.util.Log;
+import android.voiceinteraction.common.Utils;
import android.voiceinteraction.cts.services.BaseVoiceInteractionService;
import android.voiceinteraction.cts.services.NonSharedIsolatedHotwordDetectionVoiceInteractionService;
+import android.voiceinteraction.cts.testcore.AssumptionCheckerRule;
import android.voiceinteraction.cts.testcore.VoiceInteractionServiceConnectedRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -51,6 +53,11 @@ public class HotwordDetectionServiceNonSharedIsolatedTest {
+ ".NonSharedIsolatedHotwordDetectionVoiceInteractionService";
@Rule
+ public AssumptionCheckerRule checkVisualQueryDetectionServiceEnabledRule =
+ new AssumptionCheckerRule(() -> Utils.SYSPROP_VISUAL_QUERY_SERVICE_ENABLED,
+ "Testing VisualQueryDetectionService requires enabling the feature");
+
+ @Rule
public VoiceInteractionServiceConnectedRule mConnectedRule =
new VoiceInteractionServiceConnectedRule(
getInstrumentation().getTargetContext(), getTestVoiceInteractionService());
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceBasicTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceBasicTest.java
index e7230456ba1..95295d4a388 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceBasicTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceBasicTest.java
@@ -41,8 +41,10 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.RequiresDevice;
import android.service.voice.VisualQueryDetector;
import android.util.Log;
+import android.voiceinteraction.common.Utils;
import android.voiceinteraction.cts.services.BaseVoiceInteractionService;
import android.voiceinteraction.cts.services.CtsBasicVoiceInteractionService;
+import android.voiceinteraction.cts.testcore.AssumptionCheckerRule;
import android.voiceinteraction.cts.testcore.Helper;
import android.voiceinteraction.cts.testcore.VoiceInteractionServiceConnectedRule;
import android.voiceinteraction.service.MainVisualQueryDetectionService;
@@ -78,6 +80,11 @@ public class VisualQueryDetectionServiceBasicTest {
private static String sDefaultScreenOffTimeoutValue;
@Rule
+ public AssumptionCheckerRule checkVisualQueryDetectionServiceEnabledRule =
+ new AssumptionCheckerRule(() -> Utils.SYSPROP_VISUAL_QUERY_SERVICE_ENABLED,
+ "Testing VisualQueryDetectionService requires enabling the feature");
+
+ @Rule
public VoiceInteractionServiceConnectedRule mConnectedRule =
new VoiceInteractionServiceConnectedRule(
getInstrumentation().getTargetContext(), getTestVoiceInteractionService());
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonIsolatedTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonIsolatedTest.java
index ef54516f179..f282a4b6f26 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonIsolatedTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonIsolatedTest.java
@@ -25,8 +25,10 @@ import static com.google.common.truth.Truth.assertThat;
import android.platform.test.annotations.AppModeFull;
import android.service.voice.VisualQueryDetectionService;
import android.util.Log;
+import android.voiceinteraction.common.Utils;
import android.voiceinteraction.cts.services.BaseVoiceInteractionService;
import android.voiceinteraction.cts.services.NonIsolatedHotwordDetectionVoiceInteractionService;
+import android.voiceinteraction.cts.testcore.AssumptionCheckerRule;
import android.voiceinteraction.cts.testcore.VoiceInteractionServiceConnectedRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -51,6 +53,11 @@ public class VisualQueryDetectionServiceNonIsolatedTest {
+ ".NonIsolatedHotwordDetectionVoiceInteractionService";
@Rule
+ public AssumptionCheckerRule checkVisualQueryDetectionServiceEnabledRule =
+ new AssumptionCheckerRule(() -> Utils.SYSPROP_VISUAL_QUERY_SERVICE_ENABLED,
+ "Testing VisualQueryDetectionService requires enabling the feature");
+
+ @Rule
public VoiceInteractionServiceConnectedRule mConnectedRule =
new VoiceInteractionServiceConnectedRule(
getInstrumentation().getTargetContext(), getTestVoiceInteractionService());
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonSharedIsolatedTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonSharedIsolatedTest.java
index 71c2c4146b2..32df9ae2c17 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonSharedIsolatedTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectionServiceNonSharedIsolatedTest.java
@@ -25,8 +25,10 @@ import static com.google.common.truth.Truth.assertThat;
import android.platform.test.annotations.AppModeFull;
import android.service.voice.VisualQueryDetectionService;
import android.util.Log;
+import android.voiceinteraction.common.Utils;
import android.voiceinteraction.cts.services.BaseVoiceInteractionService;
import android.voiceinteraction.cts.services.NonSharedIsolatedHotwordDetectionVoiceInteractionService;
+import android.voiceinteraction.cts.testcore.AssumptionCheckerRule;
import android.voiceinteraction.cts.testcore.VoiceInteractionServiceConnectedRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -51,6 +53,11 @@ public class VisualQueryDetectionServiceNonSharedIsolatedTest {
+ ".NonSharedIsolatedHotwordDetectionVoiceInteractionService";
@Rule
+ public AssumptionCheckerRule checkVisualQueryDetectionServiceEnabledRule =
+ new AssumptionCheckerRule(() -> Utils.SYSPROP_VISUAL_QUERY_SERVICE_ENABLED,
+ "Testing VisualQueryDetectionService requires enabling the feature");
+
+ @Rule
public VoiceInteractionServiceConnectedRule mConnectedRule =
new VoiceInteractionServiceConnectedRule(
getInstrumentation().getTargetContext(), getTestVoiceInteractionService());
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectorTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectorTest.java
index 99416246994..e152eb6f589 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectorTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VisualQueryDetectorTest.java
@@ -32,8 +32,10 @@ import android.platform.test.annotations.AppModeFull;
import android.service.voice.SandboxedDetectionInitializer;
import android.service.voice.VisualQueryDetector;
import android.util.Log;
+import android.voiceinteraction.common.Utils;
import android.voiceinteraction.cts.services.BaseVoiceInteractionService;
import android.voiceinteraction.cts.services.CtsBasicVoiceInteractionService;
+import android.voiceinteraction.cts.testcore.AssumptionCheckerRule;
import android.voiceinteraction.cts.testcore.VoiceInteractionServiceConnectedRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -63,6 +65,11 @@ public class VisualQueryDetectorTest {
private CtsBasicVoiceInteractionService mService;
@Rule
+ public AssumptionCheckerRule checkVisualQueryDetectionServiceEnabledRule =
+ new AssumptionCheckerRule(() -> Utils.SYSPROP_VISUAL_QUERY_SERVICE_ENABLED,
+ "Testing VisualQueryDetectionService requires enabling the feature");
+
+ @Rule
public VoiceInteractionServiceConnectedRule mConnectedRule =
new VoiceInteractionServiceConnectedRule(mContext, getTestVoiceInteractionService());
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index 144eda8d457..e057f24645e 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.app.Activity;
import android.app.Instrumentation;
+import android.content.pm.ApplicationInfo;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
@@ -116,7 +117,6 @@ public class ListPopupWindowTest {
mCtsKeyEventUtil = new CtsKeyEventUtil(mInstrumentation.getTargetContext());
mActivity = mActivityRule.getActivity();
mItemClickListener = new PopupItemClickListener();
- mActivity.getApplicationInfo().setEnableOnBackInvokedCallback(false);
PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
}
@@ -713,28 +713,41 @@ public class ListPopupWindowTest {
@Test
public void testCustomDismissalWithBackButton() {
- WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
- () -> {
- mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
- .withDismissListener();
- mPopupWindowBuilder.show();
- });
-
- // "Point" our custom extension of EditText to our ListPopupWindow
- final MockViewForListPopupWindow anchor =
- (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
- anchor.wireTo(mPopupWindow);
- // Request focus on our EditText
- WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
- anchor::requestFocus);
- assertTrue(anchor.isFocused());
-
- // Send BACK key event. As our custom extension of EditText calls
- // ListPopupWindow.onKeyPreIme, the end result should be the dismissal of the
- // ListPopupWindow
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
- assertFalse(mPopupWindow.isShowing());
+ ApplicationInfo applicationInfo = mActivity.getApplicationInfo();
+ boolean isOnBackInvokedCallbackEnabled = applicationInfo.isOnBackInvokedCallbackEnabled();
+ // Temporarily opt-out of predictive back
+ applicationInfo.setEnableOnBackInvokedCallback(false);
+ try {
+ WidgetTestUtils.runOnMainAndDrawSync(
+ mActivityRule,
+ mActivity.getWindow().getDecorView(),
+ () -> {
+ mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
+ .withDismissListener();
+ mPopupWindowBuilder.show();
+ });
+
+ // "Point" our custom extension of EditText to our ListPopupWindow
+ final MockViewForListPopupWindow anchor =
+ (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
+ anchor.wireTo(mPopupWindow);
+ // Request focus on our EditText
+ WidgetTestUtils.runOnMainAndDrawSync(
+ mActivityRule,
+ mActivity.getWindow().getDecorView(),
+ anchor::requestFocus);
+ assertTrue(anchor.isFocused());
+
+ // Send BACK key event. As our custom extension of EditText calls
+ // ListPopupWindow.onKeyPreIme, the end result should be the dismissal of the
+ // ListPopupWindow
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
+ assertFalse(mPopupWindow.isShowing());
+ } finally {
+ // Restore predictive back
+ applicationInfo.setEnableOnBackInvokedCallback(isOnBackInvokedCallbackEnabled);
+ }
}
@Test
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
index d6a89f1daae..1af75da7210 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
@@ -34,10 +34,8 @@ import static android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK;
import static android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI;
import static android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO;
import static android.os.Process.myUid;
-
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.assertTrue;
@@ -86,6 +84,7 @@ import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -113,6 +112,8 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
private static boolean sShouldRunTest = false;
private static boolean sWasScanThrottleEnabled;
+ private final Executor mExecutor = Executors.newSingleThreadExecutor();
+
@BeforeClass
public static void setUpClass() throws Exception {
sContext = InstrumentationRegistry.getInstrumentation().getContext();
@@ -140,10 +141,10 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
ShellIdentityUtils.invokeWithShellPermissions(
() -> sWifiManager.setScanThrottleEnabled(false));
- // enable Wifi
- if (!sWifiManager.isWifiEnabled()) {
- ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(true));
- }
+ // disable then enable Wifi to clean the user selected network
+ ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false));
+ PollingCheck.check("Wifi not disabled", TIMEOUT, () -> !sWifiManager.isWifiEnabled());
+ ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(true));
PollingCheck.check("Wifi not enabled", TIMEOUT, () -> sWifiManager.isWifiEnabled());
// turn screen on
@@ -223,8 +224,7 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
new TestUsabilityStatsListener(countDownLatch);
try {
uiAutomation.adoptShellPermissionIdentity();
- sWifiManager.addOnWifiUsabilityStatsListener(
- Executors.newSingleThreadExecutor(), usabilityStatsListener);
+ sWifiManager.addOnWifiUsabilityStatsListener(mExecutor, usabilityStatsListener);
// Wait for new usability stats (while connected & screen on this is triggered
// by platform periodically).
assertThat(countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
@@ -569,14 +569,15 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
TestConnectedNetworkScorer {
TestConnectedNetworkScorerWithSessionInfo(CountDownLatch countDownLatch) {
super(countDownLatch);
+ isUserSelected = false;
}
@Override
public void onStart(WifiConnectedSessionInfo sessionInfo) {
super.onStart(sessionInfo);
synchronized (mCountDownLatch) {
- this.startSessionId = sessionInfo.getSessionId();
- this.isUserSelected = sessionInfo.isUserSelected();
+ startSessionId = sessionInfo.getSessionId();
+ isUserSelected = sessionInfo.isUserSelected();
// Build a WifiConnectedSessionInfo object
WifiConnectedSessionInfo.Builder sessionBuilder =
new WifiConnectedSessionInfo.Builder(startSessionId.intValue())
@@ -645,8 +646,7 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
sWifiManager.clearWifiConnectedNetworkScorer();
Thread.sleep(500);
- sWifiManager.setWifiConnectedNetworkScorer(
- Executors.newSingleThreadExecutor(), connectedNetworkScorer);
+ sWifiManager.setWifiConnectedNetworkScorer(mExecutor, connectedNetworkScorer);
// Since we're already connected, wait for onStart to be invoked.
assertThat(countDownLatchScorer.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
@@ -660,8 +660,7 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
scoreUpdateObserver.notifyScoreUpdate(connectedNetworkScorer.startSessionId, 50);
// Register the usability listener
- sWifiManager.addOnWifiUsabilityStatsListener(
- Executors.newSingleThreadExecutor(), usabilityStatsListener);
+ sWifiManager.addOnWifiUsabilityStatsListener(mExecutor, usabilityStatsListener);
// Trigger a usability stats update.
scoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(
connectedNetworkScorer.startSessionId);
@@ -737,8 +736,7 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
sWifiManager.clearWifiConnectedNetworkScorer();
Thread.sleep(500);
- sWifiManager.setWifiConnectedNetworkScorer(
- Executors.newSingleThreadExecutor(), connectedNetworkScorer);
+ sWifiManager.setWifiConnectedNetworkScorer(mExecutor, connectedNetworkScorer);
// Since we're already connected, wait for onStart to be invoked.
assertThat(countDownLatchScorer.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
@@ -826,8 +824,7 @@ public class ConnectedNetworkScorerTest extends WifiJUnit4TestBase {
assertThat(testNetwork).isNotNull();
// Register the external scorer.
- sWifiManager.setWifiConnectedNetworkScorer(
- Executors.newSingleThreadExecutor(), connectedNetworkScorer);
+ sWifiManager.setWifiConnectedNetworkScorer(mExecutor, connectedNetworkScorer);
// Now connect using the provided connection initiator
networkCallback = connectionInitiator.initiateConnection(testNetwork, executorService);
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index aaa61439b67..63bdc5c7545 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -116,6 +116,7 @@ import com.android.compatibility.common.util.FeatureUtil;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.PropertyUtil;
import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.ThrowingRunnable;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.MacAddressUtils;
@@ -1149,6 +1150,14 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
return;
}
boolean wifiEnabled = sWifiManager.isWifiEnabled();
+ if (wifiEnabled) {
+ // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no
+ // STA+AP concurrency.
+ ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false));
+ PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled());
+ SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled");
+ PollingCheck.check("Wifi turn on failed!", 2_000, () -> sWifiManager.isWifiEnabled());
+ }
TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
// add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization.
@@ -1922,6 +1931,14 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
boolean caughtException = false;
boolean wifiEnabled = sWifiManager.isWifiEnabled();
+ if (wifiEnabled) {
+ // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no
+ // STA+AP concurrency.
+ ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false));
+ PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled());
+ SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled");
+ PollingCheck.check("Wifi turn on failed!", 2_000, () -> sWifiManager.isWifiEnabled());
+ }
TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
@@ -2038,8 +2055,14 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
// WPA2_PSK is not allowed in 6GHz band. So test with WPA3_SAE which is
// mandatory to support in 6GHz band.
if (testBand == SoftApConfiguration.BAND_6GHZ) {
- customConfigBuilder.setPassphrase(TEST_PASSPHRASE,
+ if (lohsSoftApCallback.getCurrentSoftApCapability()
+ .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)) {
+ customConfigBuilder.setPassphrase(TEST_PASSPHRASE,
SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ } else {
+ Log.e(TAG, "SoftAp 6GHz capability is advertized without WPA3 support");
+ continue;
+ }
}
customConfigBuilder.setBand(testBand);
sWifiManager.startLocalOnlyHotspot(customConfigBuilder.build(), executor, callback);
@@ -3636,13 +3659,20 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
}
/**
- * Tests {@link WifiManager#isStaApConcurrencySupported().
+ * Tests {@link WifiManager#isStaApConcurrencySupported()}.
*/
@Test
public void testIsStaApConcurrencySupported() throws Exception {
// check that softap mode is supported by the device
assumeTrue(sWifiManager.isPortableHotspotSupported());
+ // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no
+ // STA+AP concurrency.
+ ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false));
+ PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled());
+ SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled");
+ PollingCheck.check("Wifi turn on failed!", 2_000, () -> sWifiManager.isWifiEnabled());
+
boolean isStaApConcurrencySupported = sWifiManager.isStaApConcurrencySupported();
// start local only hotspot.
TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
diff --git a/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/SharedConnectivityTest.java b/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/SharedConnectivityTest.java
index 2f11f27a124..c7985f506c1 100644
--- a/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/SharedConnectivityTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/SharedConnectivityTest.java
@@ -205,9 +205,15 @@ public class SharedConnectivityTest {
};
// Need to successfully register callback before testing unregister method.
manager.registerCallback(Runnable::run, callback);
+ assertServiceConnected(callback);
TestSharedConnectivityService service = getService();
+ CountDownLatch serviceLatch = new CountDownLatch(1);
+ service.setCountdownLatch(serviceLatch);
assertThat(manager.unregisterCallback(callback)).isTrue();
+ // Wait for the unregister call to be executed in the service
+ assertThat(serviceLatch.await(LATCH_TIMEOUT_SECS, TimeUnit.SECONDS)).isTrue();
+
// Try to use callback and validate that manager was not updated.
service.setSettingsState(buildSettingsState());
assertThat(callbackLatch.await(LATCH_TIMEOUT_SECS, TimeUnit.SECONDS)).isFalse();
diff --git a/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/app/SharedConnectivityManagerTest.java b/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/app/SharedConnectivityManagerTest.java
index 993309288e5..14cf76eab89 100644
--- a/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/app/SharedConnectivityManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/sharedconnectivity/cts/app/SharedConnectivityManagerTest.java
@@ -49,6 +49,7 @@ import android.net.wifi.sharedconnectivity.service.ISharedConnectivityService;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
+import android.os.UserManager;
import androidx.test.filters.SdkSuppress;
import androidx.test.runner.AndroidJUnit4;
@@ -102,6 +103,8 @@ public class SharedConnectivityManagerTest {
Resources mResources;
@Mock
ISharedConnectivityService.Stub mIBinder;
+ @Mock
+ UserManager mUserManager;
private static final ComponentName COMPONENT_NAME =
new ComponentName("dummypkg", "dummycls");
@@ -110,6 +113,11 @@ public class SharedConnectivityManagerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
setResources(mContext);
+ when(mContext.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+ when(mUserManager.isUserUnlocked()).thenReturn(true);
+ when(mContext.bindService(any(Intent.class), any(ServiceConnection.class),
+ anyInt())).thenReturn(true);
}
@Test
@@ -266,16 +274,6 @@ public class SharedConnectivityManagerTest {
}
@Test
- public void onServiceConnected() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
-
- verify(mClientCallback).onServiceConnected();
- }
-
- @Test
public void onServiceDisconnected() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
@@ -286,7 +284,6 @@ public class SharedConnectivityManagerTest {
verify(mClientCallback).onServiceDisconnected();
}
-
@Test
public void connectHotspotNetwork_serviceNotConnected_shouldFail() {
HotspotNetwork network = buildHotspotNetwork();
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java
index c6e69911a06..fbf2214115c 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderAdaptiveBitRateTest.java
@@ -23,6 +23,7 @@ import static android.mediav2.common.cts.CodecTestBase.ComponentClass.HARDWARE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
import android.media.MediaCodec;
import android.media.MediaFormat;
@@ -34,7 +35,6 @@ import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CddTest;
import org.junit.AfterClass;
-import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -181,7 +181,13 @@ public class VideoEncoderAdaptiveBitRateTest extends VideoEncoderValidationTestB
+ " size is %f \n Segment Relative Ratio %f \n",
segA, mSegmentBitRates[segA], mSegmentSizes[segA], segB, mSegmentBitRates[segB],
mSegmentSizes[segB], mSegmentSizes[segB] / mSegmentSizes[segA]);
- assertTrue(msg + mTestConfig + mTestEnv, mSegmentSizes[segB] / mSegmentSizes[segA] >= 1.15);
+ if (mEncCfgParams[0].mBitRateMode == BITRATE_MODE_CBR) {
+ assertTrue(msg + mTestConfig + mTestEnv,
+ mSegmentSizes[segB] / mSegmentSizes[segA] >= 1.15);
+ } else {
+ assumeTrue(msg + mTestConfig + mTestEnv,
+ mSegmentSizes[segB] / mSegmentSizes[segA] >= 1.15);
+ }
}
@CddTest(requirements = "5.2/C-2-1")
@@ -197,7 +203,7 @@ public class VideoEncoderAdaptiveBitRateTest extends VideoEncoderValidationTestB
MediaFormat format = cfg.getFormat();
ArrayList<MediaFormat> formats = new ArrayList<>();
formats.add(format);
- Assume.assumeTrue("Encoder: " + mCodecName + " doesn't support format: " + format,
+ assumeTrue("Encoder: " + mCodecName + " doesn't support format: " + format,
areFormatsSupported(mCodecName, mMediaType, formats));
RawResource res = RES_YUV_MAP.getOrDefault(mCRes.uniqueLabel(), null);
diff --git a/tests/wallpapereffectsgeneration/src/android/wallpapereffectsgeneration/cts/WallpaperEffectsGenerationManagerTest.java b/tests/wallpapereffectsgeneration/src/android/wallpapereffectsgeneration/cts/WallpaperEffectsGenerationManagerTest.java
index 79bbdbbc859..2e3bce65320 100644
--- a/tests/wallpapereffectsgeneration/src/android/wallpapereffectsgeneration/cts/WallpaperEffectsGenerationManagerTest.java
+++ b/tests/wallpapereffectsgeneration/src/android/wallpapereffectsgeneration/cts/WallpaperEffectsGenerationManagerTest.java
@@ -195,7 +195,10 @@ public class WallpaperEffectsGenerationManagerTest {
mWatcher.initialCallReturned.countDown();
} else if (cinematicEffectResponse.getStatusCode()
== CinematicEffectResponse.CINEMATIC_EFFECT_STATUS_ERROR) {
- mWatcher.errorResponse.countDown();
+ // Ignore the error response when remote service is destroyed after each test.
+ if (mWatcher != null) {
+ mWatcher.errorResponse.countDown();
+ }
}
};
}
diff --git a/tools/cts-device-info/Android.bp b/tools/cts-device-info/Android.bp
index e7cf2f95ec3..b1287827b34 100644
--- a/tools/cts-device-info/Android.bp
+++ b/tools/cts-device-info/Android.bp
@@ -96,7 +96,5 @@ genrule {
" -lo androidx.window.sidecar " +
" -p com.android.compatibility.common.deviceinfo " +
" -i androidx.test.runner.AndroidJUnitRunner " +
- " -s 23 " +
- " -t 23 " +
" -o $(out)",
}
diff --git a/tools/cts-tradefed/OWNERS b/tools/cts-tradefed/OWNERS
index 79229ba9a02..20010b140d2 100644
--- a/tools/cts-tradefed/OWNERS
+++ b/tools/cts-tradefed/OWNERS
@@ -9,5 +9,6 @@ per-file cts-meerkat.xml = alanstokes@google.com, brufino@google.com, lus@google
per-file cts-on-csi*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
per-file csi-*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
per-file cts-on-gsi*.xml = bettyzhou@google.com, ycchen@google.com, hsinyichen@google.com, tyanh@google.com
+per-file cts-on-aosp*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
per-file cts-known-failures.xml = rossyeh@google.com, mariay@google.com, robinjacob@google.com
per-file grf-*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 938af1fe7d9..0ad645eab21 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -111,9 +111,6 @@
<!-- b/64221494 -->
<option name="compatibility:exclude-filter" value="CtsSecurityHostTestCases android.security.cts.SELinuxHostTest#testAospSeappContexts" />
- <!-- b/63378294 b/64382381 -->
- <option name="compatibility:exclude-filter" value="CtsSecurityHostTestCases android.security.cts.SELinuxNeverallowRulesTest#testNeverallowRules440" />
-
<!-- b/36686383 -->
<option name="compatibility:exclude-filter" value="CtsIncidentHostTestCases com.android.server.cts.ErrorsTest#testANR" />
@@ -257,6 +254,9 @@
<option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:1:TENT] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
<option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:2:HALF_FOLDED] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
<option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:3:OPEN] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
+ <!-- b/300310474 -->
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:5:REAR_DUAL] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:5:REAR_DUAL] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
<!-- b/202357331 -->
<option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedDeviceOwnerTest#testCreateAdminSupportIntent" />
@@ -300,4 +300,12 @@
<!-- b/284406623 -->
<option name="compatibility:exclude-filter" value="CtsUwbMultiDeviceTestCase_FiraRangingTests" />
<option name="compatibility:exclude-filter" value="CtsUwbMultiDeviceTestCase_RangingMeasurementTests" />
+
+ <!-- b/296988493 -->
+ <option name="compatibility:exclude-filter" value="CtsFrameRateOverrideTestCases com.android.cts.graphics.framerateoverride.FrameRateOverrideHostTest" />
+ <option name="compatibility:exclude-filter" value="CtsFrameRateOverrideTestCases[instant] com.android.cts.graphics.framerateoverride.FrameRateOverrideHostTest" />
+
+ <!-- b/303631162 -->
+ <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.ims.cts.ImsCallingTest#testCallJoinExistingConferenceCallAfterCallSwap" />
+ <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.ims.cts.ImsCallingTest#testCallJoinExistingConferenceCallAfterCallSwapFail" />
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml b/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
index de7dfff32d7..dc5bb27e5cc 100644
--- a/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
@@ -13,6 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
+<!--
+ Please remember to update cts-on-aosp-include.xml when
+ this file is modified. See comments there for details.
+-->
+
<configuration description="Excluded tests from cts-on-aosp">
<!-- Tell all AndroidJUnitTests to exclude certain annotations -->
<option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:exclude-annotation:android.platform.test.annotations.RestrictedBuildTest" />
@@ -30,17 +36,13 @@
<option name="compatibility:exclude-filter" value="CtsNetTestCasesLegacyApi22 android.net.cts.legacy.api22.ConnectivityManagerLegacyTest#testStartUsingNetworkFeature_enableHipri" />
<option name="compatibility:exclude-filter" value="CtsPermissionPolicyTestCases android.permissionpolicy.cts.NoReceiveSmsPermissionTest#testAppSpecificSmsToken" />
<option name="compatibility:exclude-filter" value="CtsPermissionPolicyTestCases android.permissionpolicy.cts.NoReceiveSmsPermissionTest#testReceiveTextMessage" />
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testAppDetails" />
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testAppSummary" />
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testCallback" />
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testDeviceSummary" />
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testTagDetails" />
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testUidDetails" />
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testUserSummary" />
-
- <!-- Exclude not applicable testcases-->
- <option name="compatibility:exclude-filter" value="CtsSignatureTestCases" />
- <option name="compatibility:exclude-filter" value="CtsOsTestCases android.os.cts.AutoRevokeTeandroid.os.cts.AutoRevokeTestst" />
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.NetworkStatsManagerTest#testAppDetails" />
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.NetworkStatsManagerTest#testAppSummary" />
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.NetworkStatsManagerTest#testCallback" />
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.NetworkStatsManagerTest#testDeviceSummary" />
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.NetworkStatsManagerTest#testTagDetails" />
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.NetworkStatsManagerTest#testUidDetails" />
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.NetworkStatsManagerTest#testUserSummary" />
<!--
Exclude testcases failing on Pixel devices
@@ -94,9 +96,6 @@
<option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.ConnectivityManagerTest#testOpenConnection" />
<option name="compatibility:exclude-filter" value="CtsWifiTestCases android.net.wifi.rtt.cts.WifiRttTest#testRangingToTestAp" />
- <!-- b/110417203: Flaky tests -->
- <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testUidTagStateDetails" />
-
<!-- b/111101428: CtsOsTestCases irrelevant test cases -->
<option name="compatibility:exclude-filter" value="CtsOsTestCases android.os.cts.BuildTest#testIsSecureUserBuild" />
<option name="compatibility:exclude-filter" value="CtsOsTestCases android.os.cts.BuildVersionTest#testBuildFingerprint" />
diff --git a/tools/cts-tradefed/res/config/cts-on-aosp-include.xml b/tools/cts-tradefed/res/config/cts-on-aosp-include.xml
new file mode 100644
index 00000000000..fbe8c576d9f
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-on-aosp-include.xml
@@ -0,0 +1,266 @@
+<?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.
+-->
+
+<!--
+ This file is modified from cts-on-aosp-exclude.xml basically by
+ replacing all the "compatibility:exclude-filter" in the latter
+ with "compatibility:include-filter".
+
+ Telephony related tests are not included, though.
+
+ Please remember to update this file when that file is modified.
+-->
+
+<configuration description="Include tests excluded from cts-on-aosp">
+ <!-- Tell all AndroidJUnitTests to exclude certain annotations -->
+ <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:exclude-annotation:android.platform.test.annotations.RestrictedBuildTest" />
+
+ <!-- Tell all HostTests to exclude certain annotations -->
+ <option name="compatibility:test-arg" value="com.android.tradefed.testtype.HostTest:exclude-annotation:android.platform.test.annotations.RestrictedBuildTest" />
+ <option name="compatibility:test-arg" value="com.android.compatibility.common.tradefed.testtype.JarHostTest:exclude-annotation:android.platform.test.annotations.RestrictedBuildTest" />
+
+ <!-- Radio system of a general system image is not checked -->
+<!-- Not suitable for some GRF devices
+ <option name="compatibility:include-filter" value="CtsTelephonyTestCases" />
+ <option name="compatibility:include-filter" value="CtsTelephony2TestCases" />
+ <option name="compatibility:include-filter" value="CtsAppTestCases android.app.cts.SystemFeaturesTest#testLocationFeatures" />
+-->
+
+ <!-- Exclude telephony related testcases -->
+<!-- Not suitable for some GRF devices
+ <option name="compatibility:include-filter" value="CtsNetTestCasesLegacyApi22 android.net.cts.legacy.api22.ConnectivityManagerLegacyTest#testStartUsingNetworkFeature_enableHipri" />
+ <option name="compatibility:include-filter" value="CtsPermission2TestCases android.permission2.cts.NoReceiveSmsPermissionTest#testAppSpecificSmsToken" />
+ <option name="compatibility:include-filter" value="CtsPermission2TestCases android.permission2.cts.NoReceiveSmsPermissionTest#testReceiveTextMessage" />
+ <option name="compatibility:include-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testAppDetails" />
+ <option name="compatibility:include-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testAppSummary" />
+ <option name="compatibility:include-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testCallback" />
+ <option name="compatibility:include-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testDeviceSummary" />
+ <option name="compatibility:include-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testTagDetails" />
+ <option name="compatibility:include-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testUidDetails" />
+ <option name="compatibility:include-filter" value="CtsUsageStatsTestCases android.app.usage.cts.NetworkUsageStatsTest#testUserSummary" />
+-->
+
+ <!--
+ Exclude testcases failing on Pixel devices
+ TODO(jaeshin@): b/68300743
+ -->
+ <option name="compatibility:include-filter" value="CtsContentTestCases android.content.cts.AvailableIntentsTest#testVoiceCommand" />
+ <option name="compatibility:include-filter" value="CtsContentTestCases android.content.cts.AvailableIntentsTest#testVoiceSearchHandsFree" />
+
+ <!-- Excluded tese case - TODO(jiyong): b/67739526 to reenable that -->
+ <option name="compatibility:include-filter" value="CtsJniTestCases android.jni.cts.JniStaticTest#test_linker_namespaces" />
+
+ <!-- b/68190722: Remove testcases that require RRO which is planned for Pi -->
+ <option name="compatibility:include-filter" value="CtsAppTestCases android.app.cts.ActionBarTest#testOpenOptionsMenu" />
+ <option name="compatibility:include-filter" value="CtsAppTestCases android.app.cts.ActionBarTest#testOptionsMenuKey" />
+ <option name="compatibility:include-filter" value="CtsAppTestCases android.app.cts.ActivityKeyboardShortcutsTest#testRequestShowKeyboardShortcuts" />
+
+ <!-- b/161837932: Fix MediaPlayerTests that use "too small" resolution -->
+ <option name="compatibility:include-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testOnSubtitleDataListener" />
+ <option name="compatibility:include-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testChangeSubtitleTrack" />
+ <option name="compatibility:include-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testDeselectTrackForSubtitleTracks" />
+ <option name="compatibility:include-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testGetTrackInfoForVideoWithSubtitleTracks" />
+
+ <!-- b/152359655: ResumeOnReboot can't work on GSI -->
+ <option name="compatibility:include-filter" value="CtsAppSecurityHostTestCases android.appsecurity.cts.ResumeOnRebootHostTest" />
+
+ <!-- b/73727333: CtsSystemUiTestCases failure flaky -->
+ <option name="compatibility:include-filter" value="CtsSystemUiTestCases android.systemui.cts.LightBarTests#testLightNavigationBar" />
+
+ <!-- b/80388296: CtsDevicePolicyManagerTestCases failure flaky -->
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testDisallowAutofill_allowed" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testPackageInstallUserRestrictions" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testPermissionAppUpdate" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testPermissionGrant" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testPermissionMixedPolicies" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testPermissionPolicy" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testSuspendPackage" />
+
+ <!-- b/110260628: A confirmed GSI incompatibility (waiver) -->
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedDeviceOwnerTest#testKeyManagement" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedProfileOwnerTest#testKeyManagement" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testKeyManagement" />
+
+ <!-- b/110405497: Flaky tests (waiver) -->
+ <option name="compatibility:include-filter" value="CtsKeystoreTestCases android.keystore.cts.KeyAttestationTest#testDeviceIdAttestation" />
+
+ <!-- b/141113818: Allows unlock for CTS-on-GSI -->
+ <option name="compatibility:include-filter" value="CtsKeystoreTestCases android.keystore.cts.KeyAttestationTest#testEcAttestation_DeviceLocked" />
+ <option name="compatibility:include-filter" value="CtsKeystoreTestCases android.keystore.cts.KeyAttestationTest#testRsaAttestation_DeviceLocked" />
+
+ <!-- b/110385515: Flaky due to a particular SIM card requirement (excluded) -->
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.ConnectivityManagerTest#testOpenConnection" />
+ <option name="compatibility:include-filter" value="CtsWifiTestCases android.net.wifi.rtt.cts.WifiRttTest#testRangingToTestAp" />
+
+ <!-- b/111101428: CtsOsTestCases irrelevant test cases -->
+ <option name="compatibility:include-filter" value="CtsOsTestCases android.os.cts.BuildTest#testIsSecureUserBuild" />
+ <option name="compatibility:include-filter" value="CtsOsTestCases android.os.cts.BuildVersionTest#testBuildFingerprint" />
+
+ <!-- b/111967702: CtsSecurityTestCases irrelevant test cases -->
+ <option name="compatibility:include-filter" value="CtsSecurityTestCases android.security.cts.BannedFilesTest#testNoSu" />
+ <option name="compatibility:include-filter" value="CtsSecurityTestCases android.security.cts.BannedFilesTest#testNoSuInPath" />
+
+ <!-- b/157286547 CtsIncidentHostTestCases ErrorsTest failure -->
+ <option name="compatibility:include-filter" value="CtsIncidentHostTestCases com.android.server.cts.ErrorsTest#testNativeCrash" />
+
+ <!-- b/111167329: CtsCameraTestCases failure -->
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.SurfaceViewPreviewTest#testSurfaceSet"/>
+
+ <!-- b/135588722: CtsUsesLibraryHostTestCases (10_r1 waiver) -->
+ <option name="compatibility:include-filter" value="CtsUsesLibraryHostTestCases android.classloaders.cts.UsesLibraryHostTest#testMissingLibrary_full"/>
+ <option name="compatibility:include-filter" value="CtsUsesLibraryHostTestCases android.classloaders.cts.UsesLibraryHostTest#testUsesLibrary_full"/>
+ <option name="compatibility:include-filter" value="CtsCompilationTestCases android.compilation.cts.AdbRootDependentCompilationTest"/>
+
+ <!-- b/145371681: CtsContentSuggestionsTestCases and CtsAppPredictionServiceTestCases (10_r2 waiver) -->
+ <option name="compatibility:include-filter" value="CtsAppPredictionServiceTestCases" />
+ <option name="compatibility:include-filter" value="CtsContentSuggestionsTestCases" />
+
+ <!-- b/155107044: CtsNetTestCases -->
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testInterfaceCountersUdp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm64Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testInterfaceCountersUdp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacMd5Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha512Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacMd5Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha512Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha1Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha1Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha1Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha1Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm128Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm128Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm96Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha1Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm96Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testCryptTcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm128Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testCryptUdp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAuthUdp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testCryptUdp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAuthUdp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testCryptTcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha1Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testCryptTcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAuthUdp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testIkeOverUdpEncapSocket"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm128Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm128Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha256Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha256Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacMd5Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm96Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testInterfaceCountersUdp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha512Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha512Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha256Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha384Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha384Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha256Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm64Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm64Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha512Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm96Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha384Tcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm96Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha384Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha256Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacMd5Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAuthTcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacMd5Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAuthTcp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha384Tcp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm128Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testCryptUdp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAuthTcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacMd5Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm64Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha256Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm64Udp4"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha384Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm64Udp6"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesGcm96Udp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testAesCbcHmacSha512Tcp4UdpEncap"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.TrafficStatsTest#testTrafficStatsForLocalhost"/>
+ <option name="compatibility:include-filter" value="CtsNetTestCases android.net.cts.TrafficStatsTest#testValidTotalStats"/>
+
+ <!-- b/159295445, b/159294948: CtsDevicePolicyManagerTestCases -->
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedDeviceOwnerTest#testDelegatedCertInstallerDeviceIdAttestation" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testDelegatedCertInstallerDeviceIdAttestation" />
+ <option name="compatibility:include-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testDeviceIdAttestationForProfileOwner" />
+
+ <!-- b/153032202: CtsSystemUiTestCases (10_r3 waiver) -->
+ <option name="compatibility:include-filter" value="CtsSystemUiTestCases android.systemui.cts.WindowInsetsBehaviorTests#swipeOutsideLimit_systemUiVisible_allEventsCanceled"/>
+
+ <!-- b/173662175: CtsStatsdHostTestCases due to insufficient processes running -->
+ <option name="compatibility:include-filter" value="CtsStatsdHostTestCases android.cts.statsd.validation.ProcStatsValidationTests#testProcessStatePssValue"/>
+
+ <!-- b/173560279: CtsAndroidAppTestCases -->
+ <option name="compatibility:include-filter" value="CtsAndroidAppTestCases android.app.cts.ApplyOverrideConfigurationTest#testOverriddenConfigurationIsPassedIntoCallback" />
+
+ <!-- b/173560279: CtsWidgetTestCases -->
+ <option name="compatibility:include-filter" value="CtsWidgetTestCases android.widget.cts.PopupWindowTest#testClipToScreenClipsToInsets" />
+
+ <!-- b/173560279: CtsWindowManagerDeviceTestCases -->
+ <option name="compatibility:include-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.AppConfigurationTests#testAppOrientationRequestConfigChanges" />
+ <option name="compatibility:include-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.KeyguardTests#testNoTransientConfigurationWhenShowWhenLockedRequestsOrientation" />
+
+ <!-- b/173560279: CtsDpiTestCases -->
+ <option name="compatibility:include-filter" value="CtsDpiTestCases android.dpi.cts.ConfigurationScreenLayoutTest#testScreenLayout" />
+
+ <!-- b/173560279, b/176457563#comment6: CtsCameraTestCases -->
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.cts.CameraTest#testPreviewCallbackWithPicture" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.CaptureRequestTest#testColorCorrectionControl" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.CaptureRequestTest#testFocusDistanceControl" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.CaptureRequestTest#testAwbModeAndLock" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.CaptureRequestTest#testDigitalZoomPreviewCombinations" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.CaptureRequestTest#testFlashControl" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.CaptureRequestTest#testEffectModes" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.CaptureRequestTest#testFaceDetection" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testTextureImageWriterReaderOperation" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testTextureViewPreviewWithImageReader" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testTextureViewPreview" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testSharedSurfaceSwitch"/>
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testDualTextureViewAndImageReaderPreview" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testDualCameraPreview"/>
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testSharedSurfaces" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testSharedSurfaceBasic" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testSharedSurfaceLimit" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testDualTextureViewPreview" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.MultiViewTest#testSharedSurfaceImageReaderSwitch" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.StillCaptureTest#testFullRawZSLCapture" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.StillCaptureTest#testFullRawCapture" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.StillCaptureTest#testJpegExif" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.StillCaptureTest#testTakePicture" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.StillCaptureTest#testAfRegions" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.RobustnessTest#testVerifyReprocessMandatoryOutputCombinationTables" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.SurfaceViewPreviewTest#testPreparePerformance" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.BurstCaptureTest#testYuvBurst" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceSimplePreview" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceLogicalPhysicalStreaming" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDevicePreviewWithSessionParameters" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceSessionOpenAndClose" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceLogicalPhysicalSettings" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceSharedOutputUpdate" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceSimplePreview" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceLogicalPhysicalStreaming" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDevicePreviewWithSessionParameters" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceSessionOpenAndClose" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceLogicalPhysicalSettings" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeCameraDeviceTest#testCameraDeviceSharedOutputUpdate" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeStillCaptureTest#testStillCapture" />
+ <option name="compatibility:include-filter" value="CtsCameraTestCases android.hardware.camera2.cts.NativeStillCaptureTest#testStillCapture" />
+
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index a1f5efd0b62..8b0cc081836 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -121,6 +121,7 @@
<option name="compatibility:exclude-filter" value="CtsHdmiCecHostTestCases android.hdmicec.cts.tv.HdmiCecRemoteControlPassThroughTest" />
<option name="compatibility:exclude-filter" value="CtsHdmiCecHostTestCases android.hdmicec.cts.tv.HdmiCecRoutingControlTest" />
<option name="compatibility:exclude-filter" value="CtsHdmiCecHostTestCases android.hdmicec.cts.tv.HdmiCecTvOneTouchPlayTest" />
+ <option name="compatibility:exclude-filter" value="CtsHdmiCecHostTestCases android.hdmicec.cts.common.HdmiCecInvalidMessagesTest#cect_IgnoreBroadcastedFromSameSource" />
<!-- b/192113622, b/203031609, b/204402327, b/204615046, b/204860049 Remove tests for S "optional" algorithms for GRF devices -->
<option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.IpSecAlgorithmImplTest#testChaCha20Poly1305" />
@@ -154,12 +155,16 @@
<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" />
+ <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_30ms" />
+ <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_100ms" />
+ <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setFrameTimeline_preferredIndex" />
+ <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setFrameTimeline_notPreferredIndex" />
+
+ <!-- b/298915013 Remove CtsKeystoreTestCases android.keystore.cts.KeyAttestationTest from cts-on-gsi -->
+ <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.AttestKeyTest#testEcAttestKey_StrongBox" />
+ <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.AttestKeyTest#testRsaAttestKey_StrongBox" />
+ <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.KeyAttestationTest#testAttestationKmVersionMatchesFeatureVersionStrongBox" />
+ <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.DeviceOwnerKeyManagementTest#testAllVariationsOfDeviceIdAttestationUsingStrongBox" />
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-on-r.xml b/tools/cts-tradefed/res/config/cts-on-gsi-on-r.xml
index ce26ecd8f3e..64143b07ac9 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-on-r.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-on-r.xml
@@ -66,4 +66,15 @@
<!-- CtsMediaMiscTestCases: b/261813452 -->
<option name="compatibility:exclude-filter" value="CtsMediaMiscTestCases android.media.misc.cts.HeifWriterTest" />
+ <!-- CtsVideoCodecTestCases: b/276746681 -->
+ <option name="compatibility:exclude-filter" value="CtsVideoCodecTestCases android.videocodec.cts.VideoEncoderMinMaxTest" />
+
+ <!-- CtsVideoTestCases: b/284192974 -->
+ <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest" />
+
+ <!-- CtsMediaDecoderTestCases: b/284409693 -->
+ <option name="compatibility:exclude-filter" value="CtsMediaDecoderTestCases android.media.decoder.cts.VideoDecoderPerfTest" />
+
+ <!-- CtsSecurityHostTestCases: b/256140333 -->
+ <option name="compatibility:exclude-filter" value="CtsSecurityHostTestCases android.security.cts.FileSystemPermissionTest" />
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-on-s.xml b/tools/cts-tradefed/res/config/cts-on-gsi-on-s.xml
index c7d3d8b3b11..df3b5483846 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-on-s.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-on-s.xml
@@ -63,4 +63,13 @@
<!-- CtsNativeMediaAAudioTestCases: b/261824947 -->
<option name="compatibility:exclude-filter" value="CtsNativeMediaAAudioTestCases android.nativemedia.aaudio.AAudioTests" />
+ <!-- CtsVideoCodecTestCases: b/279308238 -->
+ <option name="compatibility:exclude-filter" value="CtsVideoCodecTestCases android.videocodec.cts.VideoEncoderMinMaxTest" />
+
+ <!-- CtsVideoTestCases: b/284192974 -->
+ <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest" />
+
+ <!-- CtsMediaDecoderTestCases: b/284409693 -->
+ <option name="compatibility:exclude-filter" value="CtsMediaDecoderTestCases android.media.decoder.cts.VideoDecoderPerfTest" />
+
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-validation-exclude.xml b/tools/cts-tradefed/res/config/cts-validation-exclude.xml
index edc29af288d..1da87f4c7f4 100644
--- a/tools/cts-tradefed/res/config/cts-validation-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-validation-exclude.xml
@@ -510,4 +510,12 @@
<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]" />
+ <!-- b/302404278 -->
+ <option name="compatibility:exclude-filter" value="CtsDomainVerificationDeviceMultiUserTestCases com.android.cts.packagemanager.verify.domain.device.multiuser.DomainVerificationWorkProfileCrossProfileIntentTests#inPersonal_unverified" />
+ <option name="compatibility:exclude-filter" value="CtsDomainVerificationDeviceMultiUserTestCases com.android.cts.packagemanager.verify.domain.device.multiuser.DomainVerificationWorkProfileCrossProfileIntentTests#inPersonal_verifiedInOtherProfile" />
+ <option name="compatibility:exclude-filter" value="CtsDomainVerificationDeviceMultiUserTestCases CtsDomainVerificationDeviceMultiUserTestCases com.android.cts.packagemanager.verify.domain.device.multiuser.DomainVerificationWorkProfileCrossProfileIntentTests#inPersonal_verifiedInBothProfiles" />
+ <option name="compatibility:exclude-filter" value="CtsDomainVerificationDeviceMultiUserTestCases com.android.cts.packagemanager.verify.domain.device.multiuser.DomainVerificationWorkProfileAllowParentLinkingTests#inPersonal_verifiedInOtherProfile" />
+ <option name="compatibility:exclude-filter" value="CtsDomainVerificationDeviceMultiUserTestCases com.android.cts.packagemanager.verify.domain.device.multiuser.DomainVerificationWorkProfileAllowParentLinkingTests#inPersonal_verifiedInBothProfiles" />
+ <option name="compatibility:exclude-filter" value="CtsDomainVerificationDeviceMultiUserTestCases com.android.cts.packagemanager.verify.domain.device.multiuser.DomainVerificationWorkProfileAllowParentLinkingTests#inPersonal_verifiedInCurrentProfile" />
+
</configuration>
diff --git a/tools/cts-tradefed/res/config/grf-no-telephony.xml b/tools/cts-tradefed/res/config/grf-no-telephony.xml
new file mode 100644
index 00000000000..53d8c92bcfb
--- /dev/null
+++ b/tools/cts-tradefed/res/config/grf-no-telephony.xml
@@ -0,0 +1,33 @@
+<?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="Runs a subset of CTS tests for aosp_$arch">
+ <!-- Enforce collecting vendor build information -->
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsDeviceInfoCollector" />
+
+ <!-- Common CTS config -->
+ <include name="cts" />
+
+ <!-- CTS-on-AOSP is not expected to run parameterized modules -->
+ <option name="compatibility:enable-parameterized-modules" value="false" />
+ <option name="compatibility:primary-abi-only" value="true" />
+
+ <!-- Include most tests excluded by cts-on-aosp (except telephony related tests -->
+ <include name="cts-on-aosp-include" />
+
+ <!-- Overwrite the "cts" plan configured in cts.xml -->
+ <option name="plan" value="grf-no-telephony" />
+
+</configuration>
diff --git a/tools/cts-tradefed/res/config/multi-config.xml b/tools/cts-tradefed/res/config/multi-config.xml
new file mode 100644
index 00000000000..380bd1c4d59
--- /dev/null
+++ b/tools/cts-tradefed/res/config/multi-config.xml
@@ -0,0 +1,23 @@
+<?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 contains multiple template config to include">
+
+ <template-include name="config0" default="empty"/>
+ <template-include name="config1" default="empty"/>
+ <template-include name="config2" default="empty"/>
+ <template-include name="config3" default="empty"/>
+
+</configuration>