summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/nene/src/main/java/com/android/bedstead/nene/activities/ActivityReference.java12
-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--hostsidetests/adb/OWNERS2
-rw-r--r--hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java1
-rw-r--r--hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java18
-rw-r--r--hostsidetests/edi/src/android/edi/cts/NativeDeviceInfo.java35
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java5
-rw-r--r--hostsidetests/incrementalinstall/Android.bp1
-rw-r--r--hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java30
-rw-r--r--hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java2
-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.java41
-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/src/android/devicepolicy/cts/BluetoothTest.java12
-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/window/ConfigChangeTests.java12
-rw-r--r--tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerMultiDisplayTest.java1
-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/mediapc/Android.bp3
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java140
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java4
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl213
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/VulkanRequirement.java75
-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/mpc.pb.go13
-rw-r--r--tests/mediapc/requirements/requirements.pb.go450
-rw-r--r--tests/mediapc/requirements/requirements.proto26
-rw-r--r--tests/mediapc/requirements/requirements.txtpb162
-rw-r--r--tests/mediapc/requirements/templatefns.go48
-rw-r--r--tests/mediapc/requirements/templatefns_test.go36
-rw-r--r--tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java14
-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.java23
-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/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt27
-rw-r--r--tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt9
-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.java124
-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.java211
-rw-r--r--tests/tests/libcorefileio/src/android/cts/LockHoldingService.java165
-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/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.java62
-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.bp3
-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/DeviceLockTestPlayerListener.java119
-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.java23
-rw-r--r--tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/PlayerListener.java6
-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/res/raw/ElephantsDream_2ch_48Khz_15s.mp3bin0 -> 448852 bytes
-rw-r--r--tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java35
-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/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/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/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.java26
-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/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
195 files changed, 5276 insertions, 2130 deletions
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/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/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/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/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/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/playback/HdmiCecRoutingControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
index 055653f0957..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 {
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/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/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/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 ded3568ef08..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;
@@ -83,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";
@@ -101,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"};
@@ -115,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);
}
}
}
@@ -175,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;
}
@@ -214,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);
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/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/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/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/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/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 f5f7a9a899f..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,30 +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-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
@@ -420,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],
@@ -1604,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);
}
@@ -1632,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();
@@ -2214,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 {
@@ -2366,10 +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 ConcurrentCodecRequirement addR5_1__H_1_9_1080p() {
return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_9_1080p());
}
@@ -2394,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());
@@ -2476,23 +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());
}
-
- /** Add requirement <b>7.1.4.1/H-1-3</b> */
- public VulkanRequirement addR7_1_4_1__H_1_3() {
- return this.addRequirement(VulkanRequirement.createR7_1_4_1__H_1_3());
- }
-
/* Adds requirement 7.5/H-1-1 */
public PrimaryCameraRequirement addPrimaryRearCameraReq() {
return this.addRequirement(PrimaryCameraRequirement.createRearPrimaryCamera());
@@ -2565,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());
@@ -2578,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 c52604617ec..b9c7e15cc06 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -185,10 +185,6 @@ public final class RequirementConstants {
public static final String SHORT_RESOLUTION = "short_resolution_pixels";
public static final String SUPPORTED_PERFORMANCE_POINTS = "supported_performance_points";
public static final String TEST_RESOLUTION = "resolution";
- public static final String VK_EXT_GLOBAL_PRIORITY = "vk_ext_global_priority";
- public static final String VK_NON_CPU_DEVICE_COUNT = "vk_non_cpu_device_count";
- public static final String VK_PHYSICAL_DEVICE_PROTECTED_MEMORY =
- "vk_physical_device_protected_memory";
// keep-sorted end
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 4ccf08e4aae..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 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 create{{ SafeReqID $r.GetId | UpperCase}}() {
- return {{UpperCamelCase $r.GetName}}Requirement.create();
- }
+ 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,80 +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_id}} = 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 if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}Long
- {{- else }}{{$mt}}
- {{- end }}>builder()
+ .<{{template "JavaClass" $mt}}>builder()
.setId("{{$m_id}}")
- .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 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 }})
+ .setPredicate(RequirementConstants.{{template "CompMethod" $m}})
{{- range $mpc, $s := $r.GetSpecs }}
{{- with index $s.GetRequiredValues $m_id}}
- .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 if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}, {{.GetLongValue}}L
- {{- else }}{{$mt}}
- {{- end }})
+ .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_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_id}}(
- {{- 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 if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}long
- {{- else }}{{$mt}}
- {{- end }} v) {
- this.setMeasuredValue("{{$m_id}}", 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/src/android/mediapc/cts/common/VulkanRequirement.java b/tests/mediapc/common/src/android/mediapc/cts/common/VulkanRequirement.java
deleted file mode 100644
index 4680c437d0d..00000000000
--- a/tests/mediapc/common/src/android/mediapc/cts/common/VulkanRequirement.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.common;
-
-import android.os.Build;
-
-/**
- * Constructors and measurement setters for Vulkan MPC requirements.
- */
-public final class VulkanRequirement extends Requirement {
-
- /**
- * <b>7.1.4.1/H-1-3</b> MUST support
- * {@code VkPhysicalDeviceProtectedMemoryFeatures.protectedMemory} and
- * {@code VK_EXT_global_priority}.
- */
- public static VulkanRequirement createR7_1_4_1__H_1_3() {
- RequiredMeasurement<Boolean> globalPriority =
- RequiredMeasurement.<Boolean>builder().setId(
- RequirementConstants.VK_EXT_GLOBAL_PRIORITY)
- .setPredicate(RequirementConstants.BOOLEAN_EQ)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, true)
- .build();
- RequiredMeasurement<Boolean> protectedMemory =
- RequiredMeasurement.<Boolean>builder().setId(
- RequirementConstants.VK_PHYSICAL_DEVICE_PROTECTED_MEMORY)
- .setPredicate(RequirementConstants.BOOLEAN_EQ)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, true)
- .build();
-
- RequiredMeasurement<Integer> count =
- RequiredMeasurement.<Integer>builder().setId(
- RequirementConstants.VK_NON_CPU_DEVICE_COUNT)
- .setPredicate(RequirementConstants.INTEGER_GTE)
- .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, 1)
- .build();
-
- return new VulkanRequirement(RequirementConstants.R7_1_4_1__H_1_3,
- globalPriority, protectedMemory, count);
- }
-
- private VulkanRequirement(String id, RequiredMeasurement<?>... reqs) {
- super(id, reqs);
- }
-
- /** Is {@code VK_EXT_global_priority} supported. */
- public void setGlobalPrioritySupported(boolean supported) {
- this.setMeasuredValue(RequirementConstants.VK_EXT_GLOBAL_PRIORITY, supported);
- }
-
- /** Is {@code VkPhysicalDeviceProtectedMemoryFeatures.protectedMemory} supported. */
- public void setDeviceProtectedMemorySupported(boolean supported) {
- this.setMeasuredValue(RequirementConstants.VK_PHYSICAL_DEVICE_PROTECTED_MEMORY, supported);
- }
-
- /** The count of non {@code VK_PHYSICAL_DEVICE_TYPE_CPU} Vulcan Devices. */
- public void setNonCpuVulcanDeviceCount(int count) {
- this.setMeasuredValue(RequirementConstants.VK_NON_CPU_DEVICE_COUNT, count);
-
- }
-}
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/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/requirements.pb.go b/tests/mediapc/requirements/requirements.pb.go
index 5d60dbdd4ad..599b68c870f 100644
--- a/tests/mediapc/requirements/requirements.pb.go
+++ b/tests/mediapc/requirements/requirements.pb.go
@@ -313,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() {
@@ -389,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
@@ -404,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() {
@@ -459,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
@@ -665,6 +686,108 @@ 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{
@@ -685,7 +808,7 @@ var file_cts_tests_mediapc_requirements_requirements_proto_rawDesc = []byte{
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, 0xe4, 0x04, 0x0a, 0x0b,
+ 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,
@@ -708,113 +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, 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, 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,
+ 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,
+ 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 (
@@ -830,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
@@ -840,28 +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
- 5, // 8: android.media.performanceclass.requirements.Requirement.SpecsEntry.value:type_name -> android.media.performanceclass.requirements.RequirementSpec
- 6, // 9: android.media.performanceclass.requirements.Requirement.MeasurementsEntry.value:type_name -> android.media.performanceclass.requirements.RequiredMeasurement
- 7, // 10: android.media.performanceclass.requirements.RequirementSpec.RequiredValuesEntry.value:type_name -> android.media.performanceclass.requirements.RequiredValue
- 11, // [11:11] is the sub-list for method output_type
- 11, // [11:11] is the sub-list for method input_type
- 11, // [11:11] is the sub-list for extension type_name
- 11, // [11:11] is the sub-list for extension extendee
- 0, // [0:11] 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() }
@@ -930,6 +1112,30 @@ 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),
@@ -944,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 3fa6fed5a0f..676c0c55b99 100644
--- a/tests/mediapc/requirements/requirements.proto
+++ b/tests/mediapc/requirements/requirements.proto
@@ -40,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 {
@@ -58,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 {
@@ -91,6 +101,22 @@ message RequiredValue {
}
}
+// 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;
diff --git a/tests/mediapc/requirements/requirements.txtpb b/tests/mediapc/requirements/requirements.txtpb
index ac300255fea..3cc6a9a7fc4 100644
--- a/tests/mediapc/requirements/requirements.txtpb
+++ b/tests/mediapc/requirements/requirements.txtpb
@@ -252,7 +252,9 @@ requirements {
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."
+ 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"
@@ -262,69 +264,157 @@ requirements {
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."
+ 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: {
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 65
+ }
+ }
+ }
+ }
}
}
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."
+ 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
+ }
+ }
+ }
+ }
}
}
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."
+ 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: {
+ required_values: {
+ key: "codec_initialization_latency_ms"
+ value {
+ long_value: 50
+ }
+ }
+ }
+ }
}
}
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."
+ 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: 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."
+ 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
+ }
+ }
+ }
+ }
}
}
}
@@ -508,12 +598,27 @@ requirements {
}
requirements {
id: "5.1/H-1-13"
- description: "- Decoder initialization latency"
+ 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 an audio decoder initialization latency of 30 ms or less."
+ 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 {
@@ -521,13 +626,25 @@ requirements {
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: "same"
+ 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
+ }
+ }
}
}
}
@@ -719,19 +836,40 @@ requirements {
}
requirements {
id: "5.12/H-1-2"
- description: "- RGBA_1010102 color format"
+ 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: "same"
+ 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
+ }
+ }
}
}
}
@@ -1981,7 +2119,7 @@ requirements {
}
requirements {
id: "7.1.4.1/H-1-3"
- name: "Vulcan"
+ name: "Vulkan"
description: "Must support vulkan physical device protected memory and global priority."
measurements: [
{
diff --git a/tests/mediapc/requirements/templatefns.go b/tests/mediapc/requirements/templatefns.go
index 1b743d935f6..59491d37cab 100644
--- a/tests/mediapc/requirements/templatefns.go
+++ b/tests/mediapc/requirements/templatefns.go
@@ -16,6 +16,7 @@
package templatefns
import (
+ "fmt"
"strings"
"text/template"
"unicode"
@@ -26,15 +27,17 @@ import (
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,
+ // go/keep-sorted start
+ "Dict": dict,
"KebabCase": kebabCase,
- "UpperCamelCase": upperCamelCase,
"LowerCamelCase": lowerCamelCase,
+ "LowerCase": strings.ToLower,
"SafeReqID": safeReqID,
+ "SnakeCase": snakeCase,
+ "TitleCase": titleCase,
+ "UpperCamelCase": upperCamelCase,
+ "UpperCase": strings.ToUpper,
+ // go/keep-sorted end
}
}
@@ -118,3 +121,36 @@ func safeReqID(s string) string {
}
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
index 9f60de3586b..b0eb431abbe 100644
--- a/tests/mediapc/requirements/templatefns_test.go
+++ b/tests/mediapc/requirements/templatefns_test.go
@@ -15,6 +15,7 @@
package templatefns
import (
+ "errors"
"testing"
)
@@ -144,11 +145,34 @@ func TestLowerCamelCase(t *testing.T) {
}
}
-func TestSafeReqID(t *testing.T) {
- want := "r5_1__h_1_1"
- id := "5.1/H-1-1"
- got := safeReqID(id)
- if got != want {
- t.Fatalf("safeReqID(%q) = %q, want %q", id, got, want)
+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 3da52397a5b..0f795ae95d3 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
@@ -361,15 +361,21 @@ public class CodecInitializationLatencyTest {
PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
if (isEncoder) {
if (isAudio) {
- pce.addRequirement(
- Requirements.createR5_1__H_1_8()).setCodecInitializationLatencyMs(
+ Requirements.addR5_1__H_1_8(pce).setCodecInitializationLatencyMs(
initializationLatency);
} else {
- pce.addR5_1__H_1_7(mMime).setCodecInitLatencyMs(initializationLatency);
+ 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) {
- pce.addR5_1__H_1_13().setCodecInitLatencyMs(initializationLatency);
+ Requirements.addR5_1__H_1_13(pce).setCodecInitializationLatencyMs(
+ initializationLatency);
} else {
pce.addR5_1__H_1_12().setCodecInitLatencyMs(initializationLatency);
}
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
index ae669bf7b3f..cf1e7af8401 100644
--- a/tests/mediapc/src/android/mediapc/cts/VulkanTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/VulkanTest.java
@@ -16,13 +16,13 @@
package android.mediapc.cts;
import android.mediapc.cts.common.PerformanceClassEvaluator;
-import android.mediapc.cts.common.VulkanRequirement;
+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.android.compatibility.common.util.SystemUtil;
import com.google.common.collect.ImmutableList;
@@ -49,19 +49,22 @@ public class VulkanTest {
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 {
- final String output = SystemUtil.runShellCommand("cmd gpu vkjson");
- final JSONArray vkjson = (new JSONObject(output)).getJSONArray("devices");
-
+ 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));
@@ -74,12 +77,12 @@ public class VulkanTest {
* {@code VkPhysicalDeviceProtectedMemoryFeatures.protectedMemory} and
* {@code VK_EXT_global_priority}.
*/
- @CddTest(requirements = {"7.1.4.1/H-1-2"})
+ @CddTest(requirements = {"7.1.4.1/H-1-3"})
@Test
public void checkVulkanProtectedMemoryAndGlobalPrioritySupport() throws Exception {
PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
- VulkanRequirement req = pce.addR7_1_4_1__H_1_3();
+ 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(
@@ -88,9 +91,9 @@ public class VulkanTest {
final boolean hasProtectedMemory = filteredDevices.stream().allMatch(
this::hasProtectedMemory);
- req.setNonCpuVulcanDeviceCount(filteredDevices.size());
- req.setDeviceProtectedMemorySupported(hasProtectedMemory);
- req.setGlobalPrioritySupported(extGlobalPriority);
+ req.setVkNonCpuDeviceCount(filteredDevices.size());
+ req.setVkPhysicalDeviceProtectedMemory(hasProtectedMemory);
+ req.setVkExtGlobalPriority(extGlobalPriority);
pce.submitAndCheck();
}
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/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/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 6903e949696..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);
}
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 d949250ee3c..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 = 10000;
+ 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 =
@@ -544,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 {
@@ -747,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/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/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 34de83f39b5..918abea259b 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaProjectionActivity.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaProjectionActivity.java
@@ -44,6 +44,8 @@ import android.view.WindowManager;
import androidx.annotation.Nullable;
+import com.android.compatibility.common.util.UiAutomatorUtils;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -175,18 +177,44 @@ public class MediaProjectionActivity extends Activity {
pressStartRecording(isWatch);
}
- private static boolean selectEntireScreenOption(String entireScreenString) {
- UiObject2 spinner = waitForObject(By.res(SPINNER_RESOURCE_ID));
- if (spinner == null) {
- Log.e(TAG, "Couldn't find spinner to select projection mode, now scrolling");
- scrollToGivenResource(SPINNER_RESOURCE_ID);
+ @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);
- spinner = waitForObject(By.res(SPINNER_RESOURCE_ID));
- if (spinner == null) {
- Log.e(TAG, "Couldn't find spinner to select projection mode, even after scrolling");
- return false;
+ // 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 = findUiObject(SPINNER_RESOURCE_ID);
+ if (spinner == null) {
+ Log.e(TAG, "Couldn't find spinner to select projection mode, even after scrolling");
+ return false;
+ }
spinner.click();
UiObject2 entireScreenOption = waitForObject(By.text(entireScreenString));
@@ -221,20 +249,8 @@ public class MediaProjectionActivity extends Activity {
private static void pressStartRecording(boolean isWatch) {
// May need to scroll down to the start button on small screen devices.
- UiObject2 startRecordingButton = waitForObject(By.res(ACCEPT_RESOURCE_ID));
- if (startRecordingButton == null) {
- Log.e(TAG, "Couldn't find start recording button, now attempting to scroll to it");
- scrollToGivenResource(ACCEPT_RESOURCE_ID);
-
- startRecordingButton = waitForObject(By.res(ACCEPT_RESOURCE_ID));
- if (startRecordingButton == null) {
- Log.e(TAG, "Couldn't find start recording button, even after scrolling");
- } else {
- Log.d(TAG, "found permission dialog after scrolling down, clicked");
- startRecordingButton.click();
- }
- } else {
- Log.d(TAG, "found permission dialog after searching all windows, clicked");
+ UiObject2 startRecordingButton = findUiObject(ACCEPT_RESOURCE_ID);
+ if (startRecordingButton != null) {
startRecordingButton.click();
}
}
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 5f95f923101..4a9ed91a8b9 100644
--- a/tests/tests/mediacujtest/common/Android.bp
+++ b/tests/tests/mediacujtest/common/Android.bp
@@ -30,6 +30,7 @@ android_library {
"androidx.media3.media3-exoplayer",
"androidx.media3.media3-ui",
"permission-test-util-lib",
+ "cts-wm-util",
],
libs: [
"auto_value_annotations",
@@ -38,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/DeviceLockTestPlayerListener.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/DeviceLockTestPlayerListener.java
new file mode 100644
index 00000000000..ceb7ecd88d2
--- /dev/null
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/DeviceLockTestPlayerListener.java
@@ -0,0 +1,119 @@
+/**
+ * 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.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Looper;
+import android.server.wm.UiDeviceUtils;
+import android.view.Display;
+
+import androidx.annotation.NonNull;
+import androidx.media3.common.Player;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class DeviceLockTestPlayerListener extends PlayerListener {
+
+ private static final int LOCK_DURATION_MS = 5000;
+ private static final int DELAY_MS = 2000;
+
+ private final boolean mIsAudioOnlyClip;
+
+ private Display mDisplay;
+ private boolean mIsPlayerPlaying;
+
+ public DeviceLockTestPlayerListener(long sendMessagePosition, boolean isAudioOnlyClip) {
+ super();
+ this.mSendMessagePosition = sendMessagePosition;
+ this.mIsAudioOnlyClip = isAudioOnlyClip;
+ }
+
+ @Override
+ public void onIsPlayingChanged(boolean isPlaying) {
+ super.onIsPlayingChanged(isPlaying);
+ mIsPlayerPlaying = isPlaying;
+ }
+
+ @Override
+ public TestType getTestType() {
+ return TestType.DEVICE_LOCK_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() + LOCK_DURATION_MS;
+ // Register the screen receiver to listen for screen on and off events
+ mDisplay = mActivity.getDisplay();
+ }
+ }
+
+ @Override
+ public void onEventsMediaItemTransition(@NonNull Player player) {
+ mActivity.mPlayer.createMessage((messageType, payload) -> {
+ // Lock the device
+ UiDeviceUtils.pressSleepButton();
+ // Unlock the device after LOCK_DURATION
+ Timer timer = new Timer();
+ timer.schedule(new Task(), LOCK_DURATION_MS);
+ }).setLooper(Looper.getMainLooper()).setPosition(mSendMessagePosition)
+ .setDeleteAfterDelivery(true)
+ .send();
+ mActivity.mPlayer.createMessage((messageType, payload) -> {
+ // Verify that the screen is on and player is playing while device is in unlocked state
+ assertTrue(isDisplayOn());
+ assertTrue(mIsPlayerPlaying);
+ }).setLooper(Looper.getMainLooper())
+ .setPosition(mIsAudioOnlyClip ? (mSendMessagePosition + LOCK_DURATION_MS + DELAY_MS)
+ : (mSendMessagePosition + DELAY_MS))
+ .setDeleteAfterDelivery(true)
+ .send();
+ }
+
+ private boolean isDisplayOn() {
+ return mDisplay != null && mDisplay.getState() == Display.STATE_ON;
+ }
+
+ class Task extends TimerTask {
+
+ @Override
+ public void run() {
+ unlockPhone();
+ }
+
+ private void unlockPhone() {
+ // Verify that the screen is off when device is in locked state
+ assertFalse(isDisplayOn());
+ if (mIsAudioOnlyClip) {
+ // In case of audio only clip, verify that the player is playing while device is in
+ // locked state
+ assertTrue(mIsPlayerPlaying);
+ } else {
+ // Otherwise verify that the player is not playing while device is in locked state
+ assertFalse(mIsPlayerPlaying);
+ }
+ // Unlock the device
+ UiDeviceUtils.pressWakeupButton();
+ UiDeviceUtils.pressUnlockButton();
+ }
+ }
+}
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 1c7dee3f969..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,14 +24,19 @@ 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;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
+import androidx.media3.common.Tracks.Group;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.ui.PlayerView;
+import com.google.common.collect.ImmutableList;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -47,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) {
@@ -62,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);
}
@@ -94,8 +104,15 @@ public class MainActivity extends AppCompatActivity {
*/
@Override
protected void onStop() {
- mPlayer.stop();
- super.onStop();
+ // When activity is stopped, don't pause the playback if it is an audio only clip
+ ImmutableList<Group> currentTrackGroups = mPlayer.getCurrentTracks().getGroups();
+ if ((currentTrackGroups.size() == 1) && (currentTrackGroups.get(0).getType()
+ == C.TRACK_TYPE_AUDIO)) {
+ super.onStop();
+ } else {
+ mPlayer.stop();
+ super.onStop();
+ }
}
/**
@@ -121,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 b02da44b74a..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
@@ -45,7 +45,7 @@ public abstract class PlayerListener implements Player.Listener {
public static int CURRENT_MEDIA_INDEX = 0;
// Enum Declared for Test Type
- protected enum TestType {
+ public enum TestType {
PLAYBACK_TEST,
SEEK_TEST,
ORIENTATION_TEST,
@@ -58,7 +58,9 @@ public abstract class PlayerListener implements Player.Listener {
PINCH_TO_ZOOM_TEST,
SPEED_CHANGE_TEST,
PIP_MODE_TEST,
- SPLIT_SCREEN_TEST
+ SPLIT_SCREEN_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/res/raw/ElephantsDream_2ch_48Khz_15s.mp3 b/tests/tests/mediacujtest/smalltest/res/raw/ElephantsDream_2ch_48Khz_15s.mp3
new file mode 100644
index 00000000000..101c302d92f
--- /dev/null
+++ b/tests/tests/mediacujtest/smalltest/res/raw/ElephantsDream_2ch_48Khz_15s.mp3
Binary files differ
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 bb95b35a1f8..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
@@ -18,10 +18,13 @@ 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;
import android.media.cujcommon.cts.PlaybackTestPlayerListener;
+import android.media.cujcommon.cts.PlayerListener.TestType;
import android.media.cujcommon.cts.ScrollTestPlayerListener;
import android.media.cujcommon.cts.SeekTestPlayerListener;
import android.media.cujcommon.cts.SplitScreenTestPlayerListener;
@@ -79,6 +82,8 @@ public class CtsMediaShortFormPlaybackTest extends CujTestBase {
"android.resource://android.media.cujsmalltest.cts/raw/tearsofsteel_srt_subtitles_eng_fre_5sec";
private static final String MKV_TEARS_OF_STEEL_ASSET_SSA_SUBTITLES_ENG_FRENCH_URI_STRING =
"android.resource://android.media.cujsmalltest.cts/raw/tearsofsteel_ssa_subtitles_eng_fre_5sec";
+ private static final String MP3_ELEPHANTSDREAM_2CH_48KHZ_URI_STRING =
+ "android.resource://android.media.cujsmalltest.cts/raw/ElephantsDream_2ch_48Khz_15s";
CujTestParam mCujTestParam;
private final String mTestType;
@@ -143,6 +148,18 @@ public class CtsMediaShortFormPlaybackTest extends CujTestBase {
.setTimeoutMilliSeconds(45000)
.setPlayerListener(new SplitScreenTestPlayerListener(5000)).build(),
"Hevc_720p_15sec_SplitScreenTest"},
+ {CujTestParam.builder().setMediaUrls(prepareHevc_720p_15sec_SingleVideoList())
+ .setTimeoutMilliSeconds(50000)
+ .setPlayerListener(new DeviceLockTestPlayerListener(3000, false)).build(),
+ "Hevc_720p_15sec_DeviceLockTest"},
+ {CujTestParam.builder().setMediaUrls(prepareMp3_15secAudioListForDeviceLockTest())
+ .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;
}
@@ -256,6 +273,14 @@ public class CtsMediaShortFormPlaybackTest extends CujTestBase {
return videoInput;
}
+ /**
+ * Prepare Mp3 15sec audio list for Device Lock Test.
+ */
+ public static List<String> prepareMp3_15secAudioListForDeviceLockTest() {
+ List<String> audioInput = Arrays.asList(
+ MP3_ELEPHANTSDREAM_2CH_48KHZ_URI_STRING);
+ return audioInput;
+ }
// Test to Verify video playback with and without seek
@ApiTest(apis = {"android.media.MediaCodec#configure",
@@ -284,9 +309,17 @@ 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)) {
+ Assume.assumeFalse("Skipping " + mTestType + " on watch", isWatchDevice(mActivity));
+ Assume.assumeFalse("Skipping " + mTestType + " on television", isTelevisionDevice(mActivity));
+ }
play(mCujTestParam.mediaUrls(), mCujTestParam.timeoutMilliSeconds());
}
}
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/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/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/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 41b426c9f00..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,7 +38,6 @@ 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;
@@ -52,7 +53,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.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -157,10 +158,23 @@ 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
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/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",