summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/CameraITS/utils/zoom_capture_utils.py7
-rw-r--r--apps/CtsVerifier/AndroidManifest.xml2
-rw-r--r--apps/CtsVerifier/res/values/strings.xml2
-rw-r--r--apps/CtsVerifier/res/xml/offhost_aid_list.xml4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java5
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java99
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java2
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java2
-rw-r--r--common/device-side/bedstead/activitycontext/Android.bp1
-rw-r--r--common/device-side/bedstead/deviceadminapp/Android.bp1
-rw-r--r--common/device-side/bedstead/eventlib/Android.bp1
-rw-r--r--common/device-side/bedstead/harrier/Android.bp1
-rw-r--r--common/device-side/bedstead/nene/Android.bp1
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/ActivityReference.java12
-rw-r--r--common/device-side/bedstead/queryable/Android.bp1
-rw-r--r--common/device-side/bedstead/remoteaccountauthenticator/Android.bp1
-rw-r--r--common/device-side/bedstead/remotedpc/Android.bp1
-rw-r--r--common/device-side/bedstead/testapp/Android.bp1
-rw-r--r--common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java58
-rw-r--r--common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS3
-rw-r--r--common/device-side/interactive/src/main/AndroidManifest.xml4
-rw-r--r--common/device-side/interactive/src/main/java/com/android/interactive/ScreenshotUtil.java5
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/FrameworkSpecificTest.java35
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/ModuleSpecificTest.java34
-rw-r--r--common/device-side/util-axt/tests/Android.bp1
-rw-r--r--hostsidetests/adb/OWNERS2
-rw-r--r--hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java1
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java7
-rw-r--r--hostsidetests/art/Android.bp1
-rw-r--r--hostsidetests/classloaders/Android.bp17
-rw-r--r--hostsidetests/devicepolicy/Android.bp1
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java18
-rw-r--r--hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp1
-rw-r--r--hostsidetests/dexmetadata/Android.bp17
-rw-r--r--hostsidetests/edi/src/android/edi/cts/NativeDeviceInfo.java35
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java1
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java9
-rw-r--r--hostsidetests/incrementalinstall/Android.bp1
-rw-r--r--hostsidetests/jdwpsecurity/Android.bp1
-rw-r--r--hostsidetests/jdwpsecurity/OWNERS4
-rw-r--r--hostsidetests/jdwptunnel/Android.bp1
-rw-r--r--hostsidetests/jdwptunnel/OWNERS4
-rw-r--r--hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java30
-rw-r--r--hostsidetests/jvmti/Android.bp17
-rw-r--r--hostsidetests/jvmti/OWNERS (renamed from hostsidetests/jvmti/run-tests/OWNERS)2
-rw-r--r--hostsidetests/jvmti/allocation-tracking/OWNERS2
-rw-r--r--hostsidetests/jvmti/attaching/OWNERS2
-rw-r--r--hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java2
-rw-r--r--hostsidetests/jvmti/redefining/OWNERS2
-rw-r--r--hostsidetests/jvmti/tagging/OWNERS2
-rw-r--r--hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml3
-rw-r--r--hostsidetests/mediapc/videoencodingquality/app/src/android/videoencoding/app/VideoTranscoderTest.java6
-rw-r--r--hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java218
-rw-r--r--hostsidetests/rollback/AndroidTest.xml4
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java5
-rw-r--r--hostsidetests/security/Android.bp5
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxHostTest.java27
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java21
-rw-r--r--hostsidetests/videoencodingminimum/app/AndroidManifest.xml3
-rw-r--r--hostsidetests/videoencodingminimum/app/src/android/videoencodingmin/app/VideoTranscoderTest.java7
-rw-r--r--hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java48
-rw-r--r--libs/input/src/com/android/cts/input/VirtualInputDevice.java5
-rw-r--r--libs/install/src/com/android/cts/install/lib/Install.java1
-rw-r--r--tests/JobScheduler/OWNERS5
-rw-r--r--tests/app/src/android/app/cts/DownloadManagerTest.java10
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java9
-rw-r--r--tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java16
-rw-r--r--tests/devicepolicy/Android.bp1
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java12
-rw-r--r--tests/devicepolicy/telephony/Android.bp1
-rw-r--r--tests/framework/base/grammaticalinflection/Android.bp3
-rw-r--r--tests/framework/base/locale/Android.bp1
-rw-r--r--tests/framework/base/localeconfig/Android.bp1
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/extensions/util/TestValueCountConsumer.java20
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/layout/ExtensionWindowLayoutComponentTest.java16
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java30
-rw-r--r--tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java14
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/display/MultiDisplayImeTests.java4
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/window/ConfigChangeTests.java12
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerMultiDisplayTest.java1
-rw-r--r--tests/jdwp/Android.bp1
-rw-r--r--tests/jdwp/OWNERS4
-rw-r--r--tests/libcore/Android.bp17
-rw-r--r--tests/libcore/ojluni/Android.bp93
-rw-r--r--tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java2
-rw-r--r--tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationValuesTest.java2
-rw-r--r--tests/location/location_gnss/src/android/location/cts/gnss/GnssTtffTests.java2
-rw-r--r--tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerAlignedUtils.java2
-rw-r--r--tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerUnalignedUtils.java2
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java3
-rw-r--r--tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java8
-rw-r--r--tests/media/src/android/mediav2/cts/Av1FilmGrainValidationTest.java3
-rw-r--r--tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java53
-rw-r--r--tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java51
-rw-r--r--tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java6
-rw-r--r--tests/mediapc/Android.bp3
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java161
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java5
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl217
-rw-r--r--tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementsTest.java25
-rw-r--r--tests/mediapc/jni/Android.bp40
-rw-r--r--tests/mediapc/jni/VulkanDeviceInfo.cpp46
-rw-r--r--tests/mediapc/requirements/Android.bp7
-rw-r--r--tests/mediapc/requirements/mpc.pb.go13
-rw-r--r--tests/mediapc/requirements/mpc.proto6
-rw-r--r--tests/mediapc/requirements/requirements.go44
-rw-r--r--tests/mediapc/requirements/requirements.pb.go504
-rw-r--r--tests/mediapc/requirements/requirements.proto43
-rw-r--r--tests/mediapc/requirements/requirements.txtpb3470
-rw-r--r--tests/mediapc/requirements/requirements_test.go59
-rw-r--r--tests/mediapc/requirements/requirementsdata_test.go69
-rw-r--r--tests/mediapc/requirements/templatefns.go162
-rw-r--r--tests/mediapc/requirements/templatefns_test.go178
-rw-r--r--tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java28
-rw-r--r--tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java13
-rw-r--r--tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java7
-rw-r--r--tests/mediapc/src/android/mediapc/cts/VulkanTest.java139
-rw-r--r--tests/rollback/src/com/android/cts/rollback/RollbackManagerTest.java24
-rw-r--r--tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml2
-rw-r--r--tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java8
-rw-r--r--tests/surfacecontrol/AndroidManifest.xml1
-rw-r--r--tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java161
-rw-r--r--tests/tests/app/Android.bp1
-rw-r--r--tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt1
-rw-r--r--tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt6
-rw-r--r--tests/tests/bluetooth/AndroidTest.xml6
-rw-r--r--tests/tests/bluetooth/OWNERS5
-rw-r--r--tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java14
-rw-r--r--tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java488
-rw-r--r--tests/tests/display/src/android/display/cts/VirtualDisplayTest.java2
-rw-r--r--tests/tests/graphics/jni/ImageReaderTestHelpers.cpp6
-rw-r--r--tests/tests/graphics/jni/ImageReaderTestHelpers.h2
-rw-r--r--tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml8
-rw-r--r--tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml8
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java4
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/PaintTest.java14
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java4
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java4
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java4
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java2
-rw-r--r--tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java2
-rw-r--r--tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java2
-rw-r--r--tests/tests/hardware/TEST_MAPPING4
-rw-r--r--tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt27
-rw-r--r--tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt9
-rw-r--r--tests/tests/jni/Android.bp3
-rw-r--r--tests/tests/jvmti/Android.bp17
-rw-r--r--tests/tests/jvmti/OWNERS2
-rw-r--r--tests/tests/jvmti/attaching/OWNERS2
-rw-r--r--tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml2
-rw-r--r--tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml2
-rw-r--r--tests/tests/keystore/src/android/keystore/cts/CipherTest.java27
-rw-r--r--tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java137
-rw-r--r--tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java18
-rw-r--r--tests/tests/libcorefileio/AndroidManifest.xml11
-rw-r--r--tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java224
-rw-r--r--tests/tests/libcorefileio/src/android/cts/LockHoldingService.java165
-rw-r--r--tests/tests/libnativehelper/Android.bp1
-rw-r--r--tests/tests/libthermalndk/jni/NativeThermalTest.cpp22
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java15
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java23
-rw-r--r--tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java20
-rw-r--r--tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java2
-rw-r--r--tests/tests/media/common/src/android/media/cts/MediaProjectionActivity.java82
-rw-r--r--tests/tests/media/common/src/android/media/cts/TestUtils.java136
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java45
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java2
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecoderLowLatencyTest.java276
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java217
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java7
-rw-r--r--tests/tests/media/extractor/AndroidTest.xml2
-rw-r--r--tests/tests/media/extractor/DynamicConfig.xml2
-rwxr-xr-xtests/tests/media/extractor/copy_media.sh2
-rw-r--r--tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java16
-rw-r--r--tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java2
-rw-r--r--tests/tests/media/misc/AndroidTest.xml2
-rw-r--r--tests/tests/media/misc/DynamicConfig.xml2
-rwxr-xr-xtests/tests/media/misc/copy_media.sh2
-rw-r--r--tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java12
-rw-r--r--tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java2
-rw-r--r--tests/tests/mediacujtest/common/Android.bp2
-rw-r--r--tests/tests/mediacujtest/common/res/layout/activity_main.xml10
-rw-r--r--tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java8
-rw-r--r--tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/LockPlaybackControllerTestPlayerListener.java131
-rw-r--r--tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java8
-rw-r--r--tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/PlayerListener.java3
-rw-r--r--tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/SplitScreenTestPlayerListener.java3
-rw-r--r--tests/tests/mediacujtest/largetest/AndroidManifest.xml3
-rw-r--r--tests/tests/mediacujtest/smalltest/AndroidManifest.xml3
-rw-r--r--tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java11
-rw-r--r--tests/tests/mediaediting/AndroidManifest.xml2
-rw-r--r--tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java4
-rw-r--r--tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java6
-rw-r--r--tests/tests/networksecurityconfig/manifest.xml2
-rw-r--r--tests/tests/notification/OWNERS5
-rw-r--r--tests/tests/os/src/android/os/cts/FileObserverTest.java10
-rw-r--r--tests/tests/packagewatchdog/OWNERS3
-rw-r--r--tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java2
-rw-r--r--tests/tests/security/res/raw/blocklist_diginotar.pem32
-rw-r--r--tests/tests/security/res/raw/blocklist_test_chain.pem (renamed from tests/tests/security/res/raw/blacklist_test_chain.pem)0
-rw-r--r--tests/tests/security/res/raw/blocklist_test_valid_ca.pem (renamed from tests/tests/security/res/raw/blacklist_test_valid_ca.pem)0
-rw-r--r--tests/tests/security/res/raw/blocklist_test_valid_chain.pem (renamed from tests/tests/security/res/raw/blacklist_test_valid_chain.pem)0
-rw-r--r--tests/tests/security/res/raw/test_blocklist_ca.pem (renamed from tests/tests/security/res/raw/test_blacklist_ca.pem)0
-rw-r--r--tests/tests/security/src/android/security/cts/CertBlocklistTest.java (renamed from tests/tests/security/src/android/security/cts/CertBlacklistTest.java)72
-rw-r--r--tests/tests/settings/src/android/settings/cts/WifiSliceTest.java14
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java6
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java2
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java16
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java2
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java6
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/NonUiInCallServiceTest.java2
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java2
-rw-r--r--tests/tests/telecom/src/android/telecom/cts/TransactionalApisTest.java2
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java9
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java19
-rw-r--r--tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java2
-rw-r--r--tests/tests/telephony/current/src/android/telephony/ims/cts/CallDomainSelectionTestOnMockModem.java208
-rw-r--r--tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java9
-rw-r--r--tests/tests/tv/src/android/media/tv/cts/TvViewTest.java4
-rw-r--r--tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java2
-rw-r--r--tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java3
-rw-r--r--tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java210
-rw-r--r--tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java49
-rw-r--r--tests/tests/vcn/src/android/net/vcn/cts/VcnSystemRequirementsTest.java22
-rw-r--r--tests/tests/view/src/android/view/cts/OWNERS2
-rw-r--r--tests/tests/view/src/android/view/cts/TextureViewTest.java16
-rw-r--r--tests/tests/view/src/android/view/cts/ViewTest.java5
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java120
-rw-r--r--tools/cts-api-coverage/Android.bp20
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java31
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java12
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java12
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apicommon/ApiPackage.java1
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apicommon/CoverageComparator.java (renamed from tools/cts-api-coverage/src/com/android/cts/apicoverage/CoverageComparator.java)6
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java1
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java1
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/AnnotationAnalyzer.java57
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/ApiMap.java23
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/CallGraphManager.java210
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/ClassAnalyzer.java145
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/HtmlWriter.java72
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/MethodAnalyzer.java139
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/TarJan.java101
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/apimap/XmlWriter.java278
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/ctsprofiles/AnnotationManagement.java81
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java243
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/ctsprofiles/MethodProfile.java187
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ModuleProfile.java61
-rw-r--r--tools/cts-api-coverage/src/com/android/cts/ctsprofiles/Utils.java77
-rw-r--r--tools/cts-tradefed/res/config/cts-exclude.xml7
-rw-r--r--tools/cts-tradefed/res/config/cts-known-failures.xml11
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml3
-rw-r--r--tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java1
-rw-r--r--tools/release-parser/tests/Android.bp1
-rw-r--r--tools/vm-tests-tf/Android.bp1
255 files changed, 8010 insertions, 3606 deletions
diff --git a/apps/CameraITS/utils/zoom_capture_utils.py b/apps/CameraITS/utils/zoom_capture_utils.py
index 6c966e96f69..9ba507ac182 100644
--- a/apps/CameraITS/utils/zoom_capture_utils.py
+++ b/apps/CameraITS/utils/zoom_capture_utils.py
@@ -38,6 +38,7 @@ _RADIUS_RTOL_MIN_FD = 0.15
OFFSET_RTOL = 0.15
RADIUS_RTOL = 0.10
ZOOM_MAX_THRESH = 10.0
+ZOOM_RTOL = 0.01 # variation of zoom ratio between capture result vs req
def get_test_tols_and_cap_size(cam, props, chart_distance, debug):
@@ -234,8 +235,10 @@ def verify_zoom_results(test_data, size, z_max, z_min):
zoom_max_thresh = z_max_ratio
test_data_max_z = (test_data[max(test_data.keys())]['z'] /
test_data[min(test_data.keys())]['z'])
- logging.debug('test zoom ratio max: %.2f', test_data_max_z)
- if test_data_max_z < zoom_max_thresh:
+ logging.debug('test zoom ratio max: %.2f vs threshold %.2f',
+ test_data_max_z, zoom_max_thresh)
+
+ if not math.isclose(test_data_max_z, zoom_max_thresh, rel_tol=ZOOM_RTOL):
test_failed = True
e_msg = (f'Max zoom ratio tested: {test_data_max_z:.4f}, '
f'range advertised min: {z_min}, max: {z_max} '
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index f2f1d5bf364..10f40eac2b7 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -3573,6 +3573,8 @@
android:value="multi_display_mode" />
<meta-data android:name="ApiTest"
android:value="android.widget.Toast#makeText" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.watch" />
</activity>
<activity android:name=".notifications.BubblesVerifierActivity"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 0caea4ecee3..2f0bd55f599 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1208,6 +1208,8 @@
<string name="multinetwork_connectivity_turn_wifi_off">Please turn Wi-Fi off.</string>
<string name="multinetwork_connectivity_turn_wifi_positive">OK</string>
<string name="multinetwork_connectivity_turn_wifi_negative">Cancel</string>
+ <string name="multinetwork_connectivity_connect_to_target_ap_positive">OK</string>
+ <string name="multinetwork_connectivity_connect_to_target_ap">Connect to configured SSID: %s</string>
<!-- Strings for NfcTestActivity -->
<string name="nfc_test">NFC Test</string>
<string name="nfc_test_info">The Peer-to-Peer Data Exchange tests require two devices with
diff --git a/apps/CtsVerifier/res/xml/offhost_aid_list.xml b/apps/CtsVerifier/res/xml/offhost_aid_list.xml
index 524e54d7a01..8329955d63d 100644
--- a/apps/CtsVerifier/res/xml/offhost_aid_list.xml
+++ b/apps/CtsVerifier/res/xml/offhost_aid_list.xml
@@ -1,9 +1,7 @@
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/offhostService">
<aid-group>
- <!-- OBTH card manager AID -->
<aid-filter android:name="A000000151000000"/>
- <!-- NXP card manager AID -->
- <aid-filter android:name="A000000003000000"/>
+ <aid-filter android:name="A000000444000000"/>
</aid-group>
</offhost-apdu-service>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
index baa19519c26..f603baa858f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ReportExporter.java
@@ -138,15 +138,16 @@ public class ReportExporter extends AsyncTask<Void, Void, String> {
verifierReportsDir.mkdirs();
String suiteName = Version.getMetadata(mContext, SUITE_NAME_METADATA_KEY);
+ String reportName = getReportName(suiteName);
// create a temporary directory for this particular report
- File tempDir = new File(verifierReportsDir, getReportName(suiteName));
+ File tempDir = new File(verifierReportsDir, reportName);
tempDir.mkdirs();
// Pull in any ReportLogs
copyReportFiles(tempDir);
// create a File object for a report ZIP file
- File reportZipFile = new File(verifierReportsDir, getReportName(suiteName) + ZIP_EXTENSION);
+ File reportZipFile = new File(verifierReportsDir, reportName + ZIP_EXTENSION);
try {
// Serialize the report
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java
index f1deb8d527b..44136cb59f4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java
@@ -20,14 +20,10 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
- .COMPLETED;
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
- .NOT_STARTED;
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
- .STARTED;
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
- .WAITING_FOR_USER_INPUT;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.COMPLETED;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.NOT_STARTED;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.STARTED;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.WAITING_FOR_USER_INPUT;
import android.app.ActivityManager;
import android.app.AlertDialog;
@@ -44,7 +40,6 @@ import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.wifi.SupplicantState;
-import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkSpecifier;
@@ -70,7 +65,7 @@ import java.util.Collections;
import java.util.List;
/**
- * A CTS verifier to ensure that when an app calls WifiManager#enableNetwork,
+ * A CTS verifier to ensure that when device connect to a new Wi-Fi network,
* - When the wifi network does not have internet connectivity, the device should
* not disable other forms or connectivity, for example cellular.
* - When the wifi network that the phone connects to loses connectivity, then
@@ -212,7 +207,6 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
protected void onDestroy() {
super.onDestroy();
destroyBroadcastReceivers();
- restoreOriginalWifiState();
}
private void recordCurrentWifiState() {
@@ -245,12 +239,6 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
return result;
}
- private void restoreOriginalWifiState() {
- if (mRecordedWifiConfiguration >= 0) {
- mWifiManager.enableNetwork(mRecordedWifiConfiguration, true);
- }
- }
-
private boolean requestSystemAlertWindowPerimissionIfRequired() {
if (isLowRamDevice()) {
// For low ram devices, we won't run tests that depend on this permission.
@@ -298,6 +286,23 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
alertDialog.show();
}
+ private void requestUserConnectToApAsync(ConnectApCallback callback) {
+ if (isConnectedToExpectedWifiNetwork()) {
+ callback.onComplete(/* isSuccess = */ true);
+ return;
+ }
+
+ AlertDialog alertDialog = new AlertDialog.Builder(this)
+ .setMessage(getString(R.string.multinetwork_connectivity_connect_to_target_ap,
+ mAccessPointSsid))
+ .setPositiveButton(R.string.multinetwork_connectivity_turn_wifi_positive,
+ (a, b) -> requestUserConnectToApAsync(callback))
+ .setNegativeButton(R.string.multinetwork_connectivity_turn_wifi_negative,
+ (a, b) -> callback.onComplete(/* isSuccess = */ false))
+ .create();
+ alertDialog.show();
+ }
+
private void toggleWifiAsync(SetWifiCallback callback) {
// Turn off WiFi.
requestUserEnableWifiAsync(false, (isSuccess) -> {
@@ -489,31 +494,6 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
}
}
- private WifiConfiguration buildWifiConfiguration() {
- WifiConfiguration wifiConfiguration = new WifiConfiguration();
- wifiConfiguration.SSID = "\"" + mAccessPointSsid + "\"";
- wifiConfiguration.preSharedKey = "\"" + mPskValue + "\"";
- wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
- wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
- wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
- wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
- wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
- wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
- wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
- return wifiConfiguration;
- }
-
- private int getOrAddLegacyNetwork() {
- List<WifiConfiguration> availableConfigurations = mWifiManager.getConfiguredNetworks();
- for (WifiConfiguration configuration : availableConfigurations) {
- if (mAccessPointSsid.equals(configuration.SSID)) {
- return configuration.networkId;
- }
- }
- int newNetwork = mWifiManager.addNetwork(buildWifiConfiguration());
- return newNetwork;
- }
-
private boolean isConnectedToExpectedWifiNetwork() {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
DhcpInfo dhcpInfo = mWifiManager.getDhcpInfo();
@@ -601,15 +581,7 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
}
}
- private void legacyConnectToWifiNetwork(boolean requireInternet) {
- // If device is not connected to the expected WifiNetwork, connect to the wifi Network.
- // Timeout with failure if it can't connect.
- if (!isConnectedToExpectedWifiNetwork()) {
- int network = getOrAddLegacyNetwork();
- WifiManager wifiManager = (WifiManager) getApplicationContext()
- .getSystemService(Context.WIFI_SERVICE);
- wifiManager.enableNetwork(network, true);
- }
+ private void requestNetwork(boolean requireInternet) {
startTimerDisplay(WIFI_NETWORK_CONNECT_TIMEOUT_MS / 1000);
NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI);
@@ -750,6 +722,9 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
/** Called when cellular network is connected. */
void onCellularNetworkConnected(Network network) {
+ if (mValidatorState != NOT_STARTED) {
+ return;
+ }
onContinuePreWifiConnect();
}
@@ -855,7 +830,14 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
void connectToWifi() {
mTestCallback.testProgress(R.string.multinetwork_connectivity_test_connect_wifi);
- mConnectivityState.legacyConnectToWifiNetwork(false);
+ requestUserConnectToApAsync((isSuccess) -> {
+ if (isSuccess) {
+ // Request network
+ mConnectivityState.requestNetwork(false);
+ } else {
+ endTest(false, R.string.multinetwork_status_wifi_connect_wrong_ap);
+ }
+ });
}
}
@@ -898,7 +880,14 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
void connectToWifi() {
mTestCallback.testProgress(R.string.multinetwork_connectivity_test_connect_wifi);
- mConnectivityState.legacyConnectToWifiNetwork(true);
+ requestUserConnectToApAsync((isSuccess) -> {
+ if (isSuccess) {
+ // Request network
+ mConnectivityState.requestNetwork(true);
+ } else {
+ endTest(false, R.string.multinetwork_status_unable_to_toggle_wifi);
+ }
+ });
}
@Override
@@ -1042,4 +1031,8 @@ public class MultiNetworkConnectivityTestActivity extends PassFailButtons.Activi
private interface SetWifiCallback {
void onComplete(boolean isSuccess);
}
+
+ private interface ConnectApCallback {
+ void onComplete(boolean isSuccess);
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
index d8cdf1986db..d9b18abb90b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
@@ -10,7 +10,7 @@ public class OffHostService {
public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
HceUtils.buildSelectApdu("A000000151000000", true),
HceUtils.buildCommandApdu("80CA9F7F00", true),
- HceUtils.buildSelectApdu("A000000003000000", true),
+ HceUtils.buildSelectApdu("A000000444000000", true),
HceUtils.buildCommandApdu("80CA9F7F00", true)
};
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
index b6abc3cd39d..3def4b07543 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
@@ -346,7 +346,7 @@ public class FingerprintBoundKeysTest extends PassFailButtons.Activity {
boolean tokenExpired = false;
long startTime = System.currentTimeMillis();
while (((System.currentTimeMillis() - startTime)
- < (AUTHENTICATION_DURATION_SECONDS * 1000))
+ < ((AUTHENTICATION_DURATION_SECONDS + 1) * 1000))
&& (!tokenExpired)) {
try {
Thread.sleep(1000);
diff --git a/common/device-side/bedstead/activitycontext/Android.bp b/common/device-side/bedstead/activitycontext/Android.bp
index 914898694f3..1042d309758 100644
--- a/common/device-side/bedstead/activitycontext/Android.bp
+++ b/common/device-side/bedstead/activitycontext/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/deviceadminapp/Android.bp b/common/device-side/bedstead/deviceadminapp/Android.bp
index 0adef59eaac..bba0003e894 100644
--- a/common/device-side/bedstead/deviceadminapp/Android.bp
+++ b/common/device-side/bedstead/deviceadminapp/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/eventlib/Android.bp b/common/device-side/bedstead/eventlib/Android.bp
index 942acb16f25..52584f37357 100644
--- a/common/device-side/bedstead/eventlib/Android.bp
+++ b/common/device-side/bedstead/eventlib/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/harrier/Android.bp b/common/device-side/bedstead/harrier/Android.bp
index d8fa01dec50..f0472a89d80 100644
--- a/common/device-side/bedstead/harrier/Android.bp
+++ b/common/device-side/bedstead/harrier/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/nene/Android.bp b/common/device-side/bedstead/nene/Android.bp
index 223df03b741..270d784de10 100644
--- a/common/device-side/bedstead/nene/Android.bp
+++ b/common/device-side/bedstead/nene/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/ActivityReference.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/ActivityReference.java
index a81588a4833..a9de0ace599 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/ActivityReference.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/activities/ActivityReference.java
@@ -54,10 +54,14 @@ public final class ActivityReference extends ComponentReference {
// level and work for any component
try (PermissionContext p = TestApis.permissions()
.withPermission(INTERACT_ACROSS_USERS_FULL)) {
- return TestApis.context().androidContextAsUser(user)
- .getPackageManager()
- .getActivityInfo(componentName(), MATCH_DISABLED_COMPONENTS)
- .enabled;
+ PackageManager pm = TestApis.context().androidContextAsUser(user).getPackageManager();
+ int runtimeEnabledSetting = pm.getComponentEnabledSetting(componentName());
+ if (runtimeEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ return true;
+ } else if ((runtimeEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)) {
+ return pm.getActivityInfo(componentName(), MATCH_DISABLED_COMPONENTS).enabled;
+ }
+ return false;
} catch (PackageManager.NameNotFoundException e) {
throw new NeneException("Activity does not exist or is not activity " + this, e);
}
diff --git a/common/device-side/bedstead/queryable/Android.bp b/common/device-side/bedstead/queryable/Android.bp
index 508250c0534..2cbfc33948d 100644
--- a/common/device-side/bedstead/queryable/Android.bp
+++ b/common/device-side/bedstead/queryable/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/remoteaccountauthenticator/Android.bp b/common/device-side/bedstead/remoteaccountauthenticator/Android.bp
index ffd038fdbee..9fb1a6f0bba 100644
--- a/common/device-side/bedstead/remoteaccountauthenticator/Android.bp
+++ b/common/device-side/bedstead/remoteaccountauthenticator/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/remotedpc/Android.bp b/common/device-side/bedstead/remotedpc/Android.bp
index 94342b09aef..1a717ec9c64 100644
--- a/common/device-side/bedstead/remotedpc/Android.bp
+++ b/common/device-side/bedstead/remotedpc/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/bedstead/testapp/Android.bp b/common/device-side/bedstead/testapp/Android.bp
index 764ae034066..26ec8b3ea12 100644
--- a/common/device-side/bedstead/testapp/Android.bp
+++ b/common/device-side/bedstead/testapp/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java
index d76c7b9c64e..4862679e70d 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LocaleDeviceInfo.java
@@ -15,6 +15,9 @@
*/
package com.android.compatibility.common.deviceinfo;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+
import android.icu.util.ULocale;
import android.icu.util.VersionInfo;
import android.util.Log;
@@ -35,9 +38,9 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
@@ -60,8 +63,8 @@ public final class LocaleDeviceInfo extends DeviceInfo {
store.addListResult("locale", locales);
List<String> icuLocales = Arrays.stream(ULocale.getAvailableLocales())
- .map((uLocale -> uLocale.toLanguageTag()))
- .collect(Collectors.toList());
+ .map((uLocale -> uLocale.toLanguageTag()))
+ .collect(toList());
if (icuLocales.isEmpty()) {
// default locale
icuLocales.add(ULocale.US.toLanguageTag());
@@ -82,7 +85,7 @@ public final class LocaleDeviceInfo extends DeviceInfo {
return matcher.find() ? Strings.nullToEmpty(matcher.group(1)) : "";
})
.sorted()
- .collect(Collectors.toList());
+ .collect(toList());
} catch (IOException e) {
Log.w(TAG,"Hyphenation binary folder is not exist" , e);
}
@@ -92,16 +95,27 @@ public final class LocaleDeviceInfo extends DeviceInfo {
}
/**
- * Collect the fingerprints of ICU data files. On AOSP build, there are only 2 data files.
- * The example paths are /apex/com.android.tzdata/etc/icu/icu_tzdata.dat and
+ * Collect the fingerprints of ICU data files. On AOSP build, there are 5 data files.
+ * The example paths are /apex/com.android.tzdata/etc/icu/zoneinfo64.res and
* /apex/com.android.i18n/etc/icu/icudt65l.dat
*/
private void collectLocaleDataFilesInfo(DeviceInfoStore store) throws IOException {
int icuVersion = VersionInfo.ICU_VERSION.getMajor();
- File[] fixedDatPaths = new File[] {
- new File("/apex/com.android.tzdata/etc/icu/icu_tzdata.dat"),
- new File("/apex/com.android.i18n/etc/icu/icudt" + icuVersion + "l.dat"),
- };
+
+ String icuDatFilePath = "/apex/com.android.i18n/etc/icu/icudt" + icuVersion + "l.dat";
+ Stream<String> tzdataModuleResFiles =
+ Stream.of(
+ "metaZones.res",
+ "zoneinfo64.res",
+ "timezoneTypes.res",
+ "windowsZones.res")
+ .map(fileName -> "/apex/com.android.tzdata/etc/icu/" + fileName);
+ Set<File> fixedIcuFilesPaths =
+ Stream.concat(
+ Stream.of(icuDatFilePath),
+ tzdataModuleResFiles)
+ .map(File::new)
+ .collect(toSet());
// This property has been deprecated since Android 12. The property will not work if this
// app targets SDK level 31 or higher. Thus, we add the above fixedDatPaths in case that
@@ -110,33 +124,33 @@ public final class LocaleDeviceInfo extends DeviceInfo {
String prop = System.getProperty("android.icu.impl.ICUBinary.dataPath");
store.startArray("icu_data_file_info");
- List<File> datFiles = new ArrayList<>();
+ List<File> icuFiles = new ArrayList<>();
if (prop != null) {
String[] dataDirs = prop.split(":");
// List all ".dat" files in the directories.
- datFiles = Arrays.stream(dataDirs)
+ icuFiles = Arrays.stream(dataDirs)
.filter((dir) -> dir != null && !dir.isEmpty())
.map((dir) -> new File(dir))
.filter((f) -> f.canRead() && f.isDirectory())
.map((f) -> f.listFiles())
.filter((files) -> files != null)
.flatMap(files -> Stream.of(files))
- .collect(Collectors.toList());
+ .collect(toList());
}
- datFiles.addAll(Arrays.asList(fixedDatPaths));
+ icuFiles.addAll(fixedIcuFilesPaths);
// Keep the readable paths only.
- datFiles = datFiles.stream()
+ icuFiles = icuFiles.stream()
.distinct()
- .filter((f) -> f != null && f.canRead() && f.getName().endsWith(".dat"))
- .collect(Collectors.toList());
+ .filter((f) -> f != null && f.canRead() && isIcuFile(f))
+ .collect(toList());
- for (File datFile : datFiles) {
- String sha256Hash = sha256(datFile);
+ for (File icuFile : icuFiles) {
+ String sha256Hash = sha256(icuFile);
store.startGroup();
- store.addResult("file_path", datFile.getPath());
+ store.addResult("file_path", icuFile.getPath());
// Still store the null hash to indicate an error occurring when obtaining the hash.
store.addResult("file_sha256", sha256Hash);
store.endGroup();
@@ -144,6 +158,10 @@ public final class LocaleDeviceInfo extends DeviceInfo {
store.endArray();
}
+ private static boolean isIcuFile(File file) {
+ return file.getName().endsWith(".dat") || file.getName().endsWith(".res");
+ }
+
public static @Nullable String sha256(File file) {
try (FileInputStream in = new FileInputStream(file);
FileChannel fileChannel = in.getChannel()) {
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS
index 0231a04fe9c..4de51e6ed90 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS
@@ -3,3 +3,6 @@
# Bug component: 1084732 = per-file KeystoreAttestationDeviceInfo.java
# Bug template url: http://b/new?component=1084732&template=1604634 = per-file KeystoreAttestationDeviceInfo.java
per-file KeystoreAttestationDeviceInfo.java = file:platform/cts:/tests/tests/keystore/OWNERS
+
+# Bug component: 137825 = per-file PermissionDeviceInfo.java
+per-file PermissionDeviceInfo.java = file:platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/common/device-side/interactive/src/main/AndroidManifest.xml b/common/device-side/interactive/src/main/AndroidManifest.xml
index efb8643a5c0..386a0ce1864 100644
--- a/common/device-side/interactive/src/main/AndroidManifest.xml
+++ b/common/device-side/interactive/src/main/AndroidManifest.xml
@@ -23,7 +23,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- <application>
+ <application android:requestLegacyExternalStorage="true">
<provider
android:name="com.android.interactive.AutomationFileProvider"
android:authorities="${applicationId}.interactive.automation"
@@ -33,4 +33,4 @@
</provider>
</application>
-</manifest> \ No newline at end of file
+</manifest>
diff --git a/common/device-side/interactive/src/main/java/com/android/interactive/ScreenshotUtil.java b/common/device-side/interactive/src/main/java/com/android/interactive/ScreenshotUtil.java
index f53f6a660c4..64afa197bbd 100644
--- a/common/device-side/interactive/src/main/java/com/android/interactive/ScreenshotUtil.java
+++ b/common/device-side/interactive/src/main/java/com/android/interactive/ScreenshotUtil.java
@@ -45,8 +45,9 @@ public final class ScreenshotUtil {
Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/Documents/xts/screenshots/";
File file = new File(screenshotDir);
- if (!file.exists()) {
- file.mkdirs();
+ if (!file.exists() && !file.mkdirs()) {
+ // Let the steps that require screenshots fail immediately.
+ throw new RuntimeException("Failed to create " + screenshotDir + " directory on DUT.");
}
File screenshotFile =
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/FrameworkSpecificTest.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/FrameworkSpecificTest.java
new file mode 100644
index 00000000000..e1d38acc07f
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/FrameworkSpecificTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for tests that specifically exercises Framework code (e.g. not in a mainline
+ * module). This is used to identify tests that should be skipped when running mainline
+ * module tests, such as MTS or MCTS.
+ * in summary:
+ * tag with '@FrameworkSpecificTest' -- run: CTS, skip: MCTS, MTS
+ * tag with '@ModuleSpecificTest' -- run: MCTS, MTS; skip: CTS
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface FrameworkSpecificTest {
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/ModuleSpecificTest.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/ModuleSpecificTest.java
new file mode 100644
index 00000000000..5b387018188
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/ModuleSpecificTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for tests that specifically exercises Mainline Module code.
+ * This is used to identify tests that should be skipped when running CTS.
+ * in summary:
+ * tag with '@FrameworkSpecificTest' -- run: CTS, skip: MCTS, MTS
+ * tag with '@ModuleSpecificTest' -- run: MCTS, MTS; skip: CTS
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface ModuleSpecificTest {
+}
diff --git a/common/device-side/util-axt/tests/Android.bp b/common/device-side/util-axt/tests/Android.bp
index c25bd627510..220dc64153d 100644
--- a/common/device-side/util-axt/tests/Android.bp
+++ b/common/device-side/util-axt/tests/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_framework_android_packages",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/hostsidetests/adb/OWNERS b/hostsidetests/adb/OWNERS
index 5050f5c0b5a..f86fdc1d47d 100644
--- a/hostsidetests/adb/OWNERS
+++ b/hostsidetests/adb/OWNERS
@@ -1,3 +1,3 @@
# Bug component: 1352
-shaju@google.com
+sanglardf@google.com
include platform/system/core:/janitors/OWNERS
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
index f57fe29ac70..af840c90fae 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
@@ -108,6 +108,7 @@ public final class CompatChangesValidConfigTest extends CompatChangeGatingTestCa
"OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED",
"OVERRIDE_RESPECT_REQUESTED_ORIENTATION",
"OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS",
+ "OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION",
"DEFAULT_RESCIND_BAL_FG_PRIVILEGES_BOUND_SERVICE",
"DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER",
"RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY",
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 71c8bc19b6a..a3d7e6ea431 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -51,6 +51,7 @@ import java.util.concurrent.TimeUnit;
public class AdoptableHostTest extends BaseHostJUnit4Test {
public static final String FEATURE_ADOPTABLE_STORAGE = "feature:android.software.adoptable_storage";
+ private static final int ANDROID_API_LEVEL_R = 30;
private String mListVolumesInitialState;
@@ -400,7 +401,11 @@ public class AdoptableHostTest extends BaseHostJUnit4Test {
}
private boolean isSupportedDevice() throws Exception {
- return hasFeature() || hasFstab();
+ return hasCasefoldSupport() && (hasFeature() || hasFstab());
+ }
+
+ private boolean hasCasefoldSupport() throws Exception {
+ return getDevice().getLaunchApiLevel() >= ANDROID_API_LEVEL_R;
}
private boolean hasFeature() throws Exception {
diff --git a/hostsidetests/art/Android.bp b/hostsidetests/art/Android.bp
index 155990d2e21..ef70a2790eb 100644
--- a/hostsidetests/art/Android.bp
+++ b/hostsidetests/art/Android.bp
@@ -16,6 +16,7 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_team: "trendy_team_art_performance",
}
java_test_host {
diff --git a/hostsidetests/classloaders/Android.bp b/hostsidetests/classloaders/Android.bp
new file mode 100644
index 00000000000..190d39a502c
--- /dev/null
+++ b/hostsidetests/classloaders/Android.bp
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_team: "trendy_team_art_mainline",
+}
diff --git a/hostsidetests/devicepolicy/Android.bp b/hostsidetests/devicepolicy/Android.bp
index 475ae6b65a2..eb0eb3d8916 100644
--- a/hostsidetests/devicepolicy/Android.bp
+++ b/hostsidetests/devicepolicy/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
index 236192e4957..ac90bba23bf 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
@@ -49,12 +49,18 @@ public class DeviceIdentifiersTest extends BaseDeviceAdminTest {
assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getDeviceId"),
ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
TelephonyManager::getDeviceId), telephonyManager.getDeviceId());
- assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getImei"),
- ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
- TelephonyManager::getImei), telephonyManager.getImei());
- assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getMeid"),
- ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
- TelephonyManager::getMeid), telephonyManager.getMeid());
+ if (mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_GSM)) {
+ assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getImei"),
+ ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
+ TelephonyManager::getImei), telephonyManager.getImei());
+ }
+ if (mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CDMA)) {
+ assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getMeid"),
+ ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
+ TelephonyManager::getMeid), telephonyManager.getMeid());
+ }
assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getSubscriberId"),
ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
TelephonyManager::getSubscriberId), telephonyManager.getSubscriberId());
diff --git a/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp b/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp
index 05c8016dc0e..04efba21856 100644
--- a/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp
+++ b/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/hostsidetests/dexmetadata/Android.bp b/hostsidetests/dexmetadata/Android.bp
new file mode 100644
index 00000000000..190d39a502c
--- /dev/null
+++ b/hostsidetests/dexmetadata/Android.bp
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_team: "trendy_team_art_mainline",
+}
diff --git a/hostsidetests/edi/src/android/edi/cts/NativeDeviceInfo.java b/hostsidetests/edi/src/android/edi/cts/NativeDeviceInfo.java
index cab0581d396..9bbf0b583b7 100644
--- a/hostsidetests/edi/src/android/edi/cts/NativeDeviceInfo.java
+++ b/hostsidetests/edi/src/android/edi/cts/NativeDeviceInfo.java
@@ -29,6 +29,38 @@ import java.util.regex.Pattern;
*/
public class NativeDeviceInfo extends DeviceInfo {
+ private void collectMemCG(ITestDevice device, HostInfoStore store) throws Exception {
+ CommandResult commandResult = device.executeShellV2Command("grep memory /proc/cgroups");
+
+ store.startGroup("memcg");
+ if (commandResult.getExitCode() == 0) {
+ String[] tokens = commandResult.getStdout().split("\\s+");
+ boolean memcg_enabled = tokens[3].equals("1");
+ store.addResult("enabled", memcg_enabled);
+ if (memcg_enabled) store.addResult("version", tokens[1].equals("0") ? "2" : "1");
+ } else if (commandResult.getExitCode() == 1) { // "memory" not found by grep
+ store.addResult("version", -3);
+ } else if (commandResult.getStderr().contains("No such file")) {
+ store.addResult("version", -1);
+ } else if (commandResult.getStderr().contains("Permission denied")) {
+ store.addResult("version", -2);
+ }
+ store.endGroup();
+ }
+
+ private void collectMGLRU(ITestDevice device, HostInfoStore store) throws Exception {
+ CommandResult commandResult = device.executeShellV2Command(
+ "cat /sys/kernel/mm/lru_gen/enabled");
+
+ if (commandResult.getExitCode() == 0) {
+ store.addResult("mglru_enabled", Integer.decode(commandResult.getStdout().trim()));
+ } else if (commandResult.getStderr().contains("No such file")) {
+ store.addResult("mglru_enabled", -1);
+ } else if (commandResult.getStderr().contains("Permission denied")) {
+ store.addResult("mglru_enabled", -2);
+ }
+ }
+
@Override
protected void collectDeviceInfo(HostInfoStore store) throws Exception {
ITestDevice device = getDevice();
@@ -77,5 +109,8 @@ public class NativeDeviceInfo extends DeviceInfo {
allocatorName += "_lowmemory";
}
store.addResult("allocator", allocatorName);
+
+ collectMemCG(device, store);
+ collectMGLRU(device, store);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
index 1d5d2af1805..beddf500fe4 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
@@ -30,6 +30,7 @@ public final class HdmiCecConstants {
public static final int REBOOT_TIMEOUT = 60000;
public static final int TIMEOUT_CEC_REINIT_SECONDS = 5;
public static final int TIMEOUT_SAFETY_MS = 500;
+ public static final long TIMEOUT_UI_AND_STANDBY_AFTER_ACTIVE_SOURCE_LOST_SECONDS = 35;
public static final int INVALID_VENDOR_ID = 0xFFFFFF;
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
index 7ad69634cfd..13f0b74a31c 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
@@ -18,6 +18,8 @@ package android.hdmicec.cts.playback;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeFalse;
+
import android.hdmicec.cts.BaseHdmiCecCtsTest;
import android.hdmicec.cts.CecMessage;
import android.hdmicec.cts.CecOperand;
@@ -161,6 +163,9 @@ public final class HdmiCecRoutingControlTest extends BaseHdmiCecCtsTest {
*/
@Test
public void testPowerStateChangeOnActiveSourceLost_standby() throws Exception {
+ assumeFalse("Skip for audio system devices (b/323469502)",
+ hasDeviceType(HdmiCecConstants.CEC_DEVICE_TYPE_AUDIO_SYSTEM));
+
String previousActionOnActiveSourceLost = setPowerStateChangeOnActiveSourceLost(
HdmiCecConstants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW);
try {
@@ -172,6 +177,8 @@ public final class HdmiCecRoutingControlTest extends BaseHdmiCecCtsTest {
// Now make the TV the active source
hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
CecOperand.ACTIVE_SOURCE, CecMessage.formatParams("0000"));
+ TimeUnit.SECONDS.sleep(
+ HdmiCecConstants.TIMEOUT_UI_AND_STANDBY_AFTER_ACTIVE_SOURCE_LOST_SECONDS);
assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
} finally {
/* Wake up the device */
@@ -197,6 +204,8 @@ public final class HdmiCecRoutingControlTest extends BaseHdmiCecCtsTest {
// Now make the TV the active source
hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
CecOperand.ACTIVE_SOURCE, CecMessage.formatParams("0000"));
+ TimeUnit.SECONDS.sleep(
+ HdmiCecConstants.TIMEOUT_UI_AND_STANDBY_AFTER_ACTIVE_SOURCE_LOST_SECONDS);
assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
} finally {
/* Wake up the device */
diff --git a/hostsidetests/incrementalinstall/Android.bp b/hostsidetests/incrementalinstall/Android.bp
index fdc611aa00c..abdabe73add 100644
--- a/hostsidetests/incrementalinstall/Android.bp
+++ b/hostsidetests/incrementalinstall/Android.bp
@@ -18,6 +18,7 @@ package {
java_test_host {
name: "CtsIncrementalInstallHostTestCases",
+ team: "trendy_team_incremental",
srcs: ["src/**/*.java"],
libs: [
"compatibility-host-util",
diff --git a/hostsidetests/jdwpsecurity/Android.bp b/hostsidetests/jdwpsecurity/Android.bp
index 1575dbea170..54e5c64929e 100644
--- a/hostsidetests/jdwpsecurity/Android.bp
+++ b/hostsidetests/jdwpsecurity/Android.bp
@@ -14,6 +14,7 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_team: "trendy_team_art_performance",
}
java_test_host {
diff --git a/hostsidetests/jdwpsecurity/OWNERS b/hostsidetests/jdwpsecurity/OWNERS
index 6e0629999c7..131c53fbd08 100644
--- a/hostsidetests/jdwpsecurity/OWNERS
+++ b/hostsidetests/jdwpsecurity/OWNERS
@@ -1,2 +1,2 @@
-# Bug component: 86431
-include /hostsidetests/jvmti/run-tests/OWNERS
+# Bug component: 1304319
+include platform/art:/OWNERS
diff --git a/hostsidetests/jdwptunnel/Android.bp b/hostsidetests/jdwptunnel/Android.bp
index b32d2ffda00..46d9707fe28 100644
--- a/hostsidetests/jdwptunnel/Android.bp
+++ b/hostsidetests/jdwptunnel/Android.bp
@@ -14,6 +14,7 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_team: "trendy_team_art_performance",
}
java_test_host {
diff --git a/hostsidetests/jdwptunnel/OWNERS b/hostsidetests/jdwptunnel/OWNERS
index 6e0629999c7..131c53fbd08 100644
--- a/hostsidetests/jdwptunnel/OWNERS
+++ b/hostsidetests/jdwptunnel/OWNERS
@@ -1,2 +1,2 @@
-# Bug component: 86431
-include /hostsidetests/jvmti/run-tests/OWNERS
+# Bug component: 1304319
+include platform/art:/OWNERS
diff --git a/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java b/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
index 9961273349c..c7ebd52c49c 100644
--- a/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
+++ b/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
@@ -345,13 +345,39 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
assertTrue((is.read() & 0x80) == 0x80);
}
- private void assertThreadSuspensionState(VirtualMachine vm, boolean expected) {
+ private boolean testThreadSuspensionState(VirtualMachine vm, boolean expected) {
for (ThreadReference tr : vm.allThreads()) {
boolean isSuspended = tr.isSuspended();
if (isSuspended != expected) {
- fail("Thread in unexpected state '" + tr.name() + "' isSuspended=" + isSuspended);
+ return false;
}
}
+ return true;
+ }
+
+ private String dumpThreads(VirtualMachine vm) {
+ StringBuilder result = new StringBuilder();
+ for (ThreadReference tr : vm.allThreads()) {
+ result.append("Thread: '");
+ result.append(tr.name());
+ result.append("' isSuspended=");
+ result.append(tr.isSuspended());
+ result.append("\n");
+ }
+ return result.toString();
+ }
+
+ private void assertThreadSuspensionState(VirtualMachine vm, boolean expected)
+ throws InterruptedException {
+ // If the debugger connects too fast, the VM may not have had time to hit the
+ // suspension point. We try several times to remedy to this problem.
+ for (int i = 0; i < 4; i++) {
+ if (testThreadSuspensionState(vm, expected)) {
+ return;
+ }
+ Thread.sleep(1000);
+ }
+ fail("Threads are in unexpected state (expected=" + expected + ")\n" + dumpThreads(vm));
}
// App can be started "suspended" which means all its threads will be suspended shorty after
diff --git a/hostsidetests/jvmti/Android.bp b/hostsidetests/jvmti/Android.bp
new file mode 100644
index 00000000000..8faed40643d
--- /dev/null
+++ b/hostsidetests/jvmti/Android.bp
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_team: "trendy_team_art_performance",
+}
diff --git a/hostsidetests/jvmti/run-tests/OWNERS b/hostsidetests/jvmti/OWNERS
index ef864121273..131c53fbd08 100644
--- a/hostsidetests/jvmti/run-tests/OWNERS
+++ b/hostsidetests/jvmti/OWNERS
@@ -1,2 +1,2 @@
-# Bug component: 86431
+# Bug component: 1304319
include platform/art:/OWNERS
diff --git a/hostsidetests/jvmti/allocation-tracking/OWNERS b/hostsidetests/jvmti/allocation-tracking/OWNERS
deleted file mode 100644
index 2dbff0d6606..00000000000
--- a/hostsidetests/jvmti/allocation-tracking/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 86431
-include ../run-tests/OWNERS
diff --git a/hostsidetests/jvmti/attaching/OWNERS b/hostsidetests/jvmti/attaching/OWNERS
deleted file mode 100644
index 2dbff0d6606..00000000000
--- a/hostsidetests/jvmti/attaching/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 86431
-include ../run-tests/OWNERS
diff --git a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
index cecb6ed547a..881ab719a0d 100644
--- a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
+++ b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
@@ -128,7 +128,7 @@ public class JvmtiHostTest extends DeviceTestCase implements IBuildReceiver, IAb
RemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(mTestPackageName, RUNNER,
device.getIDevice());
// set a max deadline limit to avoid hanging forever
- runner.setMaxTimeToOutputResponse(5, TimeUnit.MINUTES);
+ runner.setMaxTimeToOutputResponse(10, TimeUnit.MINUTES);
AttachAgent aa = new AttachAgent(device, mTestPackageName, mTestApk);
aa.prepare();
diff --git a/hostsidetests/jvmti/redefining/OWNERS b/hostsidetests/jvmti/redefining/OWNERS
deleted file mode 100644
index 2dbff0d6606..00000000000
--- a/hostsidetests/jvmti/redefining/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 86431
-include ../run-tests/OWNERS
diff --git a/hostsidetests/jvmti/tagging/OWNERS b/hostsidetests/jvmti/tagging/OWNERS
deleted file mode 100644
index 2dbff0d6606..00000000000
--- a/hostsidetests/jvmti/tagging/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 86431
-include ../run-tests/OWNERS
diff --git a/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml b/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml
index a3c5336c28c..54e7d959641 100644
--- a/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml
+++ b/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml
@@ -37,8 +37,5 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.videoencoding.app"
android:label="Video encoding app for android.media" >
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/hostsidetests/mediapc/videoencodingquality/app/src/android/videoencoding/app/VideoTranscoderTest.java b/hostsidetests/mediapc/videoencodingquality/app/src/android/videoencoding/app/VideoTranscoderTest.java
index e3364bf6827..294fe80f92d 100644
--- a/hostsidetests/mediapc/videoencodingquality/app/src/android/videoencoding/app/VideoTranscoderTest.java
+++ b/hostsidetests/mediapc/videoencodingquality/app/src/android/videoencoding/app/VideoTranscoderTest.java
@@ -71,7 +71,9 @@ import java.util.ArrayList;
*/
@RunWith(AndroidJUnit4.class)
public class VideoTranscoderTest {
- private static final String MEDIA_DIR = "/sdcard/veq/input/";
+ private static final String SDCARD_MOUNT_POINT =
+ Environment.getExternalStorageDirectory().getAbsolutePath();
+ private static final String MEDIA_DIR = SDCARD_MOUNT_POINT + "/veq/input/";
public static final String ENC_CONFIG_JSON = "conf-json";
private static final String ENC_CONFIG_FILE;
private static String PATH_PREFIX;
@@ -186,7 +188,7 @@ public class VideoTranscoderTest {
Assert.assertEquals("Apk does not have permissions to write to external storage",
PackageManager.PERMISSION_GRANTED,
CONTEXT.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
- File pub = new File("/sdcard/veq/output/");
+ File pub = new File(SDCARD_MOUNT_POINT + "/veq/output/");
File dir = buildPath(pub,
"output_" + ENC_CONFIG_FILE.substring(0, ENC_CONFIG_FILE.lastIndexOf('.')));
if (!dir.exists()) {
diff --git a/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java b/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
index df220112773..1b789dd93fa 100644
--- a/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
+++ b/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
@@ -21,6 +21,7 @@ import android.cts.host.utils.DeviceJUnit4Parameterized;
import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.util.CddTest;
+import com.android.ddmlib.IDevice;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.config.Option;
@@ -98,8 +99,6 @@ public class CtsVideoEncodingQualityHostTest implements IDeviceTest {
// Variables related to device-side of the test. These need to kept in sync with definitions of
// VideoEncodingApp.apk
- private static final String DEVICE_IN_DIR = "/sdcard/veq/input/";
- private static final String DEVICE_OUT_DIR = "/sdcard/veq/output/";
private static final String DEVICE_SIDE_TEST_PACKAGE = "android.videoencoding.app";
private static final String DEVICE_SIDE_TEST_CLASS =
"android.videoencoding.app.VideoTranscoderTest";
@@ -135,82 +134,129 @@ public class CtsVideoEncodingQualityHostTest implements IDeviceTest {
@Option(name = "quick-check", description = "Run a quick check.")
private boolean mQuickCheck = false;
- public CtsVideoEncodingQualityHostTest(String jsonName) {
+ public CtsVideoEncodingQualityHostTest(String jsonName,
+ @SuppressWarnings("unused") String testLabel) {
mJsonName = jsonName;
}
- private static final List<String> AVC_VBR_B0_PARAMS = Arrays.asList(
- "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
- "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p"
- + "-30fps_hw_avc_vbr_b0.json",
- "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
- + "-30fps_hw_avc_vbr_b0.json",
- "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
- "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
+ private static final List<Object[]> AVC_VBR_B0_PARAMS = Arrays.asList(new Object[][]{
+ {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
+ "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+ {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
+ ".json",
- "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
- "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p"
+ "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "-30fps_hw_avc_vbr_b0.json",
- "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
+ "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+ + "vbr_b0"},
+ {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
+ "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json"
+ , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+ {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
+ "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
+ ".json",
- "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
- + "-30fps_hw_avc_vbr_b0.json");
-
- private static final List<String> AVC_VBR_B3_PARAMS = Arrays.asList(
- "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
- "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
+ "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+ {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json"
+ , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+ + "-1080p-30fps_hw_avc_vbr_b0.json",
+ "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+ + "vbr_b0"}});
+
+ private static final List<Object[]> AVC_VBR_B3_PARAMS = Arrays.asList(new Object[][]{
+ {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
+ "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+ {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
+ ".json",
- "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+ {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "-30fps_hw_avc_vbr_b3.json",
- "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
- "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
- "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
- "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
+ "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+ + "vbr_b3"},
+ {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
+ "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+ {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json"
+ , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+ {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
+ "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+ {"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
+ ".json",
- "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
- "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
- + "-30fps_hw_avc_vbr_b3.json");
-
- private static final List<String> HEVC_VBR_B0_PARAMS = Arrays.asList(
- "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
- "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
+ "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+ {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json"
+ , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+ {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+ + "-1080p-30fps_hw_avc_vbr_b3.json",
+ "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+ + "vbr_b3"}});
+
+ private static final List<Object[]> HEVC_VBR_B0_PARAMS = Arrays.asList(new Object[][]{
+ {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
+ "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+ {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
+ ".json",
- "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "-30fps_hw_hevc_vbr_b0.json",
- "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
- "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
- "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
- "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
+ "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+ + "vbr_b0"},
+ {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
+ "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json"
+ , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+ {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
+ "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
+ ".json",
- "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
- "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
- + "-30fps_hw_hevc_vbr_b0.json");
-
- private static final List<String> HEVC_VBR_B3_PARAMS = Arrays.asList(
- "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
- "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
+ "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+ {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json"
+ , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+ {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+ + "-1080p-30fps_hw_hevc_vbr_b0.json",
+ "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+ + "vbr_b0"}});
+
+ private static final List<Object[]> HEVC_VBR_B3_PARAMS = Arrays.asList(new Object[][]{
+ {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+ "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+ {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
+ ".json",
- "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+ {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "-30fps_hw_hevc_vbr_b3.json",
- "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
- "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
- "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+ "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+ + "vbr_b3"},
+ {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+ "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+ {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json"
+ , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+ {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+ "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
// Abnormal curve, not monotonically increasing.
- /*"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
- + ".json",*/
- "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
- "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
- + "-30fps_hw_hevc_vbr_b3.json");
-
- private static final List<String> QUICK_RUN_PARAMS = Arrays.asList(
- "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ /*{"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
+ + ".json",
+ "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},*/
+ {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json"
+ , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+ {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+ + "-1080p-30fps_hw_hevc_vbr_b3.json",
+ "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+ + "vbr_b3"}});
+
+ private static final List<Object[]> QUICK_RUN_PARAMS = Arrays.asList(new Object[][]{
+ {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ "-30fps_hw_avc_vbr_b0.json",
- "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
- + "-30fps_hw_hevc_vbr_b0.json");
+ "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_" +
+ "vbr_b0"},
+ {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+ + "-30fps_hw_hevc_vbr_b0.json",
+ "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+ + "vbr_b0"}});
- @Parameterized.Parameters(name = "{index}_{0}")
- public static List<String> input() {
- final List<String> args = new ArrayList<>();
+ @Parameterized.Parameters(name = "{index}_{1}")
+ public static List<Object[]> input() {
+ final List<Object[]> args = new ArrayList<>();
args.addAll(AVC_VBR_B0_PARAMS);
args.addAll(AVC_VBR_B3_PARAMS);
args.addAll(HEVC_VBR_B0_PARAMS);
@@ -281,17 +327,32 @@ public class CtsVideoEncodingQualityHostTest implements IDeviceTest {
Assert.assertEquals("Failed to untar " + fileName, 0, result);
// Push input files to device
- Assert.assertNotNull("Failed to create directory " + DEVICE_IN_DIR + " on device ",
- getDevice().executeAdbCommand("shell", "mkdir", "-p", DEVICE_IN_DIR));
- Assert.assertTrue("Failed to push json files to " + DEVICE_IN_DIR + " on device ",
- getDevice().syncFiles(new File(sHostWorkDir.getPath() + "/json/"), DEVICE_IN_DIR));
- Assert.assertTrue("Failed to push mp4 files to " + DEVICE_IN_DIR + " on device ",
- getDevice().syncFiles(new File(sHostWorkDir.getPath() + "/samples/"),
- DEVICE_IN_DIR));
+ String deviceInDir = getDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE)
+ + "/veq/input/";
+ String deviceJsonDir = deviceInDir + "json/";
+ String deviceSamplesDir = deviceInDir + "samples/";
+ Assert.assertNotNull("Failed to create directory " + deviceJsonDir + " on device ",
+ getDevice().executeAdbCommand("shell", "mkdir", "-p", deviceJsonDir));
+ Assert.assertNotNull("Failed to create directory " + deviceSamplesDir + " on device ",
+ getDevice().executeAdbCommand("shell", "mkdir", "-p", deviceSamplesDir));
+ Assert.assertTrue("Failed to push json files to " + deviceJsonDir + " on device ",
+ getDevice().pushDir(new File(sHostWorkDir.getPath() + "/json/"), deviceJsonDir));
+ Assert.assertTrue("Failed to push mp4 files to " + deviceSamplesDir + " on device ",
+ getDevice().pushDir(new File(sHostWorkDir.getPath() + "/samples/"),
+ deviceSamplesDir));
sIsTestSetUpDone = true;
}
+ public static boolean containsJson(String jsonName, List<Object[]> params) {
+ for (Object[] param : params) {
+ if (param[0].equals(jsonName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Verify the video encoding quality requirements for the performance class 14 devices.
*/
@@ -299,19 +360,19 @@ public class CtsVideoEncodingQualityHostTest implements IDeviceTest {
@Test
public void testEncoding() throws Exception {
Assume.assumeFalse("Skipping due to quick run mode",
- mQuickCheck && !QUICK_RUN_PARAMS.contains(mJsonName));
+ mQuickCheck && !containsJson(mJsonName, QUICK_RUN_PARAMS));
Assume.assumeFalse("Skipping avc encoder tests",
- mSkipAvc && (AVC_VBR_B0_PARAMS.contains(mJsonName) || AVC_VBR_B3_PARAMS.contains(
- mJsonName)));
+ mSkipAvc && (containsJson(mJsonName, AVC_VBR_B0_PARAMS) || containsJson(mJsonName,
+ AVC_VBR_B3_PARAMS)));
Assume.assumeFalse("Skipping hevc encoder tests",
- mSkipHevc && (HEVC_VBR_B0_PARAMS.contains(mJsonName) || HEVC_VBR_B3_PARAMS.contains(
- mJsonName)));
+ mSkipHevc && (containsJson(mJsonName, HEVC_VBR_B0_PARAMS) || containsJson(mJsonName,
+ HEVC_VBR_B3_PARAMS)));
Assume.assumeFalse("Skipping b-frame tests",
- mSkipB && (AVC_VBR_B3_PARAMS.contains(mJsonName) || HEVC_VBR_B3_PARAMS.contains(
- mJsonName)));
+ mSkipB && (containsJson(mJsonName, AVC_VBR_B3_PARAMS) || containsJson(mJsonName,
+ HEVC_VBR_B3_PARAMS)));
Assume.assumeFalse("Skipping non b-frame tests",
- mSkipP && (AVC_VBR_B0_PARAMS.contains(mJsonName) || HEVC_VBR_B0_PARAMS.contains(
- mJsonName)));
+ mSkipP && (containsJson(mJsonName, AVC_VBR_B0_PARAMS) || containsJson(mJsonName,
+ HEVC_VBR_B0_PARAMS)));
// set up test environment
sLock.lock();
@@ -336,7 +397,8 @@ public class CtsVideoEncodingQualityHostTest implements IDeviceTest {
} catch (SecurityException e) {
LogUtil.CLog.e("Unable to establish output host directory : " + outHostPath.getPath());
}
- String outDevPath = DEVICE_OUT_DIR + outDir;
+ String outDevPath = getDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE) + "/veq/output/"
+ + outDir;
Assert.assertTrue("Failed to pull mp4 files from " + outDevPath
+ " to " + outHostPath.getPath(), getDevice().pullDir(outDevPath, outHostPath));
getDevice().deleteFile(outDevPath);
diff --git a/hostsidetests/rollback/AndroidTest.xml b/hostsidetests/rollback/AndroidTest.xml
index 07d21e9fbd8..d757f3e733e 100644
--- a/hostsidetests/rollback/AndroidTest.xml
+++ b/hostsidetests/rollback/AndroidTest.xml
@@ -20,6 +20,10 @@
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer">
+ <!-- flake mitigation, in case device is in bad state-->
+ <option name="pre-reboot" value="true" />
+ </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsRollbackManagerHostTestHelperApp.apk" />
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 b337265999c..c024efcfab4 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
@@ -1200,13 +1200,16 @@ public class TestUtils {
return packageManager.hasSystemFeature(feature);
}
- private static void scrollIntoView(UiSelector selector) {
+ private static void scrollIntoView(UiSelector selector) throws Exception {
UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
+ uiScrollable.setSwipeDeadZonePercentage(0.25);
try {
uiScrollable.scrollIntoView(selector);
} catch (UiObjectNotFoundException e) {
// Scrolling can fail if the UI is not scrollable
}
+ // Sleep for a few moments to let the scroll fully stop.
+ Thread.sleep(250);
}
/**
diff --git a/hostsidetests/security/Android.bp b/hostsidetests/security/Android.bp
index f42b9b434ed..e816d6b108b 100644
--- a/hostsidetests/security/Android.bp
+++ b/hostsidetests/security/Android.bp
@@ -61,11 +61,6 @@ java_test_host {
target_required: ["CtsDeviceInfo"],
}
-filegroup {
- name: "prebuilt_sepolicy_cts_data",
- srcs: [":202404_sepolicy_cts_data"],
-}
-
java_genrule_host {
name: "CtsSecurityHostTestCases_StaticLibs",
tools: [
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 2ffcfce38c6..b4fa803fb77 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -440,10 +440,29 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
* search new paths, hence this may not work on devices launching Android 11 and later.
*/
private static int getVendorSepolicyVersionFromManifests(ITestDevice device) throws Exception {
- String deviceManifestPath =
- (device.doesFileExist("/vendor/etc/vintf/manifest.xml")) ?
- "/vendor/etc/vintf/manifest.xml" :
- "/vendor/manifest.xml";
+ String deviceManifestPath = null;
+
+ //check default path /vendor/etc/vintf/manifest.xml, prefer to use by default
+ if (device.doesFileExist("/vendor/etc/vintf/manifest.xml")) {
+ deviceManifestPath = "/vendor/etc/vintf/manifest.xml";
+ }
+
+ //only if /vendor/etc/vintf/manifest.xml not exist, then check /vendor/etc/vintf/manifest_{vendorSku}.xml
+ String vendorSku = device.getProperty("ro.boot.product.vendor.sku");
+ if (deviceManifestPath == null && vendorSku != null && vendorSku.length() > 0) {
+ String vendorSkuDeviceManifestPath = "/vendor/etc/vintf/manifest_"+ vendorSku + ".xml";
+ if (device.doesFileExist(vendorSkuDeviceManifestPath)) {
+ deviceManifestPath = vendorSkuDeviceManifestPath;
+ }
+ }
+
+ //use /vendor/manifest.xml if above paths not exist
+ if (deviceManifestPath == null) {
+ deviceManifestPath = "/vendor/manifest.xml";
+ }
+
+ CLog.i("getVendorSepolicyVersionFromManifests " + deviceManifestPath);
+
File vendorManifestFile = getDeviceFile(device, sCachedDeviceVendorManifest,
deviceManifestPath, "manifest.xml");
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
index 21d8ab7b3af..b73916df81f 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
@@ -281,13 +281,22 @@ public final class DeviceUtils {
throws DeviceNotAvailableException {
String uidLine = device.executeShellCommand("cmd package list packages -U --user "
+ userId + " " + pkgName);
- String[] uidLineArr = uidLine.split(":");
- // Package uid is located at index 2.
- assertThat(uidLineArr.length).isGreaterThan(2);
- int appUid = Integer.parseInt(uidLineArr[2].trim());
- assertThat(appUid).isGreaterThan(10000);
- return appUid;
+ // Split package list by lines
+ // Sample packages response:
+ // package:com.android.server.cts.device.statsd.host uid:1010033
+ // package:com.android.server.cts.device.statsd uid:1010034
+ final String[] lines = uidLine.split("\\R+");
+ for (final String line : lines) {
+ if (line.startsWith("package:" + pkgName + " ")) {
+ final int uidIndex = line.lastIndexOf(":") + 1;
+ final int uid = Integer.parseInt(line.substring(uidIndex).trim());
+ assertThat(uid).isGreaterThan(10_000);
+ return uid;
+ }
+ }
+ throw new Error(
+ String.format("Could not find installed package: %s", pkgName));
}
/**
diff --git a/hostsidetests/videoencodingminimum/app/AndroidManifest.xml b/hostsidetests/videoencodingminimum/app/AndroidManifest.xml
index 3d252354ef4..2cc1cf8e4a8 100644
--- a/hostsidetests/videoencodingminimum/app/AndroidManifest.xml
+++ b/hostsidetests/videoencodingminimum/app/AndroidManifest.xml
@@ -37,8 +37,5 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.videoencodingmin.app"
android:label="Video encoding app for android.media" >
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/hostsidetests/videoencodingminimum/app/src/android/videoencodingmin/app/VideoTranscoderTest.java b/hostsidetests/videoencodingminimum/app/src/android/videoencodingmin/app/VideoTranscoderTest.java
index b2b86117884..fd1fa45dcf9 100644
--- a/hostsidetests/videoencodingminimum/app/src/android/videoencodingmin/app/VideoTranscoderTest.java
+++ b/hostsidetests/videoencodingminimum/app/src/android/videoencodingmin/app/VideoTranscoderTest.java
@@ -30,6 +30,7 @@ import android.mediav2.common.cts.CodecEncoderSurfaceTestBase;
import android.mediav2.common.cts.CodecTestBase;
import android.mediav2.common.cts.EncoderConfigParams;
import android.mediav2.common.cts.OutputManager;
+import android.os.Environment;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
@@ -70,7 +71,9 @@ import java.util.ArrayList;
*/
@RunWith(AndroidJUnit4.class)
public class VideoTranscoderTest {
- private static final String MEDIA_DIR = "/sdcard/vqf/input/";
+ private static final String SDCARD_MOUNT_POINT =
+ Environment.getExternalStorageDirectory().getAbsolutePath();
+ private static final String MEDIA_DIR = SDCARD_MOUNT_POINT + "/vqf/input/";
public static final String ENC_CONFIG_JSON = "conf-json";
private static final String ENC_CONFIG_FILE;
private static String PATH_PREFIX;
@@ -185,7 +188,7 @@ public class VideoTranscoderTest {
Assert.assertEquals("Apk does not have permissions to write to external storage",
PackageManager.PERMISSION_GRANTED,
CONTEXT.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
- File pub = new File("/sdcard/vqf/output/");
+ File pub = new File(SDCARD_MOUNT_POINT + "/vqf/output/");
File dir = buildPath(pub,
"output_" + ENC_CONFIG_FILE.substring(0, ENC_CONFIG_FILE.lastIndexOf('.')));
if (!dir.exists()) {
diff --git a/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
index 1af53612e20..6fb41c6a1c5 100644
--- a/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
+++ b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
@@ -20,6 +20,7 @@ import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
import android.cts.host.utils.DeviceJUnit4Parameterized;
import android.platform.test.annotations.AppModeFull;
+import com.android.ddmlib.IDevice;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.config.Option;
@@ -71,6 +72,8 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
// variables related to host-side of the test
private static final int MINIMUM_VALID_SDK = 31;
// test is not valid before sdk 31, aka Android 12, aka Android S
+ private static final float TARGET_VMAF_SCORE = 70.0f;
+ private static final float TOLERANCE = 0.95f;
private static final Lock sLock = new ReentrantLock();
private static final Condition sCondition = sLock.newCondition();
@@ -81,8 +84,6 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
// Variables related to device-side of the test. These need to kept in sync with definitions of
// VideoEncodingMinApp.apk
- private static final String DEVICE_IN_DIR = "/sdcard/vqf/input/";
- private static final String DEVICE_OUT_DIR = "/sdcard/vqf/output/";
private static final String DEVICE_SIDE_TEST_PACKAGE = "android.videoencodingmin.app";
private static final String DEVICE_SIDE_TEST_CLASS =
"android.videoencodingmin.app.VideoTranscoderTest";
@@ -99,13 +100,14 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
@Option(name = "reset", description = "Start with a fresh directory.")
private boolean mReset = false;
- public CtsVideoQualityFloorHostTest(String jsonName) {
+ public CtsVideoQualityFloorHostTest(String jsonName,
+ @SuppressWarnings("unused") String testLabel) {
mJsonName = jsonName;
}
- @Parameterized.Parameters(name = "{index}_{0}")
- public static List<String> input() {
- final List<String> args = new ArrayList<>();
+ @Parameterized.Parameters(name = "{index}_{1}")
+ public static List<Object[]> input() {
+ final List<Object[]> args = new ArrayList<>();
String[] clips = {"Fireworks", "MountainBike", "Motorcycle", "TreesAndGrass"};
String[] resolutions = {"1080p", "720p", "540p", "480p"};
String[] codecInfos = {"avcBaseline3", "avcHigh4", "avcHigh52", "hevcMain3"};
@@ -113,7 +115,10 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
for (String clip : clips) {
for (String res : resolutions) {
for (String info : codecInfos) {
- args.add(res + "-" + clip + "-" + info + ".json");
+ Object[] testArgs = new Object[2];
+ testArgs[0] = res + "-" + clip + "-" + info + ".json";
+ testArgs[1] = res + "_" + clip + "_" + info;
+ args.add(testArgs);
}
}
}
@@ -173,14 +178,19 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
Assert.assertEquals("Failed to untar " + fileName, 0, result);
// Push input files to device
- Assert.assertNotNull("Failed to create directory " + DEVICE_IN_DIR + " on device ",
- getDevice().executeAdbCommand("shell", "mkdir", "-p", DEVICE_IN_DIR));
- Assert.assertTrue("Failed to push json files to " + DEVICE_IN_DIR + " on device ",
- getDevice().syncFiles(new File(sHostWorkDir.getPath() + "/json/"), DEVICE_IN_DIR));
- Assert.assertTrue("Failed to push mp4 files to " + DEVICE_IN_DIR + " on device ",
- getDevice().syncFiles(new File(sHostWorkDir.getPath() + "/samples/"),
- DEVICE_IN_DIR));
-
+ String deviceInDir = getDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE)
+ + "/vqf/input/";
+ String deviceJsonDir = deviceInDir + "json/";
+ String deviceSamplesDir = deviceInDir + "samples/";
+ Assert.assertNotNull("Failed to create directory " + deviceJsonDir + " on device ",
+ getDevice().executeAdbCommand("shell", "mkdir", "-p", deviceJsonDir));
+ Assert.assertNotNull("Failed to create directory " + deviceSamplesDir + " on device ",
+ getDevice().executeAdbCommand("shell", "mkdir", "-p", deviceSamplesDir));
+ Assert.assertTrue("Failed to push json files to " + deviceJsonDir + " on device ",
+ getDevice().pushDir(new File(sHostWorkDir.getPath() + "/json/"), deviceJsonDir));
+ Assert.assertTrue("Failed to push mp4 files to " + deviceSamplesDir + " on device ",
+ getDevice().pushDir(new File(sHostWorkDir.getPath() + "/samples/"),
+ deviceSamplesDir));
sIsTestSetUpDone = true;
}
@@ -212,7 +222,8 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
} catch (SecurityException e) {
LogUtil.CLog.e("Unable to establish output host directory : " + outHostPath.getPath());
}
- String outDevPath = DEVICE_OUT_DIR + outDir;
+ String outDevPath = getDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE) + "/vqf/output/"
+ + outDir;
Assert.assertTrue("Failed to pull mp4 files from " + outDevPath
+ " to " + outHostPath.getPath(), getDevice().pullDir(outDevPath, outHostPath));
getDevice().deleteFile(outDevPath);
@@ -256,8 +267,9 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
if (line.contains(token)) {
line = line.substring(line.indexOf(token));
double vmaf_score = Double.parseDouble(line.substring(token.length()));
- Assert.assertTrue("Video encoding failed for " + outputName
- + " with vmaf score of " + vmaf_score, vmaf_score >= 70);
+ Assert.assertTrue(
+ "Video encoding failed for " + outputName + " with vmaf score of "
+ + vmaf_score, vmaf_score >= TARGET_VMAF_SCORE * TOLERANCE);
LogUtil.CLog.i(vmafLine);
break;
}
diff --git a/libs/input/src/com/android/cts/input/VirtualInputDevice.java b/libs/input/src/com/android/cts/input/VirtualInputDevice.java
index e261f0bb2a4..cc58a4325dc 100644
--- a/libs/input/src/com/android/cts/input/VirtualInputDevice.java
+++ b/libs/input/src/com/android/cts/input/VirtualInputDevice.java
@@ -24,6 +24,7 @@ import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.util.JsonReader;
import android.util.JsonToken;
import android.util.Log;
@@ -47,6 +48,8 @@ import java.util.concurrent.TimeUnit;
public abstract class VirtualInputDevice implements
InputManager.InputDeviceListener, AutoCloseable {
private static final String TAG = "VirtualInputDevice";
+ private static final int HW_TIMEOUT_MULTIPLIER = SystemProperties.getInt(
+ "ro.hw_timeout_multiplier", 1);
private InputStream mInputStream;
private OutputStream mOutputStream;
private Instrumentation mInstrumentation;
@@ -182,7 +185,7 @@ public abstract class VirtualInputDevice implements
// mResultThread should exit when stream is closed.
try {
// Wait for input device removed callback.
- mDeviceRemovedSignal.await(20L, TimeUnit.SECONDS);
+ mDeviceRemovedSignal.await(HW_TIMEOUT_MULTIPLIER * 20L, TimeUnit.SECONDS);
if (mDeviceRemovedSignal.getCount() != 0) {
throw new RuntimeException("Did not receive device removed notification in time");
}
diff --git a/libs/install/src/com/android/cts/install/lib/Install.java b/libs/install/src/com/android/cts/install/lib/Install.java
index cbbb925984d..b2e4040f8e4 100644
--- a/libs/install/src/com/android/cts/install/lib/Install.java
+++ b/libs/install/src/com/android/cts/install/lib/Install.java
@@ -295,6 +295,7 @@ public class Install {
if (mIsStaged) {
params.setStaged();
}
+ params.setInstallFlagAllowTest();
params.setRequestDowngrade(mIsDowngrade);
params.setEnableRollback(mEnableRollback, mRollbackDataPolicy);
if (mEnableRollback && mLifetimeMillis > 0) {
diff --git a/tests/JobScheduler/OWNERS b/tests/JobScheduler/OWNERS
index 99b5cf7bbd9..914e6886a5b 100644
--- a/tests/JobScheduler/OWNERS
+++ b/tests/JobScheduler/OWNERS
@@ -1,7 +1,4 @@
# Bug component: 330738
set noparent
-ctate@google.com
-kwekua@google.com
-omakoto@google.com
-yamasani@google.com \ No newline at end of file
+include platform/frameworks/base:/apex/jobscheduler/OWNERS
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 321ac8bca22..36424a7bfb8 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -468,11 +468,11 @@ public class DownloadManagerTest extends DownloadManagerTestBase {
}
}
- private String cannonicalizeProcessName(ApplicationInfo ai) {
- return cannonicalizeProcessName(ai.processName, ai);
+ private String canonicalizeProcessName(ApplicationInfo ai) {
+ return canonicalizeProcessName(ai.processName, ai);
}
- private String cannonicalizeProcessName(String process, ApplicationInfo ai) {
+ private String canonicalizeProcessName(String process, ApplicationInfo ai) {
if (process == null) {
return null;
}
@@ -502,10 +502,10 @@ public class DownloadManagerTest extends DownloadManagerTestBase {
ProviderInfo downloadInfo = pm.resolveContentProvider("downloads", 0);
assertNotNull(downloadInfo);
String downloadProcess
- = cannonicalizeProcessName(downloadInfo.processName, downloadInfo.applicationInfo);
+ = canonicalizeProcessName(downloadInfo.processName, downloadInfo.applicationInfo);
for (PackageInfo pi : mContext.getPackageManager().getInstalledPackages(0)) {
- if (downloadProcess.equals(cannonicalizeProcessName(pi.applicationInfo))) {
+ if (downloadProcess.equals(canonicalizeProcessName(pi.applicationInfo))) {
assertTrue("package: " + pi.applicationInfo.packageName
+ " must set android:usesCleartextTraffic=true"
,(pi.applicationInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC)
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index fef6849002f..196f2d51353 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -984,6 +984,7 @@ public class PerformanceTest {
ZoomDirection direction, ZoomRange range) throws Exception {
final int ZOOM_STEPS = 5;
final float ZOOM_ERROR_MARGIN = 0.05f;
+ final float ERROR_THRESH_FACTOR = 0.33f;
final int ZOOM_IN_MIN_IMPROVEMENT_IN_FRAMES = 1;
final int MAX_IMPROVEMENT_VARIATION = 2;
for (String id : mTestRule.getCameraIdsUnderTest()) {
@@ -1048,6 +1049,10 @@ public class PerformanceTest {
for (int j = 0; j < NUM_ZOOM_STEPS; j++) {
float zoomFactor = startRatio + (endRatio - startRatio)
* (j + 1) / NUM_ZOOM_STEPS;
+ // The error margin needs to be adjusted based on the zoom step size.
+ // We take the min of ZOOM_ERROR_MARGIN and 1/3 of zoom ratio step.
+ float zoomErrorMargin = Math.min(ZOOM_ERROR_MARGIN,
+ (float) Math.abs(zoomFactor - previousRatio) * ERROR_THRESH_FACTOR);
previewBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomFactor);
int newSequenceId = mTestRule.getCameraSession().setRepeatingRequest(
previewBuilder.build(), resultListener, mTestRule.getHandler());
@@ -1069,13 +1074,13 @@ public class PerformanceTest {
assertTrue(String.format("Zoom ratio should monotonically increase/decrease"
+ " or stay the same (previous = %f, current = %f", previousRatio,
resultZoomFactor),
- Math.abs(previousRatio - resultZoomFactor) < ZOOM_ERROR_MARGIN
+ Math.abs(previousRatio - resultZoomFactor) < zoomErrorMargin
|| (direction == ZoomDirection.ZOOM_IN
&& previousRatio < resultZoomFactor)
|| (direction == ZoomDirection.ZOOM_OUT
&& previousRatio > resultZoomFactor));
- if (Math.abs(resultZoomFactor - zoomFactor) < ZOOM_ERROR_MARGIN
+ if (Math.abs(resultZoomFactor - zoomFactor) < zoomErrorMargin
&& improvement == 0) {
improvement = (int) (lastFrameNumberForRequest + 1 - frameNumber);
}
diff --git a/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java b/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java
index b297b939f88..e827a500384 100644
--- a/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java
+++ b/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java
@@ -53,19 +53,19 @@ public class CoreTestModeFilter implements Predicate<Description> {
*/
public static Predicate<Description> createInstance(Bundle args) {
String mode = args.getString(ARGUMENT_MODE);
- if ("mts".equals(mode)) {
- // We have to hard-coded the annotation name of NonMts because the annotation definition
- // isn't built into the same apk file.
- return new CoreTestModeFilter(NonMts.class);
- } else if ("presubmit".equals(mode)) {
- return new CoreTestModeFilter(FlakyTest.class, LargeTest.class);
- } else {
- // The default mode is CTS, because most libcore test suites are prefixed with "Cts".
+ if ("cts".equals(mode)) {
// It's okay that ignoredTestsInCts.txt doesn't exist in the test .apk file, and
// the created CoreExpectationFilter doesn't skip any test in this case.
Set<String> expectationFile = Set.of("/skippedCtsTest.txt");
return new CoreTestModeFilter(NonCts.class)
.and(CoreExpectationFilter.createInstance(expectationFile));
+ } else if ("presubmit".equals(mode)) {
+ return new CoreTestModeFilter(FlakyTest.class, LargeTest.class);
+ } else {
+ // Use MTS mode by default because MCTS should dynamically download
+ // the MCTS artifacts in the same version as the ART module installed
+ // on the device.
+ return new CoreTestModeFilter(NonMts.class);
}
}
diff --git a/tests/devicepolicy/Android.bp b/tests/devicepolicy/Android.bp
index fe6294c2e59..80e7b0e168e 100644
--- a/tests/devicepolicy/Android.bp
+++ b/tests/devicepolicy/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java
index 42d10eb6804..461ae881afc 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java
@@ -413,6 +413,8 @@ public final class BluetoothTest {
@Postsubmit(reason = "new test")
@ApiTest(apis = "android.os.UserManager#DISALLOW_BLUETOOTH_SHARING")
public void share_disallowBluetoothAndSharingRestrictionsAreNotSet_canShare() {
+ Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
+
Poll.forValue("Opp Launcher Component Enabled",
() -> TestApis.packages().activity(OPP_LAUNCHER_COMPONENT)
.isEnabled(TestApis.users().system()))
@@ -420,8 +422,6 @@ public final class BluetoothTest {
.errorOnFail()
.await();
- Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
-
List<ResolveInfo> resolveInfos = sPackageManager.queryIntentActivities(
FILE_SHARING_INTENT, /* flags= */ 0);
assertThat(resolveInfosContainsActivity(resolveInfos, OPP_LAUNCHER_COMPONENT)).isTrue();
@@ -432,6 +432,8 @@ public final class BluetoothTest {
@Postsubmit(reason = "new test")
@ApiTest(apis = "android.os.UserManager#DISALLOW_BLUETOOTH_SHARING")
public void share_disallowBluetoothSharingRestrictionIsSet_canNotShare() {
+ Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
+
Poll.forValue("Opp Launcher Component Enabled",
() -> TestApis.packages().activity(OPP_LAUNCHER_COMPONENT)
.isEnabled(TestApis.users().system()))
@@ -439,8 +441,6 @@ public final class BluetoothTest {
.errorOnFail()
.await();
- Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
-
List<ResolveInfo> resolveInfos = sPackageManager.queryIntentActivities(
FILE_SHARING_INTENT, /* flags= */ 0);
assertThat(resolveInfosContainsActivity(resolveInfos, OPP_LAUNCHER_COMPONENT)).isFalse();
@@ -489,6 +489,8 @@ public final class BluetoothTest {
@ApiTest(apis = "android.os.UserManager#DISALLOW_BLUETOOTH")
@RequireNotHeadlessSystemUserMode(reason = "b/276405672 bluetooth restriction not enforced on secondary users")
public void share_disallowBluetoothRestrictionIsSet_canNotShare() {
+ Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
+
Poll.forValue("Opp Launcher Component Enabled",
() -> TestApis.packages().activity(OPP_LAUNCHER_COMPONENT)
.isEnabled(TestApis.users().system()))
@@ -496,8 +498,6 @@ public final class BluetoothTest {
.errorOnFail()
.await();
- Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
-
List<ResolveInfo> resolveInfos = sPackageManager.queryIntentActivities(
FILE_SHARING_INTENT, /* flags= */ 0);
assertThat(resolveInfosContainsActivity(resolveInfos, OPP_LAUNCHER_COMPONENT)).isFalse();
diff --git a/tests/devicepolicy/telephony/Android.bp b/tests/devicepolicy/telephony/Android.bp
index eeb0ea74f5f..ae05cb7feca 100644
--- a/tests/devicepolicy/telephony/Android.bp
+++ b/tests/devicepolicy/telephony/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/tests/framework/base/grammaticalinflection/Android.bp b/tests/framework/base/grammaticalinflection/Android.bp
index 76679b1869e..8c189684408 100644
--- a/tests/framework/base/grammaticalinflection/Android.bp
+++ b/tests/framework/base/grammaticalinflection/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License
package {
+ default_team: "trendy_team_pixel_global",
default_applicable_licenses: ["Android-Apache-2.0"],
}
@@ -43,4 +44,4 @@ android_test {
sdk_version: "test_current",
per_testcase_directory: true,
-} \ No newline at end of file
+}
diff --git a/tests/framework/base/locale/Android.bp b/tests/framework/base/locale/Android.bp
index c60ffd3384f..153629f44a9 100644
--- a/tests/framework/base/locale/Android.bp
+++ b/tests/framework/base/locale/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License
package {
+ default_team: "trendy_team_pixel_global",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/tests/framework/base/localeconfig/Android.bp b/tests/framework/base/localeconfig/Android.bp
index 773e090ab80..fb5d062abc4 100644
--- a/tests/framework/base/localeconfig/Android.bp
+++ b/tests/framework/base/localeconfig/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License
package {
+ default_team: "trendy_team_pixel_global",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/extensions/util/TestValueCountConsumer.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/extensions/util/TestValueCountConsumer.java
index 34276f0298b..cb3159202df 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/extensions/util/TestValueCountConsumer.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/extensions/util/TestValueCountConsumer.java
@@ -16,9 +16,13 @@
package android.server.wm.jetpack.extensions.util;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.window.extensions.core.util.function.Consumer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -67,6 +71,22 @@ public class TestValueCountConsumer<T> implements Consumer<T> {
}
/**
+ * Returns a list that contains the number of values set in
+ * {@link TestValueCountConsumer#setCount(int)}.
+ */
+ @NonNull
+ public List<T> waitAndGetAllValues() throws InterruptedException {
+ List<T> values = new ArrayList<>();
+ for (int i = 0; i < mCount; i++) {
+ T value = mLinkedBlockingQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ if (value != null) {
+ values.add(value);
+ }
+ }
+ return Collections.unmodifiableList(values);
+ }
+
+ /**
* Clears the queue of currently recorded values.
*/
public void clearQueue() {
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/layout/ExtensionWindowLayoutComponentTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/layout/ExtensionWindowLayoutComponentTest.java
index 71a93d4c094..2d943da5795 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/layout/ExtensionWindowLayoutComponentTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/layout/ExtensionWindowLayoutComponentTest.java
@@ -22,6 +22,7 @@ import static android.server.wm.jetpack.extensions.util.ExtensionsUtil.EXTENSION
import static android.server.wm.jetpack.extensions.util.ExtensionsUtil.assertEqualWindowLayoutInfo;
import static android.server.wm.jetpack.extensions.util.ExtensionsUtil.assumeHasDisplayFeatures;
import static android.server.wm.jetpack.extensions.util.ExtensionsUtil.getExtensionWindowLayoutInfo;
+import static android.server.wm.jetpack.extensions.util.ExtensionsUtil.getWindowExtensions;
import static android.server.wm.jetpack.extensions.util.ExtensionsUtil.isExtensionVersionAtLeast;
import static android.server.wm.jetpack.extensions.util.SidecarUtil.assumeSidecarSupportedDevice;
import static android.server.wm.jetpack.extensions.util.SidecarUtil.getSidecarInterface;
@@ -437,16 +438,21 @@ public class ExtensionWindowLayoutComponentTest extends WindowManagerJetpackTest
mWindowLayoutInfo = getExtensionWindowLayoutInfo(configHandlingActivity);
assumeHasDisplayFeatures(mWindowLayoutInfo);
- final WindowLayoutInfo initialInfo = getExtensionWindowLayoutInfo(
- configHandlingActivity);
+ TestValueCountConsumer<WindowLayoutInfo> consumer = new TestValueCountConsumer<>();
+ // We expect 3 values, 1 before entering PiP, one while in PiP, one after exiting PiP.
+ consumer.setCount(3);
+ getWindowExtensions().getWindowLayoutComponent().addWindowLayoutInfoListener(
+ configHandlingActivity, consumer);
enterPipActivityHandlesConfigChanges(configHandlingActivity);
exitPipActivityHandlesConfigChanges(configHandlingActivity);
- final WindowLayoutInfo updatedInfo = getExtensionWindowLayoutInfo(
- configHandlingActivity);
+ List<WindowLayoutInfo> values = consumer.waitAndGetAllValues();
- assertEquals(initialInfo, updatedInfo);
+ assertEquals(3, values.size());
+ assertEquals(mWindowLayoutInfo, values.get(0));
+ assertTrue(values.get(1).getDisplayFeatures().isEmpty());
+ assertEquals(mWindowLayoutInfo, values.get(2));
}
/**
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java
index e515baed57c..9161b6d1d1b 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestActivity.java
@@ -17,9 +17,11 @@
package android.server.wm.jetpack.utils;
import android.app.Activity;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.concurrent.CountDownLatch;
@@ -31,6 +33,7 @@ import java.util.concurrent.TimeUnit;
*/
public class TestActivity extends Activity implements View.OnLayoutChangeListener {
private CountDownLatch mLayoutLatch;
+ private CountDownLatch mOnConfigurationChangeLatch = new CountDownLatch(1);
private static CountDownLatch sResumeLatch = new CountDownLatch(1);
@Override
@@ -48,6 +51,12 @@ public class TestActivity extends Activity implements View.OnLayoutChangeListene
}
@Override
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mOnConfigurationChangeLatch.countDown();
+ }
+
+ @Override
protected void onResume() {
super.onResume();
sResumeLatch.countDown();
@@ -76,6 +85,27 @@ public class TestActivity extends Activity implements View.OnLayoutChangeListene
}
/**
+ * Resets the configuration change counter.
+ */
+ public void resetOnConfigurationChangeCounter() {
+ mOnConfigurationChangeLatch = new CountDownLatch(1);
+ }
+
+ /**
+ * Waits for a configuration change callback.
+ *
+ * @return {@code true} if the configuration change callback is triggered, {@code false}
+ * otherwise.
+ */
+ public boolean waitForConfigurationChange() {
+ try {
+ return mOnConfigurationChangeLatch.await(3, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ return false;
+ }
+ }
+
+ /**
* Resets layout counter when waiting for a layout to happen before calling
* {@link #waitForOnResume()}.
*/
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java
index db0edf4dcb6..adfa8042ae7 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/WindowManagerJetpackTestBase.java
@@ -281,28 +281,22 @@ public class WindowManagerJetpackTestBase extends ActivityManagerTestBase {
if (activity.isInPictureInPictureMode()) {
throw new IllegalStateException("Activity must not be in PiP");
}
- activity.resetLayoutCounter();
+ activity.resetOnConfigurationChangeCounter();
// Change the orientation
PictureInPictureParams params = (new PictureInPictureParams.Builder()).build();
activity.enterPictureInPictureMode(params);
- // Wait for the activity to layout, which will happen after the orientation change
- assertTrue(activity.waitForLayout());
- // Check that orientation matches
- assertTrue(activity.isInPictureInPictureMode());
+ activity.waitForConfigurationChange();
}
public static void exitPipActivityHandlesConfigChanges(TestActivity activity) {
if (!activity.isInPictureInPictureMode()) {
throw new IllegalStateException("Activity must be in PiP");
}
- activity.resetLayoutCounter();
+ activity.resetOnConfigurationChangeCounter();
Intent intent = new Intent(activity, activity.getClass());
intent.addFlags(FLAG_ACTIVITY_SINGLE_TOP);
activity.startActivity(intent);
- // Wait for the activity to layout, which will happen after the orientation change
- assertTrue(activity.waitForLayout());
- // Check that orientation matches
- assertFalse(activity.isInPictureInPictureMode());
+ activity.waitForConfigurationChange();
}
public static void setActivityOrientationActivityDoesNotHandleOrientationChanges(
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/display/MultiDisplayImeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/display/MultiDisplayImeTests.java
index 40fac0a7779..9ed6c3e1efa 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/display/MultiDisplayImeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/display/MultiDisplayImeTests.java
@@ -486,7 +486,7 @@ public class MultiDisplayImeTests extends MultiDisplayTestBase {
ImeTestActivity2.class, secondDisplay.mId);
// Make firstDisplay the top focus display.
- tapOnDisplayCenter(firstDisplay.mId);
+ touchAndCancelOnDisplayCenterSync(firstDisplay.mId);
mWmState.waitForWithAmState(state -> state.getFocusedDisplayId() == firstDisplay.mId,
"First display must be top focused.");
@@ -528,7 +528,7 @@ public class MultiDisplayImeTests extends MultiDisplayTestBase {
configChangeVerifyStream = clearOnConfigurationChangedFromStream(stream);
// Tap secondDisplay to change it to the top focused display.
- tapOnDisplayCenter(secondDisplay.mId);
+ touchAndCancelOnDisplayCenterSync(secondDisplay.mId);
// Move ImeTestActivity from firstDisplay to secondDisplay.
getLaunchActivityBuilder()
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/window/ConfigChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/window/ConfigChangeTests.java
index 401b1ca9e3d..e596ca6a016 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/window/ConfigChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/window/ConfigChangeTests.java
@@ -71,7 +71,7 @@ public class ConfigChangeTests extends ActivityManagerTestBase {
@Test
public void testRotation90Relaunch() {
- assumeTrue("Skipping test: no rotation support", supportsRotation());
+ assumeTrue("Skipping test: no rotation support", supportsOrientationRequest());
// Should relaunch on every rotation and receive no onConfigurationChanged()
testRotation(TEST_ACTIVITY, 1, 1, 0);
@@ -79,7 +79,7 @@ public class ConfigChangeTests extends ActivityManagerTestBase {
@Test
public void testRotation90NoRelaunch() {
- assumeTrue("Skipping test: no rotation support", supportsRotation());
+ assumeTrue("Skipping test: no rotation support", supportsOrientationRequest());
// Should receive onConfigurationChanged() on every rotation and no relaunch
testRotation(NO_RELAUNCH_ACTIVITY, 1, 0, 1);
@@ -87,7 +87,7 @@ public class ConfigChangeTests extends ActivityManagerTestBase {
@Test
public void testRotation180_RegularActivity() {
- assumeTrue("Skipping test: no rotation support", supportsRotation());
+ assumeTrue("Skipping test: no rotation support", supportsOrientationRequest());
assumeFalse("Skipping test: display cutout present, can't predict exact lifecycle",
hasDisplayCutout());
@@ -97,7 +97,7 @@ public class ConfigChangeTests extends ActivityManagerTestBase {
@Test
public void testRotation180_NoRelaunchActivity() {
- assumeTrue("Skipping test: no rotation support", supportsRotation());
+ assumeTrue("Skipping test: no rotation support", supportsOrientationRequest());
assumeFalse("Skipping test: display cutout present, can't predict exact lifecycle",
hasDisplayCutout());
@@ -111,7 +111,7 @@ public class ConfigChangeTests extends ActivityManagerTestBase {
*/
@Test
public void testRotation180RelaunchWithCutout() {
- assumeTrue("Skipping test: no rotation support", supportsRotation());
+ assumeTrue("Skipping test: no rotation support", supportsOrientationRequest());
assumeTrue("Skipping test: no display cutout", hasDisplayCutout());
testRotation180WithCutout(TEST_ACTIVITY, false /* canHandleConfigChange */);
@@ -119,7 +119,7 @@ public class ConfigChangeTests extends ActivityManagerTestBase {
@Test
public void testRotation180NoRelaunchWithCutout() {
- assumeTrue("Skipping test: no rotation support", supportsRotation());
+ assumeTrue("Skipping test: no rotation support", supportsOrientationRequest());
assumeTrue("Skipping test: no display cutout", hasDisplayCutout());
testRotation180WithCutout(NO_RELAUNCH_ACTIVITY, true /* canHandleConfigChange */);
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerMultiDisplayTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerMultiDisplayTest.java
index 14afd328479..14a9f1aebc9 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerMultiDisplayTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerMultiDisplayTest.java
@@ -69,6 +69,7 @@ public class InputMethodManagerMultiDisplayTest extends MultiDisplayTestBase {
super.setUp();
assumeTrue(mContext.getPackageManager().hasSystemFeature(FEATURE_INPUT_METHODS));
+ assumeFalse(isWatch());
mImManager = mContext.getSystemService(InputMethodManager.class);
diff --git a/tests/jdwp/Android.bp b/tests/jdwp/Android.bp
index dc2db5733ba..899b40b9eb9 100644
--- a/tests/jdwp/Android.bp
+++ b/tests/jdwp/Android.bp
@@ -14,6 +14,7 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_team: "trendy_team_art_performance",
}
java_test {
diff --git a/tests/jdwp/OWNERS b/tests/jdwp/OWNERS
index 6e0629999c7..131c53fbd08 100644
--- a/tests/jdwp/OWNERS
+++ b/tests/jdwp/OWNERS
@@ -1,2 +1,2 @@
-# Bug component: 86431
-include /hostsidetests/jvmti/run-tests/OWNERS
+# Bug component: 1304319
+include platform/art:/OWNERS
diff --git a/tests/libcore/Android.bp b/tests/libcore/Android.bp
new file mode 100644
index 00000000000..28e5d720ccc
--- /dev/null
+++ b/tests/libcore/Android.bp
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_team: "trendy_team_java_core_libraries",
+}
diff --git a/tests/libcore/ojluni/Android.bp b/tests/libcore/ojluni/Android.bp
index 1ee4d5a3e5d..9fd72706fb7 100644
--- a/tests/libcore/ojluni/Android.bp
+++ b/tests/libcore/ojluni/Android.bp
@@ -47,6 +47,7 @@ android_test {
test_suites: [
"cts",
"general-tests",
+ "mcts-art",
"mts-art",
],
data: [
@@ -55,3 +56,95 @@ android_test {
per_testcase_directory: true,
host_required: ["cts-dalvik-host-test-runner"],
}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_lang_invoke",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: [
+ "test.java.lang.invoke",
+ "org.openjdk.tests.java.lang.invoke",
+ ],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_net",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: ["test.java.net"],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_awt_font",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: ["test.java.awt.font"],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_nio_file_attribute",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: ["test.java.nio.file.attribute"],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_security_cert",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: ["test.java.security.cert"],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_time",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: [
+ "tck.java.time.serial",
+ "tck.java.time",
+ "test.java.time",
+ ],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_time_chrono",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: [
+ "tck.java.time.chrono.serial",
+ "test.java.time.chrono",
+ "tck.java.time.chrono",
+ ],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_time_format",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: [
+ "test.java.time.format",
+ "tck.java.time.format",
+ ],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_time_temporal",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: [
+ "tck.java.time.temporal",
+ "tck.java.time.temporal.serial",
+ "test.java.time.temporal",
+ ],
+}
+
+test_module_config {
+ name: "CtsLibcoreOjTestCases_time_zone",
+ base: "CtsLibcoreOjTestCases",
+ test_suites: ["general-tests"],
+ include_filters: [
+ "test.java.time.zone",
+ "tck.java.time.zone.serial",
+ "tck.java.time.zone",
+ ],
+}
diff --git a/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java b/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
index 0a2f63dbac5..bd1c042c0f8 100644
--- a/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
+++ b/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
@@ -524,7 +524,7 @@ public final class TestMeasurementUtil {
* @param measurement GnssMeasurement
* @param softAssert custom SoftAssert
* @param timeInNs event time in ns
- * */
+ */
private static void verifyReceivedSatelliteVehicleTimeInNs(GnssMeasurement measurement,
SoftAssert softAssert, long timeInNs) {
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationValuesTest.java b/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationValuesTest.java
index e00e76036ce..f7add97e1b7 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationValuesTest.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/GnssLocationValuesTest.java
@@ -205,7 +205,7 @@ public class GnssLocationValuesTest extends GnssTestCase {
// For the speed, during the cts test device shouldn't move faster than 1m/s, but allowing up
// to 5m/s for possible early fix noise in moderate signal test environments
if(location.hasSpeed()) {
- softAssert.assertTrue("In the test enviorment, speed should be in the range of [0, 5] m/s",
+ softAssert.assertTrue("In the test environment, speed should be in the range of [0, 5] m/s",
location.getSpeed() >= 0 && location.getSpeed() <= 5);
}
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/GnssTtffTests.java b/tests/location/location_gnss/src/android/location/cts/gnss/GnssTtffTests.java
index 1502f0ca9fc..3eb430364ed 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/GnssTtffTests.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/GnssTtffTests.java
@@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit;
/**
* Tests for the ttff (time to the first fix) validating whether TTFF is
- * below the expected thresholds in differnt scenario
+ * below the expected thresholds in different scenario
*/
public class GnssTtffTests extends GnssTestCase {
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerAlignedUtils.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerAlignedUtils.java
index 1255aaa05a9..d14de4270ec 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerAlignedUtils.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerAlignedUtils.java
@@ -310,7 +310,7 @@ public class PerAlignedUtils {
* Encodes an Asn1Object into a Open type field (X.691-0207, 10.2), used
* mostly for encoding Sequence and SetOf extension additions. A decode method
* hasn't been added as the extension additions should decoded
- * by their relevent Asn1Object decoders.
+ * by their relevant Asn1Object decoders.
*/
public static Iterable<BitStream> encodeOpenTypeField(
Asn1Object object){
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerUnalignedUtils.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerUnalignedUtils.java
index 63f962f9b5b..f7789408ec6 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerUnalignedUtils.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/PerUnalignedUtils.java
@@ -245,7 +245,7 @@ public class PerUnalignedUtils {
* Encodes an Asn1Object into a Open type field (X.691-0207, 10.2), used
* mostly for encoding Sequence and SetOf extension additions. A decode method
* hasn't been added as the extension additions should decoded
- * by their relevent Asn1Object decoders.
+ * by their relevant Asn1Object decoders.
*/
public static Iterable<BitStream> encodeOpenTypeField(Asn1Object object){
PacketBuilder packetBuilder = new PacketBuilder();
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java
index 9f6f5bf8d57..54c370da0c1 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java
@@ -35,6 +35,8 @@ import android.os.Build;
import android.util.Log;
import android.util.Pair;
+import androidx.test.filters.SdkSuppress;
+
import org.junit.After;
import java.util.ArrayDeque;
@@ -45,6 +47,7 @@ import java.util.UUID;
* Wrapper class for trying and testing secure mediacodec decoder components in block model large
* audio buffer mode
*/
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream")
@RequiresApi(api = Build.VERSION_CODES.R)
public class CodecDecoderBlockModelMultiAccessUnitDrmTestBase
extends CodecDecoderBlockModelMultiAccessUnitTestBase {
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java
index f4fd16c5c0c..d0521f883ad 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderTestBase.java
@@ -131,14 +131,6 @@ public class CodecDecoderTestBase extends CodecTestBase {
boolean selectHBD = doesAnyFormatHaveHDRProfile(mMediaType, formatList);
if (!selectHBD && srcFile.contains("10bit")) {
selectHBD = true;
- if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
- // In some cases, webm extractor may not signal profile for 10-bit VP9
- // clips. In such cases, set profile to a 10-bit compatible profile.
- // TODO (b/295804596) Remove the following once webm extractor signals
- // profile correctly for all 10-bit clips
- int[] profileArray = CodecTestBase.PROFILE_HDR_MAP.get(mMediaType);
- format.setInteger(MediaFormat.KEY_PROFILE, profileArray[0]);
- }
}
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
getColorFormat(mCodecName, mMediaType, mSurface != null, selectHBD));
diff --git a/tests/media/src/android/mediav2/cts/Av1FilmGrainValidationTest.java b/tests/media/src/android/mediav2/cts/Av1FilmGrainValidationTest.java
index a142204320a..091f4b34724 100644
--- a/tests/media/src/android/mediav2/cts/Av1FilmGrainValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/Av1FilmGrainValidationTest.java
@@ -33,6 +33,7 @@ import android.mediav2.common.cts.OutputManager;
import android.util.Log;
import android.util.Pair;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -163,6 +164,8 @@ public class Av1FilmGrainValidationTest extends CodecDecoderTestBase {
*/
@Test
public void testAv1FilmGrainRequirement() throws Exception {
+ Assume.assumeTrue("Skipping, Only intended for devices with SDK >= 202404",
+ BOARD_FIRST_SDK_IS_AT_LEAST_202404);
MediaFormat format = setUpSource(mTestFile);
mImageSurface = new ImageSurface();
setUpSurface(getWidth(format), getHeight(format), ImageFormat.YUV_420_888, 1, 0, null);
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java
index 5f57dc753b7..acdbdae1238 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java
@@ -25,7 +25,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
import android.media.AudioFormat;
import android.media.MediaCodec;
@@ -96,28 +95,35 @@ public class CodecEncoderBlockModelMultiAccessUnitTest extends CodecEncoderBlock
@Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
public static Collection<Object[]> input() {
List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
- // mediaType, arrays of bit-rates, sample rates, channel counts, pcm encoding
- {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000, 128000}, new int[]{8000, 12000,
- 16000, 22050, 24000, 32000, 44100, 48000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000, 128000}, new int[]{8000, 12000,
- 16000, 24000, 48000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 5150, 5900, 6700, 7400, 7950,
- 10200, 12200}, new int[]{8000}, new int[]{1},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 8850, 12650, 14250, 15850,
- 18250, 19850, 23050, 23850}, new int[]{16000}, new int[]{1},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
- new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
- new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_FLOAT},
+ // mediaType, arrays of bit-rates, sample rate, channel counts, pcm encoding
+
+ // mono testing @ common sample rates, pcm encoding
+ {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 12200}, new int[]{8000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 23850}, new int[]{16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_FLOAT},
+
+ // stereo testing @ common sample rates, pcm encoding
+ {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{128000}, new int[]{44100, 48000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{128000}, new int[]{48000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_FLOAT},
}));
List<Object[]> argsList = flattenParams(defArgsList);
- return prepareParamList(argsList, true, true, false, true);
+ return prepareParamList(argsList, true, true, false, true, ComponentClass.ALL,
+ new String[]{FEATURE_MultipleFrames});
}
public CodecEncoderBlockModelMultiAccessUnitTest(String encoder, String mediaType,
@@ -297,11 +303,6 @@ public class CodecEncoderBlockModelMultiAccessUnitTest extends CodecEncoderBlock
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testSimpleEncode() throws IOException, InterruptedException {
- assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
- isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
- assumeTrue(mCodecName + " is not compatible with LinearBlocks",
- MediaCodec.LinearBlock.isCodecCopyFreeCompatible(new String[]{mCodecName}));
-
CodecEncoderTestBase referenceBase = new CodecEncoderTestBase(mCodecName, mMediaType,
new EncoderConfigParams[]{mActiveEncCfg}, mAllTestParams);
referenceBase.encodeToMemory(mCodecName, mActiveEncCfg, mActiveRawRes, Integer.MAX_VALUE,
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java
index ed55b72a476..2dfcd087669 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java
@@ -24,7 +24,6 @@ import static android.mediav2.cts.CodecDecoderMultiAccessUnitTest.getCompression
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
import android.media.AudioFormat;
import android.media.MediaCodec;
@@ -93,28 +92,35 @@ public class CodecEncoderMultiAccessUnitTest extends CodecEncoderTestBase {
@Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
public static Collection<Object[]> input() {
List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
- // mediaType, arrays of bit-rates, sample rates, channel counts, pcm encoding
- {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000, 128000}, new int[]{8000, 12000,
- 16000, 22050, 24000, 32000, 44100, 48000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000, 128000}, new int[]{8000, 12000,
- 16000, 24000, 48000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 5150, 5900, 6700, 7400, 7950,
- 10200, 12200}, new int[]{8000}, new int[]{1},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 8850, 12650, 14250, 15850,
- 18250, 19850, 23050, 23850}, new int[]{16000}, new int[]{1},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
- new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_16BIT},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
- new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
- AudioFormat.ENCODING_PCM_FLOAT},
+ // mediaType, arrays of bit-rates, sample rate, channel counts, pcm encoding
+
+ // mono testing @ common sample rates, pcm encoding
+ {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 12200}, new int[]{8000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 23850}, new int[]{16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+ new int[]{1}, AudioFormat.ENCODING_PCM_FLOAT},
+
+ // stereo testing @ common sample rates, pcm encoding
+ {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{128000}, new int[]{44100, 48000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{128000}, new int[]{48000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+ new int[]{2}, AudioFormat.ENCODING_PCM_FLOAT},
}));
List<Object[]> argsList = flattenParams(defArgsList);
- return prepareParamList(argsList, true, true, false, true);
+ return prepareParamList(argsList, true, true, false, true, ComponentClass.ALL,
+ new String[]{FEATURE_MultipleFrames});
}
public CodecEncoderMultiAccessUnitTest(String encoder, String mediaType,
@@ -285,9 +291,6 @@ public class CodecEncoderMultiAccessUnitTest extends CodecEncoderTestBase {
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testSimpleEncode() throws IOException, InterruptedException {
- assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
- isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-
CodecEncoderTestBase cetb = new CodecEncoderTestBase(mCodecName, mMediaType,
new EncoderConfigParams[]{mActiveEncCfg}, mAllTestParams);
cetb.encodeToMemory(mCodecName, mActiveEncCfg, mActiveRawRes, Integer.MAX_VALUE, true,
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
index 3c046fac272..3fb93cceb8d 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
@@ -258,6 +258,12 @@ public class CodecEncoderSurfaceTest extends CodecEncoderSurfaceTestBase {
final List<Object[]> expandedArgsList =
CodecTestBase.prepareParamList(argsList, isEncoder, needAudio, needVideo, true);
+ // Prior to Android U, this test was not testing persistent surface. While this has
+ // been expected behavior for a long time, we only started testing it in Android U, so
+ // some older devices might not pass this test in persistent surface mode for some
+ // combination of codecs. These may show up as failures when running MTS tests for s/w
+ // encoders with h/w decoders in such cases.
+
// Prior to Android U, this test was using the first decoder for a given mediaType.
// In Android U, this was updated to test the encoders with all decoders for the
// given mediaType. There are some vendor encoders in older versions of Android
diff --git a/tests/mediapc/Android.bp b/tests/mediapc/Android.bp
index e76b60325fa..756f3ab3af9 100644
--- a/tests/mediapc/Android.bp
+++ b/tests/mediapc/Android.bp
@@ -27,6 +27,9 @@ android_test {
"MediaPerformanceClassCommon",
"mediapc-requirements",
],
+ jni_libs: [
+ "libctsmediapc_vulkan_jni",
+ ],
platform_apis: true,
srcs: ["src/**/*.java"],
// Tag this module as a cts test artifact
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index 8c81520f758..bac06fa962c 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -379,52 +379,6 @@ public class PerformanceClassEvaluator {
}
/**
- * [2.2.7.1/5.1/H-1-7] MUST have a codec initialization latency of 65(R) / 50(S) / 40(T)
- * ms or less for a 1080p or smaller video encoding session for all hardware video
- * encoders when under load. Load here is defined as a concurrent 1080p to 720p
- * video-only transcoding session using hardware video codecs together with the 1080p
- * audio-video recording initialization. For Dolby vision codec, the codec initialization
- * latency MUST be 50 ms or less.
- */
- public static CodecInitLatencyRequirement createR5_1__H_1_7(String mediaType) {
- long latency = mediaType.equals(MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION) ? 50L : 40L;
- RequiredMeasurement<Long> codec_init_latency =
- RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY)
- .setPredicate(RequirementConstants.LONG_LTE)
- .addRequiredValue(Build.VERSION_CODES.R, 65L)
- .addRequiredValue(Build.VERSION_CODES.S, 50L)
- .addRequiredValue(Build.VERSION_CODES.TIRAMISU, latency)
- .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, latency)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, latency)
- .build();
-
- return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_7,
- codec_init_latency);
- }
-
- /**
- * [2.2.7.1/5.1/H-1-8] MUST have a codec initialization latency of 50(R) / 40(S) / 30(T)
- * ms or less for a 128 kbps or lower bitrate audio encoding session for all audio
- * encoders when under load. Load here is defined as a concurrent 1080p to 720p
- * video-only transcoding session using hardware video codecs together with the 1080p
- * audio-video recording initialization.
- */
- public static CodecInitLatencyRequirement createR5_1__H_1_8() {
- RequiredMeasurement<Long> codec_init_latency =
- RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY)
- .setPredicate(RequirementConstants.LONG_LTE)
- .addRequiredValue(Build.VERSION_CODES.R, 50L)
- .addRequiredValue(Build.VERSION_CODES.S, 40L)
- .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 30L)
- .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, 30L)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, 30L)
- .build();
-
- return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_8,
- codec_init_latency);
- }
-
- /**
* [2.2.7.1/5.1/H-1-12] Codec initialization latency of 40ms or less for a 1080p or
* smaller video decoding session for all hardware video encoders when under load. Load
* here is defined as a concurrent 1080p to 720p video-only transcoding session using
@@ -442,25 +396,6 @@ public class PerformanceClassEvaluator {
return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_12,
codec_init_latency);
}
-
- /**
- * [2.2.7.1/5.1/H-1-13] Codec initialization latency of 30ms or less for a 128kbps or
- * lower bitrate audio decoding session for all audio encoders when under load. Load here
- * is defined as a concurrent 1080p to 720p video-only transcoding session using hardware
- * video codecs together with the 1080p audio-video recording initialization.
- */
- public static CodecInitLatencyRequirement createR5_1__H_1_13() {
- RequiredMeasurement<Long> codec_init_latency =
- RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY)
- .setPredicate(RequirementConstants.LONG_LTE)
- .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 30L)
- .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, 30L)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, 30L)
- .build();
-
- return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_13,
- codec_init_latency);
- }
}
// used for requirements [2.2.7.1/5.1/H-1-1], [2.2.7.1/5.1/H-1-2], [2.2.7.1/5.1/H-1-3],
@@ -1626,7 +1561,7 @@ public class PerformanceClassEvaluator {
private static final String TAG =
LogicalMultiCameraRequirement.class.getSimpleName();
- private LogicalMultiCameraRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ private LogicalMultiCameraRequirement(String id, RequiredMeasurement<?>... reqs) {
super(id, reqs);
}
@@ -1654,56 +1589,6 @@ public class PerformanceClassEvaluator {
}
}
- // used for requirements [7.6.1/H-1-1], [7.6.1/H-2-1]
- public static class MemoryRequirement extends Requirement {
- private static final String TAG = MemoryRequirement.class.getSimpleName();
-
- // Media performance requires 6 GB minimum RAM, but keeping the following to
- // 5 GB as activityManager.getMemoryInfo() typically returns around 5.4 GB on a 6 GB device,
- // so these values are a bit lower than the required value stated on the Android CDD.
- private static final long RS_REQUIRED_MEMORY_MB = Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB;
- private static final long TUV_REQUIRED_MEMORY_MB = Utils.MIN_MEMORY_PERF_CLASS_T_MB;
-
- private MemoryRequirement(String id, RequiredMeasurement<?> ... reqs) {
- super(id, reqs);
- }
-
- public void setPhysicalMemory(long physicalMemory) {
- this.<Long>setMeasuredValue(RequirementConstants.PHYSICAL_MEMORY, physicalMemory);
- }
-
- /**
- * [7.6.1/H-1-1] MUST have at least 6 GB of physical memory.
- */
- public static MemoryRequirement createR7_6_1__H_1_1() {
- RequiredMeasurement<Long> physical_memory = RequiredMeasurement
- .<Long>builder()
- .setId(RequirementConstants.PHYSICAL_MEMORY)
- .setPredicate(RequirementConstants.LONG_GTE)
- .addRequiredValue(Build.VERSION_CODES.R, RS_REQUIRED_MEMORY_MB)
- .build();
-
- return new MemoryRequirement(RequirementConstants.R7_6_1__H_1_1, physical_memory);
- }
-
- /**
- * [7.6.1/H-2-1] MUST have at least 6/8 GB of physical memory.
- */
- public static MemoryRequirement createR7_6_1__H_2_1() {
- RequiredMeasurement<Long> physical_memory = RequiredMeasurement
- .<Long>builder()
- .setId(RequirementConstants.PHYSICAL_MEMORY)
- .setPredicate(RequirementConstants.LONG_GTE)
- .addRequiredValue(Build.VERSION_CODES.S, RS_REQUIRED_MEMORY_MB)
- .addRequiredValue(Build.VERSION_CODES.TIRAMISU, TUV_REQUIRED_MEMORY_MB)
- .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, TUV_REQUIRED_MEMORY_MB)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, TUV_REQUIRED_MEMORY_MB)
- .build();
-
- return new MemoryRequirement(RequirementConstants.R7_6_1__H_2_1, physical_memory);
- }
- }
-
public static class PreviewStabilizationRequirement extends Requirement {
private static final String TAG =
PreviewStabilizationRequirement.class.getSimpleName();
@@ -2236,22 +2121,6 @@ public class PerformanceClassEvaluator {
return new VideoCodecRequirement(RequirementConstants.R5_1__H_1_22, requirement);
}
-
- /**
- * [5.12/H-1-2] MUST support RGBA_1010102 color format for all hardware AV1 and HEVC
- * encoders present on the device.
- */
- public static VideoCodecRequirement createColorFormatSupportReq() {
- RequiredMeasurement<Boolean> requirement = RequiredMeasurement
- .<Boolean>builder()
- .setId(RequirementConstants.RGBA_1010102_COLOR_FORMAT_REQ)
- .setPredicate(RequirementConstants.BOOLEAN_EQ)
- .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, true)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, true)
- .build();
-
- return new VideoCodecRequirement(RequirementConstants.R5_12__H_1_2, requirement);
- }
}
public static class UltraWideZoomRatioRequirement extends Requirement {
@@ -2388,14 +2257,6 @@ public class PerformanceClassEvaluator {
return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_6_4k());
}
- public CodecInitLatencyRequirement addR5_1__H_1_7(String mediaType) {
- return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_7(mediaType));
- }
-
- public CodecInitLatencyRequirement addR5_1__H_1_8() {
- return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_8());
- }
-
public ConcurrentCodecRequirement addR5_1__H_1_9_1080p() {
return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_9_1080p());
}
@@ -2420,10 +2281,6 @@ public class PerformanceClassEvaluator {
return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_12());
}
- public CodecInitLatencyRequirement addR5_1__H_1_13() {
- return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_13());
- }
-
/* Adds requirement 5.1/H-1-14 */
public VideoCodecRequirement addRAV1DecoderReq() {
return this.addRequirement(VideoCodecRequirement.createRAV1DecoderReq());
@@ -2502,18 +2359,11 @@ public class PerformanceClassEvaluator {
return this.addRequirement(SecureCodecRequirement.createR5_7__H_1_2());
}
-
- /* Adds requirement 5.12/H-1-2 */
- public VideoCodecRequirement addColorFormatSupportReq() {
- return this.addRequirement(VideoCodecRequirement.createColorFormatSupportReq());
- }
-
/* Adds requirement 5.12/H-1-3 */
public ExtYuvTargetRequirement addExtYUVSupportReq() {
return this.addRequirement(ExtYuvTargetRequirement.createExtensionReq());
}
-
/* Adds requirement 7.5/H-1-1 */
public PrimaryCameraRequirement addPrimaryRearCameraReq() {
return this.addRequirement(PrimaryCameraRequirement.createRearPrimaryCamera());
@@ -2586,10 +2436,6 @@ public class PerformanceClassEvaluator {
return this.<DensityRequirement>addRequirement(DensityRequirement.createR7_1_1_3__H_1_1());
}
- public MemoryRequirement addR7_6_1__H_1_1() {
- return this.<MemoryRequirement>addRequirement(MemoryRequirement.createR7_6_1__H_1_1());
- }
-
public ResolutionRequirement addR7_1_1_1__H_2_1() {
return this.<ResolutionRequirement>addRequirement(
ResolutionRequirement.createR7_1_1_1__H_2_1());
@@ -2599,11 +2445,6 @@ public class PerformanceClassEvaluator {
return this.<DensityRequirement>addRequirement(DensityRequirement.createR7_1_1_3__H_2_1());
}
- public MemoryRequirement addR7_6_1__H_2_1() {
- return this.<MemoryRequirement>addRequirement(MemoryRequirement.createR7_6_1__H_2_1());
- }
-
-
public FileSystemRequirement addR8_2__H_1_1() {
return this.addRequirement(FileSystemRequirement.createR8_2__H_1_1());
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
index a9e38017e83..b9c7e15cc06 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -66,6 +66,8 @@ public final class RequirementConstants {
public static final String R7_1_1_3__H_1_1 = "r7_1_1_3__h_1_1"; // 7.1.1.3/H-1-1
public static final String R7_1_1_3__H_2_1 = "r7_1_1_3__h_2_1"; // 7.1.1.3/H-2-1
public static final String R7_1_1_3__H_3_1 = "r7_1_1_3__H_3_1"; // 7.1.1.3/H-3-1
+ public static final String R7_1_4_1__H_1_2 = "r7_1_4_1__h_1_2"; // 7.1.4.1/H-1-2
+ public static final String R7_1_4_1__H_1_3 = "r7_1_4_1__h_1_3"; // 7.1.4.1/H-1-3
public static final String R7_5__H_1_1 = "r7_5__h_1_1"; // 7.5/H-1-1
public static final String R7_5__H_1_2 = "r7_5__h_1_2"; // 7.5/H-1-2
public static final String R7_5__H_1_3 = "r7_5__h_1_3"; // 7.5/H-1-3
@@ -116,6 +118,8 @@ public final class RequirementConstants {
public static final String DISPLAY_DENSITY = "display_density_dpi";
public static final String DISPLAY_LUMINANCE_NITS = "display_luminance_nits";
public static final String DYNAMIC_COLOR_ASPECTS = "dynamic_color_aspects";
+ public static final String EGL_EXT_PROTECTED_CONTENT = "egl_ext_protected_content";
+ public static final String EGL_IMG_CONTEXT_PRIORITY = "egl_img_context_priority";
public static final String EXT_YUV_EXTENSION = "ext_yuv_target_supported";
public static final String FILESYSTEM_IO_RATE = "filesystem_io_rate_mbps";
public static final String FRAMES_DROPPED = "frame_drops_per_30sec";
@@ -183,6 +187,7 @@ public final class RequirementConstants {
public static final String TEST_RESOLUTION = "resolution";
// keep-sorted end
+
public enum Result {
NA, MET, UNMET
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl b/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl
index 31966a1613f..b2794b97921 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl
@@ -1,3 +1,83 @@
+{{- /*
+ * CompMethod generates comparison method constant from a RequiredMeasurement
+ */}}
+{{- define "CompMethod" -}}
+ {{- $c :=.GetComparison }}
+ {{- $mt :=.GetMeasurementType }}
+ {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}BOOLEAN
+ {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}DOUBLE
+ {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}INTEGER
+ {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}STRING
+ {{- else if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}LONG
+ {{- else }}{{$mt}}
+ {{- end }}_
+ {{- if eq $c.String "COMPARISON_EQUAL" -}}EQ
+ {{- else if eq $c.String "COMPARISON_LESS_THAN" -}}LT
+ {{- else if eq $c.String "COMPARISON_LESS_THAN_OR_EQUAL" -}}LTE
+ {{- else if eq $c.String "COMPARISON_GREATER_THAN" -}}GTE
+ {{- else if eq $c.String "COMPARISON_GREATER_THAN_OR_EQUAL" -}}GTE
+ {{- else if eq $c.String "COMPARISON_INFO_ONLY" -}}INFO
+ {{- else }}{{$c}}
+ {{- end }}
+{{- end -}}
+
+
+{{- /*
+ * JavaClass generates Java class name from a MeasurementType
+ */}}
+{{- define "JavaClass" -}}
+ {{- if eq .String "MEASUREMENT_TYPE_BOOL" -}}Boolean
+ {{- else if eq .String "MEASUREMENT_TYPE_DOUBLE" -}}Double
+ {{- else if eq .String "MEASUREMENT_TYPE_INT" -}}Integer
+ {{- else if eq .String "MEASUREMENT_TYPE_STRING" -}}String
+ {{- else if eq .String "MEASUREMENT_TYPE_LONG" -}}Long
+ {{- else }}{{.}}
+ {{- end }}
+{{- end -}}
+
+{{- /*
+ * JavaClass generates Java type from a MeasurementType
+ */}}
+{{- define "JavaType" -}}
+ {{- if eq .String "MEASUREMENT_TYPE_BOOL" -}}boolean
+ {{- else if eq .String "MEASUREMENT_TYPE_DOUBLE" -}}double
+ {{- else if eq .String "MEASUREMENT_TYPE_INT" -}}int
+ {{- else if eq .String "MEASUREMENT_TYPE_STRING" -}}String
+ {{- else if eq .String "MEASUREMENT_TYPE_LONG" -}}long
+ {{- else }}{{.}}
+ {{- end }}
+{{- end -}}
+
+{{- /*
+ * VersionCode generates the android.Build VersionCode constant from an mpc value.
+ * It is an error if the mpc value listed here.
+ */}}
+{{- define "VersionCode" -}}
+ VERSION_CODES.
+ {{- if eq . 30}}R
+ {{- else if eq . 31}}S
+ {{- else if eq . 33}}TIRAMISU
+ {{- else if eq . 34}}UPSIDE_DOWN_CAKE
+ {{- else if eq . 35}}VANILLA_ICE_CREAM
+ {{- else }}{{.}}
+ {{- end }}
+{{- end -}}
+
+
+{{- /*
+ * MeasurementValue gets value from RequiredValue base on the MeasurementType
+ * It is an error if the MeasurementType is not listed here.
+ */}}
+{{- define "MeasurementValue" -}}
+ {{- if eq .MeasurementType.String "MEASUREMENT_TYPE_BOOL" -}}{{.RequiredValue.GetBoolValue}}
+ {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_DOUBLE" -}}{{printf "%f" .RequiredValue.GetDoubleValue}}
+ {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_INT" -}}{{.RequiredValue.GetIntValue}}
+ {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_STRING" -}}"{{.RequiredValue.GetStringValue}}"
+ {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_LONG" -}}{{.RequiredValue.GetLongValue}}L
+ {{- else }}{{.MeasurementType}}
+ {{- end }}
+{{- end -}}
+
/*
* Copyright (C) 2024 The Android Open Source Project
*
@@ -16,6 +96,8 @@
package android.mediapc.cts.common;
+import android.os.Build.VERSION_CODES;
+
/**
* Requirements Classes.
*/
@@ -24,14 +106,34 @@ public final class Requirements {
{{- range $r := .ReqList.GetRequirements }}
{{- if $r.GetName }}
/**
- * Create {{UpperCamelCase $r.GetName}}Requirement for requirement {{ $r.GetId }}.
+ * Add a new {{UpperCamelCase $r.GetName}}Requirement for requirement {{ $r.GetId }} to a
+ * {@code PerformanceClassEvaluator} instance.
{{- with $r.GetDescription}}
*
* {{.}}{{end}}
*/
- public static {{UpperCamelCase $r.GetName}}Requirement create{{ SafeReqID $r.GetId | UpperCase}}() {
- return {{UpperCamelCase $r.GetName}}Requirement.create();
- }
+ public static {{UpperCamelCase $r.GetName}}Requirement add{{ SafeReqID $r.GetId | UpperCase}}(
+ PerformanceClassEvaluator pce) {
+ return pce.addRequirement({{UpperCamelCase $r.GetName}}Requirement.create());
+ }
+
+ {{- range $v_id, $v := $r.GetVariants }}
+
+ /**
+ * Add a new {{UpperCamelCase $r.GetName}}Requirement for requirement {{ $r.GetId }}
+ * to a {@code PerformanceClassEvaluator} instance
+ * {{$v.GetDescription}}.
+ {{- with $r.GetDescription}}
+ *
+ * {{.}}{{end}}
+ */
+ public static {{UpperCamelCase $r.GetName}}Requirement add{{ SafeReqID $r.GetId | UpperCase}}
+ {{- UpperCamelCase $v_id}}(
+ PerformanceClassEvaluator pce) {
+ return pce.addRequirement({{UpperCamelCase $r.GetName}}Requirement.create
+ {{- UpperCamelCase $v_id}}());
+ }
+ {{- end }}{{/* range $v_id, $v */}}
/**
* {{ $r.GetId }} {{$r.GetName}}
@@ -47,76 +149,77 @@ public final class Requirements {
*
* {{.}}{{end}}
*/
- public static {{UpperCamelCase $r.GetName}}Requirement create() {
+ private static {{UpperCamelCase $r.GetName}}Requirement create() {
{{- range $m_id, $m := $r.GetMeasurements }}
{{- $mt := $m.GetMeasurementType}}
{{- $c := $m.GetComparison}}
- var {{LowerCamelCase $m.GetId}} = RequiredMeasurement
- .<
- {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}Boolean
- {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}Double
- {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}Integer
- {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}String
- {{- else }}{{$mt}}
- {{- end }}>builder()
- .setId("{{$m.GetId}}")
- .setPredicate(RequirementConstants.
- {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}BOOLEAN
- {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}DOUBLE
- {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}INTEGER
- {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}STRING
- {{- else }}{{$mt}}
- {{- end }}_
- {{- if eq $c.String "COMPARISON_EQUAL" -}}EQ
- {{- else if eq $c.String "COMPARISON_LESS_THAN" -}}LT
- {{- else if eq $c.String "COMPARISON_LESS_THAN_OR_EQUAL" -}}LTE
- {{- else if eq $c.String "COMPARISON_GREATER_THAN" -}}GTE
- {{- else if eq $c.String "COMPARISON_GREATER_THAN_OR_EQUAL" -}}GTE
- {{- else if eq $c.String "COMPARISON_INFO_ONLY" -}}INFO
- {{- else }}{{$c}}
- {{- end }})
+ var {{LowerCamelCase $m_id}} = RequiredMeasurement
+ .<{{template "JavaClass" $mt}}>builder()
+ .setId("{{$m_id}}")
+ .setPredicate(RequirementConstants.{{template "CompMethod" $m}})
{{- range $mpc, $s := $r.GetSpecs }}
- {{- with index $s.GetRequiredValues $m.GetId}}
- .addRequiredValue({{$mpc}}
- {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}, {{.GetBoolValue}}
- {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}, {{printf "%f" .GetDoubleValue}}
- {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}, {{.GetIntValue}}
- {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}, "{{.GetStringValue}}"
- {{- else }}{{$mt}}
- {{- end }})
+ {{- with index $s.GetRequiredValues $m_id}}
+ .addRequiredValue({{template "VersionCode" $mpc}}, {{template
+ "MeasurementValue" Dict "RequiredValue" . "MeasurementType" $mt}})
{{- end}}
{{- end}}
.build();
{{- end }}
- return new {{UpperCamelCase $r.GetName}}Requirement(
+ return new {{UpperCamelCase $r.GetName}}Requirement(
"{{SafeReqID $r.GetId }}"
{{- range $m_id, $m := $r.GetMeasurements }},
- {{LowerCamelCase $m.GetId}}
+ {{LowerCamelCase $m_id}}
{{- end}});
}
+ {{- range $v_id, $v := $r.GetVariants }}
+ /**
+ * {{ $r.GetId }} {{$r.GetName}}{{- with $v.GetDescription}} {{.}}{{end}}
+ {{- with $r.GetDescription}}
+ *
+ * {{.}}{{end}}
+ */
+ private static {{UpperCamelCase $r.GetName}}Requirement create{{UpperCamelCase $v_id}}() {
+ {{- range $m_id, $m := $r.GetMeasurements }}
+ {{- $mt := $m.GetMeasurementType}}
+ {{- $c := $m.GetComparison}}
+ var {{LowerCamelCase $m_id}} = RequiredMeasurement
+ .<{{template "JavaClass" $mt}}>builder()
+ .setId("{{$m_id}}")
+ .setPredicate(RequirementConstants.{{template "CompMethod" $m}})
+ {{- range $mpc, $s := $r.GetSpecs }}
+ {{- $vs := index $s.GetVariantSpecs $v_id}}
+ {{- if $vs }}
+ {{- with index $vs.GetRequiredValues $m_id}}
+ .addRequiredValue({{template "VersionCode" $mpc}}, {{template
+ "MeasurementValue" Dict "RequiredValue" . "MeasurementType" $mt}})
+ {{- end}}{{/* if $vs */}}
+ {{- end}}{{/* with rv */}}
+ {{- end}}{{/* range $mpc, $s */}}
+ .build();
+ {{- end}}{{/* range $m_id, $m */}}
+ return new {{UpperCamelCase $r.GetName}}Requirement(
+ "{{SafeReqID $r.GetId }}"
+ {{- range $m_id, $m := $r.GetMeasurements }},
+ {{LowerCamelCase $m_id}}
+ {{- end}});
+ }
+ {{- end }}{{/* range $v_id, $v */}}
- {{- range $m_id, $m := $r.GetMeasurements }}
- {{- $mt := $m.GetMeasurementType}}
- /** {{$m.GetDescription}} */
- public void set{{UpperCamelCase $m.GetId}}(
- {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}boolean
- {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}double
- {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}int
- {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}String
- {{- else }}{{$mt}}
- {{- end }} v) {
- this.setMeasuredValue("{{$m.GetId}}", v);
- }
- {{- end }}{{/* range $m_id, $m */}}
-
- private {{UpperCamelCase $r.GetName}}Requirement(String id, RequiredMeasurement<?>... reqs) {
- super(id, reqs);
- }
+ {{- range $m_id, $m := $r.GetMeasurements }}
+ {{- $mt := $m.GetMeasurementType}}
+ /** {{$m.GetDescription}} */
+ public void set{{UpperCamelCase $m_id}}({{template "JavaType" $mt}} v) {
+ this.setMeasuredValue("{{$m_id}}", v);
+ }
+ {{- end }}{{/* range $m_id, $m */}}
+ private {{UpperCamelCase $r.GetName}}Requirement(String id, RequiredMeasurement<?>... reqs) {
+ super(id, reqs);
+ }
}
{{- end }} {{/* if $r.GetName */}}
{{- end }} {{/* range $r */}}
- private Requirements () {}
+ private Requirements () {}
}
diff --git a/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementsTest.java b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementsTest.java
index 54084f0553c..aa6cc552d8e 100644
--- a/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementsTest.java
+++ b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementsTest.java
@@ -22,7 +22,9 @@ import android.mediapc.cts.common.Requirements.HDRDisplayRequirement;
import android.mediapc.cts.common.Requirements.SequentialWriteRequirement;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -30,11 +32,14 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class RequirementsTest {
+ @Rule
+ public final TestName mTestName = new TestName();
// HDRDisplayRequirement has two required measurements.
@Test
public void hdrDisplay_noHdr_1000nits() {
- var req = HDRDisplayRequirement.create();
+ var pce = new PerformanceClassEvaluator(mTestName);
+ HDRDisplayRequirement req = Requirements.addR7_1_1_3__H_3_1(pce);
req.setIsHdr(false);
req.setDisplayLuminanceNits(1000);
@@ -44,7 +49,8 @@ public class RequirementsTest {
@Test
public void hdrDisplay_900nits() {
- var req = HDRDisplayRequirement.create();
+ var pce = new PerformanceClassEvaluator(mTestName);
+ HDRDisplayRequirement req = Requirements.addR7_1_1_3__H_3_1(pce);
req.setIsHdr(true);
req.setDisplayLuminanceNits(900);
@@ -54,7 +60,8 @@ public class RequirementsTest {
@Test
public void hdrDisplay_1000nits() {
- var req = HDRDisplayRequirement.create();
+ var pce = new PerformanceClassEvaluator(mTestName);
+ HDRDisplayRequirement req = Requirements.addR7_1_1_3__H_3_1(pce);
req.setIsHdr(true);
req.setDisplayLuminanceNits(1000);
@@ -66,7 +73,8 @@ public class RequirementsTest {
// SequentialWriteRequirement has more than one MPC level.
@Test
public void sequentialWrite_90mbps() {
- var req = SequentialWriteRequirement.create();
+ var pce = new PerformanceClassEvaluator(mTestName);
+ SequentialWriteRequirement req = Requirements.addR8_2__H_1_1(pce);
req.setFilesystemIoRateMbps(90);
var pc = req.computePerformanceClass();
@@ -75,7 +83,8 @@ public class RequirementsTest {
@Test
public void sequentialWrite_100mbps() {
- var req = SequentialWriteRequirement.create();
+ var pce = new PerformanceClassEvaluator(mTestName);
+ SequentialWriteRequirement req = Requirements.addR8_2__H_1_1(pce);
req.setFilesystemIoRateMbps(100);
var pc = req.computePerformanceClass();
@@ -84,7 +93,8 @@ public class RequirementsTest {
@Test
public void sequentialWrite_125mbps() {
- var req = SequentialWriteRequirement.create();
+ var pce = new PerformanceClassEvaluator(mTestName);
+ SequentialWriteRequirement req = Requirements.addR8_2__H_1_1(pce);
req.setFilesystemIoRateMbps(125);
var pc = req.computePerformanceClass();
@@ -93,7 +103,8 @@ public class RequirementsTest {
@Test
public void sequentialWrite_150mbps() {
- var req = SequentialWriteRequirement.create();
+ var pce = new PerformanceClassEvaluator(mTestName);
+ SequentialWriteRequirement req = Requirements.addR8_2__H_1_1(pce);
req.setFilesystemIoRateMbps(150);
var pc = req.computePerformanceClass();
diff --git a/tests/mediapc/jni/Android.bp b/tests/mediapc/jni/Android.bp
new file mode 100644
index 00000000000..f5997bbbf52
--- /dev/null
+++ b/tests/mediapc/jni/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_library {
+ name: "libctsmediapc_vulkan_jni",
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ "libvulkan",
+ ],
+ srcs: [
+ "VulkanDeviceInfo.cpp",
+ ],
+ static_libs: ["libvkjson_ndk"],
+ header_libs: [
+ "jni_headers",
+ "liblog_headers",
+ ],
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+ sdk_version: "29",
+}
diff --git a/tests/mediapc/jni/VulkanDeviceInfo.cpp b/tests/mediapc/jni/VulkanDeviceInfo.cpp
new file mode 100644
index 00000000000..6833c507e70
--- /dev/null
+++ b/tests/mediapc/jni/VulkanDeviceInfo.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <android/log.h>
+#include <jni.h>
+#include <vkjson.h>
+
+namespace {
+
+jstring GetVkJSON(JNIEnv* env, jclass /*clazz*/) {
+ std::string vkjson(VkJsonInstanceToJson(VkJsonGetInstance()));
+ return env->NewStringUTF(vkjson.c_str());
+}
+
+static JNINativeMethod gMethods[] = {
+ {"nativeGetVkJSON", "()Ljava/lang/String;", (void*) GetVkJSON},
+};
+
+} // anonymous namespace
+
+extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv* env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ return JNI_ERR;
+ }
+ jclass clazz = env->FindClass("android/mediapc/cts/VulkanTest");
+ int status = env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(JNINativeMethod));
+ if (status != JNI_OK) {
+ return JNI_ERR;
+ }
+ return JNI_VERSION_1_6;
+}
diff --git a/tests/mediapc/requirements/Android.bp b/tests/mediapc/requirements/Android.bp
index 7e3bcb29d62..78ebcf2f02c 100644
--- a/tests/mediapc/requirements/Android.bp
+++ b/tests/mediapc/requirements/Android.bp
@@ -48,6 +48,13 @@ bootstrap_go_package {
],
}
+// Regenerate the go proto srcs with these commands
+// m aprotoc protoc-go-gen && \
+// aprotoc \
+// --go_out=paths=source_relative:. \
+// cts/tests/mediapc/requirements/mpc.proto \
+// cts/tests/mediapc/requirements/requirements.proto
+
bootstrap_go_package {
name: "requirements_go_proto",
pkgPath: "cts/test/mediapc/requirements/requirements_go_proto",
diff --git a/tests/mediapc/requirements/mpc.pb.go b/tests/mediapc/requirements/mpc.pb.go
index 64bfcdfd9c2..0f684e6acfb 100644
--- a/tests/mediapc/requirements/mpc.pb.go
+++ b/tests/mediapc/requirements/mpc.pb.go
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -56,6 +56,9 @@ const (
// As specified in
// https://source.android.com/docs/compatibility/14/android-14-cdd#227_handheld_media_performance_class
MediaPerformanceClass_MEDIA_PERFORMANCE_CLASS_14 MediaPerformanceClass = 34
+ // As specified in
+ // Link pending
+ MediaPerformanceClass_MEDIA_PERFORMANCE_CLASS_15 MediaPerformanceClass = 35
)
// Enum value maps for MediaPerformanceClass.
@@ -67,6 +70,7 @@ var (
31: "MEDIA_PERFORMANCE_CLASS_12",
33: "MEDIA_PERFORMANCE_CLASS_13",
34: "MEDIA_PERFORMANCE_CLASS_14",
+ 35: "MEDIA_PERFORMANCE_CLASS_15",
}
MediaPerformanceClass_value = map[string]int32{
"MEDIA_PERFORMANCE_CLASS_UNSPECIFIED": 0,
@@ -75,6 +79,7 @@ var (
"MEDIA_PERFORMANCE_CLASS_12": 31,
"MEDIA_PERFORMANCE_CLASS_13": 33,
"MEDIA_PERFORMANCE_CLASS_14": 34,
+ "MEDIA_PERFORMANCE_CLASS_15": 35,
}
)
@@ -122,7 +127,7 @@ var file_cts_tests_mediapc_requirements_mpc_proto_rawDesc = []byte{
0x61, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x2f, 0x6d, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x61, 0x6e, 0x64, 0x72,
0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72,
- 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2a, 0xee, 0x01, 0x0a, 0x15, 0x4d,
+ 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2a, 0x8e, 0x02, 0x0a, 0x15, 0x4d,
0x65, 0x64, 0x69, 0x61, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x43,
0x6c, 0x61, 0x73, 0x73, 0x12, 0x27, 0x0a, 0x23, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x45,
0x52, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
@@ -137,7 +142,9 @@ var file_cts_tests_mediapc_requirements_mpc_proto_rawDesc = []byte{
0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x4e, 0x43, 0x45,
0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x31, 0x33, 0x10, 0x21, 0x12, 0x1e, 0x0a, 0x1a, 0x4d,
0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x4e, 0x43, 0x45,
- 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x31, 0x34, 0x10, 0x22, 0x42, 0x2e, 0x50, 0x01, 0x5a,
+ 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x31, 0x34, 0x10, 0x22, 0x12, 0x1e, 0x0a, 0x1a, 0x4d,
+ 0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x4e, 0x43, 0x45,
+ 0x5f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x31, 0x35, 0x10, 0x23, 0x42, 0x2e, 0x50, 0x01, 0x5a,
0x2a, 0x63, 0x74, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x70,
0x63, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6d,
0x70, 0x63, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
diff --git a/tests/mediapc/requirements/mpc.proto b/tests/mediapc/requirements/mpc.proto
index c579f29262d..5adbe70e05d 100644
--- a/tests/mediapc/requirements/mpc.proto
+++ b/tests/mediapc/requirements/mpc.proto
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,6 +16,7 @@ syntax = "proto2";
package android.media.performanceclass;
option java_multiple_files = true;
+
option go_package = "cts/test/mediapc/requirements/mpc_go_proto";
// The Media Performance class of a device.
@@ -38,4 +39,7 @@ enum MediaPerformanceClass {
// As specified in
// https://source.android.com/docs/compatibility/14/android-14-cdd#227_handheld_media_performance_class
MEDIA_PERFORMANCE_CLASS_14 = 34;
+ // As specified in
+ // Link pending
+ MEDIA_PERFORMANCE_CLASS_15 = 35;
}
diff --git a/tests/mediapc/requirements/requirements.go b/tests/mediapc/requirements/requirements.go
index 34336495c01..5ad389d9aed 100644
--- a/tests/mediapc/requirements/requirements.go
+++ b/tests/mediapc/requirements/requirements.go
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,35 +17,35 @@
package requirements
import (
- "io"
- "text/template"
+ "io"
+ "text/template"
- "google.golang.org/protobuf/proto"
- "cts/test/mediapc/requirements/templatefns"
+ "cts/test/mediapc/requirements/templatefns"
+ "google.golang.org/protobuf/proto"
- pb "cts/test/mediapc/requirements/requirements_go_proto"
+ pb "cts/test/mediapc/requirements/requirements_go_proto"
)
// Gensrc generates source from a template using a list of MPC requirements.
func Gensrc(tmplString string, reqList *pb.RequirementList, w io.Writer) error {
- type Top struct {
- ReqList *pb.RequirementList
- }
- top := Top{ReqList: reqList}
- tmpl, err := template.New("gensrc").Funcs(templatefns.Funcs()).Parse(tmplString)
- if err != nil {
- return err
- }
- err = tmpl.Execute(w, top)
- if err != nil {
- return err
- }
- return nil
+ type Top struct {
+ ReqList *pb.RequirementList
+ }
+ top := Top{ReqList: reqList}
+ tmpl, err := template.New("gensrc").Funcs(templatefns.Funcs()).Parse(tmplString)
+ if err != nil {
+ return err
+ }
+ err = tmpl.Execute(w, top)
+ if err != nil {
+ return err
+ }
+ return nil
}
// UnmarshalRequirementList unmarshals MPC requirements data.
func UnmarshalRequirementList(reqBinary []byte) (*pb.RequirementList, error) {
- req := &pb.RequirementList{}
- err := proto.Unmarshal(reqBinary, req)
- return req, err
+ req := &pb.RequirementList{}
+ err := proto.Unmarshal(reqBinary, req)
+ return req, err
}
diff --git a/tests/mediapc/requirements/requirements.pb.go b/tests/mediapc/requirements/requirements.pb.go
index e0cf7b39c66..599b68c870f 100644
--- a/tests/mediapc/requirements/requirements.pb.go
+++ b/tests/mediapc/requirements/requirements.pb.go
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -179,6 +179,7 @@ const (
MeasurementType_MEASUREMENT_TYPE_DOUBLE MeasurementType = 2
MeasurementType_MEASUREMENT_TYPE_INT MeasurementType = 3
MeasurementType_MEASUREMENT_TYPE_STRING MeasurementType = 4
+ MeasurementType_MEASUREMENT_TYPE_LONG MeasurementType = 5
)
// Enum value maps for MeasurementType.
@@ -189,6 +190,7 @@ var (
2: "MEASUREMENT_TYPE_DOUBLE",
3: "MEASUREMENT_TYPE_INT",
4: "MEASUREMENT_TYPE_STRING",
+ 5: "MEASUREMENT_TYPE_LONG",
}
MeasurementType_value = map[string]int32{
"MEASUREMENT_TYPE_UNSPECIFIED": 0,
@@ -196,6 +198,7 @@ var (
"MEASUREMENT_TYPE_DOUBLE": 2,
"MEASUREMENT_TYPE_INT": 3,
"MEASUREMENT_TYPE_STRING": 4,
+ "MEASUREMENT_TYPE_LONG": 5,
}
)
@@ -236,12 +239,15 @@ func (MeasurementType) EnumDescriptor() ([]byte, []int) {
return file_cts_tests_mediapc_requirements_requirements_proto_rawDescGZIP(), []int{2}
}
+// A list of requirements.
type RequirementList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Requirements []*Requirement `protobuf:"bytes,1,rep,name=requirements" json:"requirements,omitempty"`
+ // All valid MPC levels
+ AllMpcs []int64 `protobuf:"varint,2,rep,packed,name=all_mpcs,json=allMpcs" json:"all_mpcs,omitempty"`
}
func (x *RequirementList) Reset() {
@@ -283,6 +289,13 @@ func (x *RequirementList) GetRequirements() []*Requirement {
return nil
}
+func (x *RequirementList) GetAllMpcs() []int64 {
+ if x != nil {
+ return x.AllMpcs
+ }
+ return nil
+}
+
// A Media Performance Class Requirement with required measurements and
// specifications including required values for each relevant MPC level.
type Requirement struct {
@@ -300,6 +313,10 @@ type Requirement struct {
// measurement_id to RequiredMeasurements
// The measurement_id is a field name safe string.
Measurements map[string]*RequiredMeasurement `protobuf:"bytes,6,rep,name=measurements" json:"measurements,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ // variant_id to Variant
+ //
+ // The variant_id is a field name safe string.
+ Variants map[string]*Variant `protobuf:"bytes,57,rep,name=variants" json:"variants,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
func (x *Requirement) Reset() {
@@ -376,6 +393,13 @@ func (x *Requirement) GetMeasurements() map[string]*RequiredMeasurement {
return nil
}
+func (x *Requirement) GetVariants() map[string]*Variant {
+ if x != nil {
+ return x.Variants
+ }
+ return nil
+}
+
type RequirementSpec struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -391,6 +415,9 @@ type RequirementSpec struct {
// The measurement_id must match the id of a RequiredMeasurement in the parent
// Requirement.
RequiredValues map[string]*RequiredValue `protobuf:"bytes,4,rep,name=required_values,json=requiredValues" json:"required_values,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ // variant_id to VariantSpec
+ // The variant_id is a field name safe string.
+ VariantSpecs map[string]*VariantSpec `protobuf:"bytes,5,rep,name=variant_specs,json=variantSpecs" json:"variant_specs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
func (x *RequirementSpec) Reset() {
@@ -446,6 +473,13 @@ func (x *RequirementSpec) GetRequiredValues() map[string]*RequiredValue {
return nil
}
+func (x *RequirementSpec) GetVariantSpecs() map[string]*VariantSpec {
+ if x != nil {
+ return x.VariantSpecs
+ }
+ return nil
+}
+
// A required measurement needed verifiy a MPC requirement.
type RequiredMeasurement struct {
state protoimpl.MessageState
@@ -526,14 +560,14 @@ type RequiredValue struct {
unknownFields protoimpl.UnknownFields
// The id is a field name safe string.
- Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
- Comparison *Comparison `protobuf:"varint,2,opt,name=comparison,enum=android.media.performanceclass.requirements.Comparison" json:"comparison,omitempty"`
+ Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
// Types that are assignable to Value:
//
// *RequiredValue_StringValue
// *RequiredValue_IntValue
// *RequiredValue_DoubleValue
// *RequiredValue_BoolValue
+ // *RequiredValue_LongValue
Value isRequiredValue_Value `protobuf_oneof:"value"`
}
@@ -576,13 +610,6 @@ func (x *RequiredValue) GetId() string {
return ""
}
-func (x *RequiredValue) GetComparison() Comparison {
- if x != nil && x.Comparison != nil {
- return *x.Comparison
- }
- return Comparison_COMPARISON_UNSPECIFIED
-}
-
func (m *RequiredValue) GetValue() isRequiredValue_Value {
if m != nil {
return m.Value
@@ -618,6 +645,13 @@ func (x *RequiredValue) GetBoolValue() bool {
return false
}
+func (x *RequiredValue) GetLongValue() int64 {
+ if x, ok := x.GetValue().(*RequiredValue_LongValue); ok {
+ return x.LongValue
+ }
+ return 0
+}
+
type isRequiredValue_Value interface {
isRequiredValue_Value()
}
@@ -638,6 +672,10 @@ type RequiredValue_BoolValue struct {
BoolValue bool `protobuf:"varint,6,opt,name=bool_value,json=boolValue,oneof"`
}
+type RequiredValue_LongValue struct {
+ LongValue int64 `protobuf:"varint,7,opt,name=long_value,json=longValue,oneof"`
+}
+
func (*RequiredValue_StringValue) isRequiredValue_Value() {}
func (*RequiredValue_IntValue) isRequiredValue_Value() {}
@@ -646,6 +684,110 @@ func (*RequiredValue_DoubleValue) isRequiredValue_Value() {}
func (*RequiredValue_BoolValue) isRequiredValue_Value() {}
+func (*RequiredValue_LongValue) isRequiredValue_Value() {}
+
+// Variants are used when an alternative set of required values should apply
+type Variant struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // When the variant should be used.
+ Description *string `protobuf:"bytes,1,opt,name=description" json:"description,omitempty"`
+}
+
+func (x *Variant) Reset() {
+ *x = Variant{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_cts_tests_mediapc_requirements_requirements_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Variant) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Variant) ProtoMessage() {}
+
+func (x *Variant) ProtoReflect() protoreflect.Message {
+ mi := &file_cts_tests_mediapc_requirements_requirements_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Variant.ProtoReflect.Descriptor instead.
+func (*Variant) Descriptor() ([]byte, []int) {
+ return file_cts_tests_mediapc_requirements_requirements_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *Variant) GetDescription() string {
+ if x != nil && x.Description != nil {
+ return *x.Description
+ }
+ return ""
+}
+
+// The set values required for a variant
+type VariantSpec struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // measurement_id to RequiredMeasurements
+ //
+ // The measurement_id is a field name safe string.
+ // The measurement_id must match the id of a RequiredMeasurement in the parent
+ // Requirement.
+ RequiredValues map[string]*RequiredValue `protobuf:"bytes,4,rep,name=required_values,json=requiredValues" json:"required_values,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+}
+
+func (x *VariantSpec) Reset() {
+ *x = VariantSpec{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_cts_tests_mediapc_requirements_requirements_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *VariantSpec) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*VariantSpec) ProtoMessage() {}
+
+func (x *VariantSpec) ProtoReflect() protoreflect.Message {
+ mi := &file_cts_tests_mediapc_requirements_requirements_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use VariantSpec.ProtoReflect.Descriptor instead.
+func (*VariantSpec) Descriptor() ([]byte, []int) {
+ return file_cts_tests_mediapc_requirements_requirements_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *VariantSpec) GetRequiredValues() map[string]*RequiredValue {
+ if x != nil {
+ return x.RequiredValues
+ }
+ return nil
+}
+
var File_cts_tests_mediapc_requirements_requirements_proto protoreflect.FileDescriptor
var file_cts_tests_mediapc_requirements_requirements_proto_rawDesc = []byte{
@@ -657,14 +799,16 @@ var file_cts_tests_mediapc_requirements_requirements_proto_rawDesc = []byte{
0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x1a, 0x28, 0x63, 0x74, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x6d, 0x65, 0x64, 0x69,
0x61, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
- 0x2f, 0x6d, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6f, 0x0a, 0x0f, 0x52, 0x65,
- 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x5c, 0x0a,
- 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65,
- 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63,
- 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74,
- 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x72,
- 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xe4, 0x04, 0x0a, 0x0b,
+ 0x2f, 0x6d, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8e, 0x01, 0x0a, 0x0f, 0x52,
+ 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x5c,
+ 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d,
+ 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c,
+ 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x08,
+ 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x70, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x42, 0x02,
+ 0x10, 0x01, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x4d, 0x70, 0x63, 0x73, 0x22, 0xbb, 0x06, 0x0a, 0x0b,
0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
@@ -687,114 +831,161 @@ var file_cts_tests_mediapc_requirements_requirements_proto_rawDesc = []byte{
0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69,
0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72,
- 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x76, 0x0a, 0x0a, 0x53, 0x70, 0x65, 0x63, 0x73, 0x45,
- 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x52, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x62, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e,
+ 0x74, 0x73, 0x18, 0x39, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d,
+ 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
+ 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x1a, 0x76, 0x0a, 0x0a, 0x53, 0x70,
+ 0x65, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x52, 0x0a, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72,
+ 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69,
+ 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
+ 0x38, 0x01, 0x1a, 0x81, 0x01, 0x0a, 0x11, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x56, 0x0a, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72,
+ 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69,
+ 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
+ 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x71, 0x0a, 0x0d, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e,
+ 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4a, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d,
+ 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x52, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xea, 0x04, 0x0a, 0x0f, 0x52, 0x65,
+ 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x47, 0x0a,
+ 0x03, 0x6d, 0x70, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f,
+ 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x4d, 0x65, 0x64, 0x69,
+ 0x61, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6c, 0x61, 0x73,
+ 0x73, 0x52, 0x03, 0x6d, 0x70, 0x63, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66,
+ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73,
+ 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x79, 0x0a, 0x0f,
+ 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18,
+ 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x50, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63,
0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53,
- 0x70, 0x65, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x81,
- 0x01, 0x0a, 0x11, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45,
- 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x56, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
- 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63,
- 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65,
- 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x61, 0x73,
- 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
- 0x38, 0x01, 0x22, 0xfa, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65,
- 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x47, 0x0a, 0x03, 0x6d, 0x70, 0x63, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65,
- 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63,
- 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72,
- 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x03, 0x6d, 0x70, 0x63, 0x12,
- 0x24, 0x0a, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x79, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
- 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x50,
+ 0x70, 0x65, 0x63, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
+ 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x73, 0x0a, 0x0d, 0x76, 0x61, 0x72, 0x69, 0x61,
+ 0x6e, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4e,
0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70,
0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e,
0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71,
- 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x52, 0x65, 0x71,
- 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
- 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
- 0x1a, 0x7d, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75,
- 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d,
- 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
- 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
- 0x89, 0x02, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x61, 0x73,
- 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x67, 0x0a, 0x10, 0x6d, 0x65, 0x61,
- 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65,
- 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63,
- 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74,
- 0x73, 0x2e, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
- 0x65, 0x52, 0x0f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79,
- 0x70, 0x65, 0x12, 0x57, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e,
- 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d,
- 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x52,
- 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x22, 0x8b, 0x02, 0x0a, 0x0d,
- 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0e, 0x0a,
- 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x57, 0x0a,
- 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x0e, 0x32, 0x37, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69,
+ 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c,
+ 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x73, 0x1a, 0x7d, 0x0a, 0x13,
+ 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e,
+ 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d,
+ 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x79, 0x0a, 0x11, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
+ 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
+ 0x65, 0x79, 0x12, 0x4e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x38, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69,
0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61,
0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e,
- 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70,
- 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
- 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b,
- 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69,
- 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00,
- 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f,
- 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01,
- 0x48, 0x00, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
- 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20,
- 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65,
- 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x6c, 0x0a, 0x05, 0x47, 0x72, 0x6f,
- 0x75, 0x70, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x55, 0x4e, 0x53, 0x50,
- 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x52, 0x4f,
- 0x55, 0x50, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x47, 0x52,
- 0x4f, 0x55, 0x50, 0x5f, 0x43, 0x41, 0x4d, 0x45, 0x52, 0x41, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e,
- 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x48, 0x41, 0x52, 0x44, 0x57, 0x41, 0x52, 0x45, 0x10, 0x03,
- 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52,
- 0x4d, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x04, 0x2a, 0xd8, 0x01, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x70,
- 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52,
- 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
- 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e,
- 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4d, 0x50,
- 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e,
- 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e,
- 0x5f, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51,
- 0x55, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49,
- 0x53, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e,
- 0x10, 0x04, 0x12, 0x24, 0x0a, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e,
- 0x5f, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52,
- 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4d, 0x50,
- 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4f, 0x4e, 0x4c, 0x59,
- 0x10, 0x06, 0x2a, 0xa2, 0x01, 0x0a, 0x0f, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65,
- 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x4d, 0x45, 0x41, 0x53, 0x55, 0x52,
- 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
- 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x41, 0x53,
- 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f,
- 0x4c, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45,
- 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x02,
- 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f,
- 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45,
- 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
- 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x42, 0x37, 0x50, 0x01, 0x5a, 0x33, 0x63, 0x74, 0x73,
- 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x70, 0x63, 0x2f, 0x72, 0x65,
- 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x69,
- 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x89, 0x02, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x69,
+ 0x72, 0x65, 0x64, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e,
+ 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20,
+ 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x12, 0x67, 0x0a, 0x10, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f,
+ 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75,
+ 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x57, 0x0a, 0x0a, 0x63, 0x6f, 0x6d,
+ 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x37, 0x2e,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72,
+ 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
+ 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73,
+ 0x6f, 0x6e, 0x22, 0xd9, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x02, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74,
+ 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74,
+ 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08,
+ 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62,
+ 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00,
+ 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a,
+ 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
+ 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f,
+ 0x0a, 0x0a, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x03, 0x48, 0x00, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42,
+ 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x2b,
+ 0x0a, 0x07, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x83, 0x02, 0x0a, 0x0b,
+ 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, 0x75, 0x0a, 0x0f, 0x72,
+ 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4c, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d,
+ 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x73, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x52,
+ 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74,
+ 0x72, 0x79, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x73, 0x1a, 0x7d, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x05, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x6f,
+ 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x72, 0x65, 0x71, 0x75,
+ 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
+ 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+ 0x01, 0x2a, 0x6c, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52,
+ 0x4f, 0x55, 0x50, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+ 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41,
+ 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x43, 0x41, 0x4d, 0x45,
+ 0x52, 0x41, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x48, 0x41,
+ 0x52, 0x44, 0x57, 0x41, 0x52, 0x45, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52, 0x4f, 0x55,
+ 0x50, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x04, 0x2a,
+ 0xd8, 0x01, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x12, 0x1a,
+ 0x0a, 0x16, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53,
+ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f,
+ 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x01,
+ 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x4c,
+ 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4f,
+ 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48,
+ 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x1b, 0x0a,
+ 0x17, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x45, 0x41,
+ 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x04, 0x12, 0x24, 0x0a, 0x20, 0x43, 0x4f,
+ 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52,
+ 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x05,
+ 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x52, 0x49, 0x53, 0x4f, 0x4e, 0x5f, 0x49,
+ 0x4e, 0x46, 0x4f, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x06, 0x2a, 0xbd, 0x01, 0x0a, 0x0f, 0x4d,
+ 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20,
+ 0x0a, 0x1c, 0x4d, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59,
+ 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
+ 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f,
+ 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4d,
+ 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
+ 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x41, 0x53,
+ 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54,
+ 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e,
+ 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12,
+ 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54,
+ 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0x05, 0x42, 0x37, 0x50, 0x01, 0x5a, 0x33,
+ 0x63, 0x74, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x70, 0x63,
+ 0x2f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x72, 0x65,
+ 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f,
}
var (
@@ -810,7 +1001,7 @@ func file_cts_tests_mediapc_requirements_requirements_proto_rawDescGZIP() []byte
}
var file_cts_tests_mediapc_requirements_requirements_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
-var file_cts_tests_mediapc_requirements_requirements_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
+var file_cts_tests_mediapc_requirements_requirements_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_cts_tests_mediapc_requirements_requirements_proto_goTypes = []interface{}{
(Group)(0), // 0: android.media.performanceclass.requirements.Group
(Comparison)(0), // 1: android.media.performanceclass.requirements.Comparison
@@ -820,29 +1011,39 @@ var file_cts_tests_mediapc_requirements_requirements_proto_goTypes = []interface
(*RequirementSpec)(nil), // 5: android.media.performanceclass.requirements.RequirementSpec
(*RequiredMeasurement)(nil), // 6: android.media.performanceclass.requirements.RequiredMeasurement
(*RequiredValue)(nil), // 7: android.media.performanceclass.requirements.RequiredValue
- nil, // 8: android.media.performanceclass.requirements.Requirement.SpecsEntry
- nil, // 9: android.media.performanceclass.requirements.Requirement.MeasurementsEntry
- nil, // 10: android.media.performanceclass.requirements.RequirementSpec.RequiredValuesEntry
- (mpc_go_proto.MediaPerformanceClass)(0), // 11: android.media.performanceclass.MediaPerformanceClass
+ (*Variant)(nil), // 8: android.media.performanceclass.requirements.Variant
+ (*VariantSpec)(nil), // 9: android.media.performanceclass.requirements.VariantSpec
+ nil, // 10: android.media.performanceclass.requirements.Requirement.SpecsEntry
+ nil, // 11: android.media.performanceclass.requirements.Requirement.MeasurementsEntry
+ nil, // 12: android.media.performanceclass.requirements.Requirement.VariantsEntry
+ nil, // 13: android.media.performanceclass.requirements.RequirementSpec.RequiredValuesEntry
+ nil, // 14: android.media.performanceclass.requirements.RequirementSpec.VariantSpecsEntry
+ nil, // 15: android.media.performanceclass.requirements.VariantSpec.RequiredValuesEntry
+ (mpc_go_proto.MediaPerformanceClass)(0), // 16: android.media.performanceclass.MediaPerformanceClass
}
var file_cts_tests_mediapc_requirements_requirements_proto_depIdxs = []int32{
4, // 0: android.media.performanceclass.requirements.RequirementList.requirements:type_name -> android.media.performanceclass.requirements.Requirement
0, // 1: android.media.performanceclass.requirements.Requirement.group:type_name -> android.media.performanceclass.requirements.Group
- 8, // 2: android.media.performanceclass.requirements.Requirement.specs:type_name -> android.media.performanceclass.requirements.Requirement.SpecsEntry
- 9, // 3: android.media.performanceclass.requirements.Requirement.measurements:type_name -> android.media.performanceclass.requirements.Requirement.MeasurementsEntry
- 11, // 4: android.media.performanceclass.requirements.RequirementSpec.mpc:type_name -> android.media.performanceclass.MediaPerformanceClass
- 10, // 5: android.media.performanceclass.requirements.RequirementSpec.required_values:type_name -> android.media.performanceclass.requirements.RequirementSpec.RequiredValuesEntry
- 2, // 6: android.media.performanceclass.requirements.RequiredMeasurement.measurement_type:type_name -> android.media.performanceclass.requirements.MeasurementType
- 1, // 7: android.media.performanceclass.requirements.RequiredMeasurement.comparison:type_name -> android.media.performanceclass.requirements.Comparison
- 1, // 8: android.media.performanceclass.requirements.RequiredValue.comparison:type_name -> android.media.performanceclass.requirements.Comparison
- 5, // 9: android.media.performanceclass.requirements.Requirement.SpecsEntry.value:type_name -> android.media.performanceclass.requirements.RequirementSpec
- 6, // 10: android.media.performanceclass.requirements.Requirement.MeasurementsEntry.value:type_name -> android.media.performanceclass.requirements.RequiredMeasurement
- 7, // 11: android.media.performanceclass.requirements.RequirementSpec.RequiredValuesEntry.value:type_name -> android.media.performanceclass.requirements.RequiredValue
- 12, // [12:12] is the sub-list for method output_type
- 12, // [12:12] is the sub-list for method input_type
- 12, // [12:12] is the sub-list for extension type_name
- 12, // [12:12] is the sub-list for extension extendee
- 0, // [0:12] is the sub-list for field type_name
+ 10, // 2: android.media.performanceclass.requirements.Requirement.specs:type_name -> android.media.performanceclass.requirements.Requirement.SpecsEntry
+ 11, // 3: android.media.performanceclass.requirements.Requirement.measurements:type_name -> android.media.performanceclass.requirements.Requirement.MeasurementsEntry
+ 12, // 4: android.media.performanceclass.requirements.Requirement.variants:type_name -> android.media.performanceclass.requirements.Requirement.VariantsEntry
+ 16, // 5: android.media.performanceclass.requirements.RequirementSpec.mpc:type_name -> android.media.performanceclass.MediaPerformanceClass
+ 13, // 6: android.media.performanceclass.requirements.RequirementSpec.required_values:type_name -> android.media.performanceclass.requirements.RequirementSpec.RequiredValuesEntry
+ 14, // 7: android.media.performanceclass.requirements.RequirementSpec.variant_specs:type_name -> android.media.performanceclass.requirements.RequirementSpec.VariantSpecsEntry
+ 2, // 8: android.media.performanceclass.requirements.RequiredMeasurement.measurement_type:type_name -> android.media.performanceclass.requirements.MeasurementType
+ 1, // 9: android.media.performanceclass.requirements.RequiredMeasurement.comparison:type_name -> android.media.performanceclass.requirements.Comparison
+ 15, // 10: android.media.performanceclass.requirements.VariantSpec.required_values:type_name -> android.media.performanceclass.requirements.VariantSpec.RequiredValuesEntry
+ 5, // 11: android.media.performanceclass.requirements.Requirement.SpecsEntry.value:type_name -> android.media.performanceclass.requirements.RequirementSpec
+ 6, // 12: android.media.performanceclass.requirements.Requirement.MeasurementsEntry.value:type_name -> android.media.performanceclass.requirements.RequiredMeasurement
+ 8, // 13: android.media.performanceclass.requirements.Requirement.VariantsEntry.value:type_name -> android.media.performanceclass.requirements.Variant
+ 7, // 14: android.media.performanceclass.requirements.RequirementSpec.RequiredValuesEntry.value:type_name -> android.media.performanceclass.requirements.RequiredValue
+ 9, // 15: android.media.performanceclass.requirements.RequirementSpec.VariantSpecsEntry.value:type_name -> android.media.performanceclass.requirements.VariantSpec
+ 7, // 16: android.media.performanceclass.requirements.VariantSpec.RequiredValuesEntry.value:type_name -> android.media.performanceclass.requirements.RequiredValue
+ 17, // [17:17] is the sub-list for method output_type
+ 17, // [17:17] is the sub-list for method input_type
+ 17, // [17:17] is the sub-list for extension type_name
+ 17, // [17:17] is the sub-list for extension extendee
+ 0, // [0:17] is the sub-list for field type_name
}
func init() { file_cts_tests_mediapc_requirements_requirements_proto_init() }
@@ -911,12 +1112,37 @@ func file_cts_tests_mediapc_requirements_requirements_proto_init() {
return nil
}
}
+ file_cts_tests_mediapc_requirements_requirements_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Variant); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_cts_tests_mediapc_requirements_requirements_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*VariantSpec); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
}
file_cts_tests_mediapc_requirements_requirements_proto_msgTypes[4].OneofWrappers = []interface{}{
(*RequiredValue_StringValue)(nil),
(*RequiredValue_IntValue)(nil),
(*RequiredValue_DoubleValue)(nil),
(*RequiredValue_BoolValue)(nil),
+ (*RequiredValue_LongValue)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -924,7 +1150,7 @@ func file_cts_tests_mediapc_requirements_requirements_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_cts_tests_mediapc_requirements_requirements_proto_rawDesc,
NumEnums: 3,
- NumMessages: 8,
+ NumMessages: 13,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/tests/mediapc/requirements/requirements.proto b/tests/mediapc/requirements/requirements.proto
index 82de3c571e4..676c0c55b99 100644
--- a/tests/mediapc/requirements/requirements.proto
+++ b/tests/mediapc/requirements/requirements.proto
@@ -4,13 +4,14 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+
syntax = "proto2";
package android.media.performanceclass.requirements;
@@ -18,12 +19,14 @@ package android.media.performanceclass.requirements;
import "cts/tests/mediapc/requirements/mpc.proto";
option java_multiple_files = true;
-option go_package = "cts/test/mediapc/requirements/requirements_go_proto";
+option go_package = "cts/test/mediapc/requirements/requirements_go_proto";
+// A list of requirements.
message RequirementList {
-
repeated Requirement requirements = 1;
+ // All valid MPC levels
+ repeated int64 all_mpcs = 2 [packed = true];
}
// A Media Performance Class Requirement with required measurements and
@@ -37,9 +40,15 @@ message Requirement {
optional Group group = 4;
map<int64, RequirementSpec> specs = 5;
+
// measurement_id to RequiredMeasurements
// The measurement_id is a field name safe string.
map<string, RequiredMeasurement> measurements = 6;
+
+ // variant_id to Variant
+ //
+ // The variant_id is a field name safe string.
+ map<string, Variant> variants = 57;
}
message RequirementSpec {
@@ -55,6 +64,10 @@ message RequirementSpec {
// The measurement_id must match the id of a RequiredMeasurement in the parent
// Requirement.
map<string, RequiredValue> required_values = 4;
+
+ // variant_id to VariantSpec
+ // The variant_id is a field name safe string.
+ map<string, VariantSpec> variant_specs = 5;
}
enum Group {
@@ -78,15 +91,32 @@ message RequiredMeasurement {
message RequiredValue {
// The id is a field name safe string.
optional string id = 1;
- optional Comparison comparison = 2;
+ reserved 2; // comparison
oneof value {
string string_value = 3;
int64 int_value = 4;
double double_value = 5;
bool bool_value = 6;
+ int64 long_value = 7;
}
}
+// Variants are used when an alternative set of required values should apply
+message Variant {
+ // When the variant should be used.
+ optional string description = 1;
+}
+
+// The set values required for a variant
+message VariantSpec {
+ // measurement_id to RequiredMeasurements
+ //
+ // The measurement_id is a field name safe string.
+ // The measurement_id must match the id of a RequiredMeasurement in the parent
+ // Requirement.
+ map<string, RequiredValue> required_values = 4;
+}
+
enum Comparison {
COMPARISON_UNSPECIFIED = 0;
COMPARISON_EQUAL = 1;
@@ -97,12 +127,11 @@ enum Comparison {
COMPARISON_INFO_ONLY = 6;
}
-
-enum MeasurementType{
+enum MeasurementType {
MEASUREMENT_TYPE_UNSPECIFIED = 0;
MEASUREMENT_TYPE_BOOL = 1;
MEASUREMENT_TYPE_DOUBLE = 2;
MEASUREMENT_TYPE_INT = 3;
MEASUREMENT_TYPE_STRING = 4;
+ MEASUREMENT_TYPE_LONG = 5;
}
-
diff --git a/tests/mediapc/requirements/requirements.txtpb b/tests/mediapc/requirements/requirements.txtpb
index 5d586c965f1..3cc6a9a7fc4 100644
--- a/tests/mediapc/requirements/requirements.txtpb
+++ b/tests/mediapc/requirements/requirements.txtpb
@@ -4,1359 +4,2175 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http:#www.apache.org/licenses/LICENSE-2.0
+# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-# proto-file: requirements.proto
+#
+# proto-file: wireless/android/mediapc_requirements/requirements.proto
# proto-message: RequirementList
-requirements {
- id: "5.1/H-1-1"
- description: "- Concurrent video codec sessions"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST advertise the maximum number of hardware video decoder sessions that can be run concurrently in any codec combination via the CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities.getSupportedPerformancePoints() methods."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.1/H-1-2"
- description: "- Concurrent video codec sessions\n- AV1 hardware decoder"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST support 6 instances of hardware video decoder sessions (AVC or HEVC) in any codec combination running concurrently at 720p resolution@30 fps."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST support 6 instances of hardware video decoder sessions (AVC, HEVC, VP9* or later) in any codec combination running concurrently at 720p resolution@30 fps. *Only 2 instances are required if VP9 codec is present."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support 6 instances of hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30 fps."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support 6 instances of 8-bit (SDR) hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 3 sessions at 1080p resolution@30 fps and 3 sessions at 4k resolution@30fps, unless AV1. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
- }
- }
-}
-requirements {
- id: "5.1/H-1-3"
- description: "- Concurrent video codec sessions"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST advertise the maximum number of hardware video encoder sessions that can be run concurrently in any codec combination via the CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities.getSupportedPerformancePoints() methods."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.1/H-1-4"
- description: "- Concurrent video codec sessions\n- AV1 hardware decoder"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST support 6 instances of hardware video encoder sessions (AVC or HEVC) in any codec combination running concurrently at 720p resolution@30 fps."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST support 6 instances of hardware video encoder sessions (AVC, HEVC, VP9* or later) in any codec combination running concurrently at 720p resolution@30 fps. *Only 2 instances are required if VP9 codec is present."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support 6 instances of hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30fps."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support 6 instances of 8-bit (SDR) hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 4 sessions at 1080p resolution@30 fps and 2 sessions at 4k resolution@30fps, unless AV1. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
- }
- }
-}
-requirements {
- id: "5.1/H-1-5"
- description: "- Concurrent video codec sessions"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST advertise the maximum number of hardware video encoder and decoder sessions that can be run concurrently in any codec combination via the CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities.getSupportedPerformancePoints() methods."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.1/H-1-6"
- description: "- Concurrent video codec sessions\n- AV1 hardware decoder"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST support 6 instances of hardware video decoder and hardware video encoder sessions (AVC or HEVC) in any codec combination running concurrently at 720p@30 fps resolution."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST support 6 instances of hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9* or later) in any codec combination running concurrently at 720p@30fps resolution. *Only 2 instances are required if VP9 codec is present."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support 6 instances of hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p@30fps resolution."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support 6 instances of 8-bit (SDR) hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 3 sessions at 4K@30fps resolution (unless AV1), out of which at most 2 are encoder sessions and 3 sessions at 1080p resolution. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
- }
- }
-}
-requirements {
- id: "5.1/H-1-7"
- description: "- Encoder initialization latency"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have a codec initialization latency of 65 ms or less for a 1080p or smaller video encoding session for all hardware video encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST have a codec initialization latency of 50 ms or less for a 1080p or smaller video encoding session for all hardware video encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have a codec initialization latency of 40 ms or less for a 1080p or smaller video encoding session for all hardware video encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST have a codec initialization latency of 40 ms or less for a 1080p or smaller video encoding session for all hardware video encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization. For Dolby vision codec, the codec initialization latency MUST be 50 ms or less."
- }
- }
-}
-requirements {
- id: "5.1/H-1-8"
- description: "- Encoder initialization latency"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have a codec initialization latency of 50 ms or less for a 128 kbps or lower bitrate audio encoding session for all audio encoders when under load.Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST have a codec initialization latency of 40 ms or less for a 128 kbps or lower bitrate audio encoding session for all audio encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have a codec initialization latency of 30 ms or less for a 128 kbps or lower bitrate audio encoding session for all audio encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.1/H-1-9"
- description: "- AV1 hardware decoder\n- Secure hardware decoders"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support 2 instances of secure hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30 fps."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support 2 instances of secure hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 4k resolution@30 fps (unless AV1) for both 8-bit (SDR) and 10-bit HDR content. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
- }
- }
-}
-requirements {
- id: "5.1/H-1-10"
- description: "- AV1 hardware decoder\n- Secure hardware decoders"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support 3 instances of non-secure hardware video decoder sessions together with 1 instance of secure hardware video decoder session (4 instances total) (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30fps."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support 3 instances of non-secure hardware video decoder sessions together with 1 instance of secure hardware video decoder session (4 instances total) (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 3 sessions at 4K resolution@30 fps (unless AV1) which includes one secure decoder session and 1 nn-secure session at 1080p resolution@30fps where at most 2 sessions can be in 10-bit HDR. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
- }
- }
-}
-requirements {
- id: "5.1/H-1-11"
- description: "- AV1 hardware decoder\n- Secure hardware decoders"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support a secure decoder for every hardware AVC, HEVC, VP9 or AV1 decoder on the device."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.1/H-1-12"
- description: "- Decoder initialization latency"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have a video decoder initialization latency of 40 ms or less."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST have a codec initialization latency of 40 ms or less for a 1080p or smaller video decoding session for all hardware video decoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video playback initialization. For Dolby vision codec, the codec initialization latency MUST be 50 ms or less."
- }
- }
-}
-requirements {
- id: "5.1/H-1-13"
- description: "- Decoder initialization latency"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have an audio decoder initialization latency of 30 ms or less."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST have a codec initialization latency of 30 ms or less for a 128 kbps or lower bitrate audio decoding session for all audio decoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video playback initialization."
- }
- }
-}
-requirements {
- id: "5.1/H-1-14"
- description: "- AV1 hardware decoder\n- Film grain effect"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support AV1 hardware decoder Main 10, Level 4.1."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support AV1 hardware decoder Main 10, Level 4.1 and film grain."
- }
- }
-}
-requirements {
- id: "5.1/H-SR-1"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "Are STRONGLY RECOMMENDED to support Film Grain for AV1 hardware decoder."
- }
- }
-}
-requirements {
- id: "5.1/H-1-15"
- description: "- Secure hardware decoders"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have at least 1 hardware video decoder supporting 4K60."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.1/H-1-16"
- description: "- Secure hardware decoders"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have at least 1 hardware video encoder supporting 4K60."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.1/H-1-17"
- description: "- AVIF Baseline Profile"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST have at least 1 hardware image decoder supporting AVIF Baseline Profile."
- }
- }
-}
-requirements {
- id: "5.1/H-1-18"
- description: "- AV1 encoder"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support AV1 encoder which can encode up to 480p resolution at 30fps and 1Mbps."
- }
- }
-}
-requirements {
- id: "5.12/H-SR"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "Are Strongly Recommended to support support the Feature_HdrEditing feature for all hardware AV1 and HEVC encoders present on the device."
- }
- }
-}
-requirements {
- id: "5.1/H-1-19"
- description: "- HDR video codecs"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support 3 instances of 10-bit (HDR) hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 4K@30fps resolution (unless AV1) out of which at most 1 is an encoder session, which could be configured in RGBA_1010102 input format through a GL surface. HDR metadata generation by the encoder is not required if encoding from the GL surface. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
- }
- }
-}
-requirements {
- id: "5.12/H-1-2"
- description: "- RGBA_1010102 color format"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support RGBA_1010102 color format for all hardware AV1 and HEVC encoders present on the device."
- }
- }
-}
-requirements {
- id: "5.12/H-1-3"
- description: "- YUV texture sampling"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST advertise support for the EXT_YUV_target extension to sample from YUV textures in both 8 and 10-bits."
- }
- }
-}
-requirements {
- id: "5.2/H-2-1"
- description: "- Video encoding quality"
-}
-requirements {
- id: "5.3/H-1-1"
- description: "- Decoder frame drops"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST NOT drop more than 1 frame in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 30 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST NOT drop more than 2 frames in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST NOT drop more than 1 frame in 10 seconds (i.e less than 0.167 percent frame drop) for a 1080p 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST NOT drop more than 1 frame in 10 seconds (i.e less than 0.167 percent frame drop) for a 4K 60 fps video session under load."
- }
- }
-}
-requirements {
- id: "5.3/H-1-2"
- description: "- Decoder frame drops"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST NOT drop more than 1 frame in 10 seconds during a video resolution change in a 30 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128Kbps AAC audio playback."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST NOT drop more than 2 frames in 10 seconds during a video resolution change in a 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST NOT drop more than 1 frame in 10 seconds during a video resolution change in a 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST NOT drop more than 1 frame in 10 seconds during a video resolution change in a 60 fps video session under load for a 4K session."
- }
- }
-}
-requirements {
- id: "5.6/H-1-1"
- description: "- Round-trip audio latency"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have a tap-to-tone latency of less than 100 milliseconds using the OboeTester tap-to-tone test or CTS Verifier tap-to-tone test."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have a tap-to-tone latency of 80 milliseconds or less using the OboeTester tap-to-tone test or CTS Verifier tap-to-tone test."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST have a tap-to-tone latency of 80 milliseconds or less using the CTS Verifier tap-to-tone test."
- }
- }
-}
-requirements {
- id: "5.6/H-1-2"
- description: "- Round-trip audio latency"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have a round-trip audio latency of 80 milliseconds or less over at least one supported data path."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.6/H-1-3"
- description: "- Wired headsets and USB audio devices"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support >=24-bit audio for stereo output over 3.5 mm audio jacks if present and over USB audio if supported through the entire data path for low latency and streaming configurations. For the low latency configuration, AAudio should be used by the app in low-latency callback mode. For the streaming configuration, a Java AudioTrack should be used by the app. In both the low latency and streaming configurations, the HAL output sink should accept either AUDIO_FORMAT_PCM_24_BIT, AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_32_BIT or AUDIO_FORMAT_PCM_FLOAT for its target output format."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.6/H-1-4"
- description: "- Wired headsets and USB audio devices"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support >=4 channel USB audio devices (This is used by DJ controllers for previewing songs.)"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "5.6/H-1-5"
- description: "- MIDI devices"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support class compliant MIDI devices and declare the MIDI feature flag."
- }
- }
- specs { key: 34 value { mpc: MEDIA_PERFORMANCE_CLASS_14 } }
-}
-requirements {
- id: "5.6/H-1-9"
- description: "- Multichannel audio mixing"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support at least 12 channel mixing. This implies the capability to open an AudioTrack with 7.1.4 channel mask and properly spatialise or downmix all channels to stereo."
- }
- }
-}
-requirements {
- id: "5.6/H-SR"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "Are STRONGLY RECOMMENDED to support 24 channel mixing with at least support for 9.1.6 and 22.2 channel masks."
- }
- }
-}
-requirements {
- id: "5.7/H-1-2"
- description: "- Hardware-backed trusted execution environment"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support MediaDrm.SECURITY_LEVEL_HW_12ECURE_ALL with the below content decryption capabilities.\nMinimum Sample size 4 MiB\nMinimum Number of Subsamples - H264 or HEVC 32\nMinimum Number of Subsamples - VP9 9\nMinimum Number of Subsamples - AV1 288\nMinimum subsample buffer size 1 MiB\nMinimum Generic crypto buffer size 500 KiB\nMinimum Number of concurrent sessions 30\nMinimum Number of keys per session 20\nMinimum Total Number of Keys (all sessions) 80\nMinimum Total Number of DRM Keys (all sessions) 6\nMessage Size 16 KiB\nDecrypted Frames per Second 60 fps"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-1"
- description: "- Resolution and frame rate"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have a primary rear facing camera with a resolution of at least 12 megapixels supporting video capture at 4k@30fps. The primary rear-facing camera is the rear-facing camera with the lowest camera ID."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-2"
- description: "- Resolution and frame rate"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have a primary front facing camera with a resolution of at least 4 megapixels supporting video capture at 1080p@30fps. The primary front-facing camera is the front-facing camera with the lowest camera ID."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST have a primary front facing camera with a resolution of at least 5 megapixels and support video capture at 1080p@30fps. The primary front-facing camera is the front-facing camera with the lowest camera ID."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST have a primary front-facing camera with a resolution of at least 6 megapixels and support video capture at 1080p@30fps. The primary front-facing camera is the front-facing camera with the lowest camera ID."
- }
- }
-}
-requirements {
- id: "7.5/H-1-3"
- description: "- FULL or better hardware level"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST support android.info.supportedHardwareLevel property as FULL or better for back primary and LIMITED or better for front primary camera."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST support android.info.supportedHardwareLevel property as FULL or better for both primary cameras."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-4"
- description: "- Timestamp source is realtime"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST support CameraMetadata.SENSOR_INFO_13IMESTAMP_12OURCE_11EALTIME for both primary cameras."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-5"
- description: "- Startup and capture latencies"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have camera2 JPEG capture latency < 1000 ms for 1080p resolution as measured by the CTS camera PerformanceTest under ITS lighting conditions (3000K) for both primary cameras."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-6"
- description: "- Startup and capture latencies"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have camera2 startup latency (open camera to first preview frame) < 600 ms as measured by the CTS camera PerformanceTest under ITS lighting conditions (3000K) for both primary cameras."
- }
- }
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have camera2 startup latency (open camera to first preview frame) < 500 ms as measured by the CTS camera PerformanceTest under ITS lighting conditions (3000K) for both primary cameras."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-8"
- description: "- RAW capability"
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST support CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_11AW and android.graphics.ImageFormat.RAW_12ENSOR for the primary back camera."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-9"
- description: "- Slow-mo recording"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-10"
- description: "- Minimum zoom ratio for ultrawide cameras"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have min ZOOM_11ATIO < 1.0 for the primary cameras if there is an ultrawide RGB camera facing the same direction."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-11"
- description: "- Concurrent camera"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST implement concurrent front-back streaming on primary cameras."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-12"
- description: "- Preview stabilization"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support CONTROL_VIDEO_12TABILIZATION_MODE_PREVIEW_12TABILIZATION for both primary front and primary back camera."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-13"
- description: "- Logical multi-camera"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support LOGICAL_MULTI_CAMERA capability for the primary cameras if there are greater than 1 RGB cameras facing the same direction."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-14"
- description: "- Stream use case"
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST support STREAM_14SE_CASE capability for both primary front and primary back camera."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.5/H-1-15"
- description: "- Night mode extension"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support ~Bokeh &~ Night mode extensions via both CameraX and Camera2 extensions for primary cameras."
- }
- }
-}
-requirements {
- id: "7.5/H-1-16"
- description: "- HDR-capable primary camera"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support DYNAMIC_RANGE_TEN_BIT capability for the primary cameras."
- }
- }
-}
-requirements {
- id: "7.5/H-1-17"
- description: "- Face detection scene mode"
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST support CONTROL_SCENE_MODE_FACE_PRIORITY and face detection (STATISTICS_FACE_DETECT_MODE_SIMPLE or STATISTICS_FACE_DETECT_MODE_FULL) for the primary cameras."
- }
- }
-}
-requirements {
- id: "7.1.1.1/H-1-1"
- description: "- Screen resolution"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have screen resolution of at least 1080p."
- }
- }
-}
-requirements {
- id: "7.1.1.1/H-2-1"
- description: "- Screen resolution"
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST have screen resolution of at least 1080p."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.1.1.3/H-1-1"
- description: "- Screen density"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have screen density of at least 400 dpi."
- }
- }
-}
-requirements {
- id: "7.1.1.3/H-2-1"
- description: "- Screen density"
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST have screen density of at least 400 dpi."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "same"
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "7.1.1.3/H-3-1"
- name: "HDR display"
- measurements: [{
- key: "is_hdr"
+all_mpcs: [30, 31, 33, 34, 35]
+requirements {
+ id: "5.1/H-1-1"
+ description: "- Concurrent video codec sessions"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST advertise the maximum number of hardware video decoder sessions that can be run concurrently in any codec combination via the CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities.getSupportedPerformancePoints() methods."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-2"
+ description: "- Concurrent video codec sessions\n- AV1 hardware decoder"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST support 6 instances of hardware video decoder sessions (AVC or HEVC) in any codec combination running concurrently at 720p resolution@30 fps."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST support 6 instances of hardware video decoder sessions (AVC, HEVC, VP9* or later) in any codec combination running concurrently at 720p resolution@30 fps. *Only 2 instances are required if VP9 codec is present."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support 6 instances of hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30 fps."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support 6 instances of 8-bit (SDR) hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 3 sessions at 1080p resolution@30 fps and 3 sessions at 4k resolution@30fps, unless AV1. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support 6 instances of 8-bit (SDR) hardware video decoder sessions (AVC, HEVC, VP9, AV1, or later) in any codec combination running concurrently with 3 sessions at 1080p resolution@30 fps and 3 sessions at 4k resolution@30fps, unless AV1. For all sessions, there MUST NOT be more than 1 frame dropped per second. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-3"
+ description: "- Concurrent video codec sessions"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST advertise the maximum number of hardware video encoder sessions that can be run concurrently in any codec combination via the CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities.getSupportedPerformancePoints() methods."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-4"
+ description: "- Concurrent video codec sessions\n- AV1 hardware decoder"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST support 6 instances of hardware video encoder sessions (AVC or HEVC) in any codec combination running concurrently at 720p resolution@30 fps."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST support 6 instances of hardware video encoder sessions (AVC, HEVC, VP9* or later) in any codec combination running concurrently at 720p resolution@30 fps. *Only 2 instances are required if VP9 codec is present."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support 6 instances of hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30fps."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support 6 instances of 8-bit (SDR) hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 4 sessions at 1080p resolution@30 fps and 2 sessions at 4k resolution@30fps, unless AV1. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support 6 instances of 8-bit (SDR) hardware video encoder sessions (AVC, HEVC, VP9, AV1, or later) in any codec combination running concurrently with 4 sessions at 1080p resolution@30 fps and 2 sessions at 4k resolution@30fps, unless AV1. For all sessions, there MUST NOT be more than 1 frame dropped per second. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-5"
+ description: "- Concurrent video codec sessions"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST advertise the maximum number of hardware video encoder and decoder sessions that can be run concurrently in any codec combination via the CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities.getSupportedPerformancePoints() methods."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-6"
+ description: "- Concurrent video codec sessions\n- AV1 hardware decoder"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST support 6 instances of hardware video decoder and hardware video encoder sessions (AVC or HEVC) in any codec combination running concurrently at 720p@30 fps resolution."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST support 6 instances of hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9* or later) in any codec combination running concurrently at 720p@30fps resolution. *Only 2 instances are required if VP9 codec is present."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support 6 instances of hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p@30fps resolution."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support 6 instances of 8-bit (SDR) hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 3 sessions at 4K@30fps resolution (unless AV1), out of which at most 2 are encoder sessions and 3 sessions at 1080p resolution. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support 6 instances of 8-bit (SDR) hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9, AV1, or later) in any codec combination running concurrently with 3 sessions at 4K@30fps resolution (unless AV1), out of which at most 2 are encoder sessions and 3 sessions at 1080p resolution. For all sessions, there MUST NOT be more than 1 frame dropped per second. AV1 codecs are only required to support 1080p resolution, but are still required to support 6 instances at 1080p30fps."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-7"
+ name: "Video encoder init latency"
+ description:
+ "Maximum codec initialization latency for a 1080p or smaller video "
+ "encoding session for all hardware video encoders when under load."
+
+ measurements: {
+ key: "codec_initialization_latency_ms"
+ value: {
+ description: "Codec initialization latency in milliseconds"
+ measurement_type: MEASUREMENT_TYPE_LONG
+ comparison: COMPARISON_LESS_THAN_OR_EQUAL
+ }
+ }
+ variants: {
+ key: "dolby"
+ value: {
+ description: "When the codec is Dolby Vision"
+ }
+ }
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification:
+ "MUST have a codec initialization latency of 65 ms or less for a 1080p "
+ "or smaller video encoding session for all hardware video encoders when "
+ "under load. Load here is defined as a concurrent 1080p to 720p "
+ "video-only transcoding session using hardware video codecs together "
+ "with the 1080p audio-video recording initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 65
+ }
+ }
+ variant_specs: {
+ key: "dolby"
value: {
- id: "is_hdr",
- description: "Does the display support HDR"
- measurement_type: MEASUREMENT_TYPE_BOOL
- comparison: COMPARISON_EQUAL
- }
- }, {
- key: "display_luminance_nits"
- value: {
- id: "display_luminance_nits",
- description: "The display luminance in nits."
- measurement_type: MEASUREMENT_TYPE_DOUBLE
- comparison: COMPARISON_GREATER_THAN_OR_EQUAL
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 65
}
- }
- ]
- specs {
- key: 35
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_INVALID ;
- specification: "MUST have a HDR display supporting at least 1000 nits"
- required_values: {
- key: "display_luminance_nits"
- value: {
- comparison: COMPARISON_GREATER_THAN_OR_EQUAL
- double_value: 1000
- }
- }
- required_values: {
- key: "is_hdr"
- value: {
- comparison: COMPARISON_EQUAL
- bool_value: true
- }
+ }
+ }
+ }
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification:
+ "MUST have a codec initialization latency of 50 ms or less for a 1080p "
+ "or smaller video encoding session for all hardware video encoders "
+ "when under load. Load here is defined as a concurrent 1080p to 720p "
+ "video-only transcoding session using hardware video codecs together "
+ "with the 1080p audio-video recording initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 50
+ }
+ }
+ variant_specs: {
+ key: "dolby"
+ value: {
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 50
}
- }
- }
-}
-requirements {
- id: "7.1.4/H1-1"
- description: "- Hardware overlays"
-}
-requirements {
- id: "7.6.1/H-1-1"
- description: "- Memory"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST have at least 6 GB of physical memory."
- }
- }
-}
-requirements {
- id: "7.6.1/H-2-1"
- description: "- Memory"
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST have at least 6 GB of physical memory."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST have at least 8 GB of physical memory."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
- }
- }
-}
-requirements {
- id: "8.2/H-1-1"
- name: "Sequential write"
- description: "Sequential write"
- measurements: {
- key: "filesystem_io_rate_mbps"
+ }
+ }
+ }
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification:
+ "MUST have a codec initialization latency of 40 ms or less for a 1080p "
+ "or smaller video encoding session for all hardware video encoders "
+ "when under load. Load here is defined as a concurrent 1080p to 720p "
+ "video-only transcoding session using hardware video codecs together "
+ "with the 1080p audio-video recording initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 40
+ }
+ }
+ variant_specs: {
+ key: "dolby"
value: {
- id: "filesystem_io_rate_mbps"
- description: "Sequential write performance in MB per second."
- measurement_type: MEASUREMENT_TYPE_DOUBLE
- comparison: COMPARISON_GREATER_THAN_OR_EQUAL
- }
- }
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST ensure a sequential write performance of at least 100 MB/s."
- required_values: {
- key: "filesystem_io_rate_mbps"
- value: {
- comparison: COMPARISON_GREATER_THAN_OR_EQUAL
- double_value: 100
- }
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 50
}
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST ensure a sequential write performance of at least 125 MB/s."
- required_values: {
- key: "filesystem_io_rate_mbps"
- value: {
- comparison: COMPARISON_GREATER_THAN_OR_EQUAL
- double_value: 125
- }
+ }
+ }
+ }
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification:
+ "MUST have a codec initialization latency of 40 ms or less for a 1080p "
+ "or smaller video encoding session for all hardware video encoders "
+ "when under load. Load here is defined as a concurrent 1080p to 720p "
+ "video-only transcoding session using hardware video codecs together "
+ "with the 1080p audio-video recording initialization. For Dolby vision "
+ "codec, the codec initialization latency MUST be 50 ms or less."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 40
+ }
+ }
+ variant_specs: {
+ key: "dolby"
+ value: {
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 50
}
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST ensure a sequential write performance of at least 150 MB/s."
- required_values: {
- key: "filesystem_io_rate_mbps"
- value: {
- comparison: COMPARISON_GREATER_THAN_OR_EQUAL
- double_value: 150
- }
+ }
+ }
+ }
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification:
+ "MUST have a codec initialization latency of 40 ms or less for a 1080p "
+ "or smaller video encoding session for all hardware video encoders "
+ "when under load. Load here is defined as a concurrent 1080p to 720p "
+ "video-only transcoding session using hardware video codecs together "
+ "with the 1080p audio-video recording initialization. For Dolby vision "
+ "codec, the codec initialization latency MUST be 50 ms or less."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 40
+ }
+ }
+ variant_specs: {
+ key: "dolby"
+ value: {
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 50
}
+ }
+ }
+ }
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-8"
+ name: "Audio encoder init latency"
+ description: "Maximum codec initialization latency for a 128 kbps or lower bitrate audio encoding session for all audio encoders when under load."
+ measurements: {
+ key: "codec_initialization_latency_ms"
+ value: {
+ description: "Codec initialization latency in milliseconds"
+ measurement_type: MEASUREMENT_TYPE_LONG
+ comparison: COMPARISON_LESS_THAN_OR_EQUAL
+ }
+ }
+ specs: {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have a codec initialization latency of 50 ms or less for a 128 kbps or lower bitrate audio encoding session for all audio encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 50
+ }
+ }
+ }
+ }
+ specs: {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST have a codec initialization latency of 40 ms or less for a 128 kbps or lower bitrate audio encoding session for all audio encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 40
+ }
+ }
+ }
+ }
+ specs: {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have a codec initialization latency of 30 ms or less for a 128 kbps or lower bitrate audio encoding session for all audio encoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video recording initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 30
+ }
+ }
+ }
+ }
+ specs: {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 30
+ }
+ }
+ }
+ }
+ specs: {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 30
+ }
+ }
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-9"
+ description: "- AV1 hardware decoder\n- Secure hardware decoders"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support 2 instances of secure hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30 fps."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support 2 instances of secure hardware video decoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 4k resolution@30 fps (unless AV1) for both 8-bit (SDR) and 10-bit HDR content. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support 2 instances of secure hardware video decoder sessions (AVC, HEVC, VP9, AV1, or later) in any codec combination running concurrently at 4k resolution@30 fps (unless AV1) for both 8-bit (SDR) and 10-bit HDR content. For all sessions, there MUST NOT be more than 1 frame dropped per second. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-10"
+ description: "- AV1 hardware decoder\n- Secure hardware decoders"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support 3 instances of non-secure hardware video decoder sessions together with 1 instance of secure hardware video decoder session (4 instances total) (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 1080p resolution@30fps."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support 3 instances of non-secure hardware video decoder sessions together with 1 instance of secure hardware video decoder session (4 instances total) (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently with 3 sessions at 4K resolution@30 fps (unless AV1) which includes one secure decoder session and 1 nn-secure session at 1080p resolution@30fps where at most 2 sessions can be in 10-bit HDR. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support 3 instances of non-secure hardware video decoder sessions together with 1 instance of secure hardware video decoder session (4 instances total) (AVC, HEVC, VP9, AV1, or later) in any codec combination running concurrently with 3 sessions at 4K resolution@30fps (unless AV1) which includes one secure decoder session and 1 nn-secure session at 1080p resolution@30fps where at most 2 sessions can be in 10-bit HDR. For all sessions, there MUST NOT be more than 1 frame dropped per second. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-11"
+ description: "- AV1 hardware decoder\n- Secure hardware decoders"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support a secure decoder for every hardware AVC, HEVC, VP9 or AV1 decoder on the device."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-12"
+ description: "- Decoder initialization latency"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have a video decoder initialization latency of 40 ms or less."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST have a codec initialization latency of 40 ms or less for a 1080p or smaller video decoding session for all hardware video decoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video playback initialization. For Dolby vision codec, the codec initialization latency MUST be 50 ms or less."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-13"
+ name: "Audio decoder init latency"
+ description: "Maximum codec initialization latency for a 128 kbps or lower bitrate audio decoding session for all audio decoders when under load."
+ measurements: {
+ key: "codec_initialization_latency_ms"
+ value: {
+ description: "Codec initialization latency in milliseconds"
+ measurement_type: MEASUREMENT_TYPE_LONG
+ comparison: COMPARISON_LESS_THAN_OR_EQUAL
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have a codec initialization latency of 30 ms or less for a 128 kbps or lower bitrate audio decoding session for all audio decoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video playback initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 30
+ }
+ }
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST have a codec initialization latency of 30 ms or less for a 128 kbps or lower bitrate audio decoding session for all audio decoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video playback initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 30
+ }
+ }
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST have a codec initialization latency of 30 ms or less for a 128 kbps or lower bitrate audio decoding session for all audio decoders when under load. Load here is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs together with the 1080p audio-video playback initialization."
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 30
+ }
+ }
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-14"
+ description: "- AV1 hardware decoder\n- Film grain effect"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support AV1 hardware decoder Main 10, Level 4.1."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support AV1 hardware decoder Main 10, Level 4.1 and film grain."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support AV1 hardware decoder Main 10, Level 4.1 with film grain effect over GPU composition."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-SR-1"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "Are STRONGLY RECOMMENDED to support Film Grain for AV1 hardware decoder."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-15"
+ description: "- Secure hardware decoders"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have at least 1 hardware video decoder supporting 4K60."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-16"
+ description: "- Secure hardware decoders"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have at least 1 hardware video encoder supporting 4K60."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-17"
+ description: "- AVIF Baseline Profile"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST have at least 1 hardware image decoder supporting AVIF Baseline Profile."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-18"
+ description: "- AV1 encoder"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support AV1 encoder which can encode up to 480p resolution at 30fps and 1Mbps."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.12/H-SR"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "Are Strongly Recommended to support support the Feature_HdrEditing feature for all hardware AV1 and HEVC encoders present on the device."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-19"
+ description: "- HDR video codecs"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support 3 instances of 10-bit (HDR) hardware video decoder and hardware video encoder sessions (AVC, HEVC, VP9, AV1 or later) in any codec combination running concurrently at 4K@30fps resolution (unless AV1) out of which at most 1 is an encoder session, which could be configured in RGBA_1010102 input format through a GL surface. HDR metadata generation by the encoder is not required if encoding from the GL surface. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support 2 instances of secure hardware video decoder sessions (AVC, HEVC, VP9, AV1, or later) in any codec combination running concurrently at 4k resolution@30 fps (unless AV1) for both 8-bit (SDR) and 10-bit HDR content. For all sessions, there MUST NOT be more than 1 frame dropped per second. AV1 codec sessions are only required to support 1080p resolution even when this requirement calls for 4K."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-20"
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support the Feature_HdrEditing feature for all hardware AV1 and HEVC encoders present on the device at 4K resolution or the largest Camera-supported resolution, whichever is less."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-21"
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support FEATURE_DynamicColorAspect for all hardware video decoders (AVC, HEVC, VP9, AV1, or later). Note: This means applications can update the color aspects of the video content during the decoding session. Decoders that support 10-bit and 8-bit content MUST support dynamically switching between 8- and 10-bit content in Surface mode. Decoders that support HDR transfer function MUST support dynamically switching between SDR and HDR content."
+ }
+ }
+}
+requirements {
+ id: "5.1/H-1-22"
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support encoding, decoding, GPU-editing and displaying video content in portrait aspect ratio regardless of the rotation metadata for the largest Camera supported resolution or 4K whichever is less. Note: this includes HDR profiles if codec supports HDR. AV1 codecs are only required to support 1080p resolution. This requirement is only for hardware codecs, GPU and the DPU."
+ }
+ }
+}
+requirements {
+ id: "5.12/H-1-2"
+ name: "RGBA 1010102 color format"
+ description: "RGBA_1010102 color format support for hardware encoders."
+ measurements: {
+ key: "rgba_1010102_color_format"
+ value: {
+ description: "Is RGBA_1010102 supported."
+ measurement_type: MEASUREMENT_TYPE_BOOL
+ comparison: COMPARISON_EQUAL
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support RGBA_1010102 color format for all hardware AV1 and HEVC encoders present on the device."
+ required_values: {
+ key: "rgba_1010102_color_format"
+ value {
+ bool_value: true
+ }
+ }
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support RGBA_1010102 color format for all hardware AV1 and HEVC encoders present on the device."
+ required_values: {
+ key: "rgba_1010102_color_format"
+ value {
+ bool_value: true
+ }
+ }
+ }
+ }
+}
+requirements {
+ id: "5.12/H-1-3"
+ description: "- YUV texture sampling"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST advertise support for the EXT_YUV_target extension to sample from YUV textures in both 8 and 10-bits."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.2/H-2-1"
+ description: "- Video encoding quality"
+}
+requirements {
+ id: "5.3/H-1-1"
+ description: "- Decoder frame drops"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST NOT drop more than 1 frame in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 30 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST NOT drop more than 2 frames in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST NOT drop more than 1 frame in 10 seconds (i.e less than 0.167 percent frame drop) for a 1080p 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST NOT drop more than 1 frame in 10 seconds (i.e less than 0.167 percent frame drop) for a 4K 60 fps video session under load."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.3/H-1-2"
+ description: "- Decoder frame drops"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST NOT drop more than 1 frame in 10 seconds during a video resolution change in a 30 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128Kbps AAC audio playback."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST NOT drop more than 2 frames in 10 seconds during a video resolution change in a 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST NOT drop more than 1 frame in 10 seconds during a video resolution change in a 60 fps video session under load. Load is defined as a concurrent 1080p to 720p video-only transcoding session using hardware video codecs, as well as a 128 kbps AAC audio playback."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST NOT drop more than 1 frame in 10 seconds during a video resolution change in a 60 fps video session under load for a 4K session."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.6/H-1-1"
+ description: "- Round-trip audio latency"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have a tap-to-tone latency of less than 100 milliseconds using the OboeTester tap-to-tone test or CTS Verifier tap-to-tone test."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have a tap-to-tone latency of 80 milliseconds or less using the OboeTester tap-to-tone test or CTS Verifier tap-to-tone test."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST have a tap-to-tone latency of 80 milliseconds or less using the CTS Verifier tap-to-tone test."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.6/H-1-2"
+ description: "- Round-trip audio latency"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have a round-trip audio latency of 80 milliseconds or less over at least one supported data path."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.6/H-1-3"
+ description: "- Wired headsets and USB audio devices"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support >=24-bit audio for stereo output over 3.5 mm audio jacks if present and over USB audio if supported through the entire data path for low latency and streaming configurations. For the low latency configuration, AAudio should be used by the app in low-latency callback mode. For the streaming configuration, a Java AudioTrack should be used by the app. In both the low latency and streaming configurations, the HAL output sink should accept either AUDIO_FORMAT_PCM_24_BIT, AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_32_BIT or AUDIO_FORMAT_PCM_FLOAT for its target output format."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.6/H-1-4"
+ description: "- Wired headsets and USB audio devices"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support >=4 channel USB audio devices (This is used by DJ controllers for previewing songs.)"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.6/H-1-5"
+ description: "- MIDI devices"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support class compliant MIDI devices and declare the MIDI feature flag."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.6/H-1-9"
+ description: "- Multichannel audio mixing"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support at least 12 channel mixing. This implies the capability to open an AudioTrack with 7.1.4 channel mask and properly spatialise or downmix all channels to stereo."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.6/H-SR"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "Are STRONGLY RECOMMENDED to support 24 channel mixing with at least support for 9.1.6 and 22.2 channel masks."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "5.7/H-1-2"
+ description: "- Hardware-backed trusted execution environment"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support MediaDrm.SECURITY_LEVEL_HW_12ECURE_ALL with the below content decryption capabilities.\nMinimum Sample size 4 MiB\nMinimum Number of Subsamples - H264 or HEVC 32\nMinimum Number of Subsamples - VP9 9\nMinimum Number of Subsamples - AV1 288\nMinimum subsample buffer size 1 MiB\nMinimum Generic crypto buffer size 500 KiB\nMinimum Number of concurrent sessions 30\nMinimum Number of keys per session 20\nMinimum Total Number of Keys (all sessions) 80\nMinimum Total Number of DRM Keys (all sessions) 6\nMessage Size 16 KiB\nDecrypted Frames per Second 60 fps"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-1"
+ description: "- Resolution and frame rate"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have a primary rear facing camera with a resolution of at least 12 megapixels supporting video capture at 4k@30fps. The primary rear-facing camera is the rear-facing camera with the lowest camera ID."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST have a primary rear facing camera with a resolution of at least 12 megapixels supporting video capture at 4k@30fps, 1080p@60fps, and 720p@60fps. The primary rear-facing camera is the rear-facing camera with the lowest camera ID."
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-2"
+ description: "- Resolution and frame rate"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have a primary front facing camera with a resolution of at least 4 megapixels supporting video capture at 1080p@30fps. The primary front-facing camera is the front-facing camera with the lowest camera ID."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST have a primary front facing camera with a resolution of at least 5 megapixels and support video capture at 1080p@30fps. The primary front-facing camera is the front-facing camera with the lowest camera ID."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST have a primary front-facing camera with a resolution of at least 6 megapixels and support video capture at 1080p@30fps. The primary front-facing camera is the front-facing camera with the lowest camera ID."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-3"
+ description: "- FULL or better hardware level"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST support android.info.supportedHardwareLevel property as FULL or better for back primary and LIMITED or better for front primary camera."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST support android.info.supportedHardwareLevel property as FULL or better for both primary cameras."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-4"
+ description: "- Timestamp source is realtime"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST support CameraMetadata.SENSOR_INFO_13IMESTAMP_12OURCE_11EALTIME for both primary cameras."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-5"
+ description: "- Startup and capture latencies"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have camera2 JPEG capture latency < 1000 ms for 1080p resolution as measured by the CTS camera PerformanceTest under ITS lighting conditions (3000K) for both primary cameras."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-6"
+ description: "- Startup and capture latencies"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have camera2 startup latency (open camera to first preview frame) < 600 ms as measured by the CTS camera PerformanceTest under ITS lighting conditions (3000K) for both primary cameras."
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have camera2 startup latency (open camera to first preview frame) < 500 ms as measured by the CTS camera PerformanceTest under ITS lighting conditions (3000K) for both primary cameras."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-8"
+ description: "- RAW capability"
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST support CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_11AW and android.graphics.ImageFormat.RAW_12ENSOR for the primary back camera."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-9"
+ description: "- Slow-mo recording"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-10"
+ description: "- Minimum zoom ratio for ultrawide cameras"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have min ZOOM_11ATIO < 1.0 for the primary cameras if there is an ultrawide RGB camera facing the same direction."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-11"
+ description: "- Concurrent camera"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST implement concurrent front-back streaming on primary cameras."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-12"
+ description: "- Preview stabilization"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support CONTROL_VIDEO_12TABILIZATION_MODE_PREVIEW_12TABILIZATION for both primary front and primary back camera."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-13"
+ description: "- Logical multi-camera"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support LOGICAL_MULTI_CAMERA capability for the primary cameras if there are greater than 1 RGB cameras facing the same direction."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-14"
+ description: "- Stream use case"
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST support STREAM_14SE_CASE capability for both primary front and primary back camera."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-15"
+ description: "- Night mode extension"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support ~Bokeh &~ Night mode extensions via both CameraX and Camera2 extensions for primary cameras."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-16"
+ description: "- HDR-capable primary camera"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support DYNAMIC_RANGE_TEN_BIT capability for the primary cameras."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-17"
+ description: "- Face detection scene mode"
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST support CONTROL_SCENE_MODE_FACE_PRIORITY and face detection (STATISTICS_FACE_DETECT_MODE_SIMPLE or STATISTICS_FACE_DETECT_MODE_FULL) for the primary cameras."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-18"
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support JPEG_R for the primary rear and primary front cameras."
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-19"
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION for 1080p HLG10 preview with maximum-size 16:9 aspect ratio JPEG, and for 720p HLG10 preview with maximum-size 16:9 aspect ratio JPEG stream combinations for the primary rear camera."
+ }
+ }
+}
+requirements {
+ id: "7.5/H-1-20"
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST by default output JPEG_R for the primary rear and primary front cameras in the native camera app."
+ }
+ }
+}
+requirements {
+ id: "7.1.1.1/H-1-1"
+ description: "- Screen resolution"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have screen resolution of at least 1080p."
+ }
+ }
+}
+requirements {
+ id: "7.1.1.1/H-2-1"
+ description: "- Screen resolution"
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST have screen resolution of at least 1080p."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.1.1.3/H-1-1"
+ description: "- Screen density"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have screen density of at least 400 dpi."
+ }
+ }
+}
+requirements {
+ id: "7.1.1.3/H-2-1"
+ description: "- Screen density"
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST have screen density of at least 400 dpi."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "7.1.1.3/H-3-1"
+ name: "HDR display"
+ description: "HDR display"
+ measurements: [
+ {
+ key: "is_hdr"
+ value: {
+ id: "is_hdr"
+ description: "Does the display support HDR"
+ measurement_type: MEASUREMENT_TYPE_BOOL
+ comparison: COMPARISON_EQUAL
+ }
+ },
+ {
+ key: "display_luminance_nits"
+ value: {
+ id: "display_luminance_nits"
+ description: "The display luminance in nits."
+ measurement_type: MEASUREMENT_TYPE_DOUBLE
+ comparison: COMPARISON_GREATER_THAN_OR_EQUAL
+ }
+ }
+ ]
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_INVALID
+ specification: "MUST have a HDR display supporting at least 1000 nits"
+ required_values: {
+ key: "display_luminance_nits"
+ value: {
+ double_value: 1000
}
- }
-}
-requirements {
- id: "8.2/H-1-2"
- description: "- Read and write performance"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST ensure a random write performance of at least 10 MB/s."
- }
- }
-}
-requirements {
- id: "8.2/H-2-2"
- description: "- Read and write performance"
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "same"
- }
- }
-}
-requirements {
- id: "8.2/H-1-3"
- description: "- Read and write performance"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST ensure a sequential read performance of at least 200 MB/s."
- }
- }
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST ensure a sequential read performance of at least 250 MB/s."
- }
- }
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "same"
+ }
+ required_values: {
+ key: "is_hdr"
+ value: {
+ bool_value: true
}
+ }
}
+ }
}
requirements {
- id: "8.2/H-2-3"
- description: "- Read and write performance"
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST ensure a sequential read performance of at least 250 MB/s."
- }
- }
+ id: "7.1.4/H1-1"
+ description: "- Hardware overlays"
}
requirements {
- id: "8.2/H-1-4"
- description: "- Read and write performance"
- specs {
- key: 30
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_11
- specification: "MUST ensure a random read performance of at least 25 MB/s."
- }
+ id: "7.6.1/H-1-1"
+ name: "Android 11 Memory"
+ description: "Minimum memory available to the kernel as reported by android.app.ActivityManager.MemoryInfo."
+ measurements: {
+ key: "physical_memory_mb"
+ value: {
+ description: "Physical memory in MiB as reported by android.app.ActivityManager.MemeryInfo.totalMemory."
+ comparison: COMPARISON_GREATER_THAN_OR_EQUAL
+ measurement_type: MEASUREMENT_TYPE_LONG
}
- specs {
- key: 33
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_13
- specification: "MUST ensure a random read performance of at least 40 MB/s."
+ }
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST have at least 6 GB of physical memory."
+ required_values: {
+ key: "physical_memory_mb"
+ value: {
+ long_value: 5120
+ }
+ }
+ }
+ }
+}
+requirements {
+ id: "7.6.1/H-2-1"
+ name: "Memory"
+ description: "Minimum memory available to the kernel as reported by android.app.ActivityManager.MemoryInfo."
+ measurements: {
+ key: "physical_memory_mb"
+ value: {
+ description: "Physical memory in MiB as reported by android.app.ActivityManager.MemeryInfo.totalMemory."
+ comparison: COMPARISON_GREATER_THAN_OR_EQUAL
+ measurement_type: MEASUREMENT_TYPE_LONG
+ }
+ }
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST have at least 6 GB of physical memory."
+ required_values: {
+ key: "physical_memory_mb"
+ value: {
+ long_value: 5120
+ }
+ }
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST have at least 8 GB of physical memory."
+ required_values: {
+ key: "physical_memory_mb"
+ value: {
+ long_value: 6800
+ }
+ }
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST have at least 8 GB of physical memory."
+ required_values: {
+ key: "physical_memory_mb"
+ value: {
+ long_value: 6800
+ }
+ }
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST have at least 8 GB of physical memory, with at least 6.64 GB available to the kernel as reported by android.app.ActivityManager.MemoryInfo."
+ required_values: {
+ key: "physical_memory_mb"
+ value: {
+ long_value: 6800
+ }
+ }
+ }
+ }
+}
+requirements {
+ id: "8.2/H-1-1"
+ name: "Sequential write"
+ description: "Sequential write"
+ measurements: {
+ key: "filesystem_io_rate_mbps"
+ value: {
+ id: "filesystem_io_rate_mbps"
+ description: "Sequential write performance in MB per second."
+ measurement_type: MEASUREMENT_TYPE_DOUBLE
+ comparison: COMPARISON_GREATER_THAN_OR_EQUAL
+ }
+ }
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST ensure a sequential write performance of at least 100 MB/s."
+ required_values: {
+ key: "filesystem_io_rate_mbps"
+ value: {
+ double_value: 100
}
+ }
}
- specs {
- key: 34
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_14
- specification: "MUST ensure a random read performance of at least 100 MB/s."
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST ensure a sequential write performance of at least 125 MB/s."
+ required_values: {
+ key: "filesystem_io_rate_mbps"
+ value: {
+ double_value: 125
}
+ }
}
-}
-requirements {
- id: "8.2/H-2-4"
- description: "- Read and write performance"
- specs {
- key: 31
- value {
- mpc: MEDIA_PERFORMANCE_CLASS_12
- specification: "MUST ensure a random read performance of at least 40 MB/s."
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST ensure a sequential write performance of at least 150 MB/s."
+ required_values: {
+ key: "filesystem_io_rate_mbps"
+ value: {
+ double_value: 150
}
+ }
}
-}
-requirements {
- id: "8.2/H-1-5"
- description: "- Read and write performance"
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST ensure a sequential write performance of at least 150&nbsp;MB/s."
+ required_values: {
+ key: "filesystem_io_rate_mbps"
+ value: {
+ double_value: 150
+ }
+ }
+ }
+ }
+}
+requirements {
+ id: "8.2/H-2-1"
+ description: "- Read and write performance"
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST ensure a sequential write performance of at least 125 MB/s."
+ }
+ }
+}
+requirements {
+ id: "8.2/H-1-2"
+ description: "- Read and write performance"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST ensure a random write performance of at least 10 MB/s."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "same"
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "8.2/H-2-2"
+ description: "- Read and write performance"
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "8.2/H-1-3"
+ description: "- Read and write performance"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST ensure a sequential read performance of at least 200 MB/s."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST ensure a sequential read performance of at least 250 MB/s."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "same"
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "8.2/H-2-3"
+ description: "- Read and write performance"
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST ensure a sequential read performance of at least 250 MB/s."
+ }
+ }
+}
+requirements {
+ id: "8.2/H-1-4"
+ description: "- Read and write performance"
+ specs {
+ key: 30
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_11
+ specification: "MUST ensure a random read performance of at least 25 MB/s."
+ }
+ }
+ specs {
+ key: 33
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_13
+ specification: "MUST ensure a random read performance of at least 40 MB/s."
+ }
+ }
+ specs {
+ key: 34
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_14
+ specification: "MUST ensure a random read performance of at least 100 MB/s."
+ }
+ }
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "same"
+ }
+ }
+}
+requirements {
+ id: "8.2/H-2-4"
+ description: "- Read and write performance"
+ specs {
+ key: 31
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_12
+ specification: "MUST ensure a random read performance of at least 40 MB/s."
+ }
+ }
+}
+requirements {
+ id: "8.2/H-1-5"
+ description: "- Read and write performance"
+}
+requirements {
+ id: "7.1.4.1/H-1-2"
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support the EGL_IMG_context_priority and EGL_EXT_protected_content extensions."
+ }
+ }
+}
+requirements {
+ id: "7.1.4.1/H-1-3"
+ name: "Vulkan"
+ description: "Must support vulkan physical device protected memory and global priority."
+ measurements: [
+ {
+ key: "vk_ext_global_priority"
+ value: {
+ description: "Is VK_EXT_global_priority supported."
+ measurement_type: MEASUREMENT_TYPE_BOOL
+ comparison: COMPARISON_EQUAL
+ }
+ },
+ {
+ key: "vk_physical_device_protected_memory"
+ value: {
+ description: "Is VkPhysicalDeviceProtectedMemoryFeatures.protectedMemory supported."
+ measurement_type: MEASUREMENT_TYPE_BOOL
+ comparison: COMPARISON_EQUAL
+ }
+ },
+ {
+ key: "vk_non_cpu_device_count"
+ value: {
+ description: "The count of non VK_PHYSICAL_DEVICE_TYPE_CPU Vulcan Devices."
+ measurement_type: MEASUREMENT_TYPE_INT
+ comparison: COMPARISON_GREATER_THAN_OR_EQUAL
+ }
+ }
+ ]
+ specs {
+ key: 35
+ value {
+ mpc: MEDIA_PERFORMANCE_CLASS_15
+ specification: "MUST support VkPhysicalDeviceProtectedMemoryFeatures.protectedMemory and VK_KHR_global_priority."
+ required_values: [
+ {
+ key: "vk_ext_global_priority"
+ value: {
+ bool_value: true
+
+ }
+ },
+ {
+ key: "vk_physical_device_protected_memory"
+ value: {
+ bool_value: true
+ }
+ },
+ {
+ key: "vk_non_cpu_device_count"
+ value: {
+ int_value: 1
+ }
+ }
+ ]
+ }
+ }
}
diff --git a/tests/mediapc/requirements/requirements_test.go b/tests/mediapc/requirements/requirements_test.go
new file mode 100644
index 00000000000..4e7a7121fb9
--- /dev/null
+++ b/tests/mediapc/requirements/requirements_test.go
@@ -0,0 +1,59 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 requirements
+
+import (
+ "bytes"
+ "testing"
+
+ _ "embed"
+)
+
+// MPC Requirements data from requirements.txtpb
+//
+//go:embed requirements.binbp
+var reqBinary []byte
+
+func TestGensrc(t *testing.T) {
+ reqList, err := UnmarshalRequirementList(reqBinary)
+ if err != nil {
+ t.Fatalf("Failed to unmarshal reqBinary: %v", err)
+ }
+
+ tests := []struct {
+ tmpl string
+ want string
+ }{
+ {
+ tmpl: "{{- $first := index .ReqList.GetRequirements 0 -}}First requirement is [{{$first.GetId}}].",
+ want: "First requirement is [5.1/H-1-1]."},
+ {
+ tmpl: "UpperCamelCase foo_bar -> {{UpperCamelCase \"foo_bar\"}}",
+ want: "UpperCamelCase foo_bar -> FooBar",
+ },
+ }
+
+ for _, tc := range tests {
+ var b bytes.Buffer
+ err = Gensrc(tc.tmpl, reqList, &b)
+ if err != nil {
+ t.Fatalf("Gensrc(%v, ...) failed: %v", tc.tmpl, err)
+ }
+ got := b.String()
+ if got != tc.want {
+ t.Errorf("Gensrc(%q, ...) = %q, want %q", tc.tmpl, got, tc.want)
+ }
+ }
+}
diff --git a/tests/mediapc/requirements/requirementsdata_test.go b/tests/mediapc/requirements/requirementsdata_test.go
new file mode 100644
index 00000000000..eeef93027e3
--- /dev/null
+++ b/tests/mediapc/requirements/requirementsdata_test.go
@@ -0,0 +1,69 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 requirementsdata_test
+
+import (
+ "testing"
+
+ "google3/third_party/android/mediapc_requirements/requirements"
+ pb "cts/test/mediapc/requirements/requirements_go_proto"
+
+ _ "embed"
+)
+
+// MPC Requirements data from requirements.txtpb
+//
+//go:embed requirements.binbp
+var reqBinary []byte
+
+func TestUniqueRequirementIDs(t *testing.T) {
+ reqList := mustUnmarshalRequirementList(t)
+
+ // Requirement ids must be unique
+ ids := make(map[string]bool)
+ for _, req := range reqList.GetRequirements() {
+ id := req.GetId()
+ if ids[id] {
+ t.Errorf("requirement [%s] is a duplicate", id)
+ }
+ ids[id] = true
+ }
+}
+
+func TestUniqueRequirementNames(t *testing.T) {
+ reqList := mustUnmarshalRequirementList(t)
+
+ // Requirement names must be unique
+ nameToID := make(map[string]string) // name to id
+ for _, req := range reqList.GetRequirements() {
+ if req.HasName() {
+ name := req.GetName()
+ if nameToID[name] != "" {
+ t.Errorf("the name %q of requirement [%s] is a duplicate of requirement [%s]'s name", req.GetId(), name, nameToID[name])
+ }
+ nameToID[name] = req.GetId()
+ }
+ }
+
+}
+
+func mustUnmarshalRequirementList(t *testing.T) *pb.RequirementList {
+ t.Helper()
+ reqList, err := requirements.UnmarshalRequirementList(reqBinary)
+ if err != nil {
+ t.Fatalf("failed to unmarshal reqBinary: %v", err)
+ }
+ return reqList
+}
diff --git a/tests/mediapc/requirements/templatefns.go b/tests/mediapc/requirements/templatefns.go
index ac823910016..59491d37cab 100644
--- a/tests/mediapc/requirements/templatefns.go
+++ b/tests/mediapc/requirements/templatefns.go
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,105 +16,141 @@
package templatefns
import (
- "strings"
- "text/template"
- "unicode"
+ "fmt"
+ "strings"
+ "text/template"
+ "unicode"
)
// Funcs returns a mapping from names of template helper functions to the
// functions themselves.
func Funcs() template.FuncMap {
- // These function are made available in templates by calling their key values, e.g. {{SnakeCase "HelloWorld"}}.
- return template.FuncMap{
- // Case conversion functions.
- "LowerCase": strings.ToLower,
- "UpperCase": strings.ToUpper,
- "TitleCase": titleCase,
- "SnakeCase": snakeCase,
- "KebabCase": kebabCase,
- "UpperCamelCase": upperCamelCase,
- "LowerCamelCase": lowerCamelCase,
- "SafeReqID": safeReqID,
- }
+ // These function are made available in templates by calling their key values, e.g. {{SnakeCase "HelloWorld"}}.
+ return template.FuncMap{
+ // go/keep-sorted start
+ "Dict": dict,
+ "KebabCase": kebabCase,
+ "LowerCamelCase": lowerCamelCase,
+ "LowerCase": strings.ToLower,
+ "SafeReqID": safeReqID,
+ "SnakeCase": snakeCase,
+ "TitleCase": titleCase,
+ "UpperCamelCase": upperCamelCase,
+ "UpperCase": strings.ToUpper,
+ // go/keep-sorted end
+ }
}
// isDelimiter checks if a rune is some kind of whitespace, '_' or '-'.
// helper function
func isDelimiter(r rune) bool {
- return r == '-' || r == '_' || unicode.IsSpace(r)
+ return r == '-' || r == '_' || unicode.IsSpace(r)
}
func shouldWriteDelimiter(r, prev, next rune) bool {
- if isDelimiter(prev) {
- // Don't delimit if we just delimited
- return false
- }
- // Delimit before new uppercase letters and after acronyms
- caseDelimit := unicode.IsUpper(r) && (unicode.IsLower(prev) || unicode.IsLower(next))
- // Delimit after digits
- digitDelimit := !unicode.IsDigit(r) && unicode.IsDigit(prev)
- return isDelimiter(r) || caseDelimit || digitDelimit
+ if isDelimiter(prev) {
+ // Don't delimit if we just delimited
+ return false
+ }
+ // Delimit before new uppercase letters and after acronyms
+ caseDelimit := unicode.IsUpper(r) && (unicode.IsLower(prev) || unicode.IsLower(next))
+ // Delimit after digits
+ digitDelimit := !unicode.IsDigit(r) && unicode.IsDigit(prev)
+ return isDelimiter(r) || caseDelimit || digitDelimit
}
// titleCase converts a string into Title Case.
func titleCase(s string) string {
- runes := []rune(s)
- var out strings.Builder
- for i, r := range runes {
- prev, next := ' ', ' '
- if i > 0 {
- prev = runes[i-1]
- if i+1 < len(runes) {
- next = runes[i+1]
- }
- }
+ runes := []rune(s)
+ var out strings.Builder
+ for i, r := range runes {
+ prev, next := ' ', ' '
+ if i > 0 {
+ prev = runes[i-1]
+ if i+1 < len(runes) {
+ next = runes[i+1]
+ }
+ }
- if shouldWriteDelimiter(r, prev, next) {
- out.WriteRune(' ')
- }
+ if shouldWriteDelimiter(r, prev, next) {
+ out.WriteRune(' ')
+ }
- if !isDelimiter(r) {
- // Output all non-delimiters unchanged
- out.WriteRune(r)
- }
- }
- return strings.Title(out.String())
+ if !isDelimiter(r) {
+ // Output all non-delimiters unchanged
+ out.WriteRune(r)
+ }
+ }
+ return strings.Title(out.String())
}
// snakeCase converts a string into snake_case.
func snakeCase(s string) string {
- return strings.ReplaceAll(strings.ToLower(titleCase(s)), " ", "_")
+ return strings.ReplaceAll(strings.ToLower(titleCase(s)), " ", "_")
}
// kebabCase converts a string into kebab-case.
func kebabCase(s string) string {
- return strings.ReplaceAll(strings.ToLower(titleCase(s)), " ", "-")
+ return strings.ReplaceAll(strings.ToLower(titleCase(s)), " ", "-")
}
// upperCamelCase converts a string into UpperCamelCase.
func upperCamelCase(s string) string {
- return strings.ReplaceAll(titleCase(s), " ", "")
+ return strings.ReplaceAll(titleCase(s), " ", "")
}
// lowerCamelCase converts a string into lowerCamelCase.
func lowerCamelCase(s string) string {
- if len(s) < 2 {
- return strings.ToLower(s)
- }
- runes := []rune(upperCamelCase(s))
- for i, r := range runes {
- // Lowercase leading acronyms
- if i > 1 && unicode.IsLower(r) {
- return strings.ToLower(string(runes[:i-1])) + string(runes[i-1:])
- }
- }
- return string(unicode.ToLower(runes[0])) + string(runes[1:])
+ if len(s) < 2 {
+ return strings.ToLower(s)
+ }
+ runes := []rune(upperCamelCase(s))
+ for i, r := range runes {
+ // Lowercase leading acronyms
+ if i > 1 && unicode.IsLower(r) {
+ return strings.ToLower(string(runes[:i-1])) + string(runes[i-1:])
+ }
+ }
+ return string(unicode.ToLower(runes[0])) + string(runes[1:])
}
// safeReqID converts a Media Performance Class (MPC) requirement id to a variable name safe string.
func safeReqID(s string) string {
- f := func(a, b, c string) string {
- return strings.Replace(a, b, c, -1)
- }
- return "r" + strings.ToLower(f(f(f(s, "/", "__"), ".", "_"), "-", "_"))
+ f := func(a, b, c string) string {
+ return strings.Replace(a, b, c, -1)
+ }
+ return "r" + strings.ToLower(f(f(f(s, "/", "__"), ".", "_"), "-", "_"))
+}
+
+// dict converts a list of key-value pairs into a map.
+// If there is an odd number of values, the last value is nil.
+// The last key is preserved so in the template it can be referenced like {{$myDict.key}}.
+func dict(v ...any) map[string]any {
+ dict := map[string]any{}
+ lenv := len(v)
+ for i := 0; i < lenv; i += 2 {
+ key := toString(v[i])
+ if i+1 >= lenv {
+ dict[key] = nil
+ continue
+ }
+ dict[key] = v[i+1]
+ }
+ return dict
+}
+
+// toString converts a value to a string.
+func toString(v any) string {
+ switch v := v.(type) {
+ case string:
+ return v
+ case []byte:
+ return string(v)
+ case error:
+ return v.Error()
+ case fmt.Stringer:
+ return v.String()
+ default:
+ return fmt.Sprintf("%v", v)
+ }
}
diff --git a/tests/mediapc/requirements/templatefns_test.go b/tests/mediapc/requirements/templatefns_test.go
new file mode 100644
index 00000000000..b0eb431abbe
--- /dev/null
+++ b/tests/mediapc/requirements/templatefns_test.go
@@ -0,0 +1,178 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 templatefns
+
+import (
+ "errors"
+ "testing"
+)
+
+var caseTests = []struct {
+ input, kebabCase, snakeCase, titleCase, upperCamelCase, lowerCamelCase string
+}{
+ {
+ input: "",
+ kebabCase: "", snakeCase: "", titleCase: "", upperCamelCase: "", lowerCamelCase: ""},
+ {
+ input: "f",
+ kebabCase: "f", snakeCase: "f", titleCase: "F", upperCamelCase: "F", lowerCamelCase: "f"},
+ {
+ input: "foo",
+ kebabCase: "foo", snakeCase: "foo", titleCase: "Foo", upperCamelCase: "Foo", lowerCamelCase: "foo"},
+ {
+ input: " foo_bar",
+ kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
+ {
+ input: " foo-bar",
+ kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
+ {
+ input: " foo bar",
+ kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
+ {
+ input: " Foo Bar",
+ kebabCase: "foo-bar", snakeCase: "foo_bar", titleCase: "Foo Bar", upperCamelCase: "FooBar", lowerCamelCase: "fooBar"},
+ {
+ input: "HTTP_status_code",
+ kebabCase: "http-status-code", snakeCase: "http_status_code", titleCase: "HTTP Status Code", upperCamelCase: "HTTPStatusCode", lowerCamelCase: "httpStatusCode"},
+ {
+ input: "foo many spaces",
+ kebabCase: "foo-many-spaces", snakeCase: "foo_many_spaces", titleCase: "Foo Many Spaces", upperCamelCase: "FooManySpaces", lowerCamelCase: "fooManySpaces"},
+ {
+ input: "foo---many-dashes",
+ kebabCase: "foo-many-dashes", snakeCase: "foo_many_dashes", titleCase: "Foo Many Dashes", upperCamelCase: "FooManyDashes", lowerCamelCase: "fooManyDashes"},
+ {
+ input: "foo___many_underline",
+ kebabCase: "foo-many-underline", snakeCase: "foo_many_underline", titleCase: "Foo Many Underline", upperCamelCase: "FooManyUnderline", lowerCamelCase: "fooManyUnderline"},
+ {
+ input: "UpperCamelCase",
+ kebabCase: "upper-camel-case", snakeCase: "upper_camel_case", titleCase: "Upper Camel Case", upperCamelCase: "UpperCamelCase", lowerCamelCase: "upperCamelCase"},
+ {
+ input: "ACRONYMInUpperCamelCase",
+ kebabCase: "acronym-in-upper-camel-case", snakeCase: "acronym_in_upper_camel_case", titleCase: "ACRONYM In Upper Camel Case", upperCamelCase: "ACRONYMInUpperCamelCase", lowerCamelCase: "acronymInUpperCamelCase"},
+ {
+ input: "FooGRPCHandler",
+ kebabCase: "foo-grpc-handler", snakeCase: "foo_grpc_handler", titleCase: "Foo GRPC Handler", upperCamelCase: "FooGRPCHandler", lowerCamelCase: "fooGRPCHandler"},
+ {
+ input: "GRPC1234Handler",
+ kebabCase: "grpc1234-handler", snakeCase: "grpc1234_handler", titleCase: "GRPC1234 Handler", upperCamelCase: "GRPC1234Handler", lowerCamelCase: "grpc1234Handler"},
+ {
+ input: "tricky4567number",
+ kebabCase: "tricky4567-number", snakeCase: "tricky4567_number", titleCase: "Tricky4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
+ {
+ input: "tricky 4567number",
+ kebabCase: "tricky-4567-number", snakeCase: "tricky_4567_number", titleCase: "Tricky 4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
+ {
+ input: "tricky 4567Number",
+ kebabCase: "tricky-4567-number", snakeCase: "tricky_4567_number", titleCase: "Tricky 4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
+ {
+ input: "tricky 4567 Number",
+ kebabCase: "tricky-4567-number", snakeCase: "tricky_4567_number", titleCase: "Tricky 4567 Number", upperCamelCase: "Tricky4567Number", lowerCamelCase: "tricky4567Number"},
+ {
+ input: "lowerCamelCase",
+ kebabCase: "lower-camel-case", snakeCase: "lower_camel_case", titleCase: "Lower Camel Case", upperCamelCase: "LowerCamelCase", lowerCamelCase: "lowerCamelCase"},
+ {
+ input: "endInCapitalT",
+ kebabCase: "end-in-capital-t", snakeCase: "end_in_capital_t", titleCase: "End In Capital T", upperCamelCase: "EndInCapitalT", lowerCamelCase: "endInCapitalT"},
+ {
+ input: "snake_case",
+ kebabCase: "snake-case", snakeCase: "snake_case", titleCase: "Snake Case", upperCamelCase: "SnakeCase", lowerCamelCase: "snakeCase"},
+ {
+ input: "kebab-case",
+ kebabCase: "kebab-case", snakeCase: "kebab_case", titleCase: "Kebab Case", upperCamelCase: "KebabCase", lowerCamelCase: "kebabCase"},
+ {
+ input: "üñicödeCäse",
+ kebabCase: "üñicöde-cäse", snakeCase: "üñicöde_cäse", titleCase: "Üñicöde Cäse", upperCamelCase: "ÜñicödeCäse", lowerCamelCase: "üñicödeCäse"}}
+
+func TestKebabCase(t *testing.T) {
+ for _, tt := range caseTests {
+ t.Run(tt.input, func(t *testing.T) {
+ if got := kebabCase(tt.input); got != tt.kebabCase {
+ t.Fatalf("KebabCase(%q) = %q, want %q", tt.input, got, tt.kebabCase)
+ }
+ })
+ }
+}
+
+func TestSnakeCase(t *testing.T) {
+ for _, tt := range caseTests {
+ t.Run(tt.input, func(t *testing.T) {
+ if got := snakeCase(tt.input); got != tt.snakeCase {
+ t.Fatalf("SnakeCase(%q) = %q, want %q", tt.input, got, tt.snakeCase)
+ }
+ })
+ }
+}
+
+func TestTitleCase(t *testing.T) {
+ for _, tt := range caseTests {
+ t.Run(tt.input, func(t *testing.T) {
+ if got := titleCase(tt.input); got != tt.titleCase {
+ t.Fatalf("TitleCase(%q) = %q, want %q", tt.input, got, tt.titleCase)
+ }
+ })
+ }
+}
+
+func TestUpperCamelCase(t *testing.T) {
+ for _, tt := range caseTests {
+ t.Run(tt.input, func(t *testing.T) {
+ if got := upperCamelCase(tt.input); got != tt.upperCamelCase {
+ t.Fatalf("upperCamelCase(%q) = %q, want %q", tt.input, got, tt.upperCamelCase)
+ }
+ })
+ }
+}
+
+func TestLowerCamelCase(t *testing.T) {
+ for _, tt := range caseTests {
+ t.Run(tt.input, func(t *testing.T) {
+ if got := lowerCamelCase(tt.input); got != tt.lowerCamelCase {
+ t.Fatalf("lowerCamelCase(%q) = %q, want %q", tt.input, got, tt.lowerCamelCase)
+ }
+ })
+ }
+}
+
+func TestDict(t *testing.T) {
+ errorValue := errors.New("error_value")
+ var dictTest = []struct {
+ values []any
+ want map[string]any
+ }{
+ {
+ values: []any{1, 2, 3},
+ want: map[string]any{
+ "1": 2,
+ "3": nil,
+ },
+ },
+ {
+ values: []any{"foo", "bar"},
+ want: map[string]any{"foo": "bar"},
+ },
+ {
+ values: []any{errors.New("error_key"), errorValue},
+ want: map[string]any{"error_key": errorValue},
+ },
+ }
+ for _, tt := range dictTest {
+ got := dict(tt.values...)
+ for k, v := range tt.want {
+ if got[k] != v {
+ t.Fatalf("dict(%v)[%q] = %q, want %q", tt.values, k, got[k], v)
+ }
+ }
+ }
+}
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
index 1948e4f4d96..0f795ae95d3 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
@@ -40,6 +40,7 @@ import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.mediapc.cts.common.PerformanceClassEvaluator;
+import android.mediapc.cts.common.Requirements;
import android.mediapc.cts.common.Utils;
import android.os.SystemClock;
import android.util.Log;
@@ -358,12 +359,27 @@ public class CodecInitializationLatencyTest {
long initializationLatency = codecInitializationLatencyMs[percentile * count / 100];
PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
- PerformanceClassEvaluator.CodecInitLatencyRequirement r5_1__H_1_Latency =
- isEncoder ? isAudio ? pce.addR5_1__H_1_8() : pce.addR5_1__H_1_7(mMime)
- : isAudio ? pce.addR5_1__H_1_13() : pce.addR5_1__H_1_12();
-
- r5_1__H_1_Latency.setCodecInitLatencyMs(initializationLatency);
-
+ if (isEncoder) {
+ if (isAudio) {
+ Requirements.addR5_1__H_1_8(pce).setCodecInitializationLatencyMs(
+ initializationLatency);
+ } else {
+ if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION)) {
+ Requirements.addR5_1__H_1_7Dolby(pce).setCodecInitializationLatencyMs(
+ initializationLatency);
+ } else {
+ Requirements.addR5_1__H_1_7(pce).setCodecInitializationLatencyMs(
+ initializationLatency);
+ }
+ }
+ } else {
+ if (isAudio) {
+ Requirements.addR5_1__H_1_13(pce).setCodecInitializationLatencyMs(
+ initializationLatency);
+ } else {
+ pce.addR5_1__H_1_12().setCodecInitLatencyMs(initializationLatency);
+ }
+ }
pce.submitAndCheck();
}
diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
index 9b7c54994cd..401278d4b15 100644
--- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
@@ -29,7 +29,9 @@ import android.media.MediaFormat;
import android.media.UnsupportedSchemeException;
import android.mediapc.cts.common.PerformanceClassEvaluator;
import android.mediapc.cts.common.Requirements;
+import android.mediapc.cts.common.Requirements.Android11MemoryRequirement;
import android.mediapc.cts.common.Requirements.HDRDisplayRequirement;
+import android.mediapc.cts.common.Requirements.MemoryRequirement;
import android.mediapc.cts.common.Utils;
import android.util.Log;
@@ -199,11 +201,11 @@ public class PerformanceClassTest {
Log.i(TAG, String.format("Total device memory = %,d MB", totalMemoryMb));
PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
- PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_1_1 = pce.addR7_6_1__H_1_1();
- PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_2_1 = pce.addR7_6_1__H_2_1();
+ Android11MemoryRequirement r7_6_1_h_1_1 = Requirements.addR7_6_1__H_1_1(pce);
+ MemoryRequirement r7_6_1_h_2_1 = Requirements.addR7_6_1__H_2_1(pce);
- r7_6_1_h_1_1.setPhysicalMemory(totalMemoryMb);
- r7_6_1_h_2_1.setPhysicalMemory(totalMemoryMb);
+ r7_6_1_h_1_1.setPhysicalMemoryMb(totalMemoryMb);
+ r7_6_1_h_2_1.setPhysicalMemoryMb(totalMemoryMb);
pce.submitAndCheck();
}
@@ -212,8 +214,7 @@ public class PerformanceClassTest {
@CddTest(requirements = {"2.2.7.3/7.1.1.3/H-3-1"})
public void testDisplayHdr() {
PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
- HDRDisplayRequirement req = pce.addRequirement(
- Requirements.createR7_1_1_3__H_3_1());
+ HDRDisplayRequirement req = Requirements.addR7_1_1_3__H_3_1(pce);
req.setIsHdr(Utils.IS_HDR);
req.setDisplayLuminanceNits(Utils.HDR_DISPLAY_AVERAGE_LUMINANCE);
diff --git a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
index e627ff1bdde..a2167eba77f 100644
--- a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java
@@ -51,6 +51,8 @@ import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.media.codec.Flags;
import android.mediapc.cts.common.PerformanceClassEvaluator;
+import android.mediapc.cts.common.Requirements;
+import android.mediapc.cts.common.Requirements.RGBA1010102ColorFormatRequirement;
import android.mediapc.cts.common.Utils;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.util.Log;
@@ -454,9 +456,8 @@ public class VideoCodecRequirementsTest {
}
PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
- PerformanceClassEvaluator.VideoCodecRequirement colorFormatSupportReq =
- pce.addColorFormatSupportReq();
- colorFormatSupportReq.setColorFormatSupportReq(isSupported);
+ RGBA1010102ColorFormatRequirement colorFormatSupportReq = Requirements.addR5_12__H_1_2(pce);
+ colorFormatSupportReq.setRgba1010102ColorFormat(isSupported);
pce.submitAndCheck();
}
diff --git a/tests/mediapc/src/android/mediapc/cts/VulkanTest.java b/tests/mediapc/src/android/mediapc/cts/VulkanTest.java
new file mode 100644
index 00000000000..cf1e7af8401
--- /dev/null
+++ b/tests/mediapc/src/android/mediapc/cts/VulkanTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.mediapc.cts;
+
+import android.mediapc.cts.common.PerformanceClassEvaluator;
+import android.mediapc.cts.common.Requirements;
+import android.mediapc.cts.common.Requirements.VulkanRequirement;
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.compatibility.common.util.CddTest;
+
+import com.google.common.collect.ImmutableList;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
+/**
+ * Verify Vulkan MPC requirements.
+ */
+@RunWith(AndroidJUnit4.class)
+public class VulkanTest {
+
+ private static final String LOG_TAG = VulkanTest.class.getSimpleName();
+ private static final int VK_PHYSICAL_DEVICE_TYPE_CPU = 4;
+
+
+ private static final String VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME = "VK_EXT_global_priority";
+ private static final int VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION = 1;
+
+ private ImmutableList<JSONObject> mVulkanDevices;
+ private static native String nativeGetVkJSON();
+
+ @Rule
+ public final TestName mTestName = new TestName();
+
+ static {
+ System.loadLibrary("ctsmediapc_vulkan_jni");
+ }
+
+ /**
+ * Test specific setup
+ */
+ @Before
+ public void setUp() throws Exception {
+ JSONObject instance = new JSONObject(nativeGetVkJSON());
+ final JSONArray vkjson = instance.getJSONArray("devices");
+ var builder = ImmutableList.<JSONObject>builder();
+ for (int i = 0; i < vkjson.length(); i++) {
+ builder.add(vkjson.getJSONObject(i));
+ }
+ mVulkanDevices = builder.build();
+ }
+
+ /**
+ * <b>7.1.4.1/H-1-3</b> MUST support
+ * {@code VkPhysicalDeviceProtectedMemoryFeatures.protectedMemory} and
+ * {@code VK_EXT_global_priority}.
+ */
+ @CddTest(requirements = {"7.1.4.1/H-1-3"})
+ @Test
+ public void checkVulkanProtectedMemoryAndGlobalPrioritySupport() throws Exception {
+
+ PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+ VulkanRequirement req = Requirements.addR7_1_4_1__H_1_3(pce);
+
+ var filteredDevices = mVulkanDevices.stream().filter(this::notCpuDevice).toList();
+ final boolean extGlobalPriority = filteredDevices.stream().allMatch(
+ device -> hasExtension(device, VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME,
+ VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION));
+ final boolean hasProtectedMemory = filteredDevices.stream().allMatch(
+ this::hasProtectedMemory);
+
+ req.setVkNonCpuDeviceCount(filteredDevices.size());
+ req.setVkPhysicalDeviceProtectedMemory(hasProtectedMemory);
+ req.setVkExtGlobalPriority(extGlobalPriority);
+
+ pce.submitAndCheck();
+ }
+
+ private boolean notCpuDevice(JSONObject device) {
+ try {
+ return device.getJSONObject("properties").getInt("deviceType")
+ != VK_PHYSICAL_DEVICE_TYPE_CPU;
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, "Failed to get device type of %s".formatted(device), e);
+ return false;
+ }
+ }
+
+ private static boolean hasExtension(JSONObject device, String name, int minVersion) {
+ try {
+ JSONArray extensions = device.getJSONArray("extensions");
+ for (int i = 0; i < extensions.length(); i++) {
+ JSONObject ext = extensions.getJSONObject(i);
+ if (ext.getString("extensionName").equals(name)
+ && ext.getInt("specVersion")
+ >= minVersion) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ Log.e(LOG_TAG,
+ "Failed to get extension %s v%s from %s".formatted(name, minVersion, device),
+ e);
+ }
+ return false;
+ }
+
+ private boolean hasProtectedMemory(JSONObject device) {
+ try {
+ return device.getJSONObject("protectedMemoryFeatures")
+ .getInt("protectedMemory") == 1;
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Failed to test for protect memory of %s".formatted(device), e);
+ }
+ return false;
+ }
+}
diff --git a/tests/rollback/src/com/android/cts/rollback/RollbackManagerTest.java b/tests/rollback/src/com/android/cts/rollback/RollbackManagerTest.java
index da8c7d2088e..f10115f0d97 100644
--- a/tests/rollback/src/com/android/cts/rollback/RollbackManagerTest.java
+++ b/tests/rollback/src/com/android/cts/rollback/RollbackManagerTest.java
@@ -677,7 +677,7 @@ public class RollbackManagerTest {
*/
@Test
public void testRollbackExpiresAfterLifetime() throws Exception {
- long expirationTime = TimeUnit.SECONDS.toMillis(30);
+ long expirationTime = TimeUnit.SECONDS.toMillis(6);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
Long.toString(expirationTime), false /* makeDefault*/);
@@ -691,8 +691,8 @@ public class RollbackManagerTest {
Thread.sleep(expirationTime / 2);
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNotNull();
- // Check that the data has expired after the expiration time (with a buffer of 1 second)
- Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(1));
+ // Check that the data has expired after the expiration time (with a buffer of 3 second)
+ Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(3));
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNull();
} finally {
// Restore default config values
@@ -708,7 +708,7 @@ public class RollbackManagerTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_ROLLBACK_LIFETIME)
public void testRollbackExpiresAfterRollbackLifetime() throws Exception {
- long expirationTimeA = TimeUnit.SECONDS.toMillis(4);
+ long expirationTimeA = TimeUnit.SECONDS.toMillis(6);
Install.single(TestApp.A1).commit();
Install.single(TestApp.A2).setEnableRollback()
.setRollbackLifetimeMillis(expirationTimeA).commit();
@@ -725,8 +725,8 @@ public class RollbackManagerTest {
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNotNull();
assertThat(RollbackUtils.getAvailableRollback(TestApp.B)).isNotNull();
- // Check that the data has expired after the expiration time (with a buffer of 1 second)
- Thread.sleep(expirationTimeA / 2 + TimeUnit.SECONDS.toMillis(1));
+ // Check that the data has expired after the expiration time (with a buffer of 3 seconds)
+ Thread.sleep(expirationTimeA / 2 + TimeUnit.SECONDS.toMillis(3));
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNull();
assertThat(RollbackUtils.getAvailableRollback(TestApp.B)).isNotNull();
}
@@ -763,7 +763,7 @@ public class RollbackManagerTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_ROLLBACK_LIFETIME)
public void testRollbackExpiresWhenLifetimeStays() throws Exception {
- long expirationTime = TimeUnit.SECONDS.toMillis(5);
+ long expirationTime = TimeUnit.SECONDS.toMillis(6);
Install.single(TestApp.A1).commit();
Install.single(TestApp.A2).setEnableRollback()
.setRollbackLifetimeMillis(expirationTime).commit();
@@ -777,7 +777,7 @@ public class RollbackManagerTest {
Thread.sleep(expirationTime / 2);
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNotNull();
// The rollback now should expire
- Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(1));
+ Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(3));
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNull();
} finally {
// Restore default config values
@@ -793,7 +793,7 @@ public class RollbackManagerTest {
*/
@Test
public void testTimeChangeDoesNotAffectLifetime() throws Exception {
- long expirationTime = TimeUnit.SECONDS.toMillis(30);
+ long expirationTime = TimeUnit.SECONDS.toMillis(6);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
Long.toString(expirationTime), false /* makeDefault*/);
@@ -811,7 +811,7 @@ public class RollbackManagerTest {
Thread.sleep(expirationTime / 2);
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNotNull();
// The rollback now should expire
- Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(1));
+ Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(3));
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNull();
} finally {
RollbackUtils.forwardTimeBy(-expirationTime);
@@ -831,7 +831,7 @@ public class RollbackManagerTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_ROLLBACK_LIFETIME)
public void testTimeChangeDoesNotAffectLifetimeMillis() throws Exception {
- long expirationTime = TimeUnit.SECONDS.toMillis(10);
+ long expirationTime = TimeUnit.SECONDS.toMillis(6);
Install.single(TestApp.A1).commit();
Install.single(TestApp.A2).setEnableRollback()
@@ -846,7 +846,7 @@ public class RollbackManagerTest {
Thread.sleep(expirationTime / 2);
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNotNull();
// The rollback now should expire
- Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(1));
+ Thread.sleep(expirationTime / 2 + TimeUnit.SECONDS.toMillis(3));
assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNull();
} finally {
RollbackUtils.forwardTimeBy(-expirationTime);
diff --git a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
index bbbd3910616..0f465e79fde 100644
--- a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
@@ -29,7 +29,7 @@
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="class" value="android.signature.cts.api.DebugClassKillswitchTest" />
<option name="runtime-hint" value="60s" />
- <option name="shell-timeout" value="45m" />
+ <option name="shell-timeout" value="65m" />
</test>
<!-- Controller that will skip the module if a native bridge situation is detected -->
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
index ee3903fdaa8..b3c26b37551 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
@@ -44,22 +44,22 @@ public abstract class BaseKillswitchTest extends AbstractApiTest {
private final static Predicate<DexMember> FIELD_FILTER =
dexMember -> (dexMember instanceof DexField);
- @Test(timeout = 2400000)
+ @Test(timeout = 3600000)
public void testKillswitchMechanismMethodsThroughReflection() {
doTestKillswitchMechanism(METHOD_FILTER, /* reflection= */ true, /* jni= */ false);
}
- @Test(timeout = 2400000)
+ @Test(timeout = 3600000)
public void testKillswitchMechanismMethodsThroughJni() {
doTestKillswitchMechanism(METHOD_FILTER, /* reflection= */ false, /* jni= */ true);
}
- @Test(timeout = 2400000)
+ @Test(timeout = 3600000)
public void testKillswitchMechanismFieldsThroughReflection() {
doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ true, /* jni= */ false);
}
- @Test(timeout = 2400000)
+ @Test(timeout = 3600000)
public void testKillswitchMechanismFieldsThroughJni() {
doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ false, /* jni= */ true);
}
diff --git a/tests/surfacecontrol/AndroidManifest.xml b/tests/surfacecontrol/AndroidManifest.xml
index ccfa2894d3d..20dcfd75274 100644
--- a/tests/surfacecontrol/AndroidManifest.xml
+++ b/tests/surfacecontrol/AndroidManifest.xml
@@ -110,7 +110,6 @@
android:label="HandleConfigurationActivity"
android:rotationAnimation="jumpcut"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
- android:theme="@android:style/Theme.Material.Dialog.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
diff --git a/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java b/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java
index c2eefe74ca2..c99eeae9ffc 100644
--- a/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java
+++ b/tests/surfacecontrol/src/android/view/surfacecontrol/cts/AttachedSurfaceControlTest.java
@@ -18,6 +18,7 @@ package android.view.surfacecontrol.cts;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
+import static android.server.wm.CtsWindowInfoUtils.waitForWindowOnTop;
import static android.view.cts.surfacevalidator.BitmapPixelChecker.validateScreenshot;
import static com.google.common.truth.Truth.assertThat;
@@ -57,6 +58,8 @@ import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ActivityScenario;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.rule.ActivityTestRule;
import com.android.compatibility.common.util.SystemUtil;
import com.android.window.flags.Flags;
@@ -89,6 +92,12 @@ public class AttachedSurfaceControlTest {
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+ @Rule
+ public ActivityTestRule<HandleConfigurationActivity> mActivityRule = new ActivityTestRule<>(
+ HandleConfigurationActivity.class);
+
+ private HandleConfigurationActivity mActivity;
+
private static class TransformHintListener implements
AttachedSurfaceControl.OnBufferTransformHintChangedListener {
Activity activity;
@@ -110,6 +119,14 @@ public class AttachedSurfaceControlTest {
+ " expected=" + expectedOrientation + " transformHint=" + hint);
Assert.assertEquals("Failed to switch orientation hint=" + hint, orientation,
expectedOrientation);
+
+ // Check the callback value matches the call to get the transform hint.
+ int actualTransformHint =
+ activity.getWindow().getRootSurfaceControl().getBufferTransformHint();
+ Assert.assertEquals(
+ "Callback " + hint + " doesn't match transform hint=" + actualTransformHint,
+ hint,
+ actualTransformHint);
hintConsumer.accept(hint);
latch.countDown();
activity.getWindow().getRootSurfaceControl()
@@ -118,9 +135,11 @@ public class AttachedSurfaceControlTest {
}
@Before
- public void setup() {
+ public void setup() throws InterruptedException {
mOrientationSession = new IgnoreOrientationRequestSession(false /* enable */);
mWmState = new WindowManagerStateHelper();
+ mActivity = mActivityRule.getActivity();
+ waitForWindowOnTop(mActivity.getWindow());
}
private void supportRotationCheck() {
@@ -147,47 +166,31 @@ public class AttachedSurfaceControlTest {
final int[] transformHintResult = new int[2];
final CountDownLatch[] firstCallback = new CountDownLatch[1];
final CountDownLatch[] secondCallback = new CountDownLatch[1];
- try (ActivityScenario<HandleConfigurationActivity> scenario =
- ActivityScenario.launch(HandleConfigurationActivity.class)) {
- scenario.moveToState(Lifecycle.State.RESUMED);
- scenario.onActivity(activity -> {
- mWmState.computeState();
- assumeFalse("Skipping test: display area is ignoring orientation request",
- mWmState.isTaskDisplayAreaIgnoringOrientationRequest(
- activity.getComponentName()));
- int requestedOrientation = getRequestedOrientation(activity);
- TransformHintListener listener = new TransformHintListener(activity,
- requestedOrientation, hint -> transformHintResult[0] = hint);
- firstCallback[0] = listener.latch;
- activity.getWindow().getRootSurfaceControl()
- .addOnBufferTransformHintChangedListener(listener);
- setRequestedOrientation(activity, requestedOrientation);
- });
- // Check we get a callback since the orientation has changed and we expect transform
- // hint to change.
- Assert.assertTrue(firstCallback[0].await(3, TimeUnit.SECONDS));
-
- // Check the callback value matches the call to get the transform hint.
- scenario.onActivity(activity -> Assert.assertEquals(transformHintResult[0],
- activity.getWindow().getRootSurfaceControl().getBufferTransformHint()));
-
- scenario.onActivity(activity -> {
- int requestedOrientation = getRequestedOrientation(activity);
- TransformHintListener listener = new TransformHintListener(activity,
- requestedOrientation, hint -> transformHintResult[1] = hint);
- secondCallback[0] = listener.latch;
- activity.getWindow().getRootSurfaceControl()
- .addOnBufferTransformHintChangedListener(listener);
- setRequestedOrientation(activity, requestedOrientation);
- });
- // Check we get a callback since the orientation has changed and we expect transform
- // hint to change.
- Assert.assertTrue(secondCallback[0].await(3, TimeUnit.SECONDS));
-
- // Check the callback value matches the call to get the transform hint.
- scenario.onActivity(activity -> Assert.assertEquals(transformHintResult[1],
- activity.getWindow().getRootSurfaceControl().getBufferTransformHint()));
- }
+ mWmState.computeState();
+ assumeFalse("Skipping test: display area is ignoring orientation request",
+ mWmState.isTaskDisplayAreaIgnoringOrientationRequest(
+ mActivity.getComponentName()));
+ int requestedOrientation = getRequestedOrientation(mActivity);
+ TransformHintListener listener = new TransformHintListener(mActivity,
+ requestedOrientation, hint -> transformHintResult[0] = hint);
+ firstCallback[0] = listener.latch;
+ mActivity.getWindow().getRootSurfaceControl()
+ .addOnBufferTransformHintChangedListener(listener);
+ setRequestedOrientation(mActivity, requestedOrientation);
+ // Check we get a callback since the orientation has changed and we expect transform
+ // hint to change.
+ Assert.assertTrue(firstCallback[0].await(10, TimeUnit.SECONDS));
+
+ requestedOrientation = getRequestedOrientation(mActivity);
+ TransformHintListener secondListener = new TransformHintListener(mActivity,
+ requestedOrientation, hint -> transformHintResult[1] = hint);
+ secondCallback[0] = secondListener.latch;
+ mActivity.getWindow().getRootSurfaceControl()
+ .addOnBufferTransformHintChangedListener(secondListener);
+ setRequestedOrientation(mActivity, requestedOrientation);
+ // Check we get a callback since the orientation has changed and we expect transform
+ // hint to change.
+ Assert.assertTrue(secondCallback[0].await(10, TimeUnit.SECONDS));
// If the app orientation was changed, we should get a different transform hint
Assert.assertNotEquals(transformHintResult[0], transformHintResult[1]);
@@ -217,51 +220,41 @@ public class AttachedSurfaceControlTest {
final int[] transformHintResult = new int[2];
final CountDownLatch[] firstCallback = new CountDownLatch[1];
final CountDownLatch[] secondCallback = new CountDownLatch[1];
- try (ActivityScenario<HandleConfigurationActivity> scenario =
- ActivityScenario.launch(HandleConfigurationActivity.class)) {
- scenario.moveToState(Lifecycle.State.RESUMED);
- scenario.onActivity(activity -> {
- mWmState.computeState();
- assumeFalse("Skipping test: display area is ignoring orientation request",
- mWmState.isTaskDisplayAreaIgnoringOrientationRequest(
- activity.getComponentName()));
- if (activity.getResources().getConfiguration().orientation
- == ORIENTATION_LANDSCAPE) {
- return;
- }
- TransformHintListener listener = new TransformHintListener(activity,
- ORIENTATION_LANDSCAPE, hint -> transformHintResult[0] = hint);
- firstCallback[0] = listener.latch;
- activity.getWindow().getRootSurfaceControl()
- .addOnBufferTransformHintChangedListener(listener);
- setRequestedOrientation(activity, ORIENTATION_LANDSCAPE);
- });
-
- // If the device is already in landscape, do nothing.
- if (firstCallback[0] != null) {
- Assert.assertTrue(firstCallback[0].await(3, TimeUnit.SECONDS));
- scenario.onActivity(activity -> Assert.assertEquals(transformHintResult[0],
- activity.getWindow().getRootSurfaceControl().getBufferTransformHint()));
- }
-
- scenario.onActivity(activity -> {
- TransformHintListener listener = new TransformHintListener(activity,
- ORIENTATION_LANDSCAPE, hint -> transformHintResult[1] = hint);
- secondCallback[0] = listener.latch;
- activity.getWindow().getRootSurfaceControl()
- .addOnBufferTransformHintChangedListener(listener);
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+ mWmState.computeState();
+ assumeFalse("Skipping test: display area is ignoring orientation request",
+ mWmState.isTaskDisplayAreaIgnoringOrientationRequest(
+ mActivity.getComponentName()));
+ if (mActivity.getResources().getConfiguration().orientation
+ != ORIENTATION_LANDSCAPE) {
+ Log.d(TAG, "Request landscape orientation");
+ TransformHintListener listener = new TransformHintListener(mActivity,
+ ORIENTATION_LANDSCAPE, hint -> {
+ transformHintResult[0] = hint;
+ Log.d(TAG, "firstListener fired with hint =" + hint);
});
- // Check we get a callback since the orientation has changed and we expect transform
- // hint to change.
- Assert.assertTrue(secondCallback[0].await(3, TimeUnit.SECONDS));
-
- // Check the callback value matches the call to get the transform hint.
- scenario.onActivity(activity -> Assert.assertEquals(transformHintResult[1],
- activity.getWindow().getRootSurfaceControl().getBufferTransformHint()));
+ firstCallback[0] = listener.latch;
+ mActivity.getWindow().getRootSurfaceControl()
+ .addOnBufferTransformHintChangedListener(listener);
+ setRequestedOrientation(mActivity, ORIENTATION_LANDSCAPE);
+ Assert.assertTrue(firstCallback[0].await(10, TimeUnit.SECONDS));
+ } else {
+ transformHintResult[0] =
+ mActivity.getWindow().getRootSurfaceControl().getBufferTransformHint();
+ Log.d(TAG, "Skipped request landscape orientation: hint=" + transformHintResult[0]);
}
- // If the app orientation was changed, we should get a different transform hint
+ TransformHintListener secondListener = new TransformHintListener(mActivity,
+ ORIENTATION_LANDSCAPE, hint -> {
+ transformHintResult[1] = hint;
+ Log.d(TAG, "secondListener fired with hint =" + hint);
+ });
+ secondCallback[0] = secondListener.latch;
+ mActivity.getWindow().getRootSurfaceControl()
+ .addOnBufferTransformHintChangedListener(secondListener);
+ Log.d(TAG, "Requesting reverse landscape");
+ mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+
+ Assert.assertTrue(secondCallback[0].await(10, TimeUnit.SECONDS));
Assert.assertNotEquals(transformHintResult[0], transformHintResult[1]);
}
diff --git a/tests/tests/app/Android.bp b/tests/tests/app/Android.bp
index 2022e5f36b2..d03334b0239 100644
--- a/tests/tests/app/Android.bp
+++ b/tests/tests/app/Android.bp
@@ -18,6 +18,7 @@ package {
android_test {
name: "CtsAndroidAppTestCases",
+ team: "trendy_team_platform_security",
defaults: ["cts_defaults"],
platform_apis: true,
libs: [
diff --git a/tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt b/tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt
index 48d3a1d843d..310195c7e77 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt
@@ -111,6 +111,7 @@ class AttributionTest {
.isEqualTo(before.attributedOpEntries[ATTRIBUTION_3]!!
.getLastAccessTime(OP_FLAGS_ALL))
}
+ runCommand("pm uninstall $PKG")
}
@Test
diff --git a/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt b/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
index 6bbabda646c..d7ad0aaac40 100644
--- a/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
@@ -22,6 +22,7 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.fail
import org.junit.Before
+import org.junit.After;
import org.junit.Test
import java.lang.Thread.sleep
@@ -49,6 +50,11 @@ class RuntimeMessageCollectionTest {
installApk("CtsAppToCollect.apk")
}
+ @After
+ fun uninstallTestApp() {
+ runCommand("pm uninstall $APP_PKG")
+ }
+
@Test
fun collectAsyncStackTrace() {
installApk("CtsAppToCollect.apk")
diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml
index 58b6c1dc3c9..6adb8db6bb6 100644
--- a/tests/tests/bluetooth/AndroidTest.xml
+++ b/tests/tests/bluetooth/AndroidTest.xml
@@ -27,6 +27,12 @@
<option name="test-file-name" value="CtsBluetoothTestCases.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="throw-if-cmd-fail" value="true" />
+ <option name="run-command" value="setprop persist.log.tag.bluetooth VERBOSE" />
+ <!-- In order for the setprop to take effect everywhere, we need to toggle OFF Bluetooth -->
+ <option name="run-command" value="settings put global ble_scan_always_enabled 0"/>
+ <option name="run-command" value="cmd bluetooth_manager disable" />
+ <option name="run-command" value="cmd bluetooth_manager wait-for-state:STATE_OFF" />
<option name="run-command" value="cmd bluetooth_manager enable" />
<option name="run-command" value="cmd bluetooth_manager wait-for-state:STATE_ON" />
<option name="teardown-command" value="cmd bluetooth_manager disable" />
diff --git a/tests/tests/bluetooth/OWNERS b/tests/tests/bluetooth/OWNERS
index 536cb7e9cb5..8ac713e3dc3 100644
--- a/tests/tests/bluetooth/OWNERS
+++ b/tests/tests/bluetooth/OWNERS
@@ -1,6 +1,7 @@
# Bug component: 27441
-licorne@google.com
-sattiraju@google.com
+muhammadfalam@google.com
+
+girardier@google.com
siyuanh@google.com
wescande@google.com
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
index d274cbe8d33..c1a96b66bb1 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
@@ -514,18 +514,10 @@ public class BluetoothAdapterTest {
assertFalse(mAdapter.registerBluetoothConnectionCallback(executor, null));
assertFalse(mAdapter.unregisterBluetoothConnectionCallback(null));
- assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
-
- // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED
- assertThrows(SecurityException.class,
- () -> mAdapter.registerBluetoothConnectionCallback(executor, callback));
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- mUiAutomation.dropShellPermissionIdentity();
- // Verify throws SecurityException without permission.BLUETOOTH_CONNECT
- assertThrows(SecurityException.class, () ->
- mAdapter.registerBluetoothConnectionCallback(executor, callback));
- assertThrows(SecurityException.class, () ->
- mAdapter.unregisterBluetoothConnectionCallback(callback));
+ assertFalse(mAdapter.registerBluetoothConnectionCallback(executor, callback));
+ assertTrue(mAdapter.unregisterBluetoothConnectionCallback(callback));
}
@Test
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
index 96b0c847d97..a1370aaa254 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
@@ -20,20 +20,24 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.Manifest.permission.BLUETOOTH_SCAN;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothHearingAid.AdvertisementServiceData;
-import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
+import android.bluetooth.test_utils.BlockingBluetoothAdapter;
+import android.bluetooth.test_utils.EnableBluetoothRule;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -45,137 +49,98 @@ import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import com.android.compatibility.common.util.CddTest;
-import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.time.Duration;
import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Unit test cases for {@link BluetoothHearingAid}.
- * <p>
- * To run the test, use adb shell am instrument -e class 'android.bluetooth.HearingAidProfileTest'
- * -w 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
+
+/** Unit test cases for {@link BluetoothHearingAid}. */
@RunWith(AndroidJUnit4.class)
public class HearingAidProfileTest {
- private static final String TAG = "HearingAidProfileTest";
-
- private static final int WAIT_FOR_INTENT_TIMEOUT_MS = 10000; // ms to wait for intent callback
- private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
- // ADAPTER_ENABLE_TIMEOUT_MS = AdapterState.BLE_START_TIMEOUT_DELAY +
- // AdapterState.BREDR_START_TIMEOUT_DELAY
- private static final int ADAPTER_ENABLE_TIMEOUT_MS = 8000;
- // ADAPTER_DISABLE_TIMEOUT_MS = AdapterState.BLE_STOP_TIMEOUT_DELAY +
- // AdapterState.BREDR_STOP_TIMEOUT_DELAY
- private static final int ADAPTER_DISABLE_TIMEOUT_MS = 5000;
- private static final String FAKE_REMOTE_ADDRESS = "00:11:22:AA:BB:CC";
-
- private Context mContext;
- private BluetoothHearingAid mService;
- private BluetoothAdapter mBluetoothAdapter;
- private BroadcastReceiver mIntentReceiver;
- private UiAutomation mUiAutomation;;
-
- private Condition mConditionProfileConnection;
- private ReentrantLock mProfileConnectionlock;
- private boolean mIsProfileReady;
- private AdvertisementServiceData mAdvertisementData;
+ private static final String TAG = HearingAidProfileTest.class.getSimpleName();
- private static List<Integer> mValidConnectionStates = new ArrayList<Integer>(
- Arrays.asList(BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED,
- BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING));
+ @ClassRule public static final EnableBluetoothRule sEnableBluetooth = new EnableBluetoothRule();
- private List<BluetoothDevice> mIntentCallbackDeviceList;
+ @Rule
+ public final AdoptShellPermissionsRule mPermissionRule =
+ new AdoptShellPermissionsRule(sUiAutomation, BLUETOOTH_CONNECT);
- @Before
- public void setUp() throws Exception {
- mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ private static final BluetoothAdapter sBluetoothAdapter = BlockingBluetoothAdapter.getAdapter();
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+ private static final UiAutomation sUiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
- Assume.assumeTrue(TestUtils.isBleSupported(mContext));
- Assume.assumeTrue(TestUtils.isProfileEnabled(BluetoothProfile.HEARING_AID));
+ private static final Duration PROXY_CONNECTION_TIMEOUT = Duration.ofMillis(500);
+ private static final Duration WAIT_FOR_INTENT_TIMEOUT = Duration.ofSeconds(1);
+ private static final BluetoothDevice sFakeDevice =
+ sBluetoothAdapter.getRemoteDevice("42:11:22:AA:BB:CC");
- mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
- mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ private static List<Integer> sValidConnectionStates =
+ List.of(
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_DISCONNECTED,
+ BluetoothProfile.STATE_DISCONNECTING);
- BluetoothManager manager = (BluetoothManager) mContext.getSystemService(
- Context.BLUETOOTH_SERVICE);
- mBluetoothAdapter = manager.getAdapter();
+ private BluetoothHearingAid mService;
- assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
- mProfileConnectionlock = new ReentrantLock();
- mConditionProfileConnection = mProfileConnectionlock.newCondition();
- mIsProfileReady = false;
- mService = null;
- mBluetoothAdapter.getProfileProxy(mContext, new HearingAidsServiceListener(),
- BluetoothProfile.HEARING_AID);
+ private static final AdvertisementServiceData sAdvertisementData;
+ static {
Parcel parcel = Parcel.obtain();
parcel.writeInt(0b110); // CSIP supported, MODE_BINAURAL, SIDE_LEFT
parcel.writeInt(1);
parcel.setDataPosition(0);
- mAdvertisementData = AdvertisementServiceData.CREATOR.createFromParcel(parcel);
- assertNotNull(mAdvertisementData);
+ sAdvertisementData = AdvertisementServiceData.CREATOR.createFromParcel(parcel);
}
- @After
- public void tearDown() {
- if (mUiAutomation != null) {
- mUiAutomation.dropShellPermissionIdentity();
- }
- }
+ @Mock BluetoothProfile.ServiceListener mServiceListener;
- @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
- @Test
- public void closeProfileProxy() {
- assertTrue(waitForProfileConnect());
- assertNotNull(mService);
- assertTrue(mIsProfileReady);
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Assume.assumeTrue(TestUtils.isBleSupported(sContext));
+ Assume.assumeTrue(TestUtils.isProfileEnabled(BluetoothProfile.HEARING_AID));
- mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEARING_AID, mService);
- assertTrue(waitForProfileDisconnect());
- assertFalse(mIsProfileReady);
+ assertThat(
+ sBluetoothAdapter.getProfileProxy(
+ sContext, mServiceListener, BluetoothProfile.HEARING_AID))
+ .isTrue();
+
+ ArgumentCaptor<BluetoothProfile> captor = ArgumentCaptor.forClass(BluetoothProfile.class);
+ verify(mServiceListener, timeout(PROXY_CONNECTION_TIMEOUT.toMillis()))
+ .onServiceConnected(eq(BluetoothProfile.HEARING_AID), captor.capture());
+ mService = (BluetoothHearingAid) captor.getValue();
+ assertThat(mService).isNotNull();
}
- /**
- * Basic test case to make sure that Hearing Aid Profile Proxy can connect.
- */
@CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
- @MediumTest
@Test
- public void getProxyServiceConnect() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
+ public void closeProfileProxy() {
+ sBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEARING_AID, mService);
+ verify(mServiceListener, timeout(PROXY_CONNECTION_TIMEOUT.toMillis()))
+ .onServiceDisconnected(eq(BluetoothProfile.HEARING_AID));
}
- /**
- * Basic test case to make sure that a fictional device is disconnected.
- */
+ /** Basic test case to make sure that a fictional device is disconnected. */
@CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
@MediumTest
@Test
public void getConnectionState() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake device
- BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
- assertNotNull(device);
-
- int connectionState = mService.getConnectionState(device);
- // Fake device should be disconnected
- assertEquals(connectionState, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mService.getConnectionState(sFakeDevice))
+ .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
}
/**
@@ -186,74 +151,37 @@ public class HearingAidProfileTest {
@MediumTest
@Test
public void setVolume() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
// This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
assertThrows(SecurityException.class, () -> mService.setVolume(42));
}
- /**
- * Basic test case to make sure that a fictional device is unknown side.
- */
+ /** Basic test case to make sure that a fictional device is unknown side. */
@CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
@MediumTest
@Test
public void getDeviceSide() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake device
- final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
- assertNotNull(device);
-
- final int side = mService.getDeviceSide(device);
- // Fake device should be no value, unknown side
- assertEquals(BluetoothHearingAid.SIDE_UNKNOWN, side);
+ assertThat(mService.getDeviceSide(sFakeDevice)).isEqualTo(BluetoothHearingAid.SIDE_UNKNOWN);
}
- /**
- * Basic test case to make sure that a fictional device is unknown mode.
- */
+ /** Basic test case to make sure that a fictional device is unknown mode. */
@CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
@MediumTest
@Test
public void getDeviceMode() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake device
- final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
- assertNotNull(device);
-
- final int mode = mService.getDeviceMode(device);
- // Fake device should be no value, unknown mode
- assertEquals(BluetoothHearingAid.MODE_UNKNOWN, mode);
+ assertThat(mService.getDeviceMode(sFakeDevice)).isEqualTo(BluetoothHearingAid.MODE_UNKNOWN);
}
/**
- * Basic test case to make sure that a fictional device's ASHA Advertisement Service Data
- * is null.
+ * Basic test case to make sure that a fictional device's ASHA Advertisement Service Data is
+ * null.
*/
@CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
@MediumTest
@Test
public void getAdvertisementServiceData() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake device
- final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
- assertNotNull(device);
-
TestUtils.adoptPermissionAsShellUid(BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED);
- // Fake device should have no service data
- assertNull(mService.getAdvertisementServiceData(device));
+ assertThat(mService.getAdvertisementServiceData(sFakeDevice)).isNull();
}
/**
@@ -264,16 +192,7 @@ public class HearingAidProfileTest {
@MediumTest
@Test
public void getAdvertisementDeviceMode() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake advertisement data
- AdvertisementServiceData data = mAdvertisementData;
-
- final int mode = data.getDeviceMode();
- // Fake device should be MODE_BINAURAL
- assertEquals(BluetoothHearingAid.MODE_BINAURAL, mode);
+ assertThat(sAdvertisementData.getDeviceMode()).isEqualTo(BluetoothHearingAid.MODE_BINAURAL);
}
/**
@@ -284,37 +203,18 @@ public class HearingAidProfileTest {
@MediumTest
@Test
public void getAdvertisementDeviceSide() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake advertisement data
- AdvertisementServiceData data = mAdvertisementData;
-
- final int side = data.getDeviceSide();
- // Fake device should be SIDE_LEFT
- assertEquals(BluetoothHearingAid.SIDE_LEFT, side);
+ assertThat(sAdvertisementData.getDeviceSide()).isEqualTo(BluetoothHearingAid.SIDE_LEFT);
}
/**
- * Basic test case to make sure that a fictional device's truncated HiSyncId is the
- * expected value.
+ * Basic test case to make sure that a fictional device's truncated HiSyncId is the expected
+ * value.
*/
@CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
@MediumTest
@Test
public void getTruncatedHiSyncId() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake advertisement data
- AdvertisementServiceData data = mAdvertisementData;
- assertNotNull(data);
-
- final int id = data.getTruncatedHiSyncId();
- // Fake device should be supported
- assertEquals(1, id);
+ assertThat(sAdvertisementData.getTruncatedHiSyncId()).isEqualTo(1);
}
/**
@@ -325,17 +225,7 @@ public class HearingAidProfileTest {
@MediumTest
@Test
public void isCsipSupported() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake advertisement data
- AdvertisementServiceData data = mAdvertisementData;
- assertNotNull(data);
-
- final boolean supported = data.isCsipSupported();
- // Fake device should be supported
- assertEquals(true, supported);
+ assertThat(sAdvertisementData.isCsipSupported()).isTrue();
}
/**
@@ -346,14 +236,6 @@ public class HearingAidProfileTest {
@MediumTest
@Test
public void isLikelyPairOfBluetoothHearingAid() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Create a fake advertisement data
- final AdvertisementServiceData data = mAdvertisementData;
- assertNotNull(data);
-
// Create another fake advertisement data
Parcel parcel = Parcel.obtain();
parcel.writeInt(0b111); // CSIP supported, MODE_BINAURAL, SIDE_RIGHT
@@ -361,31 +243,21 @@ public class HearingAidProfileTest {
parcel.setDataPosition(0);
AdvertisementServiceData dataOtherSide =
AdvertisementServiceData.CREATOR.createFromParcel(parcel);
- assertNotNull(dataOtherSide);
+ assertThat(dataOtherSide).isNotNull();
- final boolean isLikelyPair = data.isInPairWith(dataOtherSide);
// two devices should be a pair
- assertEquals(true, isLikelyPair);
+ assertThat(sAdvertisementData.isInPairWith(dataOtherSide)).isTrue();
}
- /**
- * Basic test case to get the list of connected Hearing Aid devices.
- */
+ /** Basic test case to get the list of connected Hearing Aid devices. */
@CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
@MediumTest
@Test
public void getConnectedDevices() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- List<BluetoothDevice> deviceList;
-
- deviceList = mService.getConnectedDevices();
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
Log.d(TAG, "getConnectedDevices(): size=" + deviceList.size());
for (BluetoothDevice device : deviceList) {
- int connectionState = mService.getConnectionState(device);
- checkValidConnectionState(connectionState);
+ assertThat(mService.getConnectionState(device)).isIn(sValidConnectionStates);
}
}
@@ -397,18 +269,15 @@ public class HearingAidProfileTest {
@MediumTest
@Test
public void getDevicesMatchingConnectionStates() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- for (int connectionState : mValidConnectionStates) {
- List<BluetoothDevice> deviceList;
-
- deviceList = mService.getDevicesMatchingConnectionStates(new int[]{connectionState});
- assertNotNull(deviceList);
- Log.d(TAG, "getDevicesMatchingConnectionStates(" + connectionState + "): size="
- + deviceList.size());
- checkDeviceListAndStates(deviceList, connectionState);
+ for (int connectionState : sValidConnectionStates) {
+ List<BluetoothDevice> deviceList =
+ mService.getDevicesMatchingConnectionStates(new int[] {connectionState});
+ assertThat(deviceList).isNotNull();
+ for (BluetoothDevice device : deviceList) {
+ assertWithMessage("Mismatched connection state for device=" + device)
+ .that(mService.getConnectionState(device))
+ .isEqualTo(connectionState);
+ }
}
}
@@ -420,158 +289,35 @@ public class HearingAidProfileTest {
@MediumTest
@Test
public void getConnectionStateChangedIntent() {
- waitForProfileConnect();
- assertTrue(mIsProfileReady);
- assertNotNull(mService);
-
- // Find out how many Hearing Aid bonded devices
- List<BluetoothDevice> bondedDeviceList = new ArrayList();
- int numDevices = 0;
- for (int connectionState : mValidConnectionStates) {
- List<BluetoothDevice> deviceList;
-
- deviceList = mService.getDevicesMatchingConnectionStates(new int[]{connectionState});
- bondedDeviceList.addAll(deviceList);
- numDevices += deviceList.size();
- }
-
- if (numDevices <= 0) return;
- Log.d(TAG, "Number Hearing Aids devices bonded=" + numDevices);
-
- mIntentCallbackDeviceList = new ArrayList();
-
- // Set up the Connection State Changed receiver
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
- mIntentReceiver = new HearingAidIntentReceiver();
- mContext.registerReceiver(mIntentReceiver, filter);
-
- Log.d(TAG, "getConnectionStateChangedIntent: disable adapter and wait");
- assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
-
- Log.d(TAG, "getConnectionStateChangedIntent: enable adapter and wait");
- assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
-
- int sanityCount = WAIT_FOR_INTENT_TIMEOUT_MS;
- while ((numDevices != mIntentCallbackDeviceList.size()) && (sanityCount > 0)) {
- final int SLEEP_QUANTUM_MS = 100;
- sleep(SLEEP_QUANTUM_MS);
- sanityCount -= SLEEP_QUANTUM_MS;
- }
-
- // Tear down
- mContext.unregisterReceiver(mIntentReceiver);
-
- Log.d(TAG, "getConnectionStateChangedIntent: number of bonded device="
- + numDevices + ", mIntentCallbackDeviceList.size()="
- + mIntentCallbackDeviceList.size());
- for (BluetoothDevice device : mIntentCallbackDeviceList) {
- assertTrue(bondedDeviceList.contains(device));
- }
- }
-
- private boolean waitForProfileConnect() {
- mProfileConnectionlock.lock();
+ List<BluetoothDevice> bondedDeviceList =
+ mService.getDevicesMatchingConnectionStates(
+ sValidConnectionStates.stream().mapToInt(Integer::intValue).toArray());
+
+ int numDevices = bondedDeviceList.size();
+ Assume.assumeTrue(numDevices > 0);
+
+ BroadcastReceiver mockReceiver = mock(BroadcastReceiver.class);
+ sContext.registerReceiver(
+ mockReceiver,
+ new IntentFilter(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED));
+ ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
try {
- // Wait for the Adapter to be disabled
- while (!mIsProfileReady) {
- if (!mConditionProfileConnection.await(
- PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- // Timeout
- Log.e(TAG, "Timeout while waiting for Profile Connect");
- break;
- } // else spurious wakeups
- }
- } catch(InterruptedException e) {
- Log.e(TAG, "waitForProfileConnect: interrrupted");
- } finally {
- mProfileConnectionlock.unlock();
- }
- return mIsProfileReady;
- }
+ assertThat(BlockingBluetoothAdapter.disable(true)).isTrue();
+ assertThat(BlockingBluetoothAdapter.enable()).isTrue();
- private boolean waitForProfileDisconnect() {
- mConditionProfileConnection = mProfileConnectionlock.newCondition();
- mProfileConnectionlock.lock();
- try {
- while (mIsProfileReady) {
- if (!mConditionProfileConnection.await(
- PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- // Timeout
- Log.e(TAG, "Timeout while waiting for Profile Disconnect");
- break;
- } // else spurious wakeups
- }
- } catch (InterruptedException e) {
- Log.e(TAG, "waitForProfileDisconnect: interrrupted");
+ verify(mockReceiver, timeout(WAIT_FOR_INTENT_TIMEOUT.toMillis()).times(numDevices))
+ .onReceive(any(), captor.capture());
} finally {
- mProfileConnectionlock.unlock();
- }
- return !mIsProfileReady;
- }
-
- private final class HearingAidsServiceListener
- implements BluetoothProfile.ServiceListener {
-
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- mProfileConnectionlock.lock();
- mService = (BluetoothHearingAid) proxy;
- mIsProfileReady = true;
- try {
- mConditionProfileConnection.signal();
- } finally {
- mProfileConnectionlock.unlock();
- }
- }
-
- public void onServiceDisconnected(int profile) {
- mProfileConnectionlock.lock();
- mIsProfileReady = false;
- mService = null;
- try {
- mConditionProfileConnection.signal();
- } finally {
- mProfileConnectionlock.unlock();
- }
- }
- }
-
- private class HearingAidIntentReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
- int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
- int previousState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
- Log.d(TAG,"HearingAidIntentReceiver.onReceive: device=" + device
- + ", state=" + state + ", previousState=" + previousState);
-
- checkValidConnectionState(state);
- checkValidConnectionState(previousState);
-
- mIntentCallbackDeviceList.add(device);
- }
+ sContext.unregisterReceiver(mockReceiver);
}
- }
- private void checkDeviceListAndStates(List<BluetoothDevice> deviceList, int connectionState) {
- Log.d(TAG, "checkDeviceListAndStates(): size=" + deviceList.size()
- + ", connectionState=" + connectionState);
- for (BluetoothDevice device : deviceList) {
- int deviceConnectionState = mService.getConnectionState(device);
- assertEquals("Mismatched connection state for " + device,
- connectionState, deviceConnectionState);
+ for (Intent intent : captor.getAllValues()) {
+ assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1))
+ .isIn(sValidConnectionStates);
+ assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1))
+ .isIn(sValidConnectionStates);
+ assertThat((BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))
+ .isIn(bondedDeviceList);
}
}
-
- private void checkValidConnectionState(int connectionState) {
- assertTrue(mValidConnectionStates.contains(connectionState));
- }
-
- private static void sleep(long t) {
- try {
- Thread.sleep(t);
- } catch (InterruptedException e) {}
- }
}
diff --git a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
index a93a6a683b2..2f7f7d97ba5 100644
--- a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
@@ -560,7 +560,7 @@ public class VirtualDisplayTest {
}
private final class RotationChangeWaiter {
- private static final int DISPLAY_CHANGE_TIMEOUT_SECS = 1;
+ private static final int DISPLAY_CHANGE_TIMEOUT_SECS = 3;
private final Display mDisplay;
private int mCurrentRotation;
diff --git a/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp b/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp
index 3bda711a941..15fbe3cc52b 100644
--- a/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp
+++ b/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp
@@ -41,7 +41,7 @@ ImageReaderHelper::~ImageReaderHelper() {
int ImageReaderHelper::initImageReader() {
if (mImgReader != nullptr || mImgReaderAnw != nullptr) {
- ALOGE("Cannot re-initalize image reader, mImgReader=%p, mImgReaderAnw=%p",
+ ALOGE("Cannot reinitialize image reader, mImgReader=%p, mImgReaderAnw=%p",
mImgReader, mImgReaderAnw);
return -1;
}
@@ -84,9 +84,9 @@ int ImageReaderHelper::getBufferFromCurrentImage(AHardwareBuffer **outBuffer) {
if (ret != AMEDIA_OK || outImage == nullptr) {
// When the BufferQueue is in async mode, it is still possible that
// AImageReader_acquireNextImage returns nothing after onFrameAvailable.
- ALOGW("Failed to acquire image, ret=%d, outIamge=%p.", ret, outImage);
+ ALOGW("Failed to acquire image, ret=%d, outImage=%p.", ret, outImage);
} else {
- // Any exisitng in mAcquiredImage will be deleted and released
+ // Any existing in mAcquiredImage will be deleted and released
// automatically.
mAcquiredImage.reset(outImage);
}
diff --git a/tests/tests/graphics/jni/ImageReaderTestHelpers.h b/tests/tests/graphics/jni/ImageReaderTestHelpers.h
index dcd08d95c1d..2196aca57f8 100644
--- a/tests/tests/graphics/jni/ImageReaderTestHelpers.h
+++ b/tests/tests/graphics/jni/ImageReaderTestHelpers.h
@@ -48,7 +48,7 @@ private:
uint32_t mMaxImages;
std::mutex mMutex;
- // Number of images that's avaiable for acquire.
+ // Number of images that are available to be acquired.
size_t mAvailableImages{0};
// Although AImageReader supports acquiring multiple images at a time, we
// don't really need it in this test. We only acquire one image that a time.
diff --git a/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml b/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
index d4472e2ec6c..97dfac993e8 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
@@ -38,7 +38,7 @@
android:pathData="@string/rectangle200" />
<group
- android:name="ThridLevelGroup1"
+ android:name="ThirdLevelGroup1"
android:translateX="-100.0"
android:translateY="50.0" >
<path
@@ -47,7 +47,7 @@
android:pathData="@string/rectangle200" />
</group>
<group
- android:name="ThridLevelGroup2"
+ android:name="ThirdLevelGroup2"
android:translateX="100.0"
android:translateY="50.0" >
<path
@@ -66,7 +66,7 @@
android:pathData="@string/rectangle200" />
<group
- android:name="ThridLevelGroup3"
+ android:name="ThirdLevelGroup3"
android:translateX="-100.0"
android:translateY="50.0" >
<path
@@ -75,7 +75,7 @@
android:pathData="@string/rectangle200" />
</group>
<group
- android:name="ThridLevelGroup4"
+ android:name="ThirdLevelGroup4"
android:translateX="100.0"
android:translateY="50.0" >
<path
diff --git a/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml b/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
index 6fcb3552057..964047a8e83 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
@@ -33,7 +33,7 @@
android:pathData="@string/rectangle200" />
<group
- android:name="ThridLevelGroup1"
+ android:name="ThirdLevelGroup1"
android:translateX="-100.0"
android:translateY="50.0" >
<path
@@ -42,7 +42,7 @@
android:pathData="@string/rectangle200" />
</group>
<group
- android:name="ThridLevelGroup2"
+ android:name="ThirdLevelGroup2"
android:translateX="100.0"
android:translateY="50.0" >
<path
@@ -61,7 +61,7 @@
android:pathData="@string/rectangle200" />
<group
- android:name="ThridLevelGroup3"
+ android:name="ThirdLevelGroup3"
android:translateX="-100.0"
android:translateY="50.0" >
<path
@@ -70,7 +70,7 @@
android:pathData="@string/rectangle200" />
</group>
<group
- android:name="ThridLevelGroup4"
+ android:name="ThirdLevelGroup4"
android:translateX="100.0"
android:translateY="50.0" >
<path
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
index f829e808097..52ae7c248dc 100644
--- a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -47,8 +47,8 @@ public class NinePatchTest {
private static final int ALPHA_OPAQUE = 0xFF;
private static final String NAME = "TESTNAME";
private static final int WIDTH = 80;
- private static final int HEIGTH = 120;
- private static final int[] COLOR = new int[WIDTH * HEIGTH];
+ private static final int HEIGHT = 120;
+ private static final int[] COLOR = new int[WIDTH * HEIGHT];
private NinePatch mNinePatch;
private Bitmap mBitmap;
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 86e7400bfea..d4e4d522c56 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -1810,7 +1810,7 @@ public class PaintTest {
}
@Test
- public void testEqualsForTextMeasurment() {
+ public void testEqualsForTextMeasurement() {
Paint p1 = new Paint();
Paint p2 = new Paint();
@@ -1818,7 +1818,7 @@ public class PaintTest {
}
@Test
- public void testEqualsForTextMeasurment_textSize() {
+ public void testEqualsForTextMeasurement_textSize() {
Paint p1 = new Paint();
Paint p2 = new Paint();
@@ -1829,7 +1829,7 @@ public class PaintTest {
}
@Test
- public void testEqualsForTextMeasurment_textSkew() {
+ public void testEqualsForTextMeasurement_textSkew() {
Paint p1 = new Paint();
Paint p2 = new Paint();
@@ -1840,7 +1840,7 @@ public class PaintTest {
}
@Test
- public void testEqualsForTextMeasurment_textScale() {
+ public void testEqualsForTextMeasurement_textScale() {
Paint p1 = new Paint();
Paint p2 = new Paint();
@@ -1851,7 +1851,7 @@ public class PaintTest {
}
@Test
- public void testEqualsForTextMeasurment_letterSpacing() {
+ public void testEqualsForTextMeasurement_letterSpacing() {
Paint p1 = new Paint();
Paint p2 = new Paint();
@@ -1862,7 +1862,7 @@ public class PaintTest {
}
@Test
- public void testEqualsForTextMeasurment_localeList() {
+ public void testEqualsForTextMeasurement_localeList() {
Paint p1 = new Paint();
Paint p2 = new Paint();
@@ -1876,7 +1876,7 @@ public class PaintTest {
}
@Test
- public void testEqualsForTextMeasurment_typeface() {
+ public void testEqualsForTextMeasurement_typeface() {
Paint p1 = new Paint();
Paint p2 = new Paint();
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index dd4f3e14e57..c3335b45631 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -564,7 +564,7 @@ public class TypefaceTest {
@Test
public void testTypeface_SupportedCmapEncodingTest() {
- // We support the following combinations of cmap platfrom/endcoding pairs.
+ // We support the following combinations of cmap platform/endcoding pairs.
String[] fontPaths = {
// Platform ID == 0, Encoding ID == 0
"fonts/cmap_selection/CmapPlatform0Encoding0.ttf",
@@ -673,7 +673,7 @@ public class TypefaceTest {
assertEquals(GLYPH_3EM_WIDTH, measureText("b", italicFamily), 0f);
assertEquals(GLYPH_1EM_WIDTH, measureText("c", italicFamily), 0f);
- // Draw with the italic font which weigth is 700.
+ // Draw with the italic font and weight set to 700.
final Typeface boldItalicFamily =
Typeface.create(family, 700 /* weight */, true /* italic */);
assertEquals(GLYPH_1EM_WIDTH, measureText("a", boldItalicFamily), 0f);
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java
index 969fcf89900..f87c5c8a041 100644
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java
@@ -235,6 +235,7 @@ public class VulkanFeaturesTest {
private JSONObject mVkJSON = null;
private JSONObject mVulkanDevices[];
private JSONObject mBestDevice = null;
+ private boolean mIsTV = false;
@Before
public void setup() throws Throwable {
@@ -262,6 +263,8 @@ public class VulkanFeaturesTest {
if (DEBUG) {
Log.d(TAG, feature.name + "=" + feature.version);
}
+ } else if (PackageManager.FEATURE_LEANBACK.equals(feature.name)) {
+ mIsTV = true;
}
}
}
@@ -501,6 +504,7 @@ public class VulkanFeaturesTest {
@Test
public void testAndroidBaselineProfile2021Support() throws JSONException {
assumeTrue("Skipping because Vulkan is not supported", mVulkanHardwareVersion != null);
+ assumeTrue("Skipping because ABP is not required of TV devices", !mIsTV);
if (!hasOnlyCpuDevice()) {
assertEquals("This device must support the ABP 2021.", "", nativeGetABPSupport());
diff --git a/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
index 744fd8b4528..ecdc5bd4cf6 100644
--- a/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
@@ -183,7 +183,7 @@ public class YuvImageTest {
// test if handling compression parameters correctly
verifyParameters();
- // test various cases by varing
+ // test various cases by varying
// <ImageFormat, Bitmap, HasPaddings, Rect>
for (int i = 0; i < JPEG_FORMATS.length; ++i) {
for (int j = 0; j < mTestBitmaps.length; ++j) {
@@ -524,7 +524,7 @@ public class YuvImageTest {
}
// Compress rect1 in testBitmap and rect2 in image.
- // Then, compare the two resutls to check their MSE.
+ // Then, compare the two results to check their MSE.
private void compressRects(Bitmap testBitmap, YuvImage image,
Rect rect1, Rect rect2) {
Bitmap expected = null;
diff --git a/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java b/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
index fe129e868aa..75af2705240 100644
--- a/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
+++ b/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
@@ -34,7 +34,7 @@ import android.graphics.Color;
*
* <p>XYZ is commonly used as an intermediate color space for converting between one color space to
* another. For example, to convert RGB to L*a*b*, first RGB is converted to XYZ, then XYZ is
- * convered to L*a*b*.
+ * converted to L*a*b*.
*
* <p>sRGB is a "specification originated from work in 1990s through cooperation by Hewlett-Packard
* and Microsoft, and it was designed to be a standard definition of RGB for the internet, which it
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
index 1142c20190d..9bb4962133c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
@@ -65,7 +65,7 @@ public class PictureDrawableTest {
// Check the color has been set.
assertEquals(0xff0f0b0c, destBitmap.getPixel(10, 10));
pictureDrawable.draw(canvas);
- // Check the target pixle's color, ensure it has been changed.
+ // Check the target pixel's color, ensure it has been changed.
assertEquals(0xff0a0c0b, destBitmap.getPixel(10, 10));
}
diff --git a/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java b/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java
index dc90130d513..d1dd3419e93 100644
--- a/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java
+++ b/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java
@@ -72,7 +72,7 @@ public class LineBreakerTest {
}
@Test
- public void testSetBreakStrategy_shoulNotThrowExceptions() {
+ public void testSetBreakStrategy_shouldNotThrowExceptions() {
assertNotNull(new LineBreaker.Builder().setBreakStrategy(BREAK_STRATEGY_SIMPLE).build());
assertNotNull(new LineBreaker.Builder().setBreakStrategy(BREAK_STRATEGY_HIGH_QUALITY)
.build());
diff --git a/tests/tests/hardware/TEST_MAPPING b/tests/tests/hardware/TEST_MAPPING
index a45c0a013a4..a7648e0d040 100644
--- a/tests/tests/hardware/TEST_MAPPING
+++ b/tests/tests/hardware/TEST_MAPPING
@@ -15,10 +15,6 @@
"name": "CtsHardwareTestCases",
"options": [
{
- // TODO(b/221102945):
- "exclude-filter": "android.hardware.input.cts.tests.VirtualTouchscreenTest#sendTouchEvent"
- },
- {
// TODO(b/266108817): android.hardware.input.cts.tests unexpected timeouts
"exclude-filter": "android.hardware.input.cts.tests.SonyDualshock4BluetoothTest#testAllMotions"
},
diff --git a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
index c241120cb00..a1335370ee8 100644
--- a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
+++ b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
@@ -295,8 +295,12 @@ fun openUnusedAppsNotification() {
val notifSelector = By.textContains("unused app")
if (hasFeatureWatch()) {
val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation
- expandNotificationsWatch(UiAutomatorUtils2.getUiDevice())
- waitFindObject(uiAutomation, notifSelector).click()
+ val clickRunnable = object : Runnable {
+ override fun run () {
+ waitFindObject(uiAutomation, notifSelector).click()
+ }
+ }
+ expandAndClickNotificationWatch(UiAutomatorUtils2.getUiDevice(), clickRunnable)
// In wear os, notification has one additional button to open it
waitFindObject(uiAutomation, By.textContains("Open")).click()
} else {
@@ -341,12 +345,27 @@ fun hasFeatureAutomotive(): Boolean {
PackageManager.FEATURE_AUTOMOTIVE)
}
-private fun expandNotificationsWatch(uiDevice: UiDevice) {
+private fun expandAndClickNotificationWatch(uiDevice: UiDevice, clickRunnable: Runnable) {
with(uiDevice) {
wakeUp()
- // Swipe up from bottom to reveal notifications
val x = displayWidth / 2
+ // Swipe up from bottom to reveal notifications
swipe(x, displayHeight, x, 0, 1)
+ try {
+ clickRunnable.run()
+ return
+ } catch (e: Exception) {
+ // TODO(b/338772456) we catch the exception here since som watches have their
+ // notifications tray on the horizontal swipe. Find a way to find a solution that does
+ // not require vertical/horizontal swipe retries.
+ }
+ // Upwards swipe did not find notifications. Undo the upwards swipe, and try sideways.
+ swipe(x, 0, x, displayHeight, 5)
+ val y = displayHeight / 2
+ swipe(0, y, displayWidth, y, 5)
+
+ clickRunnable.run()
+
}
}
diff --git a/tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt b/tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt
index f3448bfd8d1..9045ff5f1a2 100644
--- a/tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt
+++ b/tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt
@@ -636,13 +636,18 @@ class AutoRevokeTest {
rowItem.findObject(uninstallSelector).click()
} else {
rowItem.click()
- waitFindObject(By.text("Uninstall")).click()
+ try {
+ waitFindObject(By.text("Uninstall")).click()
+ } catch (e: Exception) {
+ // Some watch implementations do not have the "Uninstall" text and directly go
+ // to the uninstall confirmation screen, so it's ok to let this exception go.
+ }
}
}
private fun clickUninstallOk() {
val uninstallSelector = if (hasFeatureWatch()) {
- By.desc("OK")
+ By.res(Pattern.compile(".*(button1|positive_button)"))
} else {
By.text("OK")
}
diff --git a/tests/tests/jni/Android.bp b/tests/tests/jni/Android.bp
index 5aa391f2d4e..8055b1e5294 100644
--- a/tests/tests/jni/Android.bp
+++ b/tests/tests/jni/Android.bp
@@ -14,6 +14,9 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ // Team assignment based on libnativeloader and linker namespace ownership.
+ // Other JNI issues are owned by trendy_team_art_performance.
+ default_team: "trendy_team_art_mainline",
}
android_test {
diff --git a/tests/tests/jvmti/Android.bp b/tests/tests/jvmti/Android.bp
new file mode 100644
index 00000000000..8faed40643d
--- /dev/null
+++ b/tests/tests/jvmti/Android.bp
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_team: "trendy_team_art_performance",
+}
diff --git a/tests/tests/jvmti/OWNERS b/tests/tests/jvmti/OWNERS
new file mode 100644
index 00000000000..131c53fbd08
--- /dev/null
+++ b/tests/tests/jvmti/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 1304319
+include platform/art:/OWNERS
diff --git a/tests/tests/jvmti/attaching/OWNERS b/tests/tests/jvmti/attaching/OWNERS
deleted file mode 100644
index 6e0629999c7..00000000000
--- a/tests/tests/jvmti/attaching/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 86431
-include /hostsidetests/jvmti/run-tests/OWNERS
diff --git a/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml b/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml
index f7d7bd6a556..7971309e28e 100644
--- a/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml
+++ b/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml
@@ -25,8 +25,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.keystore.cts.performance"
android:label="CTS tests of android.keystore.cts.performance">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml b/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
index 12e24f20986..803f96241c0 100644
--- a/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
+++ b/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
@@ -25,8 +25,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.google.security.wycheproof"
android:label="CTS tests of com.google.security.wycheproof">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index 9de76e00ab5..3e7aecbd794 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -40,6 +40,7 @@ import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
import android.server.wm.ActivityManagerTestBase;
@@ -1366,6 +1367,32 @@ public class CipherTest {
}
@Test
+ public void testAuthBoundKeysKeyPermanentlyInvalidatedException() throws Exception {
+ assumeTrue(TestUtils.hasSecureLockScreen(getContext()));
+
+ ImportedKey key = null;
+ try (DeviceLockSession dl = new DeviceLockSession()) {
+ KeyProtection importParams =
+ TestUtils.getMinimalWorkingImportParametersForCipheringWith(BASIC_ALGORITHMS[0],
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT,
+ /* ivProvidedWhenEncrypting= */ false,
+ /* isUnlockedDeviceRequired= */ false,
+ /* isUserAuthRequired= */ true);
+ key = importDefaultKatKey(BASIC_ALGORITHMS[0], importParams);
+ assertTrue(TestUtils.keyExists(key.getAlias()));
+ } // DeviceLockSession#close() removes the secure lock screen.
+
+ // Try to use the key after removal of secure screen lock screen.
+ KatVector testVector = KAT_VECTORS.get(BASIC_ALGORITHMS[0]);
+ Cipher cipher = Cipher.getInstance(BASIC_ALGORITHMS[0]);
+ Key encryptionKey = key.getKeystoreBackedEncryptionKey();
+ // Removing the secure lock screen should have invalidated the auth-bound keys.
+ assertThrows(KeyPermanentlyInvalidatedException.class, () -> {
+ cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
+ });
+ }
+
+ @Test
public void testInitDecryptFailsWhenNotAuthorizedToDecrypt() throws Exception {
for (String transformation : EXPECTED_ALGORITHMS) {
try {
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index f27b44579eb..5a42aa97837 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -32,9 +32,7 @@ import static android.keystore.cts.AuthorizationList.KM_PURPOSE_SIGN;
import static android.keystore.cts.AuthorizationList.KM_PURPOSE_VERIFY;
import static android.keystore.cts.RootOfTrust.KM_VERIFIED_BOOT_VERIFIED;
import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_AGREE_KEY;
-import static android.security.keystore.KeyProperties.DIGEST_NONE;
import static android.security.keystore.KeyProperties.DIGEST_SHA256;
-import static android.security.keystore.KeyProperties.DIGEST_SHA512;
import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_NONE;
import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_RSA_OAEP;
import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1;
@@ -89,6 +87,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.permissions.PermissionContext;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.PropertyUtil;
import com.google.common.collect.ImmutableSet;
@@ -113,9 +112,11 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.security.spec.ECGenParameterSpec;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -152,6 +153,7 @@ public class KeyAttestationTest {
private static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
private static final int KM_ERROR_INVALID_INPUT_LENGTH = -21;
+ private static final int KM_ERROR_UNKNOWN_ERROR = -1000;
private static final int KM_ERROR_PERMISSION_DENIED = 6;
private Context getContext() {
@@ -281,16 +283,45 @@ public class KeyAttestationTest {
}
}
+ private void assertAttestationKeyMintError(KeyStoreException keyStoreException,
+ boolean devicePropertiesAttestation) {
+ int errorCode = keyStoreException.getErrorCode();
+ List<Integer> expectedErrs = new ArrayList<Integer>();
+ expectedErrs.add(KM_ERROR_INVALID_INPUT_LENGTH);
+ if (devicePropertiesAttestation) {
+ expectedErrs.add(KM_ERROR_CANNOT_ATTEST_IDS);
+ }
+ if (TestUtils.getVendorApiLevel() < 35) {
+ // b/337427860, some devices returns UNKNOWN_ERROR if large challenge is
+ // passed. So allow an extra error code for earlier devices.
+ expectedErrs.add(KM_ERROR_UNKNOWN_ERROR);
+ }
+ String assertMessage = String.format(
+ "The KeyMint implementation may only return INVALID_INPUT_LENGTH or "
+ + "CANNOT_ATTEST_IDSs as errors when the attestation challenge is "
+ + "too large (error code was %d, attestation properties %b)",
+ errorCode, devicePropertiesAttestation);
+ assertTrue(assertMessage, expectedErrs.contains(errorCode));
+ }
+
private void assertPublicAttestationError(KeyStoreException keyStoreException,
boolean devicePropertiesAttestation) {
// Assert public failure information.
int errorCode = keyStoreException.getNumericErrorCode();
+ List<Integer> expectedErrs = new ArrayList<Integer>();
+ expectedErrs.add(KeyStoreException.ERROR_INCORRECT_USAGE);
+ if (devicePropertiesAttestation) {
+ expectedErrs.add(KeyStoreException.ERROR_ID_ATTESTATION_FAILURE);
+ }
+ if (TestUtils.getVendorApiLevel() < 35) {
+ // b/337427860, some devices returns UNKNOWN_ERROR if large challenge is
+ // passed. So allow an extra error code for earlier devices.
+ expectedErrs.add(KeyStoreException.ERROR_KEYMINT_FAILURE);
+ }
String assertMessage = String.format(
"Error code was %d, device properties attestation? %b",
errorCode, devicePropertiesAttestation);
- assertTrue(assertMessage, KeyStoreException.ERROR_INCORRECT_USAGE == errorCode
- || (devicePropertiesAttestation
- && KeyStoreException.ERROR_ID_ATTESTATION_FAILURE == errorCode));
+ assertTrue(assertMessage, expectedErrs.contains(errorCode));
assertFalse("Unexpected transient failure.", keyStoreException.isTransientFailure());
}
@@ -319,16 +350,7 @@ public class KeyAttestationTest {
fail("Attestation challenges larger than 128 bytes should be rejected");
} catch (ProviderException e) {
KeyStoreException cause = (KeyStoreException) e.getCause();
- int errorCode = cause.getErrorCode();
- String assertMessage = String.format(
- "The KeyMint implementation may only return INVALID_INPUT_LENGTH or "
- + "CANNOT_ATTEST_IDSs as errors when the attestation challenge is "
- + "too large (error code was %d, attestation properties %b)",
- errorCode, devicePropertiesAttestation);
- assertTrue(assertMessage, KM_ERROR_INVALID_INPUT_LENGTH == cause.getErrorCode()
- || (devicePropertiesAttestation
- && KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
- );
+ assertAttestationKeyMintError(cause, devicePropertiesAttestation);
assertPublicAttestationError(cause, devicePropertiesAttestation);
}
}
@@ -355,7 +377,7 @@ public class KeyAttestationTest {
Date consumptionEnd = new Date(now.getTime() + CONSUMPTION_TIME_OFFSET);
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
- .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
.setAttestationChallenge(null)
.setKeyValidityStart(now)
.setKeyValidityForOriginationEnd(originationEnd)
@@ -397,18 +419,13 @@ public class KeyAttestationTest {
KeyGenParameterSpec.Builder builder =
new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(expectStrongBox))
.setAttestationChallenge(new byte[128])
.setKeyValidityStart(now)
.setKeyValidityForOriginationEnd(originationEnd)
.setKeyValidityForConsumptionEnd(consumptionEnd)
.setIsStrongBoxBacked(expectStrongBox);
- if (expectStrongBox) {
- builder.setDigests(DIGEST_NONE, DIGEST_SHA256);
- } else {
- builder.setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512);
- }
-
generateKeyPair(KEY_ALGORITHM_EC, builder.build());
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
@@ -428,6 +445,7 @@ public class KeyAttestationTest {
@RestrictedBuildTest
@RequiresDevice
@Test
+ @CddTest(requirements = {"9.10/C-0-1", "9.10/C-1-3"})
public void testEcAttestation_DeviceLocked() throws Exception {
testEcAttestation_DeviceLocked(false /* expectStrongBox */);
}
@@ -435,6 +453,7 @@ public class KeyAttestationTest {
@RestrictedBuildTest
@RequiresDevice
@Test
+ @CddTest(requirements = {"9.10/C-0-1", "9.10/C-1-3"})
public void testEcAttestation_DeviceLockedStrongbox() throws Exception {
if (!TestUtils.hasStrongBox(getContext()))
return;
@@ -445,6 +464,7 @@ public class KeyAttestationTest {
public void testAttestationKmVersionMatchesFeatureVersion() throws Exception {
if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC))
return;
+ assumeTrue("Device does not support attestation", TestUtils.isAttestationSupported());
testAttestationKmVersionMatchesFeatureVersion(false);
}
@@ -453,6 +473,7 @@ public class KeyAttestationTest {
public void testAttestationKmVersionMatchesFeatureVersionStrongBox() throws Exception {
if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC))
return;
+ assumeTrue("Device does not support attestation", TestUtils.isAttestationSupported());
int keyStoreFeatureVersionStrongBox =
TestUtils.getFeatureVersionKeystoreStrongBox(getContext());
@@ -467,7 +488,8 @@ public class KeyAttestationTest {
}
private void testAttestationKmVersionMatchesFeatureVersion(boolean isStrongBox)
- throws Exception {
+ throws Exception {
+ assumeTrue("Device does not support attestation", TestUtils.isAttestationSupported());
String keystoreAlias = "test_key";
Date now = new Date();
@@ -505,7 +527,7 @@ public class KeyAttestationTest {
// Feature Version is required on devices launching with Android 12 (API Level
// 31) but may be reported on devices launching with an earlier version. If it's
// present, it must match what is reported in attestation.
- if (PropertyUtil.getFirstApiLevel() >= 31) {
+ if (TestUtils.getVendorApiLevel() >= 31) {
assertNotEquals(0, keyStoreFeatureVersion);
}
if (keyStoreFeatureVersion != 0) {
@@ -534,7 +556,7 @@ public class KeyAttestationTest {
String keystoreAlias = "test_key";
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
- .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
.setAttestationChallenge(new byte[128])
.setUniqueIdIncluded(true)
.setIsStrongBoxBacked(isStrongBox)
@@ -579,7 +601,7 @@ public class KeyAttestationTest {
String keystoreAlias = "test_key";
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
- .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
.setAttestationChallenge(new byte[128])
.setUniqueIdIncluded(true)
.setIsStrongBoxBacked(isStrongBox)
@@ -756,16 +778,7 @@ public class KeyAttestationTest {
fail("Attestation challenges larger than 128 bytes should be rejected");
} catch(ProviderException e){
KeyStoreException cause = (KeyStoreException) e.getCause();
- int errorCode = cause.getErrorCode();
- String assertMessage = String.format(
- "The KeyMint implementation may only return INVALID_INPUT_LENGTH or "
- + "CANNOT_ATTEST_IDSs as errors when the attestation challenge is "
- + "too large (error code was %d, attestation properties %b)",
- errorCode, devicePropertiesAttestation);
- assertTrue(assertMessage, KM_ERROR_INVALID_INPUT_LENGTH == cause.getErrorCode()
- || (devicePropertiesAttestation
- && KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
- );
+ assertAttestationKeyMintError(cause, devicePropertiesAttestation);
assertPublicAttestationError(cause, devicePropertiesAttestation);
}
}
@@ -791,7 +804,7 @@ public class KeyAttestationTest {
Date originationEnd = new Date(now.getTime() + ORIGINATION_TIME_OFFSET);
Date consumptionEnd = new Date(now.getTime() + CONSUMPTION_TIME_OFFSET);
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
- .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
.setAttestationChallenge(null)
.setKeyValidityStart(now)
.setKeyValidityForOriginationEnd(originationEnd)
@@ -829,22 +842,16 @@ public class KeyAttestationTest {
Date now = new Date();
Date originationEnd = new Date(now.getTime() + ORIGINATION_TIME_OFFSET);
Date consumptionEnd = new Date(now.getTime() + CONSUMPTION_TIME_OFFSET);
- KeyGenParameterSpec.Builder builder =
- new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
- .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
- .setAttestationChallenge("challenge".getBytes())
- .setKeyValidityStart(now)
- .setKeyValidityForOriginationEnd(originationEnd)
- .setKeyValidityForConsumptionEnd(consumptionEnd)
- .setIsStrongBoxBacked(expectStrongBox);
-
- if (expectStrongBox) {
- builder.setDigests(DIGEST_NONE, DIGEST_SHA256);
- } else {
- builder.setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512);
- }
+ KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(expectStrongBox))
+ .setAttestationChallenge("challenge".getBytes())
+ .setKeyValidityStart(now)
+ .setKeyValidityForOriginationEnd(originationEnd)
+ .setKeyValidityForConsumptionEnd(consumptionEnd)
+ .setIsStrongBoxBacked(expectStrongBox)
+ .build();
- generateKeyPair(KEY_ALGORITHM_RSA, builder.build());
+ generateKeyPair(KEY_ALGORITHM_RSA, spec);
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
@@ -863,11 +870,13 @@ public class KeyAttestationTest {
@RestrictedBuildTest
@RequiresDevice // Emulators have no place to store the needed key
@Test
+ @CddTest(requirements = {"9.10/C-0-1", "9.10/C-1-3"})
public void testRsaAttestation_DeviceLocked() throws Exception {
testRsaAttestation_DeviceLocked(false /* expectStrongbox */);
}
@RestrictedBuildTest
+ @CddTest(requirements = {"9.10/C-0-1", "9.10/C-1-3"})
@RequiresDevice // Emulators have no place to store the needed key
@Test
public void testRsaAttestation_DeviceLockedStrongbox() throws Exception {
@@ -1126,7 +1135,7 @@ public class KeyAttestationTest {
KeyGenParameterSpec.Builder builder =
new KeyGenParameterSpec.Builder(keystoreAlias, purposes)
.setKeySize(keySize)
- .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
.setAttestationChallenge(challenge)
.setDevicePropertiesAttestationIncluded(devicePropertiesAttestation)
.setIsStrongBoxBacked(isStrongBox);
@@ -1201,7 +1210,7 @@ public class KeyAttestationTest {
KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(keystoreAlias,
purposes)
.setAlgorithmParameterSpec(new ECGenParameterSpec(ecCurve))
- .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+ .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
.setAttestationChallenge(challenge)
.setDevicePropertiesAttestationIncluded(devicePropertiesAttestation)
.setIsStrongBoxBacked(isStrongBox);
@@ -1314,8 +1323,11 @@ public class KeyAttestationTest {
Date startTime, boolean includesValidityDates,
boolean devicePropertiesAttestation, Attestation attestation)
throws NoSuchAlgorithmException, NameNotFoundException {
- checkKeyIndependentAttestationInfo(challenge, purposes,
- ImmutableSet.of(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_512),
+ Set digests = ImmutableSet.of(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_512);
+ if (attestation.getAttestationSecurityLevel() == KM_SECURITY_LEVEL_STRONG_BOX) {
+ digests = ImmutableSet.of(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256);
+ }
+ checkKeyIndependentAttestationInfo(challenge, purposes, digests,
startTime, includesValidityDates,
devicePropertiesAttestation, attestation);
}
@@ -1701,9 +1713,10 @@ public class KeyAttestationTest {
}
}
- private void checkEntropy(byte[] verifiedBootKey) {
- assertTrue("Failed Shannon entropy check", checkShannonEntropy(verifiedBootKey));
- assertTrue("Failed BiEntropy check", checkTresBiEntropy(verifiedBootKey));
+ private void checkEntropy(byte[] entropyData) {
+ byte[] entropyDataCopy = Arrays.copyOf(entropyData, entropyData.length);
+ assertTrue("Failed Shannon entropy check", checkShannonEntropy(entropyDataCopy));
+ assertTrue("Failed BiEntropy check", checkTresBiEntropy(entropyDataCopy));
}
private boolean checkShannonEntropy(byte[] verifiedBootKey) {
@@ -1719,6 +1732,9 @@ public class KeyAttestationTest {
return entropy;
}
+ /**
+ * Note: This method modifies the input parameter while performing bit entropy check.
+ */
private boolean checkTresBiEntropy(byte[] verifiedBootKey) {
double weightingFactor = 0;
double weightedEntropy = 0;
@@ -1736,6 +1752,9 @@ public class KeyAttestationTest {
return tresBiEntropy > 0.9;
}
+ /**
+ * Note: This method modifies the input parameter - bitString.
+ */
private void deriveBitString(byte[] bitString, int activeLength) {
int length = activeLength / 8;
if (activeLength % 8 != 0) {
diff --git a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
index 22045526055..a30074c5ab7 100644
--- a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
+++ b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
@@ -16,6 +16,10 @@
package android.keystore.cts.util;
+import static android.security.keystore.KeyProperties.DIGEST_NONE;
+import static android.security.keystore.KeyProperties.DIGEST_SHA256;
+import static android.security.keystore.KeyProperties.DIGEST_SHA512;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -121,6 +125,20 @@ public class TestUtils {
return getFeatureVersionKeystore(appContext);
}
+ /**
+ * This function returns the valid digest algorithms supported for a Strongbox or default
+ * KeyMint implementation. The isStrongbox parameter specifies the underlying KeyMint
+ * implementation. If true, it indicates Strongbox KeyMint, otherwise TEE/Software KeyMint
+ * is assumed.
+ */
+ public static @KeyProperties.DigestEnum String[] getDigestsForKeyMintImplementation(
+ boolean isStrongbox) {
+ if (isStrongbox) {
+ return new String[]{DIGEST_NONE, DIGEST_SHA256};
+ }
+ return new String[]{DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512};
+ }
+
// Returns 0 if not implemented. Otherwise returns the feature version.
//
public static int getFeatureVersionKeystore(Context appContext) {
diff --git a/tests/tests/libcorefileio/AndroidManifest.xml b/tests/tests/libcorefileio/AndroidManifest.xml
index c6a95b5af0b..4e0ad520dad 100644
--- a/tests/tests/libcorefileio/AndroidManifest.xml
+++ b/tests/tests/libcorefileio/AndroidManifest.xml
@@ -22,18 +22,11 @@
<application>
<uses-library android:name="android.test.runner"/>
+ <!-- Use ':' to indicate that lockHoldingService needs to run in a separate process.
+ See https://developer.android.com/guide/topics/manifest/service-element#proc -->
<service android:name="android.cts.LockHoldingService"
android:process=":lockHoldingService"
android:permission="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <receiver android:name="android.cts.FileChannelInterProcessLockTest$IntentReceiver"
- android:exported="true">
-
- <intent-filter>
- <action android:name="android.cts.CtsLibcoreFileIOTestCases">
- </action>
- </intent-filter>
-
- </receiver>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
index e5b25c93b9a..bc990e27166 100644
--- a/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
+++ b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
@@ -16,12 +16,19 @@
package android.cts;
-import android.content.BroadcastReceiver;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.os.Bundle;
-import android.os.Debug;
import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
import android.test.AndroidTestCase;
import java.io.File;
@@ -33,8 +40,6 @@ import java.nio.file.StandardOpenOption;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
@SuppressWarnings("deprecation")
public class FileChannelInterProcessLockTest extends AndroidTestCase {
@@ -55,11 +60,11 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
* the service. This provides ample amount of time for the service to receive the request from
* the test, then act, and respond back.
*/
- final static int MAX_WAIT_TIME = 20;
+ final static int MAX_WAIT_TIME = 10;
@Override
public void tearDown() throws Exception {
- stopService();
+ IpcChannel.unbindService();
super.tearDown();
}
@@ -419,15 +424,12 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
ChannelType localChannelType, ChannelType remoteChannelType,
boolean expectToGetLock) throws Exception {
try {
- IntentReceiver.resetReceiverState();
-
// Request that the remote lock be obtained.
- getContext().startService(new Intent(getContext(), LockHoldingService.class)
- .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType)
- .putExtra(LockHoldingService.CHANNEL_TYPE_KEY, remoteChannelType));
+ IpcChannel.bindService(getContext());
+ IpcChannel.requestRemoteLock(remoteLockType, remoteChannelType);
// Wait for a signal that the remote lock is definitely held.
- assertTrue(IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
+ assertTrue(IpcChannel.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
// Try to acquire the local lock in all cases and check whether it could be acquired or
// not as expected.
@@ -440,7 +442,7 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
}
// Release the remote lock.
} finally {
- stopService();
+ IpcChannel.unbindService();
}
}
@@ -458,30 +460,24 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
ChannelType localChannelType, ChannelType remoteChannelType,
boolean expectToWait) throws Exception {
try {
- IntentReceiver.resetReceiverState();
-
// The amount of time the remote service should hold lock.
- long remoteLockHoldTimeMillis = 7000;
+ long remoteLockHoldTimeMillis = 5000;
// The amount of time test should get to try to acquire the lock.
long sufficientOverlappingTimeInMillis = 2000;
// This is the allowable delta in the time between the time recorded after the service
// released the lock and the time recorded after the test obtained the lock.
- long lockReleasedAndReacquiredTimeDeltaInMillis = 1000;
+ long lockReleasedAndReacquiredTimeDeltaInMillis = 500;
// Tell the service to acquire a remote lock.
- Intent sendIntent = new Intent(getContext(), LockHoldingService.class)
- .putExtra(LockHoldingService.TIME_TO_HOLD_LOCK_KEY, remoteLockHoldTimeMillis)
- .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType)
- .putExtra(LockHoldingService.CHANNEL_TYPE_KEY, remoteChannelType)
- .putExtra(LockHoldingService.LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, true);
-
- getContext().startService(sendIntent);
+ IpcChannel.bindService(getContext());
+ IpcChannel.requestRemoteLockAndRelease(remoteLockType,
+ remoteChannelType, remoteLockHoldTimeMillis);
// Wait for the service to hold the lock and notify for the same.
assertTrue("No remote lock held notification",
- IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
+ IpcChannel.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
long localLockNotObtainedTime = System.currentTimeMillis();
@@ -491,9 +487,9 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
// Wait until the remote lock has definitely been released.
assertTrue("No remote lock release notification",
- IntentReceiver.lockReleasedLatch.await(MAX_WAIT_TIME, SECONDS));
+ IpcChannel.lockReleasedLatch.await(MAX_WAIT_TIME, SECONDS));
- Bundle remoteLockReleasedBundle = IntentReceiver.lockReleasedBundle;
+ Bundle remoteLockReleasedBundle = IpcChannel.lockReleasedBundle;
long remoteLockNotReleasedTime =
remoteLockReleasedBundle.getLong(LockHoldingService.LOCK_NOT_YET_RELEASED_TIMESTAMP);
long remoteLockReleasedTime =
@@ -506,11 +502,10 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
// but we can't be sure and the test may not be valid. This is why we hold the lock
// remotely for a long time compared to the delays we expect for intents to propagate
// between processes.
- assertTrue(String.format("Remote lock release start (%d), " +
- "too soon after local lock notification time (%d). " +
+ assertTrue(String.format("Remote lock release start " +
+ "too soon (%d ms) after lock notification time. " +
"Need at least %d ms",
- remoteLockReleasedTime,
- localLockNotObtainedTime,
+ remoteLockNotReleasedTime - localLockNotObtainedTime,
sufficientOverlappingTimeInMillis
),
remoteLockNotReleasedTime - localLockNotObtainedTime >
@@ -522,10 +517,10 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
// service. The localLockObtainedTime is captured after the lock was obtained by this
// thread. Therefore, there is a degree of slop inherent in the two times. We assert
// that they are "close" to each other, but we cannot assert any ordering.
- assertTrue(String.format("Local lock obtained (%d) too long " +
- "from remote lock release time (%d). " +
+ assertTrue(String.format("Local lock obtained too long (%d ms) " +
+ "from remote lock release time. " +
"Expected at most %d ms.",
- localLockObtainedTime, remoteLockReleasedTime,
+ localLockObtainedTime - remoteLockReleasedTime,
lockReleasedAndReacquiredTimeDeltaInMillis),
Math.abs(localLockObtainedTime - remoteLockReleasedTime) <
lockReleasedAndReacquiredTimeDeltaInMillis);
@@ -545,22 +540,8 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
// Asserting if the fileLock is valid.
assertTrue(fileLock.isValid());
} finally {
- stopService();
- }
- }
-
- /**
- * Requests and waits for the service to stop
- */
- void stopService() throws Exception {
- getContext().stopService(new Intent(getContext(), LockHoldingService.class));
- // onStopLatch can be null if we never start the service, possibly because of
- // an earlier failure in the test.
- if (IntentReceiver.onStopLatch != null) {
- assertTrue(IntentReceiver.onStopLatch.await(MAX_WAIT_TIME, SECONDS));
+ IpcChannel.unbindService();
}
-
- deleteDir(getContext());
}
static enum LockType {
@@ -748,57 +729,136 @@ public class FileChannelInterProcessLockTest extends AndroidTestCase {
}
/**
- * Listens to broadcasts sent by the LockHoldingService and records information / provides
- * latches so the test code can synchronize until it is informed the service has acted on
- * requests it has sent.
+ * Handles the comms with the LockHoldingService.
+ *
+ * Binds to the service and sends requests and receives callbacks from it.
+ *
+ * It records information / provides latches so the test code can synchronize until it is
+ * informed the service has acted on requests it has sent.
*/
- public static class IntentReceiver extends BroadcastReceiver {
+ public static class IpcChannel {
- static CountDownLatch onStartLatch;
-
- static CountDownLatch onStopLatch;
+ static Context context;
+ static CountDownLatch onBindLatch;
+ static CountDownLatch onUnbindLatch;
static CountDownLatch lockHeldLatch;
-
static volatile Bundle lockHeldBundle;
-
static CountDownLatch lockReleasedLatch;
-
static volatile Bundle lockReleasedBundle;
+ static volatile boolean bound = false;
+ static Messenger messenger;
+ static Messenger responseMessenger;
+ static ServiceConnection serviceConnection;
+
+ static Handler responseMessageHandler;
+
+ private static Context getContext() {
+ return context;
+ }
+
/**
- * Reset the IntentReceiver for a new test. Assumes no intents will be received from prior
- * tests.
+ * Reset the IpcChannel for a new test. Assumes no intents will be received from prior
+ * tests.
*/
- public static synchronized void resetReceiverState() {
- onStartLatch = new CountDownLatch(1);
- onStopLatch = new CountDownLatch(1);
+ static synchronized void resetReceiverState(Context testContext) {
+ context = testContext;
+ bound = false;
+ onBindLatch = new CountDownLatch(1);
+ onUnbindLatch = new CountDownLatch(1);
lockHeldLatch = new CountDownLatch(1);
lockReleasedLatch = new CountDownLatch(1);
lockHeldBundle = null;
lockReleasedBundle = null;
+
+ responseMessageHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ Bundle bundle = msg.getData();
+ if (bundle.getBoolean(LockHoldingService.NOTIFICATION_LOCK_HELD)) {
+ lockHeldBundle = bundle;
+ lockHeldLatch.countDown();
+ } else if (bundle.getBoolean(LockHoldingService.NOTIFICATION_LOCK_RELEASED)) {
+ lockReleasedBundle = bundle;
+ lockReleasedLatch.countDown();
+ } else if (bundle.getBoolean(LockHoldingService.NOTIFICATION_READY_FOR_SHUTDOWN)) {
+ onUnbindLatch.countDown();
+ } else {
+ super.handleMessage(msg);
+ }
+ }
+ };
+ responseMessenger = new Messenger(responseMessageHandler);
+
+ serviceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ messenger = new Messenger(service);
+ bound = true;
+ onBindLatch.countDown();
+ }
+
+ @Override
+ public void onBindingDied(ComponentName className) {
+ getContext().unbindService(this);
+ bound = false;
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ getContext().unbindService(this);
+ bound = false;
+ }
+ };
}
- @Override
- public void onReceive(Context context, Intent intent) {
- String msg = intent.getStringExtra(LockHoldingService.NOTIFICATION_KEY);
- switch (msg) {
- case LockHoldingService.NOTIFICATION_START:
- onStartLatch.countDown();
- break;
- case LockHoldingService.NOTIFICATION_STOP:
- onStopLatch.countDown();
- break;
- case LockHoldingService.NOTIFICATION_LOCK_HELD:
- lockHeldBundle = intent.getExtras();
- lockHeldLatch.countDown();
- break;
- case LockHoldingService.NOTIFICATION_LOCK_RELEASED:
- lockReleasedBundle = intent.getExtras();
- lockReleasedLatch.countDown();
- break;
+ static void bindService(Context testContext) throws Exception {
+ resetReceiverState(testContext);
+ getContext().bindService(new Intent(getContext(), LockHoldingService.class),
+ serviceConnection, Context.BIND_AUTO_CREATE);
+ assertTrue(onBindLatch.await(MAX_WAIT_TIME, SECONDS));
+ }
+
+ static void requestRemoteLock(LockType lockType, ChannelType channelType) throws Exception {
+ Message msg = Message.obtain(null,
+ LockHoldingService.LOCK_BEHAVIOUR_ACQUIRE_ONLY_AND_NOTIFY, 0, 0);
+ Bundle bundle = msg.getData();
+ bundle.putSerializable(LockHoldingService.LOCK_TYPE_KEY, lockType);
+ bundle.putSerializable(LockHoldingService.CHANNEL_TYPE_KEY, channelType);
+ msg.replyTo = responseMessenger;
+ messenger.send(msg);
+ }
+
+ static void requestRemoteLockAndRelease(LockType lockType, ChannelType channelType,
+ long lockHoldTimeMillis) throws Exception {
+ Message msg = Message.obtain(null,
+ LockHoldingService.LOCK_BEHAVIOR_RELEASE_AND_NOTIFY, 0, 0);
+ Bundle bundle = msg.getData();
+ bundle.putSerializable(LockHoldingService.LOCK_TYPE_KEY, lockType);
+ bundle.putSerializable(LockHoldingService.CHANNEL_TYPE_KEY, channelType);
+ bundle.putLong(LockHoldingService.TIME_TO_HOLD_LOCK_KEY, lockHoldTimeMillis);
+ msg.replyTo = responseMessenger;
+ messenger.send(msg);
+ }
+
+ /**
+ * Requests and waits for the service to stop
+ */
+ static void unbindService() throws Exception {
+ if (bound) {
+ Message msg = Message.obtain(null, LockHoldingService.PREPARE_FOR_SHUTDOWN, 0, 0);
+ msg.replyTo = responseMessenger;
+ messenger.send(msg);
+
+ assertTrue(onUnbindLatch.await(MAX_WAIT_TIME, SECONDS));
+ getContext().unbindService(serviceConnection);
+ bound = false;
}
+ messenger = null;
+ deleteDir(getContext());
}
}
+
}
diff --git a/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java b/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
index 0df884683ff..61822353f5c 100644
--- a/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
+++ b/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
@@ -16,18 +16,23 @@
package android.cts;
+import static android.cts.FileChannelInterProcessLockTest.ChannelType;
+import static android.cts.FileChannelInterProcessLockTest.LockType;
+
import android.app.Service;
import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
import android.util.Log;
import java.io.IOException;
import java.nio.channels.FileLock;
import java.util.concurrent.ExecutionException;
-import static android.cts.FileChannelInterProcessLockTest.ChannelType;
-import static android.cts.FileChannelInterProcessLockTest.LockType;
-
/**
* A Service that listens for commands from the FileChannelInterProcessLockTest to acquire locks of
* different types. It exists to test the behavior when file locks are acquired/released across
@@ -51,16 +56,6 @@ public class LockHoldingService extends Service {
static final String NOTIFICATION_KEY = "notification";
/**
- * The value for the notification sent to the test after the service starts.
- */
- static final String NOTIFICATION_START = "onStart";
-
- /**
- * The value for the notification sent to the test just before the service stops.
- */
- static final String NOTIFICATION_STOP = "onStop";
-
- /**
* The value for the notification sent to the test after the lock is acquired.
*/
static final String NOTIFICATION_LOCK_HELD = "lockHeld";
@@ -71,6 +66,11 @@ public class LockHoldingService extends Service {
static final String NOTIFICATION_LOCK_RELEASED = "lockReleased";
/**
+ * The value for the notification sent to the test after the lock is released for shutdown
+ */
+ static final String NOTIFICATION_READY_FOR_SHUTDOWN = "readyForShutdown";
+
+ /**
* The key of the Bundle extra used to send time for which the service should wait before
* releasing the lock.
*/
@@ -87,72 +87,86 @@ public class LockHoldingService extends Service {
static final String CHANNEL_TYPE_KEY = "channelType";
/**
- * The key of the Bundle extra used to let he service know whether to release the lock after
- * some time.
+ * The message code used to let he service know to release the lock after some time.
*/
- static final String LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY = "releaseAndNotify";
+ static final int LOCK_BEHAVIOR_RELEASE_AND_NOTIFY = 1;
- static final String ACTION_TYPE_FOR_INTENT_COMMUNICATION
- = "android.cts.CtsLibcoreFileIOTestCases";
+ /**
+ * The message code used to let he service know to lock without releasing.
+ */
+ static final int LOCK_BEHAVIOUR_ACQUIRE_ONLY_AND_NOTIFY = 2;
+
+ /**
+ * The message code used to let the service know to release the lock before test end, if still
+ * held.
+ */
+ static final int PREPARE_FOR_SHUTDOWN = 3;
final String LOG_MESSAGE_TAG = "CtsLibcoreFileIOTestCases";
private FileLock fileLock = null;
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startID) {
- try {
- if (intent.getBooleanExtra(LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, false)) {
- acquireLockAndThenWaitThenRelease(intent);
- } else {
- acquireLock(intent);
+ private class LockHoldingHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ switch (msg.what) {
+ case LOCK_BEHAVIOR_RELEASE_AND_NOTIFY:
+ acquireLockAndThenWaitThenRelease(msg);
+ break;
+ case LOCK_BEHAVIOUR_ACQUIRE_ONLY_AND_NOTIFY:
+ acquireLock(msg);
+ break;
+ case PREPARE_FOR_SHUTDOWN:
+ prepareForShutdown(msg);
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ } catch (Exception e) {
+ Log.e(LOG_MESSAGE_TAG, "Exception acquire lock", e);
}
- } catch (Exception e) {
- Log.e(LOG_MESSAGE_TAG, "Exception acquire lock", e);
}
- return START_STICKY;
+ }
+
+ private Messenger messenger;
+
+ public IBinder onBind(Intent intent) {
+ messenger = new Messenger(new LockHoldingHandler());
+ return messenger.getBinder();
}
/**
* Acquires the lock asked by the test indefinitely.
*/
- private void acquireLock(Intent intent) throws IOException,
- InterruptedException, ExecutionException {
- LockType lockType = (LockType) intent.getSerializableExtra(LOCK_TYPE_KEY);
- ChannelType channelType = (ChannelType) intent.getSerializableExtra(CHANNEL_TYPE_KEY);
+ private void acquireLock(Message msg) throws IOException,
+ InterruptedException, ExecutionException, RemoteException {
+ Bundle bundle = msg.getData();
+ LockType lockType = (LockType) bundle.get(LOCK_TYPE_KEY);
+ ChannelType channelType = (ChannelType) bundle.get(CHANNEL_TYPE_KEY);
// Acquire the lock based on the information contained in the intent received.
this.fileLock = FileChannelInterProcessLockTest.acquire(this, lockType, channelType);
- Intent responseIntent = new Intent()
- .setPackage("android.libcorefileio.cts")
- .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
- .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
- sendBroadcast(responseIntent);
+
+ notifyLockHeld(msg);
}
/**
- * Acquires and holds the lock for a time specified by the test. Sends a broadcast message after
+ * Acquires and holds the lock for a time specified by the test. Sends a response message after
* releasing the lock.
*/
- private void acquireLockAndThenWaitThenRelease(Intent intent)
- throws IOException, InterruptedException, ExecutionException {
- long lockHoldTimeMillis = intent.getLongExtra(TIME_TO_HOLD_LOCK_KEY, 0);
+ private void acquireLockAndThenWaitThenRelease(Message msg)
+ throws IOException, InterruptedException, ExecutionException, RemoteException {
+ Bundle bundle = msg.getData();
+ long lockHoldTimeMillis = bundle.getLong(TIME_TO_HOLD_LOCK_KEY, 0);
+ LockType lockType = (LockType) bundle.get(LOCK_TYPE_KEY);
+ ChannelType channelType = (ChannelType) bundle.get(CHANNEL_TYPE_KEY);
// Acquire the lock.
- LockType lockType = (LockType) intent.getSerializableExtra(LOCK_TYPE_KEY);
- ChannelType channelType = (ChannelType) intent.getSerializableExtra(CHANNEL_TYPE_KEY);
this.fileLock = FileChannelInterProcessLockTest.acquire(this, lockType, channelType);
// Signal the lock is now held.
- Intent heldIntent = new Intent()
- .setPackage("android.libcorefileio.cts")
- .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
- .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
- sendBroadcast(heldIntent);
+ notifyLockHeld(msg);
Thread.sleep(lockHoldTimeMillis);
@@ -164,17 +178,35 @@ public class LockHoldingService extends Service {
long lockReleasedTimestamp = System.currentTimeMillis();
// Signal the lock is released and some information about timing.
- Intent releaseIntent = new Intent()
- .setPackage("android.libcorefileio.cts")
- .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_RELEASED)
- .putExtra(LOCK_NOT_YET_RELEASED_TIMESTAMP, lockNotReleasedTimestamp)
- .putExtra(LOCK_DEFINITELY_RELEASED_TIMESTAMP, lockReleasedTimestamp)
- .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
- sendBroadcast(releaseIntent);
+ notifyLockReleased(msg, lockNotReleasedTimestamp, lockReleasedTimestamp);
}
- @Override
- public void onDestroy() {
+ private void notifyLockHeld(Message msg) throws RemoteException {
+ Message rsp = msg.obtain();
+ Bundle rspBundle = rsp.getData();
+ rspBundle.putBoolean(NOTIFICATION_LOCK_HELD, true);
+ msg.replyTo.send(rsp);
+ }
+
+ private void notifyLockReleased(Message msg, long lockNotReleasedTimestamp,
+ long lockReleasedTimestamp) throws RemoteException {
+ Message rsp = msg.obtain();
+ Bundle rspBundle = rsp.getData();
+ rspBundle.putBoolean(NOTIFICATION_LOCK_RELEASED, true);
+ rspBundle.putLong(LOCK_NOT_YET_RELEASED_TIMESTAMP, lockNotReleasedTimestamp);
+ rspBundle.putLong(LOCK_DEFINITELY_RELEASED_TIMESTAMP, lockReleasedTimestamp);
+ msg.replyTo.send(rsp);
+ }
+
+ private void prepareForShutdown(Message msg) throws RemoteException {
+ doReleaseLock();
+ Message rsp = msg.obtain();
+ Bundle rspBundle = rsp.getData();
+ rspBundle.putBoolean(NOTIFICATION_READY_FOR_SHUTDOWN, true);
+ msg.replyTo.send(rsp);
+ }
+
+ private void doReleaseLock() {
try {
if (fileLock != null) {
fileLock.release();
@@ -182,10 +214,11 @@ public class LockHoldingService extends Service {
} catch (IOException e) {
Log.e(LOG_MESSAGE_TAG, e.getMessage());
}
- Intent intent = new Intent()
- .setPackage("android.libcorefileio.cts")
- .putExtra(NOTIFICATION_KEY, NOTIFICATION_STOP)
- .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
- sendBroadcast(intent);
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ doReleaseLock();
+ return false;
}
}
diff --git a/tests/tests/libnativehelper/Android.bp b/tests/tests/libnativehelper/Android.bp
index 9705db0cfb0..1761035744e 100644
--- a/tests/tests/libnativehelper/Android.bp
+++ b/tests/tests/libnativehelper/Android.bp
@@ -14,6 +14,7 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_team: "trendy_team_art_mainline",
}
android_test {
diff --git a/tests/tests/libthermalndk/jni/NativeThermalTest.cpp b/tests/tests/libthermalndk/jni/NativeThermalTest.cpp
index dff9f2d9a3f..b4997775176 100644
--- a/tests/tests/libthermalndk/jni/NativeThermalTest.cpp
+++ b/tests/tests/libthermalndk/jni/NativeThermalTest.cpp
@@ -132,7 +132,11 @@ static std::optional<std::string> testRegisterThermalStatusListener(JNIEnv *env,
}
// Change override level and verify the listener callback
- for (int32_t level = ATHERMAL_STATUS_LIGHT; level <= ATHERMAL_STATUS_SHUTDOWN; level++) {
+ for (int32_t level = ATHERMAL_STATUS_NONE; level <= ATHERMAL_STATUS_SHUTDOWN; level++) {
+ if (thermalStatus == level) {
+ // skip overriding a status that is the current status which won't trigger callback
+ continue;
+ }
setThermalStatusOverride(env, obj, level);
if (ctx.mCv.wait_for(lock, 1s) == std::cv_status::timeout) {
return StringPrintf("Listener callback timeout at level %" PRId32, level);
@@ -221,21 +225,31 @@ static std::optional<std::string> testThermalStatusListenerDoubleRegistration
strerror(ret));
}
+ // Expect listener callback for initial registration
+ if (ctx.mCv.wait_for(lock, 1s) == std::cv_status::timeout) {
+ return "Thermal listener callback timeout for initial registration";
+ }
+
// Register the listener again with same callback and data
ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
if (ret != EINVAL) {
return "Register should fail as listener already registered";
}
+ // Expect no listener callback for double registration
+ if (ctx.mCv.wait_for(lock, 1s) != std::cv_status::timeout) {
+ return "Thermal listener got callback after double registration.";
+ }
+
// Register a listener with same callback but null data
ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, onStatusChange, nullptr);
if (ret != 0) {
return StringPrintf("Register listener with null data failed: %s", strerror(ret));
}
- // Expect listener callback
- if (ctx.mCv.wait_for(lock, 1s) == std::cv_status::timeout) {
- return "Thermal listener callback timeout";
+ // Expect no listener callback for another registration
+ if (ctx.mCv.wait_for(lock, 1s) != std::cv_status::timeout) {
+ return "Thermal listener got callback after third registration.";
}
// Unregister listener
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java
index 0c5e0895679..9a7b3bc65f0 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java
@@ -493,6 +493,10 @@ public class AudioPlaybackConfigurationTest extends CtsAndroidTestCase {
"android.media.AudioManager.AudioPlaybackCallback#isMuted",
"android.media.AudioManager.AudioPlaybackCallback#getMutedBy"})
public void testAudioTrackMuteFromAppOpsNotification() throws Exception {
+ if (isWatch()) {
+ Log.w(TAG, "Skip testAudioTrackMuteFromAppOpsNotification for Wear");
+ return;
+ }
if (!isValidPlatform("testAudioTrackMuteFromAppOpsNotification")) return;
if (hasAudioSilentProperty()) {
Log.w(TAG, "Device has ro.audio.silent set, skipping "
@@ -509,6 +513,10 @@ public class AudioPlaybackConfigurationTest extends CtsAndroidTestCase {
"android.media.AudioManager.AudioPlaybackCallback#isMuted",
"android.media.AudioManager.AudioPlaybackCallback#getMutedBy"})
public void testMediaPlayerMuteFromAppOpsNotification() throws Exception {
+ if (isWatch()) {
+ Log.w(TAG, "Skip testMediaPlayerMuteFromAppOpsNotification for Wear");
+ return;
+ }
if (!isValidPlatform("testMediaPlayerMuteFromAppOpsNotification")) return;
if (hasAudioSilentProperty()) {
Log.w(TAG, "Device has ro.audio.silent set, skipping "
@@ -700,6 +708,9 @@ public class AudioPlaybackConfigurationTest extends CtsAndroidTestCase {
assertTrue("onPlaybackConfigChanged play, format and device expected",
callback.waitForCallbacks(3,
TEST_TIMING_TOLERANCE_MS + PLAY_ROUTING_TIMING_TOLERANCE_MS));
+ if (mAt != null) {
+ Thread.sleep(TEST_TIMING_TOLERANCE_MS + PLAY_ROUTING_TIMING_TOLERANCE_MS);
+ }
} else {
Thread.sleep(TEST_TIMING_TOLERANCE_MS + PLAY_ROUTING_TIMING_TOLERANCE_MS);
}
@@ -1022,4 +1033,8 @@ public class AudioPlaybackConfigurationTest extends CtsAndroidTestCase {
}
return true;
}
+
+ private boolean isWatch() {
+ return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
}
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java b/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java
index 9a30b672ab3..91e2bb9adaa 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java
@@ -49,6 +49,8 @@ import org.junit.Rule;
import org.junit.Test;
import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
/**
* Validate that there is no discontinuity in the AudioRecord data from Remote Submix.
@@ -157,7 +159,22 @@ public class RemoteSubmixTest {
AudioRecord audioRecord = createPlaybackCaptureRecord();
ByteBuffer rawBuffer = null;
+ int[] streams = {AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION,
+ AudioManager.STREAM_SYSTEM};
+
+ // Get current device stream volume level
+ Map<Integer, Integer> streamVolume = new HashMap<Integer, Integer>();
+ for (int stream : streams) {
+ streamVolume.put(stream, mAudioManager.getStreamVolume(stream));
+ }
try {
+ for (int stream : streams) {
+ // Mute device streams
+ mAudioManager.adjustStreamVolume(
+ stream, AudioManager.ADJUST_MUTE, 0 /*no flag used*/);
+ assertEquals(mAudioManager.getStreamVolume(stream), 0);
+ }
+
audioRecord.startRecording();
mediaPlayer.start();
@@ -187,6 +204,12 @@ public class RemoteSubmixTest {
.executeShellCommand("wm dismiss-keyguard");
}
+ for (Map.Entry<Integer, Integer> map : streamVolume.entrySet()) {
+ // Restore device stream volume
+ mAudioManager.setStreamVolume(map.getKey(), map.getValue(), 0 /*no flag used*/);
+ assertEquals(mAudioManager.getStreamVolume(map.getKey()), (int) map.getValue());
+ }
+
audioRecord.release();
mediaPlayer.release();
}
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java b/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
index 660c97cbaff..f4ace49e12d 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
@@ -630,7 +630,12 @@ public class RoutingTest extends AndroidTestCase {
assertNull(mediaPlayer.getPreferredDevice());
// resets to default
+ mediaPlayer.pause();
+ //Wait for state to change before setPreferDevice
+ SystemClock.sleep(200);
assertTrue(mediaPlayer.setPreferredDevice(null));
+ mediaPlayer.start();
+ assertTrue(mediaPlayer.isPlaying());
// test each device
AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
@@ -639,12 +644,22 @@ public class RoutingTest extends AndroidTestCase {
// Device with type as TYPE_TELEPHONY requires a privileged permission.
continue;
}
+ mediaPlayer.pause();
+ //Wait for state to change before setPreferDevice
+ SystemClock.sleep(200);
assertTrue(mediaPlayer.setPreferredDevice(deviceList[index]));
+ mediaPlayer.start();
+ assertTrue(mediaPlayer.isPlaying());
assertTrue(mediaPlayer.getPreferredDevice() == deviceList[index]);
}
// Check defaults again
+ mediaPlayer.pause();
+ //Wait for state to change before setPreferDevice
+ SystemClock.sleep(200);
assertTrue(mediaPlayer.setPreferredDevice(null));
+ mediaPlayer.start();
+ assertTrue(mediaPlayer.isPlaying());
assertNull(mediaPlayer.getPreferredDevice());
mediaPlayer.stop();
@@ -737,7 +752,12 @@ public class RoutingTest extends AndroidTestCase {
for (AudioDeviceInfo device : devices) {
if (routedDevice.getId() != device.getId() &&
device.getType() != AudioDeviceInfo.TYPE_TELEPHONY) {
+ mediaPlayer.pause();
+ //Wait for state to change before setPreferDevice
+ SystemClock.sleep(200);
mediaPlayer.setPreferredDevice(device);
+ mediaPlayer.start();
+ assertTrue(mediaPlayer.isPlaying());
listener.setCallExpected(true);
listener.await(WAIT_ROUTING_CHANGE_TIME_MS);
break;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
index 697d96ba5f9..ef7f205cac1 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
@@ -74,7 +74,7 @@ public class VideoCodecTest extends VideoCodecTestBase {
// The tolerance varies by the bitrate, because lower bitrates interact with
// video quality standards introduced in Android 12.
private static final double[] MAX_CBR_BITRATE_VARIATIONS = { 0.20, 0.20, 0.20, 0.20 };
- private static final double[] MAX_VBR_BITRATE_VARIATIONS = { 0.30, 0.20, 0.20, 0.20 };
+ private static final double[] MAX_VBR_BITRATE_VARIATIONS = { 0.50, 0.30, 0.30, 0.30 };
// Average PSNR values for reference Google Video codec for the above bitrates.
private static final double[] REFERENCE_AVERAGE_PSNR = { 33.1, 35.2, 36.6, 37.8 };
// Minimum PSNR values for reference Google Video codec for the above bitrates.
diff --git a/tests/tests/media/common/src/android/media/cts/MediaProjectionActivity.java b/tests/tests/media/common/src/android/media/cts/MediaProjectionActivity.java
index 930843f502c..918abea259b 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaProjectionActivity.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaProjectionActivity.java
@@ -16,8 +16,11 @@
package android.media.cts;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
import static org.junit.Assert.assertTrue;
+import android.annotation.NonNull;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
@@ -40,7 +43,8 @@ import android.util.Log;
import android.view.WindowManager;
import androidx.annotation.Nullable;
-import androidx.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.UiAutomatorUtils;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -55,11 +59,14 @@ public class MediaProjectionActivity extends Activity {
private static final int PERMISSION_CODE = 1;
public static final int PERMISSION_DIALOG_WAIT_MS = 1000;
public static final String ACCEPT_RESOURCE_ID = "android:id/button1";
+ public static final String CANCEL_RESOURCE_ID = "android:id/button2";
public static final String SYSTEM_UI_PACKAGE = "com.android.systemui";
public static final String SPINNER_RESOURCE_ID =
SYSTEM_UI_PACKAGE + ":id/screen_share_mode_spinner";
public static final String ENTIRE_SCREEN_STRING_RES_NAME =
"screen_share_permission_dialog_option_entire_screen";
+ public static final String SINGLE_APP_STRING_RES_NAME =
+ "screen_share_permission_dialog_option_single_app";
private MediaProjectionManager mProjectionManager;
private MediaProjection mMediaProjection;
@@ -148,7 +155,7 @@ public class MediaProjectionActivity extends Activity {
assertTrue("Can't get the permission", count <= retryCount);
dismissPermissionDialog(/* isWatch= */
getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH),
- getEntireScreenString(this));
+ getResourceString(this, ENTIRE_SCREEN_STRING_RES_NAME));
count++;
} while (!mCountDownLatch.await(timeOutMs, TimeUnit.MILLISECONDS));
return mMediaProjection;
@@ -158,10 +165,11 @@ public class MediaProjectionActivity extends Activity {
public static void dismissPermissionDialog(boolean isWatch,
@Nullable String entireScreenString) {
// Ensure the device is initialized before interacting with any UI elements.
- UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ UiDevice.getInstance(getInstrumentation());
if (entireScreenString != null && !isWatch) {
// if not testing on a watch device, then we need to select the entire screen option
- // (if available) before pressing "Start recording" button.
+ // before pressing "Start recording" button. This is because single app capture is
+ // not supported on watches.
if (!selectEntireScreenOption(entireScreenString)) {
Log.e(TAG, "Couldn't select entire screen option");
}
@@ -169,10 +177,42 @@ public class MediaProjectionActivity extends Activity {
pressStartRecording(isWatch);
}
+ @Nullable
+ private static UiObject2 findUiObject(String resourceId) {
+ return findUiObject(By.res(resourceId));
+ }
+
+ @Nullable
+ private static UiObject2 findUiObject(BySelector selector) {
+ // Check if the View can be found on the current screen.
+ UiObject2 obj = waitForObject(selector);
+
+ // If the View is not found on the current screen. Try scrolling around to find it.
+ if (obj == null) {
+ Log.w(TAG, "Couldn't find " + selector + ", now scrolling to it.");
+ scrollToGivenResource(SPINNER_RESOURCE_ID);
+ obj = waitForObject(selector);
+ }
+ if (obj == null) {
+ Log.w(TAG, "Still couldn't find " + selector + ", now scrolling screen height.");
+ try {
+ obj = UiAutomatorUtils.waitFindObjectOrNull(selector);
+ } catch (UiObjectNotFoundException e) {
+ Log.e(TAG, "Error in looking for " + selector, e);
+ }
+ }
+
+ if (obj == null) {
+ Log.e(TAG, "Unable to find " + selector);
+ }
+
+ return obj;
+ }
+
private static boolean selectEntireScreenOption(String entireScreenString) {
- UiObject2 spinner = waitForObject(By.res(SPINNER_RESOURCE_ID));
+ UiObject2 spinner = findUiObject(SPINNER_RESOURCE_ID);
if (spinner == null) {
- Log.e(TAG, "Couldn't find spinner to select projection mode");
+ Log.e(TAG, "Couldn't find spinner to select projection mode, even after scrolling");
return false;
}
spinner.click();
@@ -190,7 +230,7 @@ public class MediaProjectionActivity extends Activity {
* Returns the string for the drop down option to capture the entire screen.
*/
@Nullable
- public static String getEntireScreenString(Context context) {
+ public static String getResourceString(@NonNull Context context, String resName) {
Resources sysUiResources;
try {
sysUiResources = context.getPackageManager()
@@ -199,8 +239,7 @@ public class MediaProjectionActivity extends Activity {
return null;
}
int resourceId =
- sysUiResources.getIdentifier(
- ENTIRE_SCREEN_STRING_RES_NAME, /* defType= */ "string", SYSTEM_UI_PACKAGE);
+ sysUiResources.getIdentifier(resName, /* defType= */ "string", SYSTEM_UI_PACKAGE);
if (resourceId == 0) {
// Resource id not found
return null;
@@ -209,35 +248,30 @@ public class MediaProjectionActivity extends Activity {
}
private static void pressStartRecording(boolean isWatch) {
- if (isWatch) {
- scrollToStartRecordingButton();
- }
- UiObject2 startRecordingButton = waitForObject(By.res(ACCEPT_RESOURCE_ID));
- if (startRecordingButton == null) {
- Log.e(TAG, "Couldn't find start recording button");
- } else {
- Log.d(TAG, "found permission dialog after searching all windows, clicked");
+ // May need to scroll down to the start button on small screen devices.
+ UiObject2 startRecordingButton = findUiObject(ACCEPT_RESOURCE_ID);
+ if (startRecordingButton != null) {
startRecordingButton.click();
}
}
- /** When testing on a small screen device, scrolls to a Start Recording button. */
- private static void scrollToStartRecordingButton() {
+ /** When testing on a small screen device, scrolls to a given UI element. */
+ private static void scrollToGivenResource(String resourceId) {
// Scroll down the dialog; on a device with a small screen the elements may not be visible.
final UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
try {
- if (!scrollable.scrollIntoView(new UiSelector().resourceId(ACCEPT_RESOURCE_ID))) {
- Log.e(TAG, "Didn't find " + ACCEPT_RESOURCE_ID + " when scrolling");
+ if (!scrollable.scrollIntoView(new UiSelector().resourceId(resourceId))) {
+ Log.e(TAG, "Didn't find " + resourceId + " when scrolling");
return;
}
- Log.d(TAG, "This is a watch; we finished scrolling down to the ui elements");
+ Log.d(TAG, "We finished scrolling down to the ui element " + resourceId);
} catch (UiObjectNotFoundException e) {
- Log.d(TAG, "This is a watch, but there was no scrolling (UI may not be scrollable");
+ Log.d(TAG, "There was no scrolling (UI may not be scrollable");
}
}
private static UiObject2 waitForObject(BySelector selector) {
- UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
return uiDevice.wait(Until.findObject(selector), PERMISSION_DIALOG_WAIT_MS);
}
diff --git a/tests/tests/media/common/src/android/media/cts/TestUtils.java b/tests/tests/media/common/src/android/media/cts/TestUtils.java
index 552cf65372a..6b6fc428562 100644
--- a/tests/tests/media/common/src/android/media/cts/TestUtils.java
+++ b/tests/tests/media/common/src/android/media/cts/TestUtils.java
@@ -25,15 +25,15 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.text.TextUtils;
import android.util.Log;
-import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
+import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Assert;
import org.junit.AssumptionViolatedException;
+import java.util.Locale;
import java.util.Objects;
/**
@@ -154,15 +154,113 @@ public final class TestUtils {
}
/*
- * Report whether we are in MTS mode (vs in CTS) mode.
- * Some tests (or parts of tests) are restricted to a particular mode.
+ * decide whether we are in CTS, MCTS, or MTS mode.
+ * return the appropriate constant value
*/
- public static boolean isMtsMode() {
+ public static final int TESTMODE_CTS = 0;
+ public static final int TESTMODE_MCTS = 1;
+ public static final int TESTMODE_MTS = 2;
+
+ /**
+ * Report the current testing mode, as an enumeration.
+ * Testing mode is determined by argument 'media-testing-mode'
+ * which specifies 'cts', 'mcts', or 'mts'
+ * If missing, we use the older boolean "mts-media" to generate either 'cts' or 'mts'
+ *
+ * This is most often specified in a CtsMedia* app's AndroidTest.xml, using
+ * a line like:
+ * <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ * ...
+ * <option name="instrumentation-arg" key="media-testing-mode" value="CTS" />
+ * </test>
+ *
+ * @return {@code} one of the values TESTMODE_CTS, TESTMODE_MCTS, or TESTMODE_MTS.
+ *
+ */
+ public static int currentTestMode() {
Bundle bundle = InstrumentationRegistry.getArguments();
- // null if not set
- boolean isMTS = TextUtils.equals("true", bundle.getString("mts-media"));
+ String value = bundle.getString("media-testing-mode");
+ if (value == null) {
+ value = bundle.getString("mts-media");
+ if (value == null || !value.equals("true")) {
+ value = "CTS";
+ } else {
+ value = "MTS";
+ }
+ }
+ int mode;
+ value = value.toUpperCase(Locale.ROOT);
+ if (value.equals("CTS")) {
+ mode = TESTMODE_CTS;
+ } else if (value.equals("MCTS")) {
+ mode = TESTMODE_MCTS;
+ } else if (value.equals("MTS")) {
+ mode = TESTMODE_MTS;
+ } else {
+ mode = TESTMODE_CTS;
+ }
+ return mode;
+ }
- return isMTS;
+ /**
+ * Report the current testing mode, as a string.
+ * Testing mode is determined by argument 'media-testing-mode'
+ * which specifies 'cts', 'mcts', or 'mts'
+ * If missing, we use the older boolean "mts-media" to generate either 'cts' or 'mts'
+ *
+ * @return {@code} "CTS", "MCTS", or "MTS" corresponding to the mode.
+ */
+ public static String currentTestModeName() {
+ Bundle bundle = InstrumentationRegistry.getArguments();
+ String value = bundle.getString("media-testing-mode");
+ if (value == null) {
+ value = bundle.getString("mts-media");
+ if (value == null || !value.equals("true")) {
+ value = "CTS";
+ } else {
+ value = "MTS";
+ }
+ }
+ value = value.toUpperCase(Locale.ROOT);
+ if (value.equals("CTS")) {
+ return "CTS";
+ } else if (value.equals("MCTS")) {
+ return "MCTS";
+ } else if (value.equals("MTS")) {
+ return "MTS";
+ } else {
+ // same default as currentTestMode()
+ return "CTS";
+ }
+ }
+
+ /**
+ * Report whether this test run should evaluate module functionality.
+ * Some tests (or parts of tests) are restricted to a particular mode.
+ *
+ * @return {@code} true is the current test mode is MCTS or MTS.
+ */
+ public static boolean isTestingModules() {
+ int mode = currentTestMode();
+ switch (mode) {
+ case TESTMODE_MCTS:
+ case TESTMODE_MTS:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ /**
+ * Report whether we are in MTS mode (vs CTS or MCTS) mode.
+ * Some tests (or parts of tests) are restricted to a particular mode.
+ *
+ * @return {@code} true is the current test mode is MTS.
+ */
+ public static boolean isMtsMode() {
+ int mode = currentTestMode();
+ return mode == TESTMODE_MTS;
}
/*
@@ -180,18 +278,22 @@ public final class TestUtils {
*/
public static boolean isTestableCodecInCurrentMode(String name) {
if (name == null) {
- return false;
- }
- if (!isMtsMode()) {
- // CTS mode -- test everything
return true;
}
- // MTS mode, just the codecs that live in the modules
- if (isMainlineCodec(name)) {
- return true;
+ int mode = currentTestMode();
+ boolean result = false;
+ switch (mode) {
+ case TESTMODE_CTS:
+ result = !isMainlineCodec(name);
+ break;
+ case TESTMODE_MCTS:
+ case TESTMODE_MTS:
+ result = isMainlineCodec(name);
+ break;
}
- Log.d(TAG, "Test mode MTS does not test codec " + name);
- return false;
+ Log.d(TAG, "codec " + name + (result ? " is " : " is not ")
+ + "tested in mode " + currentTestModeName());
+ return result;
}
/*
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
index fece96896f6..857acc739c7 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
@@ -1446,45 +1446,44 @@ class Media {
Log.i(TAG, "format=" + media.getFormat());
ArrayList<ByteBuffer> csds = new ArrayList<ByteBuffer>();
- // CSD in VP9 can not be combined with frame data
- if (!media.getMime().equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
- for (String tag: new String[] { "csd-0", "csd-1" }) {
- if (media.getFormat().containsKey(tag)) {
- ByteBuffer csd = media.getFormat().getByteBuffer(tag);
- Log.i(TAG, tag + "=" + AdaptivePlaybackTest.byteBufferToString(csd, 0, 16));
- csds.add(csd);
- }
+ int csdSize = 0;
+ for (String tag: new String[] { "csd-0", "csd-1" }) {
+ if (media.getFormat().containsKey(tag)) {
+ ByteBuffer csd = media.getFormat().getByteBuffer(tag);
+ Log.i(TAG, tag + "=" + AdaptivePlaybackTest.byteBufferToString(csd, 0, 16));
+ csds.add(csd);
+ csdSize += csd.capacity();
}
}
-
+ int ix = 0;
+ if (csdSize > 0) {
+ ByteBuffer csdBuf = ByteBuffer.allocate(csdSize);
+ for (ByteBuffer csd: csds) {
+ csd.clear();
+ csdBuf.put(csd);
+ csd.clear();
+ Log.i(TAG, "csd[" + csd.capacity() + "]");
+ }
+ Log.i(TAG, "frame-" + ix + "[" + csdSize + "]");
+ csds.clear();
+ media.mFrames[ix++] = new Frame(0, MediaCodec.BUFFER_FLAG_CODEC_CONFIG, csdBuf);
+ }
int maxInputSize = 0;
ByteBuffer readBuf = ByteBuffer.allocate(2000000);
- for (int ix = 0; ix < numFrames; ix++) {
+ while (ix < numFrames) {
int sampleSize = extractor.readSampleData(readBuf, 0 /* offset */);
if (sampleSize < 0) {
throw new IllegalArgumentException("media is too short at " + ix + " frames");
} else {
readBuf.position(0).limit(sampleSize);
- for (ByteBuffer csd: csds) {
- sampleSize += csd.capacity();
- }
-
if (maxInputSize < sampleSize) {
maxInputSize = sampleSize;
}
ByteBuffer buf = ByteBuffer.allocate(sampleSize);
- for (ByteBuffer csd: csds) {
- csd.clear();
- buf.put(csd);
- csd.clear();
- Log.i(TAG, "csd[" + csd.capacity() + "]");
- }
- Log.i(TAG, "frame-" + ix + "[" + sampleSize + "]");
- csds.clear();
buf.put(readBuf);
- media.mFrames[ix] = new Frame(
+ media.mFrames[ix++] = new Frame(
extractor.getSampleTime(),
extractor.getSampleFlags(),
buf);
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
index bf4faccbaa1..b78e96c116d 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
@@ -62,7 +62,7 @@ public class DecodeAccuracyTest extends DecodeAccuracyTestBase {
private static final String TAG = DecodeAccuracyTest.class.getSimpleName();
private static final Field[] fields = R.raw.class.getFields();
- private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 90;
+ private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 105;
private static final int OFFSET = 10;
private static final long PER_TEST_TIMEOUT_MS = 60000;
private static final String[] VIDEO_FILES = {
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderLowLatencyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderLowLatencyTest.java
new file mode 100644
index 00000000000..2233df45da3
--- /dev/null
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderLowLatencyTest.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media.decoder.cts;
+
+import static android.media.decoder.cts.DecoderTest.getAssetFileDescriptorFor;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.cts.MediaCodecWrapper;
+import android.media.cts.MediaHeavyPresubmitTest;
+import android.media.cts.MediaTestBase;
+import android.media.cts.NdkMediaCodec;
+import android.media.cts.SdkMediaCodec;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.view.Surface;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SdkSuppress;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.MediaUtils;
+import com.android.compatibility.common.util.NonMainlineTest;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+
+@MediaHeavyPresubmitTest
+@AppModeFull(reason = "There should be no instant apps specific behavior related to decoders")
+@RunWith(AndroidJUnit4.class)
+public class DecoderLowLatencyTest extends MediaTestBase {
+ private static final String TAG = "DecoderLowLatencyTest";
+ private static final String REPORT_LOG_NAME = "CtsMediaDecoderTestCases";
+
+ @Before
+ @Override
+ public void setUp() throws Throwable {
+ super.setUp();
+ }
+
+ @After
+ @Override
+ public void tearDown() {
+ super.tearDown();
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
+ @Test
+ public void testLowLatencyVp9At1280x720() throws Exception {
+ testLowLatencyVideo(
+ "video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm", 300,
+ false /* useNdk */);
+ testLowLatencyVideo(
+ "video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm", 300,
+ true /* useNdk */);
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
+ @Test
+ public void testLowLatencyVp9At1920x1080() throws Exception {
+ testLowLatencyVideo(
+ "bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm", 300,
+ false /* useNdk */);
+ testLowLatencyVideo(
+ "bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm", 300,
+ true /* useNdk */);
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
+ @Test
+ public void testLowLatencyVp9At3840x2160() throws Exception {
+ testLowLatencyVideo(
+ "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm", 300,
+ false /* useNdk */);
+ testLowLatencyVideo(
+ "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm", 300,
+ true /* useNdk */);
+ }
+
+ @NonMainlineTest
+ @Test
+ public void testLowLatencyAVCAt1280x720() throws Exception {
+ testLowLatencyVideo(
+ "video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 300,
+ false /* useNdk */);
+ testLowLatencyVideo(
+ "video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 300,
+ true /* useNdk */);
+ }
+
+ @NonMainlineTest
+ @Test
+ public void testLowLatencyHEVCAt480x360() throws Exception {
+ testLowLatencyVideo(
+ "video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4", 300,
+ false /* useNdk */);
+ testLowLatencyVideo(
+ "video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4", 300,
+ true /* useNdk */);
+ }
+
+ private void testLowLatencyVideo(String testVideo, int frameCount, boolean useNdk)
+ throws Exception {
+ AssetFileDescriptor fd = getAssetFileDescriptorFor(testVideo);
+ MediaExtractor extractor = new MediaExtractor();
+ extractor.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+ fd.close();
+
+ MediaFormat format = null;
+ int trackIndex = -1;
+ for (int i = 0; i < extractor.getTrackCount(); i++) {
+ format = extractor.getTrackFormat(i);
+ if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
+ trackIndex = i;
+ break;
+ }
+ }
+
+ assertTrue("No video track was found", trackIndex >= 0);
+
+ extractor.selectTrack(trackIndex);
+ format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency,
+ true /* enable */);
+
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ String decoderName = mcl.findDecoderForFormat(format);
+ if (decoderName == null) {
+ MediaUtils.skipTest("no low latency decoder for " + format);
+ return;
+ }
+ String entry = (useNdk ? "NDK" : "SDK");
+ Log.v(TAG, "found " + entry + " decoder " + decoderName + " for format: " + format);
+
+ Surface surface = getActivity().getSurfaceHolder().getSurface();
+ MediaCodecWrapper decoder = null;
+ if (useNdk) {
+ decoder = new NdkMediaCodec(decoderName);
+ } else {
+ decoder = new SdkMediaCodec(MediaCodec.createByCodecName(decoderName));
+ }
+ format.removeFeature(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency);
+ format.setInteger(MediaFormat.KEY_LOW_LATENCY, 1);
+ decoder.configure(format, 0 /* flags */, surface);
+ decoder.start();
+
+ if (!useNdk) {
+ decoder.getInputBuffers();
+ }
+ ByteBuffer[] codecOutputBuffers = decoder.getOutputBuffers();
+ String decoderOutputFormatString = null;
+
+ // start decoding
+ final long kTimeOutUs = 1000000; // 1 second
+ MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+ int bufferCounter = 0;
+ long[] latencyMs = new long[frameCount];
+ boolean waitingForOutput = false;
+ long startTimeMs = System.currentTimeMillis();
+ while (bufferCounter < frameCount) {
+ if (!waitingForOutput) {
+ int inputBufferId = decoder.dequeueInputBuffer(kTimeOutUs);
+ if (inputBufferId < 0) {
+ Log.v(TAG, "no input buffer");
+ break;
+ }
+
+ ByteBuffer dstBuf = decoder.getInputBuffer(inputBufferId);
+
+ int sampleSize = extractor.readSampleData(dstBuf, 0 /* offset */);
+ long presentationTimeUs = 0;
+ if (sampleSize < 0) {
+ Log.v(TAG, "had input EOS, early termination at frame " + bufferCounter);
+ break;
+ } else {
+ presentationTimeUs = extractor.getSampleTime();
+ }
+
+ startTimeMs = System.currentTimeMillis();
+ decoder.queueInputBuffer(
+ inputBufferId,
+ 0 /* offset */,
+ sampleSize,
+ presentationTimeUs,
+ 0 /* flags */);
+
+ extractor.advance();
+ waitingForOutput = true;
+ }
+
+ int outputBufferId = decoder.dequeueOutputBuffer(info, kTimeOutUs);
+
+ if (outputBufferId >= 0) {
+ waitingForOutput = false;
+ //Log.d(TAG, "got output, size " + info.size + ", time " + info.presentationTimeUs);
+ latencyMs[bufferCounter++] = System.currentTimeMillis() - startTimeMs;
+ // TODO: render the frame and find the rendering time to calculate the total delay
+ decoder.releaseOutputBuffer(outputBufferId, false /* render */);
+ } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+ codecOutputBuffers = decoder.getOutputBuffers();
+ Log.d(TAG, "output buffers have changed.");
+ } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ decoderOutputFormatString = decoder.getOutputFormatString();
+ Log.d(TAG, "output format has changed to " + decoderOutputFormatString);
+ } else {
+ fail("No output buffer returned without frame delay, status " + outputBufferId);
+ }
+ }
+
+ assertTrue("No INFO_OUTPUT_FORMAT_CHANGED from decoder", decoderOutputFormatString != null);
+
+ long latencyMean = 0;
+ long latencyMax = 0;
+ int maxIndex = 0;
+ for (int i = 0; i < bufferCounter; ++i) {
+ latencyMean += latencyMs[i];
+ if (latencyMs[i] > latencyMax) {
+ latencyMax = latencyMs[i];
+ maxIndex = i;
+ }
+ }
+ if (bufferCounter > 0) {
+ latencyMean /= bufferCounter;
+ }
+ Log.d(TAG, entry + " latency average " + latencyMean + " ms, max " + latencyMax +
+ " ms at frame " + maxIndex);
+
+ DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, "video_decoder_latency");
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ int width = format.getInteger(MediaFormat.KEY_WIDTH);
+ int height = format.getInteger(MediaFormat.KEY_HEIGHT);
+ log.addValue("codec_name", decoderName, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("mime_type", mime, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("width", width, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("height", height, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("video_res", testVideo, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("decode_to", surface == null ? "buffer" : "surface",
+ ResultType.NEUTRAL, ResultUnit.NONE);
+
+ log.addValue("average_latency", latencyMean, ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.addValue("max_latency", latencyMax, ResultType.LOWER_BETTER, ResultUnit.MS);
+
+ log.submit(getInstrumentation());
+
+ decoder.stop();
+ decoder.release();
+ extractor.release();
+ }
+}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
index b29e4161c9a..c93c0f081df 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
@@ -3839,6 +3839,21 @@ public class DecoderTest extends MediaTestBase {
Thread.sleep(200);
mMediaCodecPlayer.stopDrainingAudioOutputBuffers(false);
+ // Wait until underrun recovers, otherwise false detection of end of playback occurs
+ {
+ long underrunRecoveryTimeoutMs = 200;
+ long startTimeMs = System.currentTimeMillis();
+ AudioTimestamp previousTimestamp;
+ do {
+ assertTrue(String.format("No underrun recovery after %d milliseconds",
+ underrunRecoveryTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < underrunRecoveryTimeoutMs);
+ previousTimestamp = mMediaCodecPlayer.getTimestamp();
+ Thread.sleep(50);
+ } while (mMediaCodecPlayer.getTimestamp().framePosition
+ == previousTimestamp.framePosition);
+ }
+
// Sleep till framePosition stabilizes, i.e. playback is complete
{
long endOfPlayackTimeoutMs = 20000;
@@ -4503,206 +4518,4 @@ public class DecoderTest extends MediaTestBase {
PackageManager pm = mContext.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
}
-
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
- @Test
- public void testLowLatencyVp9At1280x720() throws Exception {
- testLowLatencyVideo(
- "video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm", 300,
- false /* useNdk */);
- testLowLatencyVideo(
- "video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm", 300,
- true /* useNdk */);
- }
-
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
- @Test
- public void testLowLatencyVp9At1920x1080() throws Exception {
- testLowLatencyVideo(
- "bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm", 300,
- false /* useNdk */);
- testLowLatencyVideo(
- "bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm", 300,
- true /* useNdk */);
- }
-
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
- @Test
- public void testLowLatencyVp9At3840x2160() throws Exception {
- testLowLatencyVideo(
- "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm", 300,
- false /* useNdk */);
- testLowLatencyVideo(
- "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm", 300,
- true /* useNdk */);
- }
-
- @NonMainlineTest
- @Test
- public void testLowLatencyAVCAt1280x720() throws Exception {
- testLowLatencyVideo(
- "video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 300,
- false /* useNdk */);
- testLowLatencyVideo(
- "video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 300,
- true /* useNdk */);
- }
-
- @NonMainlineTest
- @Test
- public void testLowLatencyHEVCAt480x360() throws Exception {
- testLowLatencyVideo(
- "video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4", 300,
- false /* useNdk */);
- testLowLatencyVideo(
- "video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4", 300,
- true /* useNdk */);
- }
-
- private void testLowLatencyVideo(String testVideo, int frameCount, boolean useNdk)
- throws Exception {
- AssetFileDescriptor fd = getAssetFileDescriptorFor(testVideo);
- MediaExtractor extractor = new MediaExtractor();
- extractor.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
- fd.close();
-
- MediaFormat format = null;
- int trackIndex = -1;
- for (int i = 0; i < extractor.getTrackCount(); i++) {
- format = extractor.getTrackFormat(i);
- if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
- trackIndex = i;
- break;
- }
- }
-
- assertTrue("No video track was found", trackIndex >= 0);
-
- extractor.selectTrack(trackIndex);
- format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency,
- true /* enable */);
-
- MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
- String decoderName = mcl.findDecoderForFormat(format);
- if (decoderName == null) {
- MediaUtils.skipTest("no low latency decoder for " + format);
- return;
- }
- String entry = (useNdk ? "NDK" : "SDK");
- Log.v(TAG, "found " + entry + " decoder " + decoderName + " for format: " + format);
-
- Surface surface = getActivity().getSurfaceHolder().getSurface();
- MediaCodecWrapper decoder = null;
- if (useNdk) {
- decoder = new NdkMediaCodec(decoderName);
- } else {
- decoder = new SdkMediaCodec(MediaCodec.createByCodecName(decoderName));
- }
- format.removeFeature(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency);
- format.setInteger(MediaFormat.KEY_LOW_LATENCY, 1);
- decoder.configure(format, 0 /* flags */, surface);
- decoder.start();
-
- if (!useNdk) {
- decoder.getInputBuffers();
- }
- ByteBuffer[] codecOutputBuffers = decoder.getOutputBuffers();
- String decoderOutputFormatString = null;
-
- // start decoding
- final long kTimeOutUs = 1000000; // 1 second
- MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
- int bufferCounter = 0;
- long[] latencyMs = new long[frameCount];
- boolean waitingForOutput = false;
- long startTimeMs = System.currentTimeMillis();
- while (bufferCounter < frameCount) {
- if (!waitingForOutput) {
- int inputBufferId = decoder.dequeueInputBuffer(kTimeOutUs);
- if (inputBufferId < 0) {
- Log.v(TAG, "no input buffer");
- break;
- }
-
- ByteBuffer dstBuf = decoder.getInputBuffer(inputBufferId);
-
- int sampleSize = extractor.readSampleData(dstBuf, 0 /* offset */);
- long presentationTimeUs = 0;
- if (sampleSize < 0) {
- Log.v(TAG, "had input EOS, early termination at frame " + bufferCounter);
- break;
- } else {
- presentationTimeUs = extractor.getSampleTime();
- }
-
- startTimeMs = System.currentTimeMillis();
- decoder.queueInputBuffer(
- inputBufferId,
- 0 /* offset */,
- sampleSize,
- presentationTimeUs,
- 0 /* flags */);
-
- extractor.advance();
- waitingForOutput = true;
- }
-
- int outputBufferId = decoder.dequeueOutputBuffer(info, kTimeOutUs);
-
- if (outputBufferId >= 0) {
- waitingForOutput = false;
- //Log.d(TAG, "got output, size " + info.size + ", time " + info.presentationTimeUs);
- latencyMs[bufferCounter++] = System.currentTimeMillis() - startTimeMs;
- // TODO: render the frame and find the rendering time to calculate the total delay
- decoder.releaseOutputBuffer(outputBufferId, false /* render */);
- } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
- codecOutputBuffers = decoder.getOutputBuffers();
- Log.d(TAG, "output buffers have changed.");
- } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- decoderOutputFormatString = decoder.getOutputFormatString();
- Log.d(TAG, "output format has changed to " + decoderOutputFormatString);
- } else {
- fail("No output buffer returned without frame delay, status " + outputBufferId);
- }
- }
-
- assertTrue("No INFO_OUTPUT_FORMAT_CHANGED from decoder", decoderOutputFormatString != null);
-
- long latencyMean = 0;
- long latencyMax = 0;
- int maxIndex = 0;
- for (int i = 0; i < bufferCounter; ++i) {
- latencyMean += latencyMs[i];
- if (latencyMs[i] > latencyMax) {
- latencyMax = latencyMs[i];
- maxIndex = i;
- }
- }
- if (bufferCounter > 0) {
- latencyMean /= bufferCounter;
- }
- Log.d(TAG, entry + " latency average " + latencyMean + " ms, max " + latencyMax +
- " ms at frame " + maxIndex);
-
- DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, "video_decoder_latency");
- String mime = format.getString(MediaFormat.KEY_MIME);
- int width = format.getInteger(MediaFormat.KEY_WIDTH);
- int height = format.getInteger(MediaFormat.KEY_HEIGHT);
- log.addValue("codec_name", decoderName, ResultType.NEUTRAL, ResultUnit.NONE);
- log.addValue("mime_type", mime, ResultType.NEUTRAL, ResultUnit.NONE);
- log.addValue("width", width, ResultType.NEUTRAL, ResultUnit.NONE);
- log.addValue("height", height, ResultType.NEUTRAL, ResultUnit.NONE);
- log.addValue("video_res", testVideo, ResultType.NEUTRAL, ResultUnit.NONE);
- log.addValue("decode_to", surface == null ? "buffer" : "surface",
- ResultType.NEUTRAL, ResultUnit.NONE);
-
- log.addValue("average_latency", latencyMean, ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue("max_latency", latencyMax, ResultType.LOWER_BETTER, ResultUnit.MS);
-
- log.submit(getInstrumentation());
-
- decoder.stop();
- decoder.release();
- extractor.release();
- }
}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
index 5a9921bb18a..92da87697be 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
@@ -364,13 +364,6 @@ public class ImageReaderDecoderTest {
mediaFormat = mExtractor.getTrackFormat(0);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
- if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9) && video.contains("10bit")) {
- // TODO: b/295804596 - parse color profiles in vp9
- // In some cases, webm extractor may not signal
- // profile for 10-bit VP9 clips. In such cases, set profile to a
- // 10-bit compatible profile.
- mediaFormat.setInteger(MediaFormat.KEY_PROFILE, CodecProfileLevel.VP9Profile2);
- }
MediaCodecInfo info = mDecoder.getCodecInfo();
CodecCapabilities caps = info.getCapabilitiesForType(mMime);
diff --git a/tests/tests/media/extractor/AndroidTest.xml b/tests/tests/media/extractor/AndroidTest.xml
index e88c69c9c6e..6df771dbf43 100644
--- a/tests/tests/media/extractor/AndroidTest.xml
+++ b/tests/tests/media/extractor/AndroidTest.xml
@@ -41,7 +41,7 @@
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
- <option name="media-folder-name" value="CtsMediaExtractorTestCases-2.1" />
+ <option name="media-folder-name" value="CtsMediaExtractorTestCases-2.2" />
<option name="dynamic-config-module" value="CtsMediaExtractorTestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/media/extractor/DynamicConfig.xml b/tests/tests/media/extractor/DynamicConfig.xml
index 0056677a140..766524c8926 100644
--- a/tests/tests/media/extractor/DynamicConfig.xml
+++ b/tests/tests/media/extractor/DynamicConfig.xml
@@ -15,6 +15,6 @@
<dynamicConfig>
<entry key="media_files_url">
- <value>https://dl.google.com/android/xts/cts/tests/tests/media/extractor/CtsMediaExtractorTestCases-2.1.zip</value>
+ <value>https://dl.google.com/android/xts/cts/tests/tests/media/extractor/CtsMediaExtractorTestCases-2.2.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/tests/media/extractor/copy_media.sh b/tests/tests/media/extractor/copy_media.sh
index 8b83bdf18b7..b4e5ba03762 100755
--- a/tests/tests/media/extractor/copy_media.sh
+++ b/tests/tests/media/extractor/copy_media.sh
@@ -17,4 +17,4 @@
[ -z "$MEDIA_ROOT_DIR" ] && MEDIA_ROOT_DIR=$(dirname $0)/..
source $MEDIA_ROOT_DIR/common/copy_media_utils.sh
get_adb_options "$@"
-copy_media "extractor" "CtsMediaExtractorTestCases-2.1"
+copy_media "extractor" "CtsMediaExtractorTestCases-2.2"
diff --git a/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java b/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
index d4e3ff4a21b..51775516924 100644
--- a/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
+++ b/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
@@ -372,6 +372,22 @@ public class MediaExtractorTest {
assertEquals("video/av01", mimeType);
}
+ // DolbyVisionMediaExtractor for trimmed Dolby Vision file.
+ // Please check https://issuetracker.google.com/329121650 for details.
+ @Test
+ public void testTrimmedDolbyVisionFileTrackDuration() throws Exception {
+ TestMediaDataSource dataSource = setDataSource("video_dovi_dvhe_08_trimmed.mp4");
+
+ final int trackCount = mExtractor.getTrackCount();
+ assertTrue("There should be at least one track", 0 < trackCount);
+
+ long expectedTrackDurationUs = 3_026_666;
+ for (int i = 0; i < trackCount; i++) {
+ MediaFormat trackFormat = mExtractor.getTrackFormat(i);
+ assertEquals(expectedTrackDurationUs, trackFormat.getLong(MediaFormat.KEY_DURATION));
+ }
+ }
+
//MPEG-H 3D Audio single stream (mha1)
@Test
public void testMpegh3dAudioMediaExtractorMha1() throws Exception {
diff --git a/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java b/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
index 8b847e26e05..31c069e2378 100644
--- a/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
+++ b/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
@@ -20,6 +20,6 @@ import android.media.cts.WorkDirBase;
class WorkDir extends WorkDirBase {
public static final String getMediaDirString() {
- return getMediaDirString("CtsMediaExtractorTestCases-2.1");
+ return getMediaDirString("CtsMediaExtractorTestCases-2.2");
}
}
diff --git a/tests/tests/media/misc/AndroidTest.xml b/tests/tests/media/misc/AndroidTest.xml
index ed3133fe29c..546a15bac8d 100644
--- a/tests/tests/media/misc/AndroidTest.xml
+++ b/tests/tests/media/misc/AndroidTest.xml
@@ -41,7 +41,7 @@
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
- <option name="media-folder-name" value="CtsMediaMiscTestCases-2.2" />
+ <option name="media-folder-name" value="CtsMediaMiscTestCases-2.3" />
<option name="dynamic-config-module" value="CtsMediaMiscTestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/media/misc/DynamicConfig.xml b/tests/tests/media/misc/DynamicConfig.xml
index ed21ce3cd35..2eec4491804 100644
--- a/tests/tests/media/misc/DynamicConfig.xml
+++ b/tests/tests/media/misc/DynamicConfig.xml
@@ -15,6 +15,6 @@
<dynamicConfig>
<entry key="media_files_url">
- <value>https://dl.google.com/android/xts/cts/tests/tests/media/misc/CtsMediaMiscTestCases-2.2.zip</value>
+ <value>https://dl.google.com/android/xts/cts/tests/tests/media/misc/CtsMediaMiscTestCases-2.3.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/tests/media/misc/copy_media.sh b/tests/tests/media/misc/copy_media.sh
index c8381975d7b..16538a1bf95 100755
--- a/tests/tests/media/misc/copy_media.sh
+++ b/tests/tests/media/misc/copy_media.sh
@@ -17,4 +17,4 @@
[ -z "$MEDIA_ROOT_DIR" ] && MEDIA_ROOT_DIR=$(dirname $0)/..
source $MEDIA_ROOT_DIR/common/copy_media_utils.sh
get_adb_options "$@"
-copy_media "misc" "CtsMediaMiscTestCases-2.2"
+copy_media "misc" "CtsMediaMiscTestCases-2.3"
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
index 8c5bf2fd5eb..020fd09895e 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
@@ -1242,17 +1242,15 @@ public class MediaMetadataRetrieverTest {
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
codeName = "VanillaIceCream")
public void testGetImageAtIndexAvifWithCrop() throws Exception {
- // sample_1960x1120_crop_20_20_1920_1080.avif is a 1960x1120 AVIF image with the crop window
- // set to left: 20 top: 20 crop width: 1920 crop height: 1080. The cropped image should
+ // sample_720x480_crop_20_20_680_440.avif is a 720x480 AVIF image with the crop window
+ // set to left: 20 top: 20 crop width: 680 crop height: 440. The cropped image should
// contain the same pixels as other sample AVIF images. So in order to verify the cropping,
// it is sufficient to pass checkColor to true to testGetImage. If the cropping was
// incorrect, then checking of color bars will fail. The expected width and height should be
// that of the cropped image.
- if (!MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AV1, 1960, 1120, 30)) {
- MediaUtils.skipTest("No AV1 codec for 1960x1120");
- return;
- }
- testGetImage("sample_1960x1120_crop_20_20_1920_1080.avif", 1920, 1080, "image/avif",
+ assumeTrue("No AV1 codec for 720x480",
+ MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AV1, 720, 480, 30));
+ testGetImage("sample_720x480_crop_20_20_680_440.avif", 680, 440, "image/avif",
0 /*rotation*/, 1 /*imageCount*/, 0 /*primary*/, false /*useGrid*/,
true /*checkColor*/);
}
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
index 6cbab7c5376..e8e3e183aed 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
@@ -20,6 +20,6 @@ import android.media.cts.WorkDirBase;
class WorkDir extends WorkDirBase {
public static final String getMediaDirString() {
- return getMediaDirString("CtsMediaMiscTestCases-2.2");
+ return getMediaDirString("CtsMediaMiscTestCases-2.3");
}
}
diff --git a/tests/tests/mediacujtest/common/Android.bp b/tests/tests/mediacujtest/common/Android.bp
index 67b6f4c0b52..4a9ed91a8b9 100644
--- a/tests/tests/mediacujtest/common/Android.bp
+++ b/tests/tests/mediacujtest/common/Android.bp
@@ -39,6 +39,6 @@ android_library {
"src/**/*.java",
],
plugins: ["auto_value_plugin"],
+ platform_apis: true,
min_sdk_version: "30",
- sdk_version: "current",
}
diff --git a/tests/tests/mediacujtest/common/res/layout/activity_main.xml b/tests/tests/mediacujtest/common/res/layout/activity_main.xml
index c34567d791e..17a17d6e355 100644
--- a/tests/tests/mediacujtest/common/res/layout/activity_main.xml
+++ b/tests/tests/mediacujtest/common/res/layout/activity_main.xml
@@ -16,6 +16,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@@ -23,5 +24,12 @@
<androidx.media3.ui.PlayerView
android:id="@+id/exoplayer"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent">
+ <ImageButton
+ android:id="@+id/lock_controller"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:srcCompat="@android:drawable/ic_lock_idle_lock" />
+ </androidx.media3.ui.PlayerView>
+
</LinearLayout>
diff --git a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java
index 6181f8eef38..3b246cb14f5 100644
--- a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java
@@ -19,6 +19,7 @@ package android.media.cujcommon.cts;
import static org.junit.Assert.assertEquals;
import android.app.Activity;
+import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -93,6 +94,13 @@ public class CujTestBase {
}
/**
+ * Whether the device supports split-screen feature.
+ */
+ public static boolean deviceSupportSplitScreenMode(final Activity activity) {
+ return ActivityTaskManager.supportsSplitScreenMultiWindow(activity);
+ }
+
+ /**
* Whether the device is a watch.
*/
public static boolean isWatchDevice(final Activity activity) {
diff --git a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/LockPlaybackControllerTestPlayerListener.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/LockPlaybackControllerTestPlayerListener.java
new file mode 100644
index 00000000000..40ca776f502
--- /dev/null
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/LockPlaybackControllerTestPlayerListener.java
@@ -0,0 +1,131 @@
+/**
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.media.cujcommon.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Looper;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.media3.common.Player;
+import androidx.media3.common.Player.PositionInfo;
+
+public class LockPlaybackControllerTestPlayerListener extends PlayerListener {
+
+ private static final int MESSAGE_INTERVAL_MS = 2000;
+
+ private boolean mRewindDone;
+ private boolean mIsControllerLocked;
+
+ public LockPlaybackControllerTestPlayerListener(long sendMessagePosition) {
+ super();
+ this.mSendMessagePosition = sendMessagePosition;
+ }
+
+ @Override
+ public void onPositionDiscontinuity(PositionInfo oldPosition, PositionInfo newPosition,
+ int reason) {
+ super.onPositionDiscontinuity(oldPosition, newPosition, reason);
+ // Verify that the position has changed due to seek
+ assertEquals(Player.DISCONTINUITY_REASON_SEEK, reason);
+ // Update the variable if rewind has been executed
+ mRewindDone = (newPosition.positionMs < oldPosition.positionMs);
+ // Add change in duration due to seek
+ mExpectedTotalTime += (mSendMessagePosition - newPosition.positionMs);
+ }
+
+ @Override
+ public TestType getTestType() {
+ return TestType.LOCK_PLAYBACK_CONTROLLER_TEST;
+ }
+
+ @Override
+ public void onEventsPlaybackStateChanged(@NonNull Player player) {
+ if (player.getPlaybackState() == Player.STATE_READY) {
+ // At the first media transition player is not ready. So, add duration of
+ // first clip when player is ready
+ mExpectedTotalTime += player.getDuration();
+ // Set the controller show timeout to 0 so that controller UI stays eternally
+ mActivity.mExoplayerView.setControllerShowTimeoutMs(0);
+ mActivity.mExoplayerView.showController();
+ activateLockButton(mActivity);
+ }
+ }
+
+ @Override
+ public void onEventsMediaItemTransition(@NonNull Player player) {
+ mActivity.mPlayer.createMessage((messageType, payload) -> {
+ // Rewind by 5 sec
+ mActivity.mExoRewindButton.performClick();
+ }).setLooper(Looper.getMainLooper())
+ .setPosition(mSendMessagePosition)
+ .setDeleteAfterDelivery(true)
+ .send();
+ mActivity.mPlayer.createMessage((messageType, payload) -> {
+ // Verify that the rewind has been executed
+ assertTrue(mRewindDone);
+ mRewindDone = false;
+ // Lock the playback controller
+ mActivity.mLockControllerButton.performClick();
+ }).setLooper(Looper.getMainLooper())
+ .setPosition(mSendMessagePosition + MESSAGE_INTERVAL_MS)
+ .setDeleteAfterDelivery(true)
+ .send();
+ mActivity.mPlayer.createMessage((messageType, payload) -> {
+ // Verify that the controller UI is locked
+ assertTrue(mIsControllerLocked);
+ // Try to rewind while the controller UI is locked
+ mActivity.mExoRewindButton.performClick();
+ }).setLooper(Looper.getMainLooper())
+ .setPosition(mSendMessagePosition + 2 * MESSAGE_INTERVAL_MS)
+ .setDeleteAfterDelivery(true)
+ .send();
+ mActivity.mPlayer.createMessage((messageType, payload) -> {
+ // Verify that the rewind has not been executed
+ assertFalse(mRewindDone);
+ // Unlock the playback controller
+ mActivity.mLockControllerButton.performClick();
+ }).setLooper(Looper.getMainLooper())
+ .setPosition(mSendMessagePosition + 3 * MESSAGE_INTERVAL_MS)
+ .setDeleteAfterDelivery(true)
+ .send();
+ }
+
+ /**
+ * By default, the lock controller button is invisible. So we need to make it visible and set its
+ * onClick listener.
+ *
+ * @param activity MainActivity
+ */
+ private void activateLockButton(MainActivity activity) {
+ activity.mLockControllerButton.setVisibility(View.VISIBLE);
+ activity.mLockControllerButton.setOnClickListener(view -> {
+ if (mIsControllerLocked) {
+ mIsControllerLocked = false;
+ activity.mExoplayerView.setUseController(true);
+ activity.mExoplayerView.showController();
+ } else {
+ mIsControllerLocked = true;
+ activity.mExoplayerView.hideController();
+ activity.mExoplayerView.setUseController(false);
+ }
+ });
+ }
+}
diff --git a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java
index e50bbed8a64..1a97ce80181 100644
--- a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java
@@ -24,6 +24,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
+import android.view.View;
import android.view.WindowManager;
import androidx.annotation.NonNull;
@@ -51,6 +52,8 @@ public class MainActivity extends AppCompatActivity {
protected boolean mIsInPipMode;
protected boolean mConfiguredSplitScreenMode;
protected boolean mIsInMultiWindowMode;
+ protected View mExoRewindButton;
+ protected View mLockControllerButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -66,6 +69,9 @@ public class MainActivity extends AppCompatActivity {
protected void buildPlayer() {
mPlayer = new ExoPlayer.Builder(this).build();
mExoplayerView = findViewById(R.id.exoplayer);
+ mLockControllerButton = findViewById(R.id.lock_controller);
+ mLockControllerButton.setVisibility(View.INVISIBLE);
+ mExoRewindButton = findViewById(androidx.media3.ui.R.id.exo_rew_with_amount);
mExoplayerView.setPlayer(mPlayer);
}
@@ -132,7 +138,7 @@ public class MainActivity extends AppCompatActivity {
if (mScaleGestureDetector != null) {
mScaleGestureDetector.onTouchEvent(event);
}
- return true;
+ return super.dispatchTouchEvent(event);
}
/**
diff --git a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/PlayerListener.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/PlayerListener.java
index 2956a56228a..1a6fe308bd4 100644
--- a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/PlayerListener.java
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/PlayerListener.java
@@ -59,7 +59,8 @@ public abstract class PlayerListener implements Player.Listener {
SPEED_CHANGE_TEST,
PIP_MODE_TEST,
SPLIT_SCREEN_TEST,
- DEVICE_LOCK_TEST
+ DEVICE_LOCK_TEST,
+ LOCK_PLAYBACK_CONTROLLER_TEST
}
public static boolean mPlaybackEnded;
diff --git a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/SplitScreenTestPlayerListener.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/SplitScreenTestPlayerListener.java
index da1f9766af2..8c9e5213281 100644
--- a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/SplitScreenTestPlayerListener.java
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/SplitScreenTestPlayerListener.java
@@ -20,7 +20,6 @@ import static org.junit.Assert.assertTrue;
import android.content.Intent;
import android.os.Looper;
-import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.media3.common.Player;
@@ -52,7 +51,7 @@ public class SplitScreenTestPlayerListener extends PlayerListener {
public void onEventsMediaItemTransition(@NonNull Player player) {
mActivity.mPlayer.createMessage((messageType, payload) -> {
// Switch to split screen mode
- Intent intent = new Intent(Settings.ACTION_SETTINGS);
+ Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity.startActivity(intent);
mActivity.mConfiguredSplitScreenMode = true;
diff --git a/tests/tests/mediacujtest/largetest/AndroidManifest.xml b/tests/tests/mediacujtest/largetest/AndroidManifest.xml
index 8b2be7a6481..a58d3dd0d5e 100644
--- a/tests/tests/mediacujtest/largetest/AndroidManifest.xml
+++ b/tests/tests/mediacujtest/largetest/AndroidManifest.xml
@@ -40,9 +40,6 @@
android:label="Media E2E tests InstrumentationRunner"
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.media.cujlargetest.cts">
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/tests/mediacujtest/smalltest/AndroidManifest.xml b/tests/tests/mediacujtest/smalltest/AndroidManifest.xml
index a748dbeb9ea..3d988702325 100644
--- a/tests/tests/mediacujtest/smalltest/AndroidManifest.xml
+++ b/tests/tests/mediacujtest/smalltest/AndroidManifest.xml
@@ -38,8 +38,5 @@
android:label="Media E2E tests InstrumentationRunner"
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.media.cujsmalltest.cts">
- <meta-data
- android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java b/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java
index 717d27c7a35..693026375f8 100644
--- a/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java
+++ b/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java
@@ -19,6 +19,7 @@ package android.media.cujsmalltest.cts;
import android.media.cujcommon.cts.CujTestBase;
import android.media.cujcommon.cts.CujTestParam;
import android.media.cujcommon.cts.DeviceLockTestPlayerListener;
+import android.media.cujcommon.cts.LockPlaybackControllerTestPlayerListener;
import android.media.cujcommon.cts.OrientationTestPlayerListener;
import android.media.cujcommon.cts.PinchToZoomTestPlayerListener;
import android.media.cujcommon.cts.PipModeTestPlayerListener;
@@ -155,6 +156,10 @@ public class CtsMediaShortFormPlaybackTest extends CujTestBase {
.setTimeoutMilliSeconds(45000)
.setPlayerListener(new DeviceLockTestPlayerListener(3000, true)).build(),
"Mp3_15sec_DeviceLockTest"},
+ {CujTestParam.builder().setMediaUrls(prepareMp3_15secAudioListForDeviceLockTest())
+ .setTimeoutMilliSeconds(50000)
+ .setPlayerListener(new LockPlaybackControllerTestPlayerListener(6000)).build(),
+ "Hevc_720p_15sec_LockPlaybackTest"},
}));
return exhaustiveArgsList;
}
@@ -304,7 +309,11 @@ public class CtsMediaShortFormPlaybackTest extends CujTestBase {
deviceSupportPipMode(mActivity));
}
if (mCujTestParam.playerListener().isSplitScreenTest()) {
- Assume.assumeFalse("Skipping " + mTestType + " on television", isTelevisionDevice(mActivity));
+ Assume.assumeTrue("Skipping " + mTestType + " as device doesn't support split screen feature",
+ deviceSupportSplitScreenMode(mActivity));
+ }
+ if (mCujTestParam.playerListener().getTestType()
+ .equals(TestType.LOCK_PLAYBACK_CONTROLLER_TEST)) {
Assume.assumeFalse("Skipping " + mTestType + " on watch", isWatchDevice(mActivity));
}
if (mCujTestParam.playerListener().getTestType().equals(TestType.DEVICE_LOCK_TEST)) {
diff --git a/tests/tests/mediaediting/AndroidManifest.xml b/tests/tests/mediaediting/AndroidManifest.xml
index 789cd48a110..72e76c1a2fe 100644
--- a/tests/tests/mediaediting/AndroidManifest.xml
+++ b/tests/tests/mediaediting/AndroidManifest.xml
@@ -31,8 +31,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.media.mediaediting.cts"
android:label="Media editing tests InstrumentationRunner">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener"/>
</instrumentation>
</manifest>
diff --git a/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java b/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java
index 6517f2f9fcc..d3749c967e1 100644
--- a/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java
+++ b/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java
@@ -628,7 +628,9 @@ public final class AndroidTestUtil {
if (image == null) {
break;
}
- bitmaps.add(BitmapPixelTestUtil.createGrayscaleArgb8888BitmapFromYuv420888Image(image));
+ bitmaps.add(
+ BitmapPixelTestUtil.createGrayscaleBitmapFromYuv420888Image(
+ image, Bitmap.Config.ARGB_8888));
image.close();
}
}
diff --git a/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java b/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java
index 94ae747478e..f72b1b6300c 100644
--- a/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java
+++ b/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java
@@ -196,6 +196,12 @@ public final class TranscodeQualityTest {
.setRequestCalculateSsim(true)
.build()
.run(testId, editedMediaItem);
+
+ if (!isWithinCddRequirements) {
+ Assume.assumeFalse("Skipping transcodeTest for " + testId,
+ result.fallbackDetails != null
+ && result.fallbackDetails.fallbackOutputHeight != height);
+ }
assertThat(result.ssim).isGreaterThan(EXPECTED_MINIMUM_SSIM);
}
}
diff --git a/tests/tests/networksecurityconfig/manifest.xml b/tests/tests/networksecurityconfig/manifest.xml
index 2950baf7109..93250d75ff3 100644
--- a/tests/tests/networksecurityconfig/manifest.xml
+++ b/tests/tests/networksecurityconfig/manifest.xml
@@ -28,7 +28,5 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.security.net.config.cts"
android:label="">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/tests/notification/OWNERS b/tests/tests/notification/OWNERS
index ad9dd5955b7..4628f8c5f64 100644
--- a/tests/tests/notification/OWNERS
+++ b/tests/tests/notification/OWNERS
@@ -1,4 +1 @@
-# Bug component: 181562
-juliacr@google.com
-jeffdq@google.com
-dsandler@android.com \ No newline at end of file
+include platform/frameworks/base:/services/core/java/com/android/server/notification/OWNERS \ No newline at end of file
diff --git a/tests/tests/os/src/android/os/cts/FileObserverTest.java b/tests/tests/os/src/android/os/cts/FileObserverTest.java
index 26ea8952bc0..96e5e0282b5 100644
--- a/tests/tests/os/src/android/os/cts/FileObserverTest.java
+++ b/tests/tests/os/src/android/os/cts/FileObserverTest.java
@@ -205,19 +205,27 @@ public class FileObserverTest extends AndroidTestCase {
private void verifyTriggeredEventsOnFile(MockFileObserver fileObserver,
File testFile, boolean isEmulated) throws Exception {
+ // We create, write, close the file
+ // The effects of this vary - create first truncates the existing file,
+ // then opens it, then modifies it, then closes it
+ // Prior to kernel 6.6, this produced a modify/open/modify/close-write
+ // In 6.6, the behavior was changed to combine the two modifies
+ // See:
+ // https://lore.kernel.org/all/CAL=UVf5hZNVUPv4WdLsyMw5X8kP-3=gwU9mymWS_3APTVuSacQ@mail.gmail.com/T/
+ // though unfortunately the reply from the maintainer seems to have been lost
final FileOutputStream out = new FileOutputStream(testFile);
out.write(FILE_DATA); // modify, open, write, modify
out.close(); // close_write
final int[] expected = {
- FileObserver.MODIFY,
FileObserver.OPEN,
FileObserver.MODIFY,
FileObserver.CLOSE_WRITE
};
final FileEvent[] moveEvents = waitForEvent(fileObserver);
+
assertEventsContains(testFile, expected, moveEvents);
}
diff --git a/tests/tests/packagewatchdog/OWNERS b/tests/tests/packagewatchdog/OWNERS
index 7448086fe69..57af335fefd 100644
--- a/tests/tests/packagewatchdog/OWNERS
+++ b/tests/tests/packagewatchdog/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 557916
-gavincorkery@google.com
-olilan@google.com
+include platform/frameworks/base:/services/core/java/com/android/server/crashrecovery/OWNERS
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
index 1f54ad0d722..dd0931b9e16 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -174,6 +175,7 @@ public class MediaStore_FilesTest {
@Test
public void testCaseSensitivity() throws IOException {
+ assumeTrue(Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R);
final String name = "Test-" + System.nanoTime() + ".Mp3";
final File dir = ProviderTestUtils.stageDir(mVolumeName);
final File file = new File(dir, name);
diff --git a/tests/tests/security/res/raw/blocklist_diginotar.pem b/tests/tests/security/res/raw/blocklist_diginotar.pem
new file mode 100644
index 00000000000..b972b4bc50c
--- /dev/null
+++ b/tests/tests/security/res/raw/blocklist_diginotar.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQDHbanJEMTiye/hXQWJM8TDANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdp
+Tm90YXIgUm9vdCBDQTEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmww
+HhcNMDcwNTE2MTcxOTM2WhcNMjUwMzMxMTgxOTIxWjBfMQswCQYDVQQGEwJOTDES
+MBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdpTm90YXIgUm9vdCBDQTEg
+MB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmwwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCssFjBAL3YIQgLK5r+blYwBZ8bd5AQQVzDDYcRd46B
+8cp86Yxq7Th0Nbva3/m7wAk3tJZzgX0zGpg595NvlX89ubF1h7pRSOiLcD6VBMXY
+tsMW2YiwsYcdcNqGtA8Ui3rPENF0NqISe3eGSnnme98CEWilToauNFibJBN4ViIl
+HgGLS1Fx+4LMWZZpiFpoU8W5DQI3y0u8ZkqQfioLBQftFl9VkHXYRskbg+IIvvEj
+zJkd1ioPgyAVWCeCLvriIsJJsbkBgWqdbZ1Ad2h2TiEqbYRAhU52mXyC8/O3AlnU
+JgEbjt+tUwbRrhjd4rI6y9eIOI6sWym5GdOY+RgDz0iChmYLG2kPyes4iHomGgVM
+ktck1JbyrFIto0fVUvY//s6EBnCmqj6i8rZWNBhXouSBbefK8GrTx5FrAoNBfBXv
+a5pkXuPQPOWx63tdhvvL5ndJzaNl3Pe5nLjkC1+Tz8wwGjIczhxjlaX56uF0i57p
+K6kwe6AYHw4YC+VbqdPRbB4HZ4+RS6mKvNJmqpMBiLKR+jFc1abBUggJzQpjotMi
+puih2TkGl/VujQKQjBR7P4DNG5y6xFhyI6+2Vp/GekIzKQc/gsnmHwUNzUwoNovT
+yD4cxojvXu6JZOkd69qJfjKmadHdzIif0dDJZiHcBmfFlHqabWJMfczgZICynkeO
+owIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wDQYJKoZIhvcNAQEFBQADggIBADsC
+jcs8MOhuoK3yc7NfniUTBAXT9uOLuwt5zlPe5JbF0a9zvNXD0EBVfEB/zRtfCdXy
+fJ9oHbtdzno5wozWmHvFg1Wo1X1AyuAe94leY12hE8JdiraKfADzI8PthV9xdvBo
+Y6pFITlIYXg23PFDk9Qlx/KAZeFTAnVR/Ho67zerhChXDNjU1JlWbOOi/lmEtDHo
+M/hklJRRl6s5xUvt2t2AC298KQ3EjopyDedTFLJgQT2EkTFoPSdE2+Xe9PpjRchM
+Ppj1P0G6Tss3DbpmmPHdy59c91Q2gmssvBNhl0L4eLvMyKKfyvBovWsdst+Nbwed
+2o5nx0ceyrm/KkKRt2NTZvFCo+H0Wk1Ya7XkpDOtXHAd3ODy63MUkZoDweoAZbwH
+/M8SESIsrqC9OuCiKthZ6SnTGDWkrBFfGbW1G/8iSlzGeuQX7yCpp/Q/rYqnmgQl
+nQ7KN+ZQ/YxCKQSa7LnPS3K94gg2ryMvYuXKAdNw23yCIywWMQzGNgeQerEfZ1jE
+O1hZibCMjFCz2IbLaKPECudpSyDOwR5WS5WpI2jYMNjD67BVUc3l/Su49bsRn1NU
+9jQZjHkJNsphFyUXC4KYcwx3dMPVDceoEkzHp1RxRy4sGn3J4ys7SN4nhKdjNrN9
+j6BkOSQNPXuHr2ZcdBtLc7LljPCGmbjlxd+Ewbfr
+-----END CERTIFICATE-----
diff --git a/tests/tests/security/res/raw/blacklist_test_chain.pem b/tests/tests/security/res/raw/blocklist_test_chain.pem
index bc7931e9c17..bc7931e9c17 100644
--- a/tests/tests/security/res/raw/blacklist_test_chain.pem
+++ b/tests/tests/security/res/raw/blocklist_test_chain.pem
diff --git a/tests/tests/security/res/raw/blacklist_test_valid_ca.pem b/tests/tests/security/res/raw/blocklist_test_valid_ca.pem
index 43aafeddc6f..43aafeddc6f 100644
--- a/tests/tests/security/res/raw/blacklist_test_valid_ca.pem
+++ b/tests/tests/security/res/raw/blocklist_test_valid_ca.pem
diff --git a/tests/tests/security/res/raw/blacklist_test_valid_chain.pem b/tests/tests/security/res/raw/blocklist_test_valid_chain.pem
index f572627362f..f572627362f 100644
--- a/tests/tests/security/res/raw/blacklist_test_valid_chain.pem
+++ b/tests/tests/security/res/raw/blocklist_test_valid_chain.pem
diff --git a/tests/tests/security/res/raw/test_blacklist_ca.pem b/tests/tests/security/res/raw/test_blocklist_ca.pem
index 74e1c6de00a..74e1c6de00a 100644
--- a/tests/tests/security/res/raw/test_blacklist_ca.pem
+++ b/tests/tests/security/res/raw/test_blocklist_ca.pem
diff --git a/tests/tests/security/src/android/security/cts/CertBlacklistTest.java b/tests/tests/security/src/android/security/cts/CertBlocklistTest.java
index d7a199e29a5..fde5bc9b4bb 100644
--- a/tests/tests/security/src/android/security/cts/CertBlacklistTest.java
+++ b/tests/tests/security/src/android/security/cts/CertBlocklistTest.java
@@ -16,70 +16,80 @@
package android.security.cts;
-import android.content.Context;
import android.test.AndroidTestCase;
import java.io.InputStream;
-import java.util.Collection;
+import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import java.security.KeyStore;
+import java.util.Collection;
+
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
/**
- * End to end version of org.conscrypt.CertBlacklistTest that tests the platform default
+ * End to end version of org.conscrypt.CertBlocklistTest that tests the platform default
* {@link X509TrustManager}.
*
- * The test blacklisted CA's private key can be found in
- * external/conscrypt/src/test/resources/blacklist_ca_key.pem
+ * The test blocklisted CA's private key can be found in
+ * external/conscrypt/src/test/resources/blocklist_ca_key.pem
*/
-public class CertBlacklistTest extends AndroidTestCase {
+public class CertBlocklistTest extends AndroidTestCase {
- private static final int BLACKLIST_CA = R.raw.test_blacklist_ca;
- private static final int BLACKLISTED_CHAIN = R.raw.blacklist_test_chain;
- private static final int BLACKLIST_FALLBACK_VALID_CA = R.raw.blacklist_test_valid_ca;
- private static final int BLACKLISTED_VALID_CHAIN = R.raw.blacklist_test_valid_chain;
+ private static final int BLOCKLIST_CA = R.raw.test_blocklist_ca;
+ private static final int BLOCKLIST_DIGINOTAR = R.raw.blocklist_diginotar;
+ private static final int BLOCKLISTED_CHAIN = R.raw.blocklist_test_chain;
+ private static final int BLOCKLIST_FALLBACK_VALID_CA = R.raw.blocklist_test_valid_ca;
+ private static final int BLOCKLISTED_VALID_CHAIN = R.raw.blocklist_test_valid_chain;
+
+ /**
+ * Checks that the blocklisted CA is rejected even if it used as a root of trust
+ */
+ public void testBlocklistedCaUntrusted() throws Exception {
+ X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_CA);
+ assertUntrusted(new X509Certificate[] {blocklistedCa}, getTrustManager(blocklistedCa));
+ }
/**
- * Checks that the blacklisted CA is rejected even if it used as a root of trust
+ * Checks that a known compromised CA certificate is blocked.
*/
- public void testBlacklistedCaUntrusted() throws Exception {
- X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
- assertUntrusted(new X509Certificate[] {blacklistedCa}, getTrustManager(blacklistedCa));
+ public void testBlocklistedDiginotar() throws Exception {
+ // Public Key SHA1 = 410f36363258f30b347d12ce4863e433437806a8
+ X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_DIGINOTAR);
+ assertUntrusted(new X509Certificate[] {blocklistedCa}, getTrustManager(blocklistedCa));
}
/**
- * Checks that a chain that is rooted in a blacklisted trusted CA is rejected.
+ * Checks that a chain that is rooted in a blocklisted trusted CA is rejected.
*/
- public void testBlacklistedRootOfTrust() throws Exception {
- // Chain is leaf -> blacklisted
- X509Certificate[] chain = loadCertificates(BLACKLISTED_CHAIN);
- X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
- assertUntrusted(chain, getTrustManager(blacklistedCa));
+ public void testBlocklistedRootOfTrust() throws Exception {
+ // Chain is leaf -> blocklisted
+ X509Certificate[] chain = loadCertificates(BLOCKLISTED_CHAIN);
+ X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_CA);
+ assertUntrusted(chain, getTrustManager(blocklistedCa));
}
/**
- * Tests that the path building correctly routes around a blacklisted cert where there are
+ * Tests that the path building correctly routes around a blocklisted cert where there are
* other valid paths available. This prevents breakage where a cert was cross signed by a
- * blacklisted CA but is still valid due to also being cross signed by CAs that remain trusted.
+ * blocklisted CA but is still valid due to also being cross signed by CAs that remain trusted.
* Path:
*
- * leaf -> intermediate -> blacklisted_ca
+ * leaf -> intermediate -> blocklisted_ca
* \
* -------> trusted_ca
*/
- public void testBlacklistedIntermediateFallback() throws Exception {
- X509Certificate[] chain = loadCertificates(BLACKLISTED_VALID_CHAIN);
- X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
- X509Certificate validCa = loadCertificate(BLACKLIST_FALLBACK_VALID_CA);
- assertTrusted(chain, getTrustManager(blacklistedCa, validCa));
+ public void testBlocklistedIntermediateFallback() throws Exception {
+ X509Certificate[] chain = loadCertificates(BLOCKLISTED_VALID_CHAIN);
+ X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_CA);
+ X509Certificate validCa = loadCertificate(BLOCKLIST_FALLBACK_VALID_CA);
+ assertTrusted(chain, getTrustManager(blocklistedCa, validCa));
// Check that without the trusted_ca the chain is invalid (since it only chains to a
- // blacklisted ca)
- assertUntrusted(chain, getTrustManager(blacklistedCa));
+ // blocklisted ca)
+ assertUntrusted(chain, getTrustManager(blocklistedCa));
}
private X509Certificate loadCertificate(int resId) throws Exception {
diff --git a/tests/tests/settings/src/android/settings/cts/WifiSliceTest.java b/tests/tests/settings/src/android/settings/cts/WifiSliceTest.java
index 78461cebfad..2c156e99d40 100644
--- a/tests/tests/settings/src/android/settings/cts/WifiSliceTest.java
+++ b/tests/tests/settings/src/android/settings/cts/WifiSliceTest.java
@@ -18,7 +18,9 @@ package android.settings.cts;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.provider.Settings.Secure;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assume.assumeFalse;
import android.app.slice.Slice;
@@ -153,8 +155,18 @@ public class WifiSliceTest {
final ResolveInfo info = pm.resolveActivity(requestDefaultAssistant, 0);
if (info != null) {
+ final String packageName;
+ if (!TextUtils.isEmpty(mAssistant)) {
+ packageName = ComponentName.unflattenFromString(mAssistant).getPackageName();
+ Log.i(TAG, "Default assistant: " + packageName);
+ } else {
+ packageName = info.activityInfo.packageName;
+ Log.i(TAG, "Set assistant: " + packageName);
+ Secure.putString(mContext.getContentResolver(), ASSISTANT,
+ new ComponentName(packageName, info.activityInfo.name).flattenToString());
+ }
final int testPid = Process.myPid();
- final int testUid = pm.getPackageUid(info.activityInfo.packageName, 0);
+ final int testUid = pm.getPackageUid(packageName, 0);
assertThat(mSliceManager.checkSlicePermission(WIFI_SLICE_URI, testPid, testUid))
.isEqualTo(PERMISSION_GRANTED);
diff --git a/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java b/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java
index f0a6d890b01..046429ec17e 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java
@@ -226,7 +226,7 @@ public class BackgroundCallAudioTest extends BaseTelecomTestWithMockServices {
}
public void testAudioProcessingFromCallScreeningAllowPlaceEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -271,7 +271,7 @@ public class BackgroundCallAudioTest extends BaseTelecomTestWithMockServices {
}
public void testAudioProcessingFromIncomingActivePlaceEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -379,7 +379,7 @@ public class BackgroundCallAudioTest extends BaseTelecomTestWithMockServices {
}
public void testAudioProcessOutgoingActiveEmergencyCallPlaced() throws Exception {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
index 39b8774b8f8..961ebb7a5d0 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
@@ -218,7 +218,7 @@ public class CallRedirectionServiceTest extends BaseTelecomTestWithMockServices
}
public void testCantRedirectEmergencyCall() throws Exception {
- if (!shouldTestTelecom(mContext)) {
+ if (!shouldTestTelecom(mContext) || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
Bundle extras = new Bundle();
diff --git a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
index 117ab1a16a3..1eaf6e33e68 100644
--- a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
+++ b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
@@ -56,7 +56,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
// Sets up this package as default dialer in super.
super.setUp();
NewOutgoingCallBroadcastReceiver.reset();
- if (!mShouldTestTelecom) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
TestUtils.executeShellCommand(getInstrumentation(),
@@ -93,7 +93,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
* invocations to induce the failure method.
*/
public void testEmergencyCallFailureDueToInvalidPhoneAccounts() throws Exception {
- if (!mShouldTestTelecom) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
// needed in order to call mTelecomManager.getPhoneAccountsForPackage()
InstrumentationRegistry.getInstrumentation().getUiAutomation()
@@ -135,7 +135,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
* Place an outgoing emergency call and ensure it is started successfully.
*/
public void testStartEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
Connection conn = placeAndVerifyEmergencyCall(true /*supportsHold*/);
Call eCall = getInCallService().getLastCall();
assertCallState(eCall, Call.STATE_DIALING);
@@ -187,7 +187,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
* Place an outgoing emergency call fail it to trigger persisting of diagnostic data
*/
public void testEmergencyCallFailureCreatesDropboxEntries() throws Exception {
- if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
long startTime = System.currentTimeMillis()
- DAYS_BACK_TO_SEARCH_EMERGENCY_DROP_BOX_ENTRIES_IN_MS;
mContext.registerReceiver(new BroadcastReceiver() {
@@ -235,7 +235,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
* will automatically be rejected as well.
*/
public void testOngoingEmergencyCallAndReceiveIncomingCall() throws Exception {
- if (!mShouldTestTelecom) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
Connection eConnection = placeAndVerifyEmergencyCall(true /*supportsHold*/);
assertIsInCall(true);
@@ -259,7 +259,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
* rejected and logged as a new missed call.
*/
public void testIncomingRingingCallAndPlaceEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
Uri normalCallNumber = createRandomTestNumber();
addAndVerifyNewIncomingCall(normalCallNumber, null);
@@ -294,7 +294,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
* as a new missed call.
*/
public void testActiveCallAndIncomingRingingCallAndPlaceEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
Uri normalOutgoingCallNumber = createRandomTestNumber();
Bundle extras = new Bundle();
@@ -331,7 +331,7 @@ public class EmergencyCallTests extends BaseTelecomTestWithMockServices {
}
public void testEmergencyCallAndNoAdditionalCallPermitted() throws Exception {
- if (!mShouldTestTelecom) return;
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) return;
Connection eConnection = placeAndVerifyEmergencyCall(true);
Call eCall = getInCallService().getLastCall();
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index 4890bdf6a4a..1e2f40bb4ca 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -863,7 +863,7 @@ public class ExtendedInCallServiceTest extends BaseTelecomTestWithMockServices {
}
public void testOnCannedTextResponsesLoaded() {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java b/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java
index 57ec66c1baf..ec68a42f6d1 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java
@@ -118,7 +118,7 @@ public class ExternalCallTest extends BaseTelecomTestWithMockServices {
* CAPABILITY_CAN_PLACE_CALL capability is removed.
*/
public void testPullCallCapabilityRemovedInEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -140,7 +140,7 @@ public class ExternalCallTest extends BaseTelecomTestWithMockServices {
* ongoing emergency call, the request is not completed.
*/
public void testTryToPullCallWhileInEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -166,7 +166,7 @@ public class ExternalCallTest extends BaseTelecomTestWithMockServices {
* test to check external call and pull external call with call and connection states check
*/
public void testExternalCallAndPullCall() throws Exception {
- if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/NonUiInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/NonUiInCallServiceTest.java
index d4096aa5555..11780a13ff4 100644
--- a/tests/tests/telecom/src/android/telecom/cts/NonUiInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/NonUiInCallServiceTest.java
@@ -19,6 +19,7 @@ import android.util.Log;
import android.util.Pair;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import java.util.Arrays;
@@ -99,6 +100,7 @@ public class NonUiInCallServiceTest extends BaseTelecomTestWithMockServices {
* enablement.
* @throws Exception
*/
+ @FlakyTest
public void testMidCallComponentEnablementWithNoneAvailableAtStart() throws Exception {
if (!mShouldTestTelecom) {
return;
diff --git a/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java b/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java
index cb2ecd591ae..7d20eae7356 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java
@@ -151,7 +151,7 @@ public class TelecomManagerTest extends BaseTelecomTestWithMockServices {
}
public void testIsInEmergencyCall_ongoingEmergencyCall() throws Exception {
- if (!mShouldTestTelecom) {
+ if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
return;
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/TransactionalApisTest.java b/tests/tests/telecom/src/android/telecom/cts/TransactionalApisTest.java
index 356552230c8..92581c501ab 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TransactionalApisTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TransactionalApisTest.java
@@ -49,6 +49,7 @@ import android.util.Log;
import android.util.Pair;
import androidx.annotation.NonNull;
+import androidx.test.filters.FlakyTest;
import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CddTest;
@@ -796,6 +797,7 @@ public class TransactionalApisTest extends BaseTelecomTestWithMockServices {
@ApiTest(apis = {"android.telecom.TelecomManager#addCall",
"android.telecom.CallControl#disconnect",
"android.telecom.CallEventCallback#onCallEndpointChanged"})
+ @FlakyTest
public void testOnChangedCallEndpoint() {
if (!mShouldTestTelecom) {
return;
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java b/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java
index ca0cee2272a..b63e1de5378 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java
@@ -34,6 +34,15 @@ public class AsyncSmsMessageListener {
new LinkedBlockingQueue<>(1);
/**
+ * Clear internal cache data.
+ */
+ public void clear() {
+ mMessages.clear();
+ mSentMessageResults.clear();
+ mDeliveredMessageResults.clear();
+ }
+
+ /**
* Offer a SMS message to the queue of SMS messages waiting to be processed.
*/
public void offerSmsMessage(String smsMessage) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
index 24805d6b6c9..16bb603c654 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
@@ -140,6 +140,10 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("br", "2654", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("br", "2652", SMS_CATEGORY_FREE_SHORT_CODE),
+ new ShortCodeTest("bw", "166416", SMS_CATEGORY_NOT_SHORT_CODE),
+ new ShortCodeTest("bw", "16649", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("bw", "16641", SMS_CATEGORY_FREE_SHORT_CODE),
+
new ShortCodeTest("by", "112", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("by", "1234", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("by", "3336", SMS_CATEGORY_PREMIUM_SHORT_CODE),
@@ -222,6 +226,7 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("do", "9128922", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("do", "912898", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("do", "912892", SMS_CATEGORY_FREE_SHORT_CODE),
+ new ShortCodeTest("do", "912", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("ec", "4664534", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("ec", "466499", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
@@ -288,9 +293,10 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("ge", "95208", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("ge", "952014", SMS_CATEGORY_NOT_SHORT_CODE),
- new ShortCodeTest("gh", "377789", SMS_CATEGORY_NOT_SHORT_CODE),
+ new ShortCodeTest("gh", "37778", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("gh", "3775", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("gh", "3777", SMS_CATEGORY_FREE_SHORT_CODE),
+ new ShortCodeTest("gh", "2333", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("gr", "112", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("gr", "116117", SMS_CATEGORY_FREE_SHORT_CODE),
@@ -390,6 +396,7 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("kw", "509761", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("kw", "50979", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("kw", "50976", SMS_CATEGORY_FREE_SHORT_CODE),
+ new ShortCodeTest("kw", "7112", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("id", "992626", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("id", "99268", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
@@ -440,6 +447,7 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("mx", "30303025", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("mx", "3030302", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("mx", "3030303", SMS_CATEGORY_FREE_SHORT_CODE),
+ new ShortCodeTest("mx", "81811", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("mw", "427611", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("mw", "4279", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
@@ -495,7 +503,8 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("pk", "90958", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("pk", "9092", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("pk", "909203", SMS_CATEGORY_FREE_SHORT_CODE),
- new ShortCodeTest("pk", "909201", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("pk", "909219", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("pk", "909201", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("pl", "112", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("pl", "116117", SMS_CATEGORY_FREE_SHORT_CODE),
@@ -634,9 +643,11 @@ public class SmsUsageMonitorShortCodeTest {
new ShortCodeTest("uy", "191238", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("uy", "191289", SMS_CATEGORY_FREE_SHORT_CODE),
- new ShortCodeTest("vn", "807982", SMS_CATEGORY_NOT_SHORT_CODE),
- new ShortCodeTest("vn", "8078", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("vn", "8079", SMS_CATEGORY_FREE_SHORT_CODE),
+ new ShortCodeTest("vn", "90002", SMS_CATEGORY_FREE_SHORT_CODE),
+ new ShortCodeTest("vn", "1189892", SMS_CATEGORY_NOT_SHORT_CODE),
+ new ShortCodeTest("vn", "118998", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("vn", "118989", SMS_CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("ve", "5383526", SMS_CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("ve", "538358", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
diff --git a/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java b/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
index eed8158a66b..0f359d90835 100644
--- a/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
@@ -29,6 +29,7 @@ import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.FileServiceInfo;
import android.telephony.mbms.MbmsErrors;
+import org.junit.Ignore;
import org.junit.Test;
import java.io.File;
@@ -49,6 +50,7 @@ public class MbmsDownloadSessionTest extends MbmsDownloadTestBase {
}
}
+ @Ignore
@Test
public void testRequestUpdateDownloadServices() throws Exception {
List<String> testClasses = Arrays.asList("class1", "class2");
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/CallDomainSelectionTestOnMockModem.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/CallDomainSelectionTestOnMockModem.java
index 19fb54c187d..33bf1f16619 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/CallDomainSelectionTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/CallDomainSelectionTestOnMockModem.java
@@ -957,86 +957,57 @@ public class CallDomainSelectionTestOnMockModem extends ImsCallingBase {
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING,
getRegState(Domain.CS, subId));
- // Register call state change callback
- mCallState = TelephonyManager.CALL_STATE_IDLE;
- sCallStateChangeCallbackHandler.post(
- () -> {
- sCallStateCallback = new CallStateListener();
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- sTelephonyManager,
- (tm) ->
- tm.registerTelephonyCallback(
- mCallStateChangeExecutor, sCallStateCallback));
- });
-
// place first call
placeOutgoingCall(TEST_DIAL_NUMBER);
TimeUnit.SECONDS.sleep(1);
- // Verify call state
- synchronized (mCallStateChangeLock) {
- if (mCallState == TelephonyManager.CALL_STATE_IDLE) {
- Log.d(TAG, "Wait for call state change to offhook");
- mCallStateChangeLock.wait(WAIT_UPDATE_TIMEOUT_MS);
- }
- assertEquals(TelephonyManager.CALL_STATE_OFFHOOK, mCallState);
- }
Call call1 = getCall(mCurrentCallId);
+ // IMS call1
assertTrue(isPsDialing());
+ TestImsCallSessionImpl callSession1 =
+ sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
+
// place second call
placeOutgoingCall(TEST_DIAL_NUMBER + 1);
TimeUnit.SECONDS.sleep(1);
- // call1 on hold
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
- assertEquals("Call is not on Hold", Call.STATE_HOLDING, call1.getDetails().getState());
Call call2 = getCall(mCurrentCallId);
+
+ // IMS call2
assertTrue(isPsDialing());
+ TestImsCallSessionImpl callSession2 =
+ sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
+
+ // call2 should be IMS and active
+ isCallActive(call2, callSession2);
+ // IMS call1 on hold
+ isCallHolding(call1, callSession1);
+
// Swap the call
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
call1.unhold();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
- assertEquals("Call2 is not on Hold", Call.STATE_HOLDING, call2.getDetails().getState());
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_ACTIVE, WAIT_FOR_CALL_STATE));
- assertEquals("Call1 is not Active", Call.STATE_ACTIVE, call1.getDetails().getState());
+ // call1 should be IMS and active
+ isCallActive(call1, callSession1);
+ // IMS call2 on hold
+ isCallHolding(call2, callSession2);
- // After successful call swap disconnect the call
+ // disconnect call1
call1.disconnect();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTED, WAIT_FOR_CALL_STATE));
- assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
+ // IMS call1 disconnected
+ isCallDisconnected(call1, callSession1);
- // Wait till second call is in active state
- waitUntilConditionIsTrueOrTimeout(
- new Condition() {
- @Override
- public Object expected() {
- return true;
- }
+ // call2 should be IMS and active
+ isCallActive(call2, callSession2);
- @Override
- public Object actual() {
- return call2.getDetails().getState() == Call.STATE_ACTIVE;
- }
- },
- WAIT_FOR_CALL_STATE_ACTIVE,
- "Call in Active State");
-
- // Call 2 is active
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_ACTIVE, WAIT_FOR_CALL_STATE));
-
- // disconnect call 2
+ // disconnect call2
call2.disconnect();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTED, WAIT_FOR_CALL_STATE));
+ // IMS call2 disconnected
+ isCallDisconnected(call2, callSession2);
- // Unregister call state change callback
- sTelephonyManager.unregisterTelephonyCallback(sCallStateCallback);
- sCallStateCallback = null;
waitForUnboundService();
}
@@ -1061,18 +1032,6 @@ public class CallDomainSelectionTestOnMockModem extends ImsCallingBase {
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING,
getRegState(Domain.CS, subId));
- // Register call state change callback
- mCallState = TelephonyManager.CALL_STATE_IDLE;
- sCallStateChangeCallbackHandler.post(
- () -> {
- sCallStateCallback = new CallStateListener();
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- sTelephonyManager,
- (tm) ->
- tm.registerTelephonyCallback(
- mCallStateChangeExecutor, sCallStateCallback));
- });
-
Bundle extras = new Bundle();
extras.putBoolean("android.telephony.ims.feature.extra.IS_USSD", false);
extras.putBoolean("android.telephony.ims.feature.extra.IS_UNKNOWN_CALL", false);
@@ -1091,37 +1050,33 @@ public class CallDomainSelectionTestOnMockModem extends ImsCallingBase {
}
}
+ TestImsCallSessionImpl mtCallSession =
+ sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
+
+ // IMS MT call active
+ isCallActive(mtCall, mtCallSession);
+
// Place outgoing call
placeOutgoingCall(TEST_DIAL_NUMBER);
+
+ // IMS MO Call active
assertTrue(isPsDialing());
Call moCall = getCall(mCurrentCallId);
- // Register call state change callback
- // Verify call state change
- synchronized (mCallStateChangeLock) {
- Log.d(TAG, "Wait for call state change");
- mCallStateChangeLock.wait(WAIT_UPDATE_TIMEOUT_MS);
- moCall.answer(0);
- }
-
- assertEquals("MO call is not Active ", Call.STATE_ACTIVE, moCall.getDetails().getState());
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
- assertEquals("MT call is not on Hold ", Call.STATE_HOLDING, mtCall.getDetails().getState());
+ // IMS MT call on hold
+ isCallHolding(mtCall, mtCallSession);
+ // disconnect MO call
moCall.disconnect();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
- assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
- // mtCall should activate
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_ACTIVE, WAIT_FOR_CALL_STATE));
- assertEquals("MT call is not Active ", Call.STATE_ACTIVE, mtCall.getDetails().getState());
+ // IMS MT call active
+ isCallActive(mtCall, mtCallSession);
+ // disconenct MT call
mtCall.disconnect();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
+ //IMS MT call disconnected
+ isCallDisconnected(mtCall, mtCallSession);
- // Unregister call state change callback
- sTelephonyManager.unregisterTelephonyCallback(sCallStateCallback);
- sCallStateCallback = null;
waitForUnboundService();
}
@@ -1144,86 +1099,55 @@ public class CallDomainSelectionTestOnMockModem extends ImsCallingBase {
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING,
getRegState(Domain.CS, subId));
- // Register call state change callback
- mCallState = TelephonyManager.CALL_STATE_IDLE;
- sCallStateChangeCallbackHandler.post(
- () -> {
- sCallStateCallback = new CallStateListener();
- ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
- sTelephonyManager,
- (tm) ->
- tm.registerTelephonyCallback(
- mCallStateChangeExecutor, sCallStateCallback));
- });
-
// place first call
placeOutgoingCall(TEST_DIAL_NUMBER);
TimeUnit.SECONDS.sleep(1);
- // Verify call state
- synchronized (mCallStateChangeLock) {
- if (mCallState == TelephonyManager.CALL_STATE_IDLE) {
- Log.d(TAG, "Wait for call state change to offhook");
- mCallStateChangeLock.wait(WAIT_UPDATE_TIMEOUT_MS);
- }
- assertEquals(TelephonyManager.CALL_STATE_OFFHOOK, mCallState);
- }
Call call1 = getCall(mCurrentCallId);
+ // IMS call1 active
assertTrue(isPsDialing());
+ TestImsCallSessionImpl callSession1 =
+ sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
+
// place second call
placeOutgoingCall(TEST_DIAL_NUMBER + 1);
TimeUnit.SECONDS.sleep(1);
- // call1 on hold
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
- assertEquals("Call is not on Hold", Call.STATE_HOLDING, call1.getDetails().getState());
Call call2 = getCall(mCurrentCallId);
+
+ // IMS call2 active
assertTrue(isPsDialing());
+ TestImsCallSessionImpl callSession2 =
+ sServiceConnector.getCarrierService().getMmTelFeature().getImsCallsession();
+
+ // IMS call1 is on hold
+ isCallHolding(call1, callSession1);
+
// Swap the call
ImsUtils.waitInCurrentState(WAIT_IN_CURRENT_STATE);
call1.unhold();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
- assertEquals("Call2 is not on Hold", Call.STATE_HOLDING, call2.getDetails().getState());
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_ACTIVE, WAIT_FOR_CALL_STATE));
- assertEquals("Call1 is not Active", Call.STATE_ACTIVE, call1.getDetails().getState());
+ // IMS call1 is active
+ isCallActive(call1, callSession1);
+ // IMS call2 is on hold
+ isCallHolding(call2, callSession2);
- // After successful call swap disconnect the call
+ // After successful call swap disconnect call1
call1.disconnect();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTED, WAIT_FOR_CALL_STATE));
- assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
-
- // Wait till second call is in active state
- waitUntilConditionIsTrueOrTimeout(
- new Condition() {
- @Override
- public Object expected() {
- return true;
- }
+ // IMS call1 disconnected
+ isCallDisconnected(call1, callSession1);
- @Override
- public Object actual() {
- return call2.getDetails().getState() == Call.STATE_ACTIVE;
- }
- },
- WAIT_FOR_CALL_STATE_ACTIVE,
- "Call in Active State");
-
- // Call 2 is active
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_ACTIVE, WAIT_FOR_CALL_STATE));
+ // IMS call2 is active
+ isCallActive(call2, callSession2);
- // disconnect call 2
+ // disconnect call2
call2.disconnect();
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
- assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTED, WAIT_FOR_CALL_STATE));
+ // IMS call2 disconnected
+ isCallDisconnected(call2, callSession2);
- // Unregister call state change callback
- sTelephonyManager.unregisterTelephonyCallback(sCallStateCallback);
- sCallStateCallback = null;
waitForUnboundService();
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index a723a7fa8d4..0abdfd98c39 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -993,6 +993,9 @@ public class ImsServiceTest {
SmsManager.getSmsManagerForSubscriptionId(sTestSub)
.setStorageMonitorMemoryStatusOverride(false);
+ // Clear cached data before starting test.
+ AsyncSmsMessageListener.getInstance().clear();
+
//Message received
sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
.receiveSmsWaitForAcknowledgeMemoryFull(123456789, SmsMessage.FORMAT_3GPP,
@@ -1021,6 +1024,9 @@ public class ImsServiceTest {
}
setupImsServiceForSms();
+ // Clear cached data before starting test.
+ AsyncSmsMessageListener.getInstance().clear();
+
// Message received
sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
.receiveSmsWaitForAcknowledge(123456789, SmsMessage.FORMAT_3GPP,
@@ -1047,6 +1053,9 @@ public class ImsServiceTest {
setupImsServiceForSms();
+ // Clear cached data before starting test.
+ AsyncSmsMessageListener.getInstance().clear();
+
// Message received
sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
.receiveSmsWaitForAcknowledge(123456789, SmsMessage.FORMAT_3GPP,
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
index 4100d40be94..213415ce802 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
@@ -450,9 +450,9 @@ public class TvViewTest extends ActivityInstrumentationTestCase2<TvViewStubActiv
assertTrue(mTvView.isFocused());
verifyKeyEvent(
- new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BUTTON_16), unhandledEvent);
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0), unhandledEvent);
verifyKeyEvent(
- new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BUTTON_16), unhandledEvent);
+ new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0), unhandledEvent);
}
public void testConnectionFailed() throws Throwable {
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
index 6ed80ce9ae8..a2684388382 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
@@ -62,7 +62,7 @@ public class SharedFilterTestService extends Service {
mTuner, getExecutor(), getFilterCallback());
// Open dvr playback as data source
- mDvrPlayback = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+ mDvrPlayback = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
return mFilter.acquireSharedFilterToken();
}
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java
index e7145088bb3..93cdf000e15 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java
@@ -69,6 +69,9 @@ public class TunerResourceTestService extends Service {
mFeInfo = infos.get(frontendIndex);
mFeSettings = TunerTest.createFrontendSettings(mFeInfo);
+ // apply target frontend only, for case when there are multiple instances in frontend type
+ mTuner.applyFrontend(mFeInfo);
+
// tune
return mTuner.tune(mFeSettings);
}
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
index 16b3be390b8..0d07786977f 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
import android.content.ComponentName;
import android.content.Context;
@@ -1111,7 +1112,8 @@ public class TunerTest {
return;
}
- assertEquals(lnb.setVoltage(Lnb.VOLTAGE_5V), Tuner.RESULT_SUCCESS);
+ int targetLnbVoltage = getTargetLnbVoltage();
+ assertEquals(lnb.setVoltage(targetLnbVoltage), Tuner.RESULT_SUCCESS);
assertEquals(lnb.setTone(Lnb.TONE_NONE), Tuner.RESULT_SUCCESS);
assertEquals(
lnb.setSatellitePosition(Lnb.POSITION_A), Tuner.RESULT_SUCCESS);
@@ -1597,14 +1599,14 @@ public class TunerTest {
@Test
public void testOpenDvrRecorder() throws Exception {
- DvrRecorder d = mTuner.openDvrRecorder(100, getExecutor(), getRecordListener());
+ DvrRecorder d = mTuner.openDvrRecorder(188, getExecutor(), getRecordListener());
assertNotNull(d);
d.close();
}
@Test
public void testOpenDvPlayback() throws Exception {
- DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+ DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
assertNotNull(d);
d.close();
}
@@ -1662,17 +1664,17 @@ public class TunerTest {
assertFalse(ids.isEmpty());
int targetFrontendId = sTunerCtsConfiguration.getTargetFrontendId().intValueExact();
FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
- FrontendSettings feSettings = createFrontendSettings(info);
- // first tune with mTuner to acquire resource
- int res = mTuner.tune(feSettings);
+ // first apply frontend with mTuner to acquire resource
+ int res = mTuner.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
assertNotNull(mTuner.getFrontendInfo());
- // now tune with a higher priority tuner to have mTuner's resource reclaimed
+ // now apply frontend with a higher priority tuner to have mTuner's resource reclaimed
Tuner higherPrioTuner = new Tuner(mContext, null, 200);
- res = higherPrioTuner.tune(feSettings);
+ res = higherPrioTuner.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
+
assertNotNull(higherPrioTuner.getFrontendInfo());
higherPrioTuner.close();
@@ -1688,8 +1690,8 @@ public class TunerTest {
FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
FrontendSettings feSettings = createFrontendSettings(info);
- // first tune with mTuner to acquire resource
- int res = mTuner.tune(feSettings);
+ // first apply frontend with mTuner to acquire resource
+ int res = mTuner.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
assertNotNull(mTuner.getFrontendInfo());
@@ -1749,9 +1751,11 @@ public class TunerTest {
tunerResourceTestServer = connection.getService();
// CASE1 - normal reclaim
- //
- // first tune with mTuner to acquire resource
- int res = mTuner.tune(feSettings);
+
+ // first apply frontend with mTuner to acquire resource
+ int res = mTuner.applyFrontend(info);
+ assertEquals(Tuner.RESULT_SUCCESS, res);
+
boolean tunerReclaimed = false;
assertEquals(Tuner.RESULT_SUCCESS, res);
assertNotNull(mTuner.getFrontendInfo());
@@ -1827,27 +1831,27 @@ public class TunerTest {
@Test
public void testShareFrontendFromTuner() throws Exception {
- Tuner tuner100 = new Tuner(mContext, null, 100);
- List<Integer> ids = tuner100.getFrontendIds();
+ List<Integer> ids = mTuner.getFrontendIds();
assumeNotNull(ids);
assertFalse(ids.isEmpty());
int targetFrontendId = sTunerCtsConfiguration.getTargetFrontendId().intValueExact();
- FrontendInfo info = tuner100.getFrontendInfoById(ids.get(targetFrontendId));
+ FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
FrontendSettings feSettings = createFrontendSettings(info);
+
int[] statusTypes = {1};
- boolean exceptionThrown = false;
- int res;
+ boolean exceptionThrown;
- // CASE1: check resource reclaim while sharee's priority < owner's priority
- // let tuner100 share from tuner200
+ Tuner tuner100 = new Tuner(mContext, null, 100);
Tuner tuner200 = new Tuner(mContext, null, 200);
- res = tuner200.tune(feSettings);
- assertEquals(Tuner.RESULT_SUCCESS, res);
+ Tuner tuner300 = new Tuner(mContext, null, 300);
- info = tuner200.getFrontendInfoById(ids.get(targetFrontendId));
- res = tuner200.tune(feSettings);
+ // CASE1: check resource reclaim while sharee's priority < owner's priority
+
+ // apply target frontend only, for case when there are multiple instances in frontend type
+ int res = tuner200.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
+ // let tuner100 share from tuner200
tuner100.shareFrontendFromTuner(tuner200);
// call openFilter to trigger ITunerDemux.setFrontendDataSourceById()
Filter f = tuner100.openFilter(
@@ -1859,7 +1863,6 @@ public class TunerTest {
TunerTestOnTuneEventListener cb200 = new TunerTestOnTuneEventListener();
// tune again on the owner
- info = tuner200.getFrontendInfoById(ids.get(1));
tuner100.setOnTuneEventListener(getExecutor(), cb100);
tuner200.setOnTuneEventListener(getExecutor(), cb200);
res = tuner200.tune(feSettings);
@@ -1870,8 +1873,7 @@ public class TunerTest {
tuner200.clearOnTuneEventListener();
// now let the higher priority tuner steal the resource
- Tuner tuner300 = new Tuner(mContext, null, 300);
- res = tuner300.tune(feSettings);
+ res = tuner300.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
// confirm owner & sharee's resource gets reclaimed by confirming an exception is thrown
@@ -1898,7 +1900,9 @@ public class TunerTest {
// CASE2: check resource reclaim fail when sharee's priority > new requester
tuner100 = new Tuner(mContext, null, 100);
- res = tuner100.tune(feSettings);
+
+ // apply target frontend only, for case when there are multiple instances in frontend type
+ res = tuner100.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
tuner300 = new Tuner(mContext, null, 300);
@@ -1908,7 +1912,9 @@ public class TunerTest {
assertNotNull(f);
tuner200 = new Tuner(mContext, null, 200);
- res = tuner200.tune(feSettings);
+
+ // apply target frontend only, for case when there are multiple instances in frontend type
+ res = tuner200.applyFrontend(info);
assertNotEquals(Tuner.RESULT_SUCCESS, res);
// confirm the original tuner is still intact
@@ -1926,19 +1932,21 @@ public class TunerTest {
assertFalse(ids.isEmpty());
int targetFrontendId = sTunerCtsConfiguration.getTargetFrontendId().intValueExact();
FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
- FrontendSettings feSettings = createFrontendSettings(info);
+ createFrontendSettings(info);
// SCENARIO 1 - transfer and close the previous owner
- // First create a tuner and tune() to acquire frontend resource
+ // First create a tuner and applyFrontend() to acquire frontend resource
Tuner tunerA = new Tuner(mContext, null, 100);
- int res = tunerA.tune(feSettings);
+
+ // apply target frontend only, for case when there are multiple instances in frontend type
+ int res = tunerA.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
// Create another tuner and share frontend from tunerA
Tuner tunerB = new Tuner(mContext, null, 500);
tunerB.shareFrontendFromTuner(tunerA);
- DvrRecorder d = tunerB.openDvrRecorder(100, getExecutor(), getRecordListener());
+ DvrRecorder d = tunerB.openDvrRecorder(188, getExecutor(), getRecordListener());
assertNotNull(d);
// Call transferOwner in the wrong configurations and confirm it fails
@@ -1962,9 +1970,11 @@ public class TunerTest {
// SCENARIO 2 - transfer and closeFrontend and tune on the previous owner
- // First create a tuner and tune() to acquire frontend resource
+ // First create a tuner and applyFrontend() to acquire frontend resource
tunerA = new Tuner(mContext, null, 200);
- res = tunerA.tune(feSettings);
+
+ // apply target frontend only, for case when there are multiple instances in frontend type
+ res = tunerA.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
// Create another tuner and share frontend from tunerA
@@ -1981,7 +1991,9 @@ public class TunerTest {
// Confirm tune works without going through Tuner.close() even after transferOwner()
// The purpose isn't to get tunerB's frontend revoked, but doing so as singletuner
// based test has wider coverage
- res = tunerA.tune(feSettings); // this should reclaim tunerB
+
+ // apply target frontend only, for case when there are multiple instances in frontend type
+ res = tunerA.applyFrontend(info);
assertEquals(Tuner.RESULT_SUCCESS, res);
// Confirm tuberB is revoked
@@ -2071,8 +2083,9 @@ public class TunerTest {
// Open Lnb and check the callback
TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback();
Lnb lnbA = tunerA.openLnb(getExecutor(), lnbCB1);
- assertNotNull(lnbA);
- lnbA.setVoltage(Lnb.VOLTAGE_5V);
+ assumeTrue(lnbA != null);
+ int targetLnbVoltage = getTargetLnbVoltage();
+ lnbA.setVoltage(targetLnbVoltage);
lnbA.setTone(Lnb.TONE_CONTINUOUS);
lnbA.sendDiseqcMessage(new byte[] {1, 2});
assertTrue(lnbCB1.getOnDiseqcMessageCalled());
@@ -2706,7 +2719,7 @@ public class TunerTest {
assertTrue(token2 == null);
// Use DvrPlayback as data source
- DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+ DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
assertNotNull(d);
Settings settings = SectionSettingsWithTableInfo
@@ -2848,7 +2861,7 @@ public class TunerTest {
assertTrue(token != null);
// Use DvrPlayer as data source
- DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+ DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
assertNotNull(d);
assertTrue(mSharedFilterTestServer.verifySharedFilter(token));
@@ -2887,7 +2900,7 @@ public class TunerTest {
f.configure(config);
- DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+ DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
assertNotNull(d);
d.configure(getDvrSettings());
@@ -2937,29 +2950,33 @@ public class TunerTest {
int type = mTuner.getFrontendInfoById(ids.get(i)).getType();
if (TunerVersionChecker.isHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_2_0)) {
- int defaultMax = -1;
+ int defaultMax = mTuner.getMaxNumberOfFrontends(type);
int status;
- // Check default value
- defaultMax = mTuner.getMaxNumberOfFrontends(type);
- assertTrue(defaultMax > 0);
- // Set to -1
- status = mTuner.setMaxNumberOfFrontends(type, -1);
- assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
- // Set to defaultMax + 1
- status = mTuner.setMaxNumberOfFrontends(type, defaultMax + 1);
- assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
- // Set to 0
- status = mTuner.setMaxNumberOfFrontends(type, 0);
- assertEquals(Tuner.RESULT_SUCCESS, status);
- // Check after set
- int currentMax = -1;
- currentMax = mTuner.getMaxNumberOfFrontends(type);
- assertEquals(currentMax, 0);
- // Reset to default
- status = mTuner.setMaxNumberOfFrontends(type, defaultMax);
- assertEquals(Tuner.RESULT_SUCCESS, status);
- currentMax = mTuner.getMaxNumberOfFrontends(type);
- assertEquals(defaultMax, currentMax);
+ // Use try block to ensure restoring the max Tuner
+ try {
+ // Check default value
+ assertTrue(defaultMax > 0);
+ // Set to -1
+ status = mTuner.setMaxNumberOfFrontends(type, -1);
+ assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
+ // Set to defaultMax + 1
+ status = mTuner.setMaxNumberOfFrontends(type, defaultMax + 1);
+ assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
+ // Set to 0
+ status = mTuner.setMaxNumberOfFrontends(type, 0);
+ assertEquals(Tuner.RESULT_SUCCESS, status);
+ // Check after set
+ int currentMax = mTuner.getMaxNumberOfFrontends(type);
+ assertEquals(currentMax, 0);
+ } catch (Exception e) {
+ throw (e);
+ } finally {
+ // Reset to default
+ status = mTuner.setMaxNumberOfFrontends(type, defaultMax);
+ assertEquals(Tuner.RESULT_SUCCESS, status);
+ int currentMax = mTuner.getMaxNumberOfFrontends(type);
+ assertEquals(defaultMax, currentMax);
+ }
} else {
int defaultMax = mTuner.getMaxNumberOfFrontends(type);
assertEquals(defaultMax, -1);
@@ -2979,45 +2996,64 @@ public class TunerTest {
assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1));
assertNotNull(mTuner.getFrontendInfo());
- // validate that set max cannot be set to lower value than current usage
- assertEquals(Tuner.RESULT_INVALID_ARGUMENT,
+ // Use try block to ensure restoring the max Tuner
+ try {
+ // validate that set max cannot be set to lower value than current usage
+ assertEquals(Tuner.RESULT_INVALID_ARGUMENT,
mTuner.setMaxNumberOfFrontends(type1, 0));
- // validate max value is reflected in the tune behavior
- mTuner.closeFrontend();
- assertEquals(Tuner.RESULT_SUCCESS,
+ // validate max value is reflected in the tune behavior
+ mTuner.closeFrontend();
+ assertEquals(Tuner.RESULT_SUCCESS,
mTuner.setMaxNumberOfFrontends(type1, 0));
- assertEquals(Tuner.RESULT_UNAVAILABLE,
+ assertEquals(Tuner.RESULT_UNAVAILABLE,
mTuner.tune(feSettings1));
- assertEquals(Tuner.RESULT_SUCCESS,
+ assertEquals(Tuner.RESULT_SUCCESS,
mTuner.setMaxNumberOfFrontends(type1, originalMax1));
- assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1));
- assertNotNull(mTuner.getFrontendInfo());
- mTuner.closeFrontend();
+ assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1));
+ assertNotNull(mTuner.getFrontendInfo());
+ mTuner.closeFrontend();
+ } catch (Exception e) {
+ throw(e);
+ } finally {
+ assertEquals(Tuner.RESULT_SUCCESS,
+ mTuner.setMaxNumberOfFrontends(type1, originalMax1));
+ }
}
// validate max number on one frontend type has no impact on other
if (ids.size() >= 2) {
- FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(1));
- int type2 = info2.getType();
- int originalMax2 = mTuner.getMaxNumberOfFrontends(type2);
-
- assertEquals(Tuner.RESULT_SUCCESS,
- mTuner.setMaxNumberOfFrontends(type2, 0));
- assertEquals(Tuner.RESULT_SUCCESS,
- mTuner.tune(feSettings1));
- assertNotNull(mTuner.getFrontendInfo());
-
- // set it back to the original max
- assertEquals(Tuner.RESULT_SUCCESS,
- mTuner.setMaxNumberOfFrontends(type2, originalMax2));
- mTuner.closeFrontend();
+ int type2 = type1;
+ for (int i = 0; i < ids.size(); i++) {
+ FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(i));
+ type2 = info2.getType();
+ if (type1 != type2) break;
+ }
+ if (type1 != type2) {
+ int originalMax2 = mTuner.getMaxNumberOfFrontends(type2);
+ // Use try block to ensure restoring the max Tuner
+ try {
+ assertEquals(Tuner.RESULT_SUCCESS,
+ mTuner.setMaxNumberOfFrontends(type2, 0));
+ assertEquals(Tuner.RESULT_SUCCESS,
+ mTuner.tune(feSettings1));
+ assertNotNull(mTuner.getFrontendInfo());
+ mTuner.closeFrontend();
+ } catch (Exception e) {
+ throw (e);
+ } finally {
+ // set it back to the original max
+ assertEquals(Tuner.RESULT_SUCCESS,
+ mTuner.setMaxNumberOfFrontends(type2, originalMax2));
+ }
+ }
}
}
}
+
public static Filter createTsSectionFilter(
Tuner tuner, Executor e, FilterCallback cb) {
Filter f = tuner.openFilter(Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, e, cb);
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
index a1e5c351d81..7d13fea0b2c 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -16,6 +16,8 @@
package android.net.vcn.cts;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION;
import static android.ipsec.ike.cts.IkeTunUtils.PortPair;
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS;
import static android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT;
@@ -36,22 +38,22 @@ import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
-import static android.net.vcn.cts.VcnSystemRequirementsTest.assumeNotNullVcnDependencies;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.TestUtils.waitUntil;
import static com.android.internal.util.HexDump.hexStringToByteArray;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -119,6 +121,8 @@ public class VcnManagerTest extends VcnTestBase {
private static final int TIMEOUT_MS = 500;
private static final long SAFEMODE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(35);
+ private static final int ACTIVE_SUB_ID_TIMEOUT_SECONDS = 60;
+
private static final Executor INLINE_EXECUTOR = Runnable::run;
private static final int TEST_NETWORK_MTU = 1500;
@@ -154,14 +158,29 @@ public class VcnManagerTest extends VcnTestBase {
@Before
public void setUp() throws Exception {
- // This test assumes the device supports VCN and its dependent system services. Refer to
- // VcnSystemRequirementsTest for comprehensive verification of VCN system requirements.
- assumeNotNullVcnDependencies(mContext);
- assumeNotNull(mVcnManager);
+ final boolean hasFeatureTelephony =
+ mContext.getPackageManager().hasSystemFeature(FEATURE_TELEPHONY);
+ final boolean hasFeatureTelSubscription =
+ mContext.getPackageManager().hasSystemFeature(FEATURE_TELEPHONY_SUBSCRIPTION);
+ final boolean hasTelephonyFlag = hasFeatureTelephony || hasFeatureTelSubscription;
+
+ // Before V, only devices with FEATURE_TELEPHONY are required to run the tests. Starting
+ // from V, tests are also required on following cases:
+ //
+ // Device that has a non-null VcnManager even if it has neither of FEATURE_TELEPHONY or
+ // FEATURE_TELEPHONY_SUBSCRIPTION.
+ //
+ // Device that has FEATURE_TELEPHONY_SUBSCRIPTION. This should not be a new requirement
+ // since before V devices with FEATURE_TELEPHONY_SUBSCRIPTION are already enforced to have
+ // FEATURE_TELEPHONY.
+ assumeTrue(hasTelephonyFlag || mVcnManager != null);
+
getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
// Ensure Internet probing check will be performed on VCN networks
setCaptivePortalMode(mContext, CAPTIVE_PORTAL_MODE_PROMPT);
+
+ runShellCommand("cmd connectivity airplane-mode disable");
}
@After
@@ -195,13 +214,17 @@ public class VcnManagerTest extends VcnTestBase {
return buildVcnConfigBase().setIsTestModeProfile().build();
}
- private int verifyAndGetValidDataSubId() {
- final int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
- assertNotEquals(
+ private int verifyAndGetValidDataSubId() throws Exception {
+ // Wait for an active sub ID to mitigate the cuttlefish test issue where the CTS will
+ // start before a valid data subId is ready. In most cases this should return immediately
+ // without needing to wait.
+ waitUntil(
"There must be an active data subscription to complete CTS",
- INVALID_SUBSCRIPTION_ID,
- dataSubId);
- return dataSubId;
+ ACTIVE_SUB_ID_TIMEOUT_SECONDS,
+ () ->
+ SubscriptionManager.getDefaultDataSubscriptionId()
+ != INVALID_SUBSCRIPTION_ID);
+ return SubscriptionManager.getDefaultDataSubscriptionId();
}
@Test(expected = SecurityException.class)
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnSystemRequirementsTest.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnSystemRequirementsTest.java
index 2672b3b82f8..b095d7f674b 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnSystemRequirementsTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnSystemRequirementsTest.java
@@ -57,15 +57,6 @@ public class VcnSystemRequirementsTest {
context.getSystemService(TelephonyManager.class));
}
- // Package private for use in VcnManagerTest
- static void assumeNotNullVcnDependencies(Context context) {
- try {
- assertNotNullVcnDependencies(context);
- } catch (AssertionError e) {
- assumeTrue(e.toString(), false);
- }
- }
-
/**
* This test verifies that devices with vendor API greater than or equal to V, and which support
* FEATURE_TELEPHONY_SUBSCRIPTION, must also implement VCN and its dependent system services.
@@ -80,17 +71,4 @@ public class VcnSystemRequirementsTest {
assertNotNullVcnDependencies(mContext);
assertNotNull("VcnManager must be present on this device", mVcnManager);
}
-
- /**
- * For devices with vendor API lower than V, it is not mandatory to support VCN or VCN's
- * dependent system services. However, if all VCN dependencies are present, the device must
- * support VCN.
- */
- @Test
- public void testVcndDependenciesOnDevicesBeforeV() throws Exception {
- assumeTrue(getVsrApiLevel() < VENDOR_API_FOR_ANDROID_V);
- assumeNotNullVcnDependencies(mContext);
-
- assertNotNull("VcnManager must be present on this device", mVcnManager);
- }
}
diff --git a/tests/tests/view/src/android/view/cts/OWNERS b/tests/tests/view/src/android/view/cts/OWNERS
index fae65c55352..b5449803b17 100644
--- a/tests/tests/view/src/android/view/cts/OWNERS
+++ b/tests/tests/view/src/android/view/cts/OWNERS
@@ -13,3 +13,5 @@ per-file *KeyEvent* = file:platform/frameworks/base:/INPUT_OWNERS
per-file *PointerCapture* = file:platform/frameworks/base:/INPUT_OWNERS
per-file *MotionEvent* = file:platform/frameworks/base:/INPUT_OWNERS
per-file *VelocityTracker* = file:platform/frameworks/base:/INPUT_OWNERS
+
+per-file *NativeHeapLeakDetector* = file:platform/frameworks/base:/INPUT_OWNERS
diff --git a/tests/tests/view/src/android/view/cts/TextureViewTest.java b/tests/tests/view/src/android/view/cts/TextureViewTest.java
index 14b8797975e..99a7b656c78 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewTest.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewTest.java
@@ -23,8 +23,7 @@ import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glEnable;
import static android.opengl.GLES20.glScissor;
import static android.view.WindowInsets.Type.captionBar;
-import static android.view.WindowInsets.Type.navigationBars;
-import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowInsets.Type.systemBars;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -386,11 +385,11 @@ public class TextureViewTest {
mSDRActivityRule, textureView, () -> textureView.getBitmap(textureViewScreenshot));
WindowInsets rootWindowInsets = activity.getWindow().getDecorView().getRootWindowInsets();
- int extraSurfaceTopOffset = rootWindowInsets.getInsets(captionBar()).top;
- // If the caption bar is present, the surface top edge in the screenshot is shifted.
- extraSurfaceTopOffset += rootWindowInsets.getInsets(statusBars()).top;
- int extraSurfaceBottomOffset = rootWindowInsets.getInsets(navigationBars()).bottom;
+ int extraSurfaceTopOffset = rootWindowInsets.getInsets(systemBars()).top;
+ int extraSurfaceRightOffset = rootWindowInsets.getInsets(systemBars()).right;
+ int extraSurfaceBottomOffset = rootWindowInsets.getInsets(systemBars()).bottom;
+ int extraSurfaceLeftOffset = rootWindowInsets.getInsets(systemBars()).left;
// sample 5 pixels on the edge for bitmap comparison.
// TextureView and SurfaceView use different shaders, so compare these two with tolerance.
@@ -400,7 +399,7 @@ public class TextureViewTest {
try {
assertPixelsAreSame(surfaceViewScreenshot.getPixel(width / 2, extraSurfaceTopOffset),
textureViewScreenshot.getPixel(width / 2, 0), threshold);
- assertPixelsAreSame(surfaceViewScreenshot.getPixel(0, height / 2),
+ assertPixelsAreSame(surfaceViewScreenshot.getPixel(extraSurfaceLeftOffset, height / 2),
textureViewScreenshot.getPixel(0, height / 2), threshold);
assertPixelsAreSame(surfaceViewScreenshot.getPixel(width / 2, height / 2),
textureViewScreenshot.getPixel(width / 2, height / 2), threshold);
@@ -410,7 +409,8 @@ public class TextureViewTest {
textureViewScreenshot.getPixel(width / 2,
height - 1),
threshold);
- assertPixelsAreSame(surfaceViewScreenshot.getPixel(width - 1, height / 2),
+ assertPixelsAreSame(
+ surfaceViewScreenshot.getPixel(width - 1 - extraSurfaceRightOffset, height / 2),
textureViewScreenshot.getPixel(width - 1, height / 2), threshold);
} catch (AssertionError err) {
BitmapDumper.dumpBitmap(textureViewScreenshot,
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 7607569e230..f32376d0036 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -4124,24 +4124,29 @@ public class ViewTest {
CtsMouseUtil.obtainMouseEvent(MotionEvent.ACTION_SCROLL, mockView,
mockView.getWidth() - 1, 0);
mInstrumentation.sendPointerSync(event);
+ mInstrumentation.waitForIdleSync();
assertTrue(fitWindowsView.isInTouchMode());
mInstrumentation.sendKeySync(keyEvent);
+ mInstrumentation.waitForIdleSync();
mActivityRule.runOnUiThread(() -> assertFalse(fitWindowsView.isInTouchMode()));
event.setAction(MotionEvent.ACTION_DOWN);
mInstrumentation.sendPointerSync(event);
event.setAction(MotionEvent.ACTION_UP);
mInstrumentation.sendPointerSync(event);
+ mInstrumentation.waitForIdleSync();
assertTrue(fitWindowsView.isInTouchMode());
mInstrumentation.sendKeySync(keyEvent);
+ mInstrumentation.waitForIdleSync();
mActivityRule.runOnUiThread(() -> assertFalse(fitWindowsView.isInTouchMode()));
// Stylus events should trigger touch mode.
event.setAction(MotionEvent.ACTION_DOWN);
event.setSource(InputDevice.SOURCE_STYLUS);
mInstrumentation.sendPointerSync(event);
+ mInstrumentation.waitForIdleSync();
assertTrue(fitWindowsView.isInTouchMode());
}
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index 83f70e0301c..21e156c8d1a 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -1173,26 +1173,30 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
}
boolean wifiEnabled = sWifiManager.isWifiEnabled();
if (wifiEnabled) {
- // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no
- // STA+AP concurrency.
- ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false));
+ // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's
+ // no STA+AP concurrency.
+ ShellIdentityUtils.invokeWithShellPermissions(() ->
+ sWifiManager.setWifiEnabled(false));
PollingCheck.check("Wifi turn off failed!", WIFI_OFF_ON_TIMEOUT_MILLIS,
() -> !sWifiManager.isWifiEnabled());
SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled");
PollingCheck.check("Wifi turn on failed!", WIFI_OFF_ON_TIMEOUT_MILLIS,
() -> sWifiManager.isWifiEnabled());
}
- TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+ runWithScanning(() -> {
+ TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
- // add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization.
- // TODO: remove this sleep as soon as b/124330089 is fixed.
- Log.d(TAG, "Sleeping for 2 seconds");
- Thread.sleep(2000);
+ // add sleep to avoid calling stopLocalOnlyHotspot before TetherController
+ // initialization.
+ // TODO: remove this sleep as soon as b/124330089 is fixed.
+ Log.d(TAG, "Sleeping for 2 seconds");
+ Thread.sleep(2000);
- stopLocalOnlyHotspot(callback, wifiEnabled);
+ stopLocalOnlyHotspot(callback, wifiEnabled);
- // wifi should either stay on, or come back on
- assertEquals(wifiEnabled, sWifiManager.isWifiEnabled());
+ // wifi should either stay on, or come back on
+ assertEquals(wifiEnabled, sWifiManager.isWifiEnabled());
+ }, false);
}
/**
@@ -1952,13 +1956,12 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
// check that softap mode is supported by the device
assumeTrue(sWifiManager.isPortableHotspotSupported());
- boolean caughtException = false;
-
boolean wifiEnabled = sWifiManager.isWifiEnabled();
if (wifiEnabled) {
- // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no
- // STA+AP concurrency.
- ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false));
+ // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's
+ // no STA+AP concurrency.
+ ShellIdentityUtils.invokeWithShellPermissions(() ->
+ sWifiManager.setWifiEnabled(false));
PollingCheck.check("Wifi turn off failed!", WIFI_OFF_ON_TIMEOUT_MILLIS,
() -> !sWifiManager.isWifiEnabled());
SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled");
@@ -1966,36 +1969,42 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
() -> sWifiManager.isWifiEnabled());
}
- TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+ runWithScanning(() -> {
+ boolean caughtException = false;
+ TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
- // now make a second request - this should fail.
- TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLock);
- try {
- sWifiManager.startLocalOnlyHotspot(callback2, null);
- } catch (IllegalStateException e) {
- Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice");
- caughtException = true;
- }
- if (!caughtException) {
- // second start did not fail, should clean up the hotspot.
+ // now make a second request - this should fail.
+ TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLock);
+ try {
+ sWifiManager.startLocalOnlyHotspot(callback2, null);
+ } catch (IllegalStateException e) {
+ Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice");
+ caughtException = true;
+ }
+ if (!caughtException) {
+ // second start did not fail, should clean up the hotspot.
+
+ // add sleep to avoid calling stopLocalOnlyHotspot before TetherController
+ // initialization.
+ // TODO: remove this sleep as soon as b/124330089 is fixed.
+ Log.d(TAG, "Sleeping for 2 seconds");
+ Thread.sleep(2000);
- // add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization.
+ stopLocalOnlyHotspot(callback2, wifiEnabled);
+ }
+ assertTrue(caughtException);
+
+ // add sleep to avoid calling stopLocalOnlyHotspot before TetherController
+ // initialization.
// TODO: remove this sleep as soon as b/124330089 is fixed.
Log.d(TAG, "Sleeping for 2 seconds");
Thread.sleep(2000);
- stopLocalOnlyHotspot(callback2, wifiEnabled);
- }
- assertTrue(caughtException);
-
- // add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization.
- // TODO: remove this sleep as soon as b/124330089 is fixed.
- Log.d(TAG, "Sleeping for 2 seconds");
- Thread.sleep(2000);
-
- stopLocalOnlyHotspot(callback, wifiEnabled);
+ stopLocalOnlyHotspot(callback, wifiEnabled);
+ }, false);
}
+
private static class TestExecutor implements Executor {
private ConcurrentLinkedQueue<Runnable> tasks = new ConcurrentLinkedQueue<>();
@@ -3701,28 +3710,29 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
// Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no
// STA+AP concurrency.
ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false));
- PollingCheck.check("Wifi turn off failed!", WIFI_OFF_ON_TIMEOUT_MILLIS,
- () -> !sWifiManager.isWifiEnabled());
+ PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled());
SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled");
PollingCheck.check("Wifi turn on failed!", WIFI_OFF_ON_TIMEOUT_MILLIS,
() -> sWifiManager.isWifiEnabled());
- boolean isStaApConcurrencySupported = sWifiManager.isStaApConcurrencySupported();
- // start local only hotspot.
- TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
- try {
- if (isStaApConcurrencySupported) {
- assertTrue(sWifiManager.isWifiEnabled());
- } else {
- // no concurrency, wifi should be disabled.
- assertFalse(sWifiManager.isWifiEnabled());
+ runWithScanning(() -> {
+ boolean isStaApConcurrencySupported = sWifiManager.isStaApConcurrencySupported();
+ // start local only hotspot.
+ TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+ try {
+ if (isStaApConcurrencySupported) {
+ assertTrue(sWifiManager.isWifiEnabled());
+ } else {
+ // no concurrency, wifi should be disabled.
+ assertFalse(sWifiManager.isWifiEnabled());
+ }
+ } finally {
+ // clean up local only hotspot no matter if assertion passed or failed
+ stopLocalOnlyHotspot(callback, true);
}
- } finally {
- // clean up local only hotspot no matter if assertion passed or failed
- stopLocalOnlyHotspot(callback, true);
- }
- assertTrue(sWifiManager.isWifiEnabled());
+ assertTrue(sWifiManager.isWifiEnabled());
+ }, false);
}
/**
@@ -3811,7 +3821,7 @@ public class WifiManagerTest extends WifiJUnit4TestBase {
boolean newState = !currState;
sWifiManager.setScanAlwaysAvailable(newState);
PollingCheck.check(
- "Wifi settings toggle failed!",
+ "Wifi scanning toggle failed!",
DURATION_SETTINGS_TOGGLE,
() -> sWifiManager.isScanAlwaysAvailable() == newState);
assertEquals(newState, sWifiManager.isScanAlwaysAvailable());
diff --git a/tools/cts-api-coverage/Android.bp b/tools/cts-api-coverage/Android.bp
index e9aeb8ca070..51d57de70c3 100644
--- a/tools/cts-api-coverage/Android.bp
+++ b/tools/cts-api-coverage/Android.bp
@@ -20,7 +20,8 @@ java_library_host {
name: "api-coverage",
srcs: [
- "**/*.java",
+ "src/com/android/cts/apicommon/**/*.java",
+ "src/com/android/cts/apicoverage/**/*.java",
"proto/**/*.proto",
],
@@ -55,3 +56,20 @@ java_binary_host {
static_libs: ["api-coverage"],
manifest: "MANIFEST.mf",
}
+
+java_library_host {
+ name: "api-map",
+ srcs: [
+ "src/com/android/cts/apicommon/**/*.java",
+ "src/com/android/cts/apimap/**/*.java",
+ "src/com/android/cts/ctsprofiles/**/*.java",
+ ],
+ static_libs: [
+ "apache-commons-math3",
+ "jsr305",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ ],
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java
index 59c5d534cc7..b05d74e4920 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java
@@ -114,6 +114,37 @@ public class ApiClass implements Comparable<ApiClass>, HasCoverage {
mApiMethods.add(method);
}
+ /** Look for a matching constructor and mark it as covered by the given test method */
+ public void markConstructorCoveredTest(
+ List<String> parameterTypes, String testMethod) {
+ if (mSuperClass != null) {
+ // Mark matching constructors in the superclass
+ mSuperClass.markConstructorCoveredTest(parameterTypes, testMethod);
+ }
+ Optional<ApiConstructor> apiConstructor = getConstructor(parameterTypes);
+ apiConstructor.ifPresent(constructor -> constructor.setCoveredTest(testMethod));
+ }
+
+
+ /** Look for a matching method and if found and mark it as covered by the given test method */
+ public void markMethodCoveredTest(
+ String name, List<String> parameterTypes, String testMethod) {
+ if (mSuperClass != null) {
+ // Mark matching methods in the super class
+ mSuperClass.markMethodCoveredTest(name, parameterTypes, testMethod);
+ }
+ if (!mInterfaceMap.isEmpty()) {
+ // Mark matching methods in the interfaces
+ for (ApiClass mInterface : mInterfaceMap.values()) {
+ if (mInterface != null) {
+ mInterface.markMethodCoveredTest(name, parameterTypes, testMethod);
+ }
+ }
+ }
+ Optional<ApiMethod> apiMethod = getMethod(name, parameterTypes);
+ apiMethod.ifPresent(method -> method.setCoveredTest(testMethod));
+ }
+
/** Look for a matching constructor and mark it as covered */
public void markConstructorCovered(List<String> parameterTypes, String coveredbyApk) {
if (mSuperClass != null) {
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java
index af9c99ec88c..1f765e7cc3d 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java
@@ -35,6 +35,9 @@ public class ApiConstructor implements Comparable<ApiConstructor> {
// A list of test APKs (aka CTS modules) that use this method.
private final Map<String, Boolean> mCoveredWith = new ConcurrentHashMap<>();
+ // A list of CTS test methods that call this API constructor.
+ private final Map<String, Boolean> mCoveredTests = new ConcurrentHashMap<>();
+
public ApiConstructor(String name, List<String> parameterTypes, boolean deprecated) {
mName = name;
mParameterTypes = new ArrayList<String>(parameterTypes);
@@ -69,7 +72,16 @@ public class ApiConstructor implements Comparable<ApiConstructor> {
mCoveredWith.put(coveredWithModule, true);
}
+ /** Adds a test method that is calling this API. */
+ public void setCoveredTest(String testMethod) {
+ mCoveredTests.put(testMethod, true);
+ }
+
public Set<String> getCoveredWith() {
return mCoveredWith.keySet();
}
+
+ public Set<String> getCoveredTests() {
+ return mCoveredTests.keySet();
+ }
}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java
index 43746c51035..eb900cee862 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java
@@ -46,6 +46,9 @@ public class ApiMethod implements Comparable<ApiMethod> {
// A list of test APKs (aka CTS modules) that use this method.
private final Map<String, Boolean> mCoveredWith = new ConcurrentHashMap<>();
+ // A list of CTS test methods that call this API method.
+ private final Map<String, Boolean> mCoveredTests = new ConcurrentHashMap<>();
+
public ApiMethod(
String name,
List<String> parameterTypes,
@@ -110,6 +113,10 @@ public class ApiMethod implements Comparable<ApiMethod> {
return mCoveredWith.keySet();
}
+ public Set<String> getCoveredTests() {
+ return mCoveredTests.keySet();
+ }
+
public void setCovered(String coveredWithModule) {
if (coveredWithModule.endsWith(".apk")) {
coveredWithModule = coveredWithModule.substring(0, coveredWithModule.length() - 4);
@@ -117,4 +124,9 @@ public class ApiMethod implements Comparable<ApiMethod> {
mCoveredWith.put(coveredWithModule, true);
}
+
+ /** Adds a test method that is calling this API. */
+ public void setCoveredTest(String coveredTest) {
+ mCoveredTests.put(coveredTest, true);
+ }
}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiPackage.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiPackage.java
index 902f53872eb..9f588b43c17 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiPackage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiPackage.java
@@ -117,4 +117,3 @@ public class ApiPackage implements HasCoverage {
return null;
}
}
-
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CoverageComparator.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/CoverageComparator.java
index f33a839daf3..8169c254916 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CoverageComparator.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/CoverageComparator.java
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-package com.android.cts.apicoverage;
-
-import com.android.cts.apicommon.HasCoverage;
+package com.android.cts.apicommon;
import java.util.Comparator;
public class CoverageComparator implements Comparator<HasCoverage> {
+
+ /** Compares whether two coverage entities are same. */
public int compare(HasCoverage entity, HasCoverage otherEntity) {
int lhsPct = Math.round(entity.getCoveragePercentage());
int rhsPct = Math.round(otherEntity.getCoveragePercentage());
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
index 2ab69ddc865..3450a7bf2f0 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
@@ -21,6 +21,7 @@ import com.android.cts.apicommon.ApiConstructor;
import com.android.cts.apicommon.ApiCoverage;
import com.android.cts.apicommon.ApiMethod;
import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.apicommon.CoverageComparator;
import java.io.OutputStream;
import java.io.PrintStream;
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
index 8302882a4ce..ec656d53668 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
@@ -21,6 +21,7 @@ import com.android.cts.apicommon.ApiConstructor;
import com.android.cts.apicommon.ApiCoverage;
import com.android.cts.apicommon.ApiMethod;
import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.apicommon.CoverageComparator;
import java.io.File;
import java.io.OutputStream;
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/AnnotationAnalyzer.java b/tools/cts-api-coverage/src/com/android/cts/apimap/AnnotationAnalyzer.java
new file mode 100644
index 00000000000..9bd28b04a0b
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/AnnotationAnalyzer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+import com.android.cts.ctsprofiles.AnnotationManagement;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+
+/** A class for collecting annotation values. */
+class AnnotationAnalyzer extends AnnotationVisitor {
+
+ private final AnnotationManagement mAnnotationManagement;
+
+ private final String mFieldSignature;
+
+ AnnotationAnalyzer(
+ AnnotationManagement annotationManagement,
+ String fieldSignature) {
+ super(Opcodes.ASM9);
+ mAnnotationManagement = annotationManagement;
+ mFieldSignature = fieldSignature;
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ return new AnnotationAnalyzer(mAnnotationManagement, getFieldSignature(name));
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ mAnnotationManagement.addTestMetadata(
+ getFieldSignature(name), String.valueOf(value));
+ }
+
+ /** Appends an annotation field name to the field signature. */
+ private String getFieldSignature(String fieldName) {
+ if (fieldName == null) {
+ return mFieldSignature;
+ }
+ return String.format("%s:%s", mFieldSignature, fieldName);
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/ApiMap.java b/tools/cts-api-coverage/src/com/android/cts/apimap/ApiMap.java
new file mode 100644
index 00000000000..e7a929ed102
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/ApiMap.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+public class ApiMap {
+
+ /** Entry of the CTS-M automation tool. */
+ public static void main(String[] args) {}
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/CallGraphManager.java b/tools/cts-api-coverage/src/com/android/cts/apimap/CallGraphManager.java
new file mode 100644
index 00000000000..f1eca857113
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/CallGraphManager.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+import com.android.cts.apicommon.ApiClass;
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.ctsprofiles.ClassProfile;
+import com.android.cts.ctsprofiles.MethodProfile;
+import com.android.cts.ctsprofiles.ModuleProfile;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+
+/** A class for collecting APIs covered by a CTS module. */
+public class CallGraphManager {
+
+ // Cache API calls for each CTS method.
+ private final Map<String, CoveredApiCache> mCoveredApiCaches = new HashMap<>();
+
+ private final ModuleProfile mModule;
+
+ /** Cache the covered API list for a CTS method. */
+ static class CoveredApiCache {
+
+ private final Map<String, MethodProfile> mApiConstructors = new HashMap<>();
+
+ private final Map<String, MethodProfile> mApiMethods = new HashMap<>();
+
+ public void mergeApis(CoveredApiCache apis) {
+ addMethods(apis.getApiMethods());
+ addConstructors(apis.getApiConstructors());
+ }
+
+ public void addMethods(Map<String, MethodProfile> methods) {
+ mApiMethods.putAll(methods);
+ }
+
+ public void addConstructors(Map<String, MethodProfile> constructors) {
+ mApiConstructors.putAll(constructors);
+ }
+
+ public Map<String, MethodProfile> getApiConstructors() {
+ return mApiConstructors;
+ }
+
+ public Map<String, MethodProfile> getApiMethods() {
+ return mApiMethods;
+ }
+ }
+
+ public CallGraphManager(ModuleProfile moduleProfile) {
+ mModule = moduleProfile;
+ }
+
+ public ModuleProfile getModule() {
+ return mModule;
+ }
+
+ /**
+ * Maps detected APIs to CTS test methods and marks them as covered by this CTS module.
+ */
+ public void resolveCoveredApis(ApiCoverage apiCoverage) {
+ for (ClassProfile classProfile : mModule.getClasses()) {
+ if (!classProfile.isNonAbstractTestClass()) {
+ continue;
+ }
+ for (MethodProfile methodProfile : classProfile.getTestMethods().values()) {
+ TarJan tarjan = new TarJan(methodProfile, mCoveredApiCaches.keySet());
+ Stack<Integer> stack = new Stack<>();
+ Set<Integer> visitedComponents = new HashSet<>();
+ String methodSignature = methodProfile.getMethodSignatureWithClass();
+ stack.add(tarjan.getComponentID(methodSignature));
+ visitedComponents.add(tarjan.getComponentID(methodSignature));
+ // Do recursive search for API calls.
+ resolveMethodCoveredApis(stack, visitedComponents, tarjan);
+ markCoveredApisWithCaller(methodSignature, apiCoverage);
+ }
+ }
+ markCoveredApisWithoutCaller(apiCoverage);
+ }
+
+ /** Collects covered APIs for a test method via memorized search. */
+ private CoveredApiCache resolveMethodCoveredApis(
+ Stack<Integer> stack,
+ Set<Integer> visitedComponents,
+ TarJan tarjan) {
+ List<MethodProfile> methods = tarjan.getComponent(stack.peek());
+ String methodSignature = methods.get(0).getMethodSignatureWithClass();
+ CoveredApiCache coveredApis = mCoveredApiCaches.get(methodSignature);
+ if (coveredApis != null) {
+ return coveredApis;
+ }
+ coveredApis = new CoveredApiCache();
+ for (MethodProfile method: methods) {
+ coveredApis.addMethods(method.getApiMethodCalls());
+ coveredApis.addConstructors(method.getApiConstructorCalls());
+ }
+ for (MethodProfile method: methods) {
+ for (MethodProfile methodCall : method.getCommonMethodCalls().values()) {
+ String methodCallSignature = methodCall.getMethodSignatureWithClass();
+ int componentID = tarjan.getComponentID(methodCallSignature);
+ if (visitedComponents.contains(componentID)) {
+ continue;
+ }
+ visitedComponents.add(componentID);
+ stack.add(componentID);
+ CoveredApiCache apis = resolveMethodCoveredApis(stack, visitedComponents, tarjan);
+ coveredApis.mergeApis(apis);
+ stack.pop();
+ }
+ }
+ for (MethodProfile method: methods) {
+ mCoveredApiCaches.put(method.getMethodSignatureWithClass(), coveredApis);
+ }
+ return coveredApis;
+ }
+
+ /** Searches for the API class based on the given package name and class name. */
+ private ApiClass getApiClass(
+ String packageName, String className, ApiCoverage apiCoverage) {
+ ApiPackage apiPackage = apiCoverage.getPackage(packageName);
+ if (apiPackage != null) {
+ return apiPackage.getClass(className);
+ }
+ return null;
+ }
+
+ /** Marks that APIs are covered by this CTS module. */
+ private void markCoveredApisWithoutCaller(ApiCoverage apiCoverage) {
+ for (ClassProfile classProfile: mModule.getClasses()) {
+ if (!classProfile.isApiClass()) {
+ continue;
+ }
+ ApiClass apiClass = getApiClass(
+ classProfile.getPackageName(),
+ classProfile.getClassName(),
+ apiCoverage
+ );
+ if (apiClass == null) {
+ continue;
+ }
+ for (MethodProfile methodProfile: classProfile.getMethods().values()) {
+ if (methodProfile.getMethodName().equals("<init>")) {
+ apiClass.markConstructorCovered(
+ methodProfile.getMethodParams(),
+ mModule.getModuleName()
+ );
+ } else {
+ apiClass.markMethodCovered(
+ methodProfile.getMethodName(),
+ methodProfile.getMethodParams(),
+ mModule.getModuleName()
+ );
+ }
+ }
+ }
+ }
+
+ /** Marks that APIs are called by the given CTS test method. */
+ private void markCoveredApisWithCaller(String methodSignature, ApiCoverage apiCoverage) {
+ CoveredApiCache apiCache = mCoveredApiCaches.get(methodSignature);
+ if (apiCache == null) {
+ return;
+ }
+ for (MethodProfile apiConstructor : apiCache.getApiConstructors().values()) {
+ ApiClass apiClass = getApiClass(
+ apiConstructor.getPackageName(),
+ apiConstructor.getClassName(),
+ apiCoverage
+ );
+ if (apiClass != null) {
+ apiClass.markConstructorCoveredTest(
+ apiConstructor.getMethodParams(),
+ String.format("[%s] %s", mModule.getModuleName(), methodSignature)
+ );
+ }
+ }
+ for (MethodProfile apiMethod : apiCache.getApiMethods().values()) {
+ ApiClass apiClass = getApiClass(
+ apiMethod.getPackageName(), apiMethod.getClassName(), apiCoverage);
+ if (apiClass != null) {
+ apiClass.markMethodCoveredTest(
+ apiMethod.getMethodName(),
+ apiMethod.getMethodParams(),
+ String.format("[%s] %s", mModule.getModuleName(), methodSignature)
+ );
+ }
+ }
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/ClassAnalyzer.java b/tools/cts-api-coverage/src/com/android/cts/apimap/ClassAnalyzer.java
new file mode 100644
index 00000000000..87d932690da
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/ClassAnalyzer.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.ctsprofiles.ClassProfile;
+import com.android.cts.ctsprofiles.ClassProfile.ClassType;
+import com.android.cts.ctsprofiles.MethodProfile;
+import com.android.cts.ctsprofiles.MethodProfile.MethodType;
+import com.android.cts.ctsprofiles.ModuleProfile;
+import com.android.cts.ctsprofiles.Utils;
+
+import org.apache.commons.math3.util.Pair;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+
+/** A class for collecting class methods and annotations. */
+public class ClassAnalyzer extends ClassVisitor {
+
+ private final ClassProfile mClass;
+
+ private final ModuleProfile mModule;
+
+ private final ApiCoverage mApiCoverage;
+
+ static final Set<String> XTS_ANNOTATIONS = new HashSet<>(
+ List.of("com.android.compatibility.common.util.CddTest",
+ "com.android.compatibility.common.util.ApiTest",
+ "com.android.compatibility.common.util.GmsTest",
+ "com.android.compatibility.common.util.VsrTest",
+ "android.platform.test.annotations.RequiresFlagsEnabled",
+ "android.platform.test.annotations.RequiresFlagsDisabled")
+ );
+
+ public ClassAnalyzer(
+ ClassProfile classProfile, ModuleProfile moduleProfile, ApiCoverage apiCoverage) {
+ super(Opcodes.ASM9);
+ mClass = classProfile;
+ mModule = moduleProfile;
+ mApiCoverage = apiCoverage;
+ }
+
+ @Override
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ addClassType(access, Opcodes.ACC_ABSTRACT, ClassType.ABSTRACT);
+ addClassType(access, Opcodes.ACC_INTERFACE, ClassType.INTERFACE);
+ addClassType(access, Opcodes.ACC_ANNOTATION, ClassType.ANNOTATION);
+ if (superName != null) {
+ mClass.setSuperClass(getClassProfile(superName));
+ }
+ if (interfaces != null) {
+ for (String interfaceName : interfaces) {
+ mClass.addInterface(getClassProfile(interfaceName));
+ }
+ }
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions) {
+ // Add a method in the class.
+ List<String> params = new ArrayList<>();
+ for (Type type: Type.getArgumentTypes(desc)) {
+ params.add(type.getClassName().replace("\\$", "."));
+ }
+ MethodProfile method = mClass.getOrCreateMethod(name, params);
+ method.addMethodType(MethodType.DIRECT_MEMBER);
+ Type returnType = Type.getReturnType(desc);
+ // Set the method type to common if it is not a test methods candidate.
+ if ((access & Opcodes.ACC_PUBLIC) == 0
+ || !returnType.getClassName().equals("void")
+ || !params.isEmpty()) {
+ method.addMethodType(MethodType.COMMON);
+ }
+ return new MethodAnalyzer(method, mModule, mApiCoverage);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ // Add an annotation for the class.
+ String type = Type.getType(desc).getClassName();
+ if (!shouldRecordAnnotation(type)) {
+ return super.visitAnnotation(desc, visible);
+ }
+ Pair<String, String> packageClass = Utils.getPackageClass(type);
+ ClassProfile annotationClass = mModule.getOrCreateClass(
+ packageClass.getFirst(), packageClass.getSecond(), mApiCoverage);
+ mClass.annotationManagement.addAnnotation(annotationClass);
+ if (XTS_ANNOTATIONS.contains(type)) {
+ return new AnnotationAnalyzer(mClass.annotationManagement, packageClass.getSecond());
+ }
+ return super.visitAnnotation(desc, visible);
+ }
+
+ private ClassProfile getClassProfile(String asmClassName) {
+ // Add a class in the module.
+ Pair<String, String> packageClass = Utils.getPackageClassFromASM(asmClassName);
+ return mModule.getOrCreateClass(
+ packageClass.getFirst(), packageClass.getSecond(), mApiCoverage);
+ }
+
+ private void addClassType(int access, int asmType, ClassType classType) {
+ if ((access & asmType) != 0) {
+ mClass.addClassType(classType);
+ }
+ }
+
+ private static boolean shouldRecordAnnotation(String name) {
+ // TODO(slotus): Filter out some annotations.
+ return true;
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/HtmlWriter.java b/tools/cts-api-coverage/src/com/android/cts/apimap/HtmlWriter.java
new file mode 100644
index 00000000000..de2fb6fcfa2
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/HtmlWriter.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * Class that outputs an HTML report of the API mapping data. The format is as same as
+ * cts-api-coverage HTML reports.
+ */
+class HtmlWriter {
+
+ public static void printHtmlReport(XmlWriter xmlWriter, OutputStream htmlOut)
+ throws TransformerException, IOException {
+
+ final PipedOutputStream xmlOut = new PipedOutputStream();
+ final PipedInputStream xmlIn = new PipedInputStream(xmlOut);
+
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ xmlWriter.dumpXml(xmlOut);
+ } catch (FileNotFoundException | TransformerException e) {
+ throw new RuntimeException(e);
+ }
+ // Close the output stream to avoid "Write dead end" errors.
+ try {
+ xmlOut.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ t.start();
+
+ InputStream xsl = ApiMap.class.getResourceAsStream("/api-coverage.xsl");
+ StreamSource xslSource = new StreamSource(xsl);
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer(xslSource);
+
+ StreamSource xmlSource = new StreamSource(xmlIn);
+ StreamResult result = new StreamResult(htmlOut);
+ transformer.transform(xmlSource, result);
+ }
+}
+
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/MethodAnalyzer.java b/tools/cts-api-coverage/src/com/android/cts/apimap/MethodAnalyzer.java
new file mode 100644
index 00000000000..fef283ac693
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/MethodAnalyzer.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+import static com.android.cts.apimap.ClassAnalyzer.XTS_ANNOTATIONS;
+
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.ctsprofiles.ClassProfile;
+import com.android.cts.ctsprofiles.MethodProfile;
+import com.android.cts.ctsprofiles.ModuleProfile;
+import com.android.cts.ctsprofiles.Utils;
+
+import org.apache.commons.math3.util.Pair;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+
+/** A class for collecting method calls and method annotations. */
+public class MethodAnalyzer extends MethodVisitor {
+
+ private final MethodProfile mMethod;
+
+ private final ModuleProfile mModule;
+
+ private final ApiCoverage mApiCoverage;
+
+ // TODO: Add known common method packages that don't need to be recorded.
+ private static final Set<String> COMMON_PACKAGES = new HashSet<>(List.of());
+
+ public MethodAnalyzer(
+ MethodProfile methodProfile,
+ ModuleProfile moduleProfile,
+ ApiCoverage apiCoverage) {
+ super(Opcodes.ASM9);
+ mMethod = methodProfile;
+ mModule = moduleProfile;
+ mApiCoverage = apiCoverage;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ // Add an annotation for the method.
+ String type = Type.getType(desc).getClassName();
+ if (!shouldRecordAnnotation(type)) {
+ return super.visitAnnotation(desc, visible);
+ }
+ Pair<String, String> packageClass = Utils.getPackageClass(type);
+ ClassProfile annotationClass = mModule.getOrCreateClass(
+ packageClass.getFirst(), packageClass.getSecond(), mApiCoverage);
+ mMethod.annotationManagement.addAnnotation(annotationClass);
+ if (XTS_ANNOTATIONS.contains(type)) {
+ return new AnnotationAnalyzer(mMethod.annotationManagement, packageClass.getSecond());
+ }
+ return super.visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ String name,
+ String desc,
+ Handle bootstrapMethodHandle, Object... bootstrapMethodArgs) {
+ for (Object obj : bootstrapMethodArgs) {
+ if (!(obj instanceof Handle handle)) {
+ continue;
+ }
+ handleMethodCall(handle.getOwner(), handle.getName(), handle.getDesc());
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owners, String name, String desc, boolean itf) {
+ handleMethodCall(owners, name, desc);
+ }
+
+ /** Records a method call. */
+ private void handleMethodCall(String owners, String name, String desc) {
+ Pair<String, String> packageClass = Utils.getPackageClassFromASM(owners);
+ String packageName = packageClass.getFirst();
+ String className = packageClass.getSecond();
+ if (!shouldRecordMethodCall(packageName, className)) {
+ return;
+ }
+ List<String> params = new ArrayList<>();
+ for (Type type : Type.getArgumentTypes(desc)) {
+ params.add(type.getClassName().replaceAll("\\$", "."));
+ }
+ ClassProfile classProfile = mModule.getOrCreateClass(
+ packageName, className, mApiCoverage);
+ MethodProfile callMethod = classProfile.getOrCreateMethod(name, params);
+ if (classProfile.isApiClass()) {
+ if (name.equals("<init>")) {
+ mMethod.addApiConstructorCall(callMethod);
+ } else {
+ mMethod.addApiMethodCall(callMethod);
+ }
+ } else {
+ mMethod.addCommonMethodCall(callMethod);
+ }
+ }
+
+ private static boolean shouldRecordMethodCall(String packageName, String className) {
+ if (className.startsWith("[")) {
+ return false;
+ }
+ for (String commonPackage: COMMON_PACKAGES) {
+ if (packageName.startsWith(commonPackage)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean shouldRecordAnnotation(String name) {
+ // TODO(slotus): Filter out some annotations.
+ return true;
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/TarJan.java b/tools/cts-api-coverage/src/com/android/cts/apimap/TarJan.java
new file mode 100644
index 00000000000..c4b80392215
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/TarJan.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+import com.android.cts.ctsprofiles.MethodProfile;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+/** A class to implement Tarjan's strongly connected components algorithm. */
+public final class TarJan {
+
+ private int mTime = 0;
+ private int mNewNodeIndex = 0;
+ private final Map<String, Node> mVertices = new HashMap<>();
+ private final Stack<Node> mStack = new Stack<>();
+ private final Set<String> mResolvedMethods;
+ private final Map<String, Integer> mComponentIDs = new HashMap<>();
+ private final Map<Integer, List<MethodProfile>> mComponentNodes = new HashMap<>();
+
+ private static final class Node {
+ final int mDfn;
+ final MethodProfile mMethod;
+ int mLow;
+ boolean mInStack;
+
+ Node(int index, MethodProfile method) {
+ mDfn = index;
+ mMethod = method;
+ }
+ }
+
+ public TarJan(MethodProfile testMethod, Set<String> resolvedMethods) {
+ mResolvedMethods = resolvedMethods;
+ tarjan(testMethod);
+ }
+
+ /** Gets the strongly connected component the given method belongs to. */
+ public int getComponentID(String methodSignature) {
+ return mComponentIDs.get(methodSignature);
+ }
+
+ /** Gets a list methods belong to the given strongly connected component. */
+ public List<MethodProfile> getComponent(int id) {
+ return mComponentNodes.get(id);
+ }
+
+ private Node tarjan(MethodProfile method) {
+ Node v = new Node(mTime++, method);
+ v.mLow = v.mDfn;
+ String methodSignature = method.getMethodSignatureWithClass();
+ mVertices.put(methodSignature, v);
+ mStack.add(v);
+ v.mInStack = true;
+
+ if (!mResolvedMethods.contains(methodSignature)) {
+ for (MethodProfile callee: method.getCommonMethodCalls().values()) {
+ String calleeSignature = callee.getMethodSignatureWithClass();
+ Node w = mVertices.get(calleeSignature);
+ if (w == null) {
+ w = tarjan(callee);
+ v.mLow = Math.min(v.mLow, w.mLow);
+ } else if (w.mInStack) {
+ v.mLow = Math.min(v.mLow, w.mDfn);
+ }
+ }
+ }
+
+ if (v.mLow == v.mDfn) {
+ Node w;
+ mNewNodeIndex++;
+ mComponentNodes.put(mNewNodeIndex, new ArrayList<>());
+ do {
+ w = mStack.pop();
+ mComponentIDs.put(methodSignature, mNewNodeIndex);
+ mComponentNodes.get(mNewNodeIndex).add(w.mMethod);
+ w.mInStack = false;
+ } while (!w.equals(v));
+ }
+ return v;
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/XmlWriter.java b/tools/cts-api-coverage/src/com/android/cts/apimap/XmlWriter.java
new file mode 100644
index 00000000000..93b8f1ee4d7
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/XmlWriter.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.apimap;
+
+import com.android.cts.apicommon.ApiClass;
+import com.android.cts.apicommon.ApiConstructor;
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.apicommon.ApiMethod;
+import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.apicommon.CoverageComparator;
+import com.android.cts.ctsprofiles.ClassProfile;
+import com.android.cts.ctsprofiles.MethodProfile;
+import com.android.cts.ctsprofiles.ModuleProfile;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.ProcessingInstruction;
+
+import java.io.FileNotFoundException;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+/** Class that outputs an XML report of API and xTS-annotation mapping data. */
+public class XmlWriter {
+
+ private final Document mDoc;
+
+ private final Element mXTSAnnotationMapElement;
+
+ private final Element mXTSApiMapElement;
+
+ public XmlWriter() throws ParserConfigurationException {
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = docFactory.newDocumentBuilder();
+ mDoc = documentBuilder.newDocument();
+ ProcessingInstruction pi = mDoc.createProcessingInstruction(
+ "xml-stylesheet", "type=\"text/xsl\" href=\"api-map.xsl\"?>");
+ SimpleDateFormat format = new SimpleDateFormat(
+ "EEE, MMM d, yyyy h:mm a z", Locale.CHINA);
+ String date = format.format(new Date(System.currentTimeMillis()));
+ Element rootElement = mDoc.createElement("api-coverage");
+ rootElement.setAttribute("generatedTime", date);
+ rootElement.setAttribute("title", "cts-m-automation");
+ mDoc.appendChild(rootElement);
+ mDoc.insertBefore(pi, rootElement);
+ mXTSAnnotationMapElement = mDoc.createElement("xts-annotation");
+ rootElement.appendChild(mXTSAnnotationMapElement);
+ mXTSApiMapElement = mDoc.createElement("api");
+ rootElement.appendChild(mXTSApiMapElement);
+ }
+
+ /** Dumps the document to an xml file. */
+ public void dumpXml(OutputStream outputStream)
+ throws FileNotFoundException, TransformerException {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ transformer.setOutputProperty("indent", "yes");
+ DOMSource source = new DOMSource(mDoc);
+ StreamResult result = new StreamResult(outputStream);
+ transformer.transform(source, result);
+ }
+
+ /** Generates the data for API coverage. */
+ public void generateApiMapData(ApiCoverage apiCoverage) {
+ CoverageComparator comparator = new CoverageComparator();
+ List<ApiPackage> packages = new ArrayList<>(apiCoverage.getPackages());
+ packages.sort(comparator);
+ ApiStatistics statistics = new ApiStatistics();
+ for (ApiPackage pkg : packages) {
+ if (pkg.getTotalMethods() > 0) {
+ mXTSApiMapElement.appendChild(createApiPackageElement(pkg, statistics));
+ }
+ }
+ mXTSApiMapElement.appendChild(createApiTotalElement(
+ statistics.mTotalMethods, statistics.mTotalCoveredMethods));
+ }
+
+ /** Generates the data for xTS annotations. */
+ public void generateXtsAnnotationMapData(ModuleProfile module) {
+ Element moduleElement = mDoc.createElement("test-module");
+ moduleElement.setAttribute("module", module.getModuleName());
+ for (ClassProfile classProfile : module.getClasses()) {
+ if (!classProfile.isNonAbstractTestClass()) {
+ continue;
+ }
+ Element classElement = createTestClassElement(classProfile);
+ if (classElement.hasChildNodes()) {
+ moduleElement.appendChild(classElement);
+ }
+ }
+ if (moduleElement.hasChildNodes()) {
+ mXTSAnnotationMapElement.appendChild(moduleElement);
+ }
+ }
+
+ private Element createApiConstructorElement(
+ ApiConstructor constructor, ApiStatistics statistics) {
+ if (constructor.isDeprecated()) {
+ if (constructor.isCovered()) {
+ statistics.mTotalCoveredMethods -= 1;
+ }
+ statistics.mTotalMethods -= 1;
+ }
+ List<String> coveredWithList = new ArrayList<>(constructor.getCoveredWith());
+ Collections.sort(coveredWithList);
+ String coveredWith = String.join(",", coveredWithList);
+ Element element = mDoc.createElement("constructor");
+ element.setAttribute("name", constructor.getName());
+ element.setAttribute("deprecated", String.valueOf(constructor.isDeprecated()));
+ element.setAttribute("covered", String.valueOf(constructor.isCovered()));
+ element.setAttribute("with", coveredWith);
+ for (String parameterType : constructor.getParameterTypes()) {
+ Element paramElement = mDoc.createElement("parameter");
+ paramElement.setAttribute("type", parameterType);
+ element.appendChild(paramElement);
+ }
+ for (String test: constructor.getCoveredTests()) {
+ element.appendChild(createCoveredByElement(test));
+ }
+ return element;
+ }
+
+ private Element createApiMethodElement(ApiMethod method, ApiStatistics statistics) {
+ if (method.isDeprecated()) {
+ if (method.isCovered()) {
+ statistics.mTotalCoveredMethods -= 1;
+ }
+ statistics.mTotalMethods -= 1;
+ }
+ List<String> coveredWithList = new ArrayList<>(method.getCoveredWith());
+ Collections.sort(coveredWithList);
+ String coveredWith = String.join(",", coveredWithList);
+ Element element = mDoc.createElement("method");
+ element.setAttribute("name", method.getName());
+ element.setAttribute("returnType", method.getReturnType());
+ element.setAttribute("deprecated", String.valueOf(method.isDeprecated()));
+ element.setAttribute("static", String.valueOf(method.isStaticMethod()));
+ element.setAttribute("final", String.valueOf(method.isFinalMethod()));
+ element.setAttribute("visibility", method.getVisibility());
+ element.setAttribute("abstract", String.valueOf(method.isAbstractMethod()));
+ element.setAttribute("covered", String.valueOf(method.isCovered()));
+ element.setAttribute("with", coveredWith);
+ for (String parameterType : method.getParameterTypes()) {
+ Element paramElement = mDoc.createElement("parameter");
+ paramElement.setAttribute("type", parameterType);
+ element.appendChild(paramElement);
+ }
+ for (String test: method.getCoveredTests()) {
+ element.appendChild(createCoveredByElement(test));
+ }
+ return element;
+ }
+
+ private Element createCoveredByElement(String test) {
+ Element element = mDoc.createElement("covered-by");
+ element.setAttribute("name", test);
+ return element;
+ }
+
+ private Element createApiPackageElement(ApiPackage pkg, ApiStatistics statistics) {
+ Element element = mDoc.createElement("package");
+ element.setAttribute("name", pkg.getName());
+ element.setAttribute("numCovered", String.valueOf(pkg.getNumCoveredMethods()));
+ element.setAttribute("numTotal", String.valueOf(pkg.getTotalMethods()));
+ element.setAttribute("coveragePercentage", String.valueOf(
+ Math.round(pkg.getCoveragePercentage())));
+ statistics.mTotalMethods += pkg.getTotalMethods();
+ statistics.mTotalCoveredMethods += pkg.getNumCoveredMethods();
+ List<ApiClass> classes = new ArrayList<>(pkg.getClasses());
+ CoverageComparator comparator = new CoverageComparator();
+ classes.sort(comparator);
+ for (ApiClass apiClass : classes) {
+ if (apiClass.getTotalMethods() > 0) {
+ element.appendChild(createApiClassElement(apiClass, statistics));
+ }
+ }
+ return element;
+ }
+
+ private Element createApiClassElement(ApiClass apiClass, ApiStatistics statistics) {
+ Element element = mDoc.createElement("class");
+ element.setAttribute("name", apiClass.getName());
+ element.setAttribute("numCovered", String.valueOf(apiClass.getNumCoveredMethods()));
+ element.setAttribute("numTotal", String.valueOf(apiClass.getTotalMethods()));
+ element.setAttribute("deprecated", String.valueOf(apiClass.isDeprecated()));
+ element.setAttribute("coveragePercentage", String.valueOf(
+ Math.round(apiClass.getCoveragePercentage())));
+ for (ApiConstructor constructor : apiClass.getConstructors()) {
+ element.appendChild(createApiConstructorElement(constructor, statistics));
+ }
+ for (ApiMethod method : apiClass.getMethods()) {
+ element.appendChild(createApiMethodElement(method, statistics));
+ }
+ return element;
+ }
+
+ private Element createApiTotalElement(int totalMethods, int totalCoveredMethods) {
+ Element total = mDoc.createElement("total");
+ total.setAttribute("numCovered", String.valueOf(totalCoveredMethods));
+ total.setAttribute("numTotal", String.valueOf(totalMethods));
+ total.setAttribute("coveragePercentage", String.valueOf(
+ Math.round((float) totalCoveredMethods / totalMethods * 100.0f)));
+ return total;
+ }
+
+ private Element createTestClassElement(ClassProfile classProfile) {
+ Element classElement = mDoc.createElement("test-class");
+ classElement.setAttribute("package", classProfile.getPackageName());
+ classElement.setAttribute("name", classProfile.getClassName());
+ for (Map.Entry<String, Set<String>> xtsAnnotation :
+ classProfile.annotationManagement.getTestMetadata().entrySet()) {
+ classElement.appendChild(createXtsAnnotationElement(
+ xtsAnnotation.getKey(),
+ xtsAnnotation.getValue()));
+ }
+ for (MethodProfile testMethod : classProfile.getTestMethods().values()) {
+ Element methodElement = createTestMethodElement(testMethod);
+ if (methodElement.hasChildNodes()) {
+ classElement.appendChild(methodElement);
+ }
+ }
+ return classElement;
+ }
+
+ private Element createTestMethodElement(MethodProfile methodProfile) {
+ Element methodElement = mDoc.createElement("test-method");
+ methodElement.setAttribute("name", methodProfile.getMethodName());
+ for (Map.Entry<String, Set<String>> xtsAnnotation :
+ methodProfile.annotationManagement.getTestMetadata().entrySet()) {
+ methodElement.appendChild(createXtsAnnotationElement(
+ xtsAnnotation.getKey(),
+ xtsAnnotation.getValue()));
+ }
+ return methodElement;
+ }
+
+ private Element createXtsAnnotationElement(String name, Set<String> values) {
+ Element element = mDoc.createElement("cts-annotation");
+ element.setAttribute("name", name);
+ element.setAttribute("values", String.join(";", values));
+ return element;
+ }
+
+ static final class ApiStatistics {
+ int mTotalMethods = 0;
+ int mTotalCoveredMethods = 0;
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/AnnotationManagement.java b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/AnnotationManagement.java
new file mode 100644
index 00000000000..abe5b85b324
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/AnnotationManagement.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ctsprofiles;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** A class to manage annotations marked on the CTS class/method. */
+public final class AnnotationManagement {
+
+ private static final String TEST_METADATA_ERROR_MSG = "Not allowed to add new test metadata";
+
+ // A list of annotations marked on the CTS class/method.
+ private final List<ClassProfile> mAnnotations = new ArrayList<>();
+
+ // A map to store useful annotation values. For example, values collected from @ApiTest,
+ // @CddTest annotations. This values are indicating what the class/method is testing.
+ private final Map<String, Set<String>> mTestMetadata = new HashMap<>();
+
+ private boolean mTestMetadataMerged = false;
+
+ /** Gets all xTS annotation values mapped to the class/method. */
+ public List<ClassProfile> getAnnotations() {
+ return mAnnotations;
+ }
+
+ /** Gets all test metadata mapped to the class/method. */
+ public Map<String, Set<String>> getTestMetadata() {
+ if (!mTestMetadataMerged) {
+ resolveNestedTestMetadata();
+ }
+ return mTestMetadata;
+ }
+
+ /** Adds a test metadata. */
+ public void addTestMetadata(String type, String value) {
+ if (mTestMetadataMerged) {
+ throw new RuntimeException(TEST_METADATA_ERROR_MSG);
+ }
+ mTestMetadata.putIfAbsent(type, new HashSet<>());
+ mTestMetadata.get(type).add(value);
+ }
+
+ /** Adds an annotation marked on the class/method. */
+ public void addAnnotation(ClassProfile classProfile) {
+ mAnnotations.add(classProfile);
+ }
+
+ /**
+ * Merges nested test metadata. For example, a customized annotation @MyAnnotation could be
+ * annotated by @ApiTest.
+ */
+ private void resolveNestedTestMetadata() {
+ for (ClassProfile annotation : mAnnotations) {
+ annotation.annotationManagement.getTestMetadata().forEach((key, value) -> {
+ mTestMetadata.putIfAbsent(key, new HashSet<>());
+ mTestMetadata.get(key).addAll(value);
+ });
+ }
+ mTestMetadataMerged = true;
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java
new file mode 100644
index 00000000000..3b169fcb7f2
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ctsprofiles;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** Representation of a class included in the CTS package. */
+public class ClassProfile {
+
+ public final AnnotationManagement annotationManagement = new AnnotationManagement();
+
+ private final String mModule;
+
+ private final String mPackage;
+
+ private final String mClass;
+
+ private int mClassType = 0;
+
+ private ClassProfile mSuperClass = null;
+
+ // A list of interfaces implemented by this class.
+ private final List<ClassProfile> mInterfaces = new ArrayList<>();
+
+ // A map of methods defined in this class with the method signature as the key.
+ private final Map<String, MethodProfile> mMethods = new HashMap<>();
+
+ // A map of test methods defined in this class with the method signature as the key.
+ private Map<String, MethodProfile> mTestMethods = null;
+
+ // TODO(slotus): Add known patterns.
+ private static final Set<String> JUNIT4_ANNOTATION_PATTERNS = new HashSet<>(List.of());
+
+ // TODO(slotus): Add known patterns.
+ private static final Set<String> JUNIT3_CLASS_PATTERNS = new HashSet<>(List.of());
+
+ public ClassProfile(String moduleName, String packageName, String className, boolean apiClass) {
+ mModule = moduleName;
+ mClass = className;
+ mPackage = packageName;
+ if (apiClass) {
+ mClassType |= ClassType.API.getValue();
+ }
+ }
+
+ /** Representation of the class type. */
+ public enum ClassType {
+ INTERFACE(1),
+ ABSTRACT(2),
+ JUNIT3(4),
+ JUNIT4(8),
+ ANNOTATION(16),
+ /** A non-test and non-annotation class.*/
+ COMMON(32),
+ API(64);
+
+ private final int mValue;
+
+ ClassType(int value) {
+ mValue = value;
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+ }
+
+ public String getClassSignature() {
+ return Utils.getClassSignature(mPackage, mClass);
+ }
+
+ public String getClassName() {
+ return mClass;
+ }
+
+ public String getPackageName() {
+ return mPackage;
+ }
+
+ public String getModuleName() {
+ return mModule;
+ }
+
+ public Map<String, MethodProfile> getMethods() {
+ return mMethods;
+ }
+
+ /** Creates a class method. */
+ public MethodProfile getOrCreateMethod(
+ String methodName, List<String> params) {
+ String methodSignature = Utils.getMethodSignature(methodName, params);
+ if (!mMethods.containsKey(methodSignature)) {
+ mMethods.put(methodSignature, new MethodProfile(this, methodName, params));
+ }
+ return mMethods.get(methodSignature);
+ }
+
+ /** Adds an interface implemented by the class. */
+ public void addInterface(ClassProfile interfaceProfile) {
+ mInterfaces.add(interfaceProfile);
+ }
+
+ /** Adds a class type for the class. */
+ public void addClassType(ClassType classType) {
+ mClassType |= classType.getValue();
+ }
+
+ public void setSuperClass(ClassProfile superClass) {
+ mSuperClass = superClass;
+ }
+
+ /** Collects all test methods contained in the class. */
+ public Map<String, MethodProfile> getTestMethods() {
+ if (mTestMethods != null) {
+ return mTestMethods;
+ }
+ mTestMethods = new HashMap<>();
+ mMethods.forEach((methodKey, method) -> {
+ if (method.isTestMethod()) {
+ mTestMethods.put(methodKey, method);
+ }
+ });
+ // Test methods defined in the super class will also be collected.
+ if (mSuperClass != null) {
+ mSuperClass.getTestMethods().forEach(mTestMethods::putIfAbsent);
+ }
+ return mTestMethods;
+ }
+
+ /** Returns true if the class is a test class. */
+ public boolean isTestClass() {
+ if (matchAnyTypes(ClassType.ANNOTATION.getValue() | ClassType.API.getValue())) {
+ return false;
+ }
+ if (!isJunit4Class() && !isJunit3Class()) {
+ addClassType(ClassType.COMMON);
+ return false;
+ }
+ return true;
+ }
+
+ /** Returns true if the class is an API class. */
+ public boolean isApiClass() {
+ return matchAllTypes(ClassType.API.getValue());
+ }
+
+ /** Returns true if the class is a test class but not an abstract class. */
+ public boolean isNonAbstractTestClass() {
+ return (isTestClass() && !matchAnyTypes(
+ ClassType.ABSTRACT.getValue() | ClassType.INTERFACE.getValue()));
+ }
+
+
+ /** Returns true if it is decided that whether this is a test class or not. */
+ private boolean testClassResolved() {
+ return matchAnyTypes(
+ ClassType.JUNIT3.getValue()
+ | ClassType.JUNIT4.getValue()
+ | ClassType.COMMON.getValue()
+ | ClassType.ANNOTATION.getValue()
+ | ClassType.API.getValue()
+ );
+ }
+
+ /** Returns true if the class is a Junit4 test class. */
+ protected boolean isJunit4Class() {
+ if (testClassResolved()) {
+ return matchAllTypes(ClassType.JUNIT4.getValue());
+ }
+ // Check if the class is marked by a Junit4 runner.
+ for (ClassProfile annotation : annotationManagement.getAnnotations()) {
+ for (String pattern : JUNIT4_ANNOTATION_PATTERNS) {
+ if (annotation.getClassSignature().matches(pattern)) {
+ addClassType(ClassType.JUNIT4);
+ return true;
+ }
+ }
+ }
+ // Check if any methods are marked by a Junit4 annotation.
+ for (MethodProfile method : mMethods.values()) {
+ if (method.isJunit4Method()) {
+ addClassType(ClassType.JUNIT4);
+ return true;
+ }
+ }
+ // Check if the class is extended from a Junit4 class.
+ if (mSuperClass != null && mSuperClass.isJunit4Class()) {
+ addClassType(ClassType.JUNIT4);
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if the class is a Junit3 test class. */
+ protected boolean isJunit3Class() {
+ if (testClassResolved()) {
+ return matchAllTypes(ClassType.JUNIT3.getValue());
+ }
+ if (mSuperClass != null) {
+ // Check if the class is extended from a Junit3 base class.
+ for (String pattern : JUNIT3_CLASS_PATTERNS) {
+ if (mSuperClass.getClassSignature().matches(pattern)) {
+ addClassType(ClassType.JUNIT3);
+ return true;
+ }
+ }
+ // Check if the class is extended from a Junit3 class.
+ if (mSuperClass.isJunit3Class()) {
+ addClassType(ClassType.JUNIT3);
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private boolean matchAnyTypes(int typesValue) {
+ return (mClassType & typesValue) != 0;
+ }
+
+ private boolean matchAllTypes(int typesValue) {
+ return (mClassType & typesValue) == typesValue;
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/MethodProfile.java b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/MethodProfile.java
new file mode 100644
index 00000000000..e4a4315195c
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/MethodProfile.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ctsprofiles;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** Representation of a method included in the CTS package. */
+public class MethodProfile {
+
+ public final AnnotationManagement annotationManagement = new AnnotationManagement();
+
+ private final String mMethod;
+
+ private final ClassProfile mClass;
+
+ private final List<String> mParams;
+
+ private int mMethodType = 0;
+
+ // A map of non-api methods called by this method with the method signature as the key.
+ private final HashMap<String, MethodProfile> mCommonMethodCalls = new HashMap<>();
+
+ // A map of api methods called by this method with the method signature as the key.
+ private final HashMap<String, MethodProfile> mApiMethodCalls = new HashMap<>();
+
+ // A map of api constructors called by this method with the method signature as the key.
+ private final HashMap<String, MethodProfile> mApiConstructorCalls = new HashMap<>();
+
+ // TODO(slotus): Add known patterns.
+ private static final Set<String> JUNIT4_ANNOTATION_PATTERNS = new HashSet<>(List.of());
+
+ public enum MethodType {
+ JUNIT3(1),
+ JUNIT4(2),
+ /** A non-test method.*/
+ COMMON(4),
+ // TODO(slotus): Solve the override case.
+ /** A method that is not extended from the super class. */
+ DIRECT_MEMBER(8);
+
+ private final int mValue;
+
+ MethodType(int value) {
+ mValue = value;
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+ }
+
+ public MethodProfile(
+ ClassProfile classProfile, String methodName, List<String> params) {
+ mClass = classProfile;
+ mMethod = methodName;
+ mParams = params;
+ }
+
+ public String getMethodName() {
+ return mMethod;
+ }
+
+ public String getModuleName() {
+ return mClass.getModuleName();
+ }
+
+ public String getPackageName() {
+ return mClass.getPackageName();
+ }
+
+ public String getClassName() {
+ return mClass.getClassName();
+ }
+
+ public List<String> getMethodParams() {
+ return mParams;
+ }
+
+ public Map<String, MethodProfile> getApiMethodCalls() {
+ return mApiMethodCalls;
+ }
+
+ public Map<String, MethodProfile> getApiConstructorCalls() {
+ return mApiConstructorCalls;
+ }
+
+ public Map<String, MethodProfile> getCommonMethodCalls() {
+ return mCommonMethodCalls;
+ }
+
+ public String getMethodSignatureWithClass() {
+ return Utils.getMethodSignatureWithClass(
+ mClass.getPackageName(), mClass.getClassName(), mMethod, mParams);
+ }
+
+ /** Adds an API method called by the method. **/
+ public void addApiMethodCall(MethodProfile apiMethod) {
+ mApiMethodCalls.putIfAbsent(apiMethod.getMethodSignatureWithClass(), apiMethod);
+ }
+
+ /** Adds an API constructor called by the method. **/
+ public void addApiConstructorCall(MethodProfile apiConstructor) {
+ mApiConstructorCalls.putIfAbsent(
+ apiConstructor.getMethodSignatureWithClass(), apiConstructor);
+ }
+
+ /** Adds a non-API method called by the method. **/
+ public void addCommonMethodCall(MethodProfile method) {
+ mCommonMethodCalls.putIfAbsent(method.getMethodSignatureWithClass(), method);
+ }
+
+ /** Adds a method type for the method. */
+ public void addMethodType(MethodType methodType) {
+ mMethodType |= methodType.getValue();
+ }
+
+ /** Returns true if it is decided that whether this is a test method or not. */
+ private boolean testMethodResolved() {
+ return matchAnyTypes(
+ MethodType.JUNIT3.getValue()
+ | MethodType.JUNIT4.getValue()
+ | MethodType.COMMON.getValue());
+ }
+
+ /** Returns true if the method is a test method. */
+ public boolean isTestMethod() {
+ if (!isJunit4Method() && !isJunit3Method()) {
+ addMethodType(MethodType.COMMON);
+ return false;
+ }
+ return true;
+ }
+
+ /** Returns true if the method is a JUnit3 test method. */
+ protected boolean isJunit3Method() {
+ if (testMethodResolved()) {
+ return matchAllTypes(MethodType.JUNIT3.getValue());
+ }
+ if (mClass.isJunit3Class() && mMethod.startsWith("test")) {
+ addMethodType(MethodType.JUNIT3);
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if the method is a JUnit4 test method. */
+ protected boolean isJunit4Method() {
+ if (testMethodResolved()) {
+ return matchAllTypes(MethodType.JUNIT4.getValue());
+ }
+ for (ClassProfile annotation : annotationManagement.getAnnotations()) {
+ for (String pattern : JUNIT4_ANNOTATION_PATTERNS) {
+ if (annotation.getClassSignature().matches(pattern)) {
+ addMethodType(MethodType.JUNIT4);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean matchAnyTypes(int typesValue) {
+ return (mMethodType & typesValue) != 0;
+ }
+
+ private boolean matchAllTypes(int typesValue) {
+ return (mMethodType & typesValue) == typesValue;
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ModuleProfile.java b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ModuleProfile.java
new file mode 100644
index 00000000000..1855c3d3a10
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ModuleProfile.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ctsprofiles;
+
+import com.android.cts.apicommon.ApiClass;
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.apicommon.ApiPackage;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Representation of a CTS module. */
+public class ModuleProfile {
+
+ private final Map<String, ClassProfile> mClasses = new HashMap<>();
+
+ private final String mName;
+
+ public ModuleProfile(String name) {
+ mName = name;
+ }
+
+ /** Creates a class packaged in the module. */
+ public ClassProfile getOrCreateClass(
+ String packageName, String className, ApiCoverage apiCoverage) {
+ String classSignature = Utils.getClassSignature(packageName, className);
+ ApiPackage apiPackage = apiCoverage.getPackage(packageName);
+ ApiClass apiClass = apiPackage != null ? apiPackage.getClass(className) : null;
+ if (!mClasses.containsKey(classSignature)) {
+ mClasses.put(
+ classSignature,
+ new ClassProfile(mName, packageName, className, apiClass != null)
+ );
+ }
+ return mClasses.get(classSignature);
+ }
+
+ public String getModuleName() {
+ return mName;
+ }
+
+ public Collection<ClassProfile> getClasses() {
+ return Collections.unmodifiableCollection(mClasses.values());
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/Utils.java b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/Utils.java
new file mode 100644
index 00000000000..c4e9a8df7e3
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/Utils.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ctsprofiles;
+
+import org.apache.commons.math3.util.Pair;
+
+import java.util.List;
+
+/** Utility for generating package, class or method information. */
+public final class Utils {
+
+ /** Splits a class signature and returns the (package, class) pair. */
+ public static Pair<String, String> getPackageClass(String classSignature) {
+ int splitPos = classSignature.lastIndexOf('.');
+ String className = classSignature.substring(splitPos + 1);
+ String packageName = "";
+ if (splitPos > 0) {
+ packageName = classSignature.substring(0, splitPos);
+ }
+ return Pair.create(packageName, className.replaceAll("\\$", "."));
+ }
+
+ /** Splits a class name represented in ASM and returns the (package, class) pair. */
+ public static Pair<String, String> getPackageClassFromASM(String packageClass) {
+ // The class name obtained from ASM includes package information and is separated by "/".
+ // For example, the class com.my.package.MyClass.NestClass is represented as
+ // com/my/package/MyClass$NestClass in ASM.
+ int splitPos = packageClass.lastIndexOf("/");
+ String packageName = "";
+ if (splitPos != -1) {
+ packageName = packageClass.substring(0, splitPos);
+ }
+ String className = packageClass.substring(splitPos + 1);
+ return Pair.create(
+ packageName.replaceAll("/", "."),
+ className.replaceAll("\\$", ".")
+ );
+ }
+
+ /** Returns a class signature in the format {package}.{class}. */
+ public static String getClassSignature(String packageName, String className) {
+ if (packageName.isEmpty()) {
+ return className;
+ }
+ return String.format("%s.%s", packageName, className);
+ }
+
+ /** Returns a method signature in the format {method}({param1}, {param2}, ...). */
+ public static String getMethodSignature(String methodName, List<String> paramTypes) {
+ return String.format("%s(%s)", methodName, String.join(", ", paramTypes));
+ }
+
+ /**
+ * Returns a full method signature in the format
+ * {package}.{class}#{method}({param1}, {param2}, ...).
+ */
+ public static String getMethodSignatureWithClass(
+ String packageName, String className, String methodName, List<String> paramTypes) {
+ String classSignature = getClassSignature(packageName, className);
+ String methodSignature = getMethodSignature(methodName, paramTypes);
+ return String.format("%s#%s", classSignature, methodSignature);
+ }
+}
diff --git a/tools/cts-tradefed/res/config/cts-exclude.xml b/tools/cts-tradefed/res/config/cts-exclude.xml
index b754596cd74..75d417a3368 100644
--- a/tools/cts-tradefed/res/config/cts-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-exclude.xml
@@ -33,4 +33,11 @@
<!-- Exclude @SecurityTest tests from CTS. These are tested in STS. b/180417031-->
<option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:exclude-annotation:android.platform.test.annotations.AsbSecurityTest" />
<option name="compatibility:test-arg" value="com.android.compatibility.common.tradefed.testtype.JarHostTest:exclude-annotation:android.platform.test.annotations.AsbSecurityTest" />
+
+ <!-- Exclude CtsJvmtiRunTest912HostTestCases as it depends on implementation details of the ART
+ module. b/287732826 -->
+ <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest912HostTestCases" />
+ <!-- Exclude CtsJvmtiRunTest911HostTestCases as it depends on line numbers which were changed
+ due to openjdk 17 upgrade. b/338607812 -->
+ <option name="compatibility:exclude-filter" value="CtsJvmtiRunTest911HostTestCases" />
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 89605d7c201..0872306802c 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -246,6 +246,17 @@
<!-- b/300310474 -->
<option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:5:REAR_DUAL] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
<option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:5:REAR_DUAL] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
+ <!-- b/319385496 -->
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:2:HALF_OPENED] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:3:OPENED] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:4:OPENED_REVERSE] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:5:OPENED_PRESENTATION] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:6:OPENED_REVERSE_PRESENTATION] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:2:HALF_OPENED] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:3:OPENED] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:4:OPENED_REVERSE] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:5:OPENED_PRESENTATION] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
+ <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[foldable:6:OPENED_REVERSE_PRESENTATION] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
<!-- b/202357331 -->
<option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedDeviceOwnerTest#testCreateAdminSupportIntent" />
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index f194a52ec87..884df2c2907 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -137,6 +137,9 @@
<option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testChaCha20Poly1305Udp4UdpEncap" />
<option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.IpSecManagerTest#testChaCha20Poly1305Tcp4UdpEncap" />
+ <!-- b/335351293 Remove ApfIntegrationTest running against broken vendor images on GSI -->
+ <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.ApfIntegrationTest" />
+
<!-- b/285247534 Remove WM Extension tests on GSI -->
<option name="compatibility:exclude-filter" value="CtsWindowManagerJetpackTestCases android.server.wm.jetpack.SdkAvailabilityTest" />
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
index 364123949a1..c89c6b23e63 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
@@ -95,6 +95,7 @@ public class CtsConfigLoadingTest {
"systems",
"sysui",
"telecom",
+ "threadnetwork",
"tv",
"uitoolkit",
"uwb",
diff --git a/tools/release-parser/tests/Android.bp b/tools/release-parser/tests/Android.bp
index 37827d31676..c04da1b1640 100644
--- a/tools/release-parser/tests/Android.bp
+++ b/tools/release-parser/tests/Android.bp
@@ -15,6 +15,7 @@
// cts release-parser java unit test library
// ============================================================
package {
+ default_team: "trendy_team_automotive",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/tools/vm-tests-tf/Android.bp b/tools/vm-tests-tf/Android.bp
index 15428fb6b0c..da8c93baa8c 100644
--- a/tools/vm-tests-tf/Android.bp
+++ b/tools/vm-tests-tf/Android.bp
@@ -14,6 +14,7 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_team: "trendy_team_art_mainline",
}
java_library {